Skip to main content

Як виконати rolling update у Docker Swarm?

Rolling-update у Docker Swarm замінює running-task по batch за раз, чекаючи health між batch. Вбудований механізм Swarm реально хороший у цьому, з auto-rollback на failure як first-class фічею.

Теорія

TL;DR

  • docker service update з --image тригер. Swarm замінює task за політикою update_config.
  • Ключові параметри: parallelism (скільки за раз), delay (між batch), monitor (як довго стежити за кожним), failure-action (continue/pause/rollback).
  • Порядок: stop-first (дефолт, короткий gap per task) або start-first (zero-downtime, якщо застосунок підтримує паралельні старий/новий).
  • Rollback одна команда (docker service rollback) або автоматично на failure.
  • Healthcheck на сервісі це те, що робить «failure» виявленим. Без нього Swarm вважає started=healthy.

Update-flow

Сервіси: 6 реплік api:1.0 --update-parallelism=2 --update-delay=30s t=0: [v1.0 v1.0 v1.0 v1.0 v1.0 v1.0] випуск update t=0: [STOP STOP v1.0 v1.0 v1.0 v1.0] stop 2 (або start-first: додатковий v1.1 spawn) t=5: [v1.1 v1.1 v1.0 v1.0 v1.0 v1.0] 2 нових task healthy t=35: [v1.1 v1.1 STOP STOP v1.0 v1.0] delay+30s, наступний batch t=40: [v1.1 v1.1 v1.1 v1.1 v1.0 v1.0] t=70: [v1.1 v1.1 v1.1 v1.1 v1.1 v1.1] готово

Під час update трафік продовжує йти на ті репліки, що healthy.

Імперативна форма (CLI)

bash
docker service update \ --image myorg/api:1.1 \ --update-parallelism 1 \ --update-delay 30s \ --update-monitor 30s \ --update-failure-action rollback \ --update-max-failure-ratio 0.2 \ --update-order start-first \ api

Що робить кожен флаг:

  • --update-parallelism N — замінити N task за раз (дефолт 1).
  • --update-delay 30s — чекати між batch.
  • --update-monitor 30s — стежити за кожним batch на failure стільки.
  • --update-failure-action <continue|pause|rollback> — що робити на failure.
  • --update-max-failure-ratio 0.2 — щонайбільше 20% task можуть впасти перед тригером action.
  • --update-order <stop-first|start-first> — заміна через stop спочатку або start нового спочатку.

Декларативна форма (stack-файл)

yaml
version: '3.9' services: api: image: myorg/api:1.0 deploy: replicas: 6 update_config: parallelism: 1 delay: 30s order: start-first failure_action: rollback monitor: 30s max_failure_ratio: 0.2 rollback_config: parallelism: 2 delay: 5s failure_action: pause
bash
docker stack deploy -c stack.yaml mystack # Редагуй image на 1.1, redeploy → тригерить rolling update з config вище.

Stack-файл це канонічне місце, version-controlled, reviewable.

Health-driven gating

Swarm вирішує «чи цей batch healthy?» через:

  1. Container стартонув успішно (без exit під час monitor-періоду).
  2. Якщо healthcheck визначено, container healthy.
  3. Не більше ніж max_failure_ratio failures у batch.

Без healthcheck Swarm знає лише «процес стартонув». Застосунок, що стартує, але одразу misbehaving, ще рахується як «healthy» для Swarm. Healthcheck критичні для безпечного rolling-update.

Rollback

bash
# Ручний rollback у будь-який час docker service rollback api # Повертає до попереднього image-tag

Або через failure_action: rollback Swarm rollback'ить автоматично, коли failure-ratio перевищено. У комбінації з monitor отримуєш «якщо 1 з 5 у новому batch unhealthy після 30 секунд, roll back усього сервісу» семантику.

start-first vs stop-first

yaml
order: stop-first # дефолт — невеликий gap per task order: start-first # підняти новий поряд зі старим, тоді drain старий

start-first шлях до справжнього zero-downtime, але потребує застосунку, що толерує короткий overlap (дві версії крутяться разом). Для stateless web/API нормально. Для workers зі строгою singleton-семантикою може потребувати code-зміни.

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

Update без healthcheck

yaml
services: api: image: myorg/api # БЕЗ healthcheck → Swarm не може виявити погані версії

Без healthcheck зламаний новий image rolls out на усі репліки до того, як failure стане видимим. Додай healthcheck:, щоб Swarm gate'нути прогрес на реальний app-readiness.

Поставити parallelism надто високим

yaml
update_config: parallelism: 5 # усі 6 реплік одразу

Під час короткого replacement-вікна у тебе дуже мало healthy task. Сплеск load = накопичення. Нижчий parallelism = безпечніше.

Забути rollback_config

Rollback використовує свій окремий блок конфігурації. Якщо ставиш лише update_config, rollback бере дефолти (часто повільніший, ніж хочеш). Визнач rollback_config явно.

Image-tag все ще latest для --rollback

bash
docker service rollback api No previous image to roll back to: same tag

Якщо обидва нові і старі були tagged latest, Swarm не може їх розрізнити. Завжди tag версією (або commit SHA), щоб rollback працював.

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

  • Прод-деплої на Swarm-кластерах — кожен новий image тригерить service update; Swarm обробляє parallelism + monitoring.
  • Staged canary — спочатку deploy 1 з 10 з parallelism=1 і довгим monitor; якщо стабілізується, підніми parallelism для решти.
  • Hotfix-rolloutservice update --image hotfix:1.0 з високим parallelism (швидше) і агресивним monitoring (ловити failures швидко).
  • DB-міграції — ніколи через rolling-update напряму. Спочатку запусти one-off migrator-сервіс, тоді update app-репліки.

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

Q: Що відбувається з in-flight запитами під час task-replacement?


A: Task, scheduled for replacement, отримують SIGTERM і налаштований grace-період (stop_grace_period). Застосунки мають drain in-flight запити перед виходом. У комбінації з routing mesh трафік steer'иться від stopping-task перед SIGTERM.

Q: Чи можу update'нути кілька сервісів разом?


A: Edit stack-файл з новими image для кожного, тоді docker stack deploy -c stack.yaml mystack. Кожен сервіс update'ься незалежно за своїм config; cross-service ordering не отримаєш.

Q: Як Swarm rolling-update відрізняється від K8s rolling-update?


A: Концептуально ідентично. K8s deployment: maxSurge, maxUnavailable ≈ Swarm parallelism і order. K8s readiness-probes ≈ Swarm healthcheck. Та сама модель, інший синтаксис.

Q: Яка різниця між update_config і rollback_config?


A: update_config контролює forward-update (1.0 → 1.1). rollback_config контролює reverse-update (1.1 → 1.0). Часто хочеш повільніший, безпечніший rollback, ніж forward-update.

Q: (Senior) Як спроектувати rolling-update параметри для сервісу, що бере 90 секунд на прогрів?


A: start_period у healthcheck = 120с (дай warmup час перед рахунком failures). update-monitor = 180с (чекай досить довго, щоб побачити реальні failures emerge). parallelism = 1 (повільний rollout, 90с warmup × репліки = загальний update-час). failure_action = rollback. Патерн: monitor-period > start-period > observation, потрібний для стабільності. Швидші rollout ховають warmup-related failures; цей консервативний config їх ловить.

Приклади

Production-якості rollout

yaml
version: '3.9' services: api: image: myorg/api:1.0 deploy: replicas: 6 update_config: parallelism: 2 delay: 30s order: start-first failure_action: rollback monitor: 60s max_failure_ratio: 0.2 rollback_config: parallelism: 2 delay: 10s restart_policy: condition: any healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 10s timeout: 3s retries: 3 start_period: 30s

Deploy з новим image:

bash
sed -i 's/myorg\/api:1.0/myorg\/api:1.1/' stack.yaml docker stack deploy -c stack.yaml mystack docker service ps mystack_api # Дивись, як task замінюються 2 за раз, з 30с gap, monitored 60с кожен.

Manual rollout з імперативними флагами

bash
docker service update \ --image myorg/api:1.1 \ --update-parallelism 1 \ --update-delay 60s \ --update-monitor 120s \ --update-failure-action rollback \ --update-max-failure-ratio 0.0 \ --update-order start-first \ api # Строго: будь-який failure тригерить rollback.

Корисно для one-off tightly-controlled rollout.

Watching rollout

bash
$ watch -n 2 'docker service ps mystack_api --format "table {{.Name}}\t{{.Image}}\t{{.CurrentState}}"' # Live-view, які task якої версії, у якому стані.

Чудово для верифікації, що rollout прогресує як очікувано.

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

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

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

Коментарі

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