Skip to main content

Поясніть концепцію immutable infrastructure з Docker.

Immutable infrastructure це deployment-філософія: як runtime-instance deployed, він ніколи не модифікується in place. Update, patch і config-зміни відбуваються через build нового artifact (новий image, нова VM, новий container) і заміну старого. Docker enforce'ить це natural'но, бо image read-only, а container'и дешеві для recreate. Результат: reproducible, predictable-infrastructure.

Теорія

TL;DR

  • Mutable: patch running-server in place (SSH, apt upgrade, edit-config). State кожного сервера розходиться з часом. «Snowflake-server».
  • Immutable: build новий artifact (image), deploy, retire старий. Кожен instance identical. «Phoenix-server».
  • Docker робить immutable легким: image = artifact, container = instance, redeploy = stop+start.
  • State має бути external: DB на managed-сервісі або persistent-volume, file у object-storage, session у Redis. Сам container disposable.
  • Rollback це просто «deploy попередній tag».
  • Натурально комбінується з blue-green, canary, rolling-update.

Mental shift

Mutable mindset:

  • «Сервер prod-1 крутиться 3 роки. Ми застосували 47 patch».
  • Config живе на disk; всі мають SSH-access; з часом, ні два сервера не identical.
  • Нова версія = SSH-in, run installer, restart service.
  • Drift між staging і production constant fight.

Immutable mindset:

  • «Цей release це image-tag 1.7.3. Кожен running-container з того самого digest».
  • Config приходять з env-var або mounted-файлів на start-time.
  • Нова версія = новий image, новий container, той самий image крутиться в dev/staging/prod.
  • Drift impossible, бо нічого не модифікує running-instance.

Що йде поза container

Щоб immutable працював, все, що потребує change at runtime має жити поза:

ConcernДе живе
Application-binary, lib, runtimeВсередині image (immutable).
Static-config, що варіюються by envEnv-var або mounted-file.
SecretsMounted з secret-manager (Vault, AWS Secrets Manager, Docker Secrets).
User-data, DB-stateExternal DB / managed-service / persistent-volume.
Uploaded-fileObject-storage (S3) або shared-volume.
LogіStreaming у log-aggregator (Loki, ELK, CloudWatch).
SessionRedis, JWT або signed-cookie, ніколи in-memory, прив'язаний до single-container.

Якщо щось з цього на writable-layer container, immutable зламано: заміна container втрачає дані.

Чому immutable виграє

  1. Reproducibility. Даний image-tag, run де завгодно, behave однаково. Dev = staging = prod.
  2. Легкий rollback. «Deploy 1.7.2 знову». Одна команда. Без restoration system-state.
  3. Без config-drift. Кожен container того ж tag bit-identical.
  4. Auditability. Що крутиться? docker inspect показує image-digest. Trace до git-SHA через build-label.
  5. Forces good hygiene. Не можеш SSH і «just fix it», pushing назад у image-build-process виробляє permanent-fix.
  6. Pair з deployment-патернами. Blue-green, canary, rolling, всі припускають identical-replica, які можна swap.

Trade-off

  • Ціна externalization-state. Setup Postgres, Redis, S3 тощо більше upfront-work, ніж slap data на local-disk.
  • Build-pipeline має бути solid. Якщо твій CI flaky, кожна зміна коштує.
  • Image-size. 2 GB-image OK у mutable-land, але сповільнює immutable-redeploy. Оптимізуй image-size агресивно.
  • Cold-start-ціна. Новий container starts cold; warm-cache gone. Мітигуй через startup-warmup або readiness-probe.

Приклади

Mutable vs Immutable: та сама зміна

Фікс: підняти max-body-size API з 1 MB до 5 MB.

Mutable workflow:

bash
ssh prod-1 "sudo vi /etc/api/config.yaml" # (edit max_body_size: 5MB) ssh prod-1 "sudo systemctl restart api" # Повторити на prod-2, prod-3... # Забув prod-4. Тепер prod-4 має 1 MB-limit. Drift.

Immutable workflow:

bash
# Edit config у repo git checkout -b bump-body-size vi config/api.yaml # max_body_size: 5MB git commit -am "Bump body size" && git push # CI build'ить image myorg/api:1.7.4 # Deploy: kubectl set image deployment/api api=myorg/api:1.7.4 # Або: docker compose pull && docker compose up -d # Кожен container підбирає новий image. Drift impossible.

Externalization state

Добре:

yaml
# docker-compose.yaml services: app: image: myorg/app:1.0 environment: DATABASE_URL: ${DATABASE_URL} REDIS_URL: ${REDIS_URL} S3_BUCKET: my-uploads # Нота: без «db»-сервісу. DB це RDS/Cloud SQL/тощо.

Погано (state всередині container):

yaml
services: app: image: myorg/app:1.0 # Якщо втратимо цей container, втратимо дані!

Immutable + blue-green

bash
# Image v1 крутиться docker run -d --name app-blue myorg/app:1.0 # Build і push v2 docker build -t myorg/app:2.0 . docker push myorg/app:2.0 # Підняти green з нового image docker run -d --name app-green myorg/app:2.0 # Traffic flip через load-balancer # Підтверди, що v2 healthy # Прибери blue docker stop app-blue && docker rm app-blue

Blue і green обидва immutable: blue крутить 1.0, green крутить 2.0, ні один не мутується mid-flight.

Immutable + canary

bash
# 9 копій v1, 1 копія v2, load-balancer шле 10% на v2 # Дивись метрики. Якщо хороше, поступово заміни більше v1 на v2.

Кожна копія immutable; rollout це серія замін, не in-place upgrade.

Immutable + rolling-update (Swarm)

bash
docker service update --image myorg/app:2.0 myapp # Swarm заміняє task one at a time, кожен task свіжий container з нового image.

Pinning by digest для true immutability

yaml
image: myorg/app@sha256:abc123def456...

Tag типу myorg/app:1.0 може бути re-pushed (хтось міг overwrite). Digest не може. Для максимальної reproducibility (і security), pin by digest у production.

bash
# Знайди digest після push docker inspect myorg/app:1.0 --format='{{.Id}}' # sha256:abc...

Build-system може lock digest у deploy-manifest:

yaml
image: myorg/app:1.0@sha256:abc123...

Реальне застосування

  • Microservice на Kubernetes: кожен Pod це container з конкретного image; без kubectl exec для fix bug у prod.
  • Serverless / containers-as-a-service (Cloud Run, Fargate): platform enforce'ить immutability, не можеш SSH-in.
  • Compose-managed dev-environment: redeploy на кожну зміну; container throwaway.
  • CI build-agent: кожен job крутиться у fresh-container.
  • Hardened production-environment: container-image підписані і scanned, deployed через GitOps (Argo CD, Flux). Уся pipeline immutable end-to-end.

Anti-patterns to avoid

SSH-in у running-container, щоб fix щось

bash
docker exec -it api bash # vi /etc/api/config.yaml ← ПОГАНО

Fix живе до restart container, потім gone. Гірше, відрізняється від твого image. Push fix у repo, rebuild, redeploy.

Зберігати дані у writable-layer container

Коли container заміщений, ці дані gone. Завжди бери volume або external-сервіси.

Re-use того ж tag для нових build

bash
docker build -t myorg/app:latest . docker push myorg/app:latest # Тепер що це «:latest»? Вчорашній? Сьогоднішній?

Бери meaningful-tag (semver, git-SHA, timestamp). Резервуй latest для dev-зручності; ніколи не deploy з latest у prod.

Treating host як immutable, а container як mutable

Якщо docker exec у container, щоб patch'ити, ти небагато виграв. Весь стек має слідувати дисципліні.

Типові помилки

Забувати, що volume ламає модель

Volume це mutable-state. Це OK, це externalized-data. Але розумій: коли redeploy, новий container reuse той самий volume. Якщо deploy-migration corrupt'ить дані, наступний deploy inherit corruption. Treat volume (і DB-schema) обережно.

Config запечений у image

dockerfile
COPY config/prod.yaml /etc/api/config.yaml

Тепер той самий image не portable через environment. Mount або env-inject config на run-time.

Long-lived container з hot-reload

Якщо твій dev-workflow це docker exec api npm run reload, ти зробив container mutable. Для dev це OK. Для prod, ніколи.

Питання для поглиблення

Q: Чи immutable infrastructure досяжна лише з container?


A: Ні. AMI, Packer-built-image, terraform-recreated-сервери всі enable. Container'и роблять дешевше, бо rebuild + redeploy швидкий.

Q: Що з secret, що змінюються без redeploy?


A: Mount їх з secret-manager (Vault, AWS, GCP). Container читає на startup або refresh периодично. Сам image без secret.

Q: Чи immutable значить, що я не можу restart container?


A: Restart OK, не модифікує image, лише re-run. «Immutable» referring до image і on-disk filesystem running-container, не його lifecycle.

Q: (Senior) Як reason'ити про довгий in-memory-state (cache-warmup, leader-election) під immutable?


A: Дві стратегії. (1) Make state externally-durable: leader-election через shared-сервіс (etcd, ZooKeeper); cache backed Redis. (2) Embrace cold-start: кожен новий container warmup from cold. Combine з rolling-deploy, щоб traffic shift поступово, без thundering-herd. Реальні системи беруть обидва: warm-cache коли важливо, externalize коли correctness залежить.

Q: (Senior) Як immutable infrastructure взаємодіє з regulated-environment (PCI, HIPAA)?


A: Прекрасно. Аудитори обожнюють. Кожна running-version мапиться назад до signed-image (cosign/Notary), який мапиться до CI-build, який мапиться до git-commit. Provenance end-to-end. Patching це code-change з PR, review і CI-artifact, не хтось SSH-in у prod і edit config. Більшість compliance-framework тепер явно favor immutable + GitOps як сильніший control-surface за mutable patch-management.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Коментарі

Ще немає коментарів