Як виконати 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)
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-файл)
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: pausedocker stack deploy -c stack.yaml mystack
# Редагуй image на 1.1, redeploy → тригерить rolling update з config вище.Stack-файл це канонічне місце, version-controlled, reviewable.
Health-driven gating
Swarm вирішує «чи цей batch healthy?» через:
- Container стартонув успішно (без exit під час monitor-періоду).
- Якщо
healthcheckвизначено, containerhealthy. - Не більше ніж
max_failure_ratiofailures у batch.
Без healthcheck Swarm знає лише «процес стартонув». Застосунок, що стартує, але одразу misbehaving, ще рахується як «healthy» для Swarm. Healthcheck критичні для безпечного rolling-update.
Rollback
# Ручний 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
order: stop-first # дефолт — невеликий gap per task
order: start-first # підняти новий поряд зі старим, тоді drain старийstart-first шлях до справжнього zero-downtime, але потребує застосунку, що толерує короткий overlap (дві версії крутяться разом). Для stateless web/API нормально. Для workers зі строгою singleton-семантикою може потребувати code-зміни.
Типові помилки
Update без healthcheck
services:
api:
image: myorg/api
# БЕЗ healthcheck → Swarm не може виявити погані версіїБез healthcheck зламаний новий image rolls out на усі репліки до того, як failure стане видимим. Додай healthcheck:, щоб Swarm gate'нути прогрес на реальний app-readiness.
Поставити parallelism надто високим
update_config:
parallelism: 5 # усі 6 реплік одразуПід час короткого replacement-вікна у тебе дуже мало healthy task. Сплеск load = накопичення. Нижчий parallelism = безпечніше.
Забути rollback_config
Rollback використовує свій окремий блок конфігурації. Якщо ставиш лише update_config, rollback бере дефолти (часто повільніший, ніж хочеш). Визнач rollback_config явно.
Image-tag все ще latest для --rollback
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-rollout —
service 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
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: 30sDeploy з новим image:
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 з імперативними флагами
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
$ watch -n 2 'docker service ps mystack_api --format "table {{.Name}}\t{{.Image}}\t{{.CurrentState}}"'
# Live-view, які task якої версії, у якому стані.Чудово для верифікації, що rollout прогресує як очікувано.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.
Коментарі
Ще немає коментарів