Services: масштабирование и rolling updates
В Swarm приложения запускаются как services — декларативное описание желаемого состояния. Swarm сам следит чтобы нужное количество реплик всегда работало.
Service vs Container
# Обычный контейнер (docker run)
docker run -d nginx # запустил и забыл — упал, никто не перезапустит
# Swarm service
docker service create --name web --replicas 3 nginx
# Swarm следит: упала реплика → запустить новую на свободной нодеService — это желаемое состояние (desired state). Reconciliation loop постоянно сравнивает желаемое с фактическим и исправляет расхождения.
Создание сервиса
docker service create \
--name web \
--replicas 3 \
--publish published=80,target=80 \
--env NODE_ENV=production \
--limit-cpu 0.5 \
--limit-memory 512M \
nginx:alpinedocker service ls # список сервисов
docker service ps web # задачи сервиса (где работают реплики)
docker service inspect web # полные настройки
docker service logs web # логи всех репликМасштабирование
docker service scale web=5 # увеличить до 5 реплик
docker service scale web=1 # уменьшить до 1
# Несколько сервисов сразу
docker service scale web=5 api=3 worker=10Swarm распределяет реплики по нодам равномерно. Если нода недоступна — реплики переезжают на другие.
Попробуй в симуляции
Rolling Update
Обновление без остановки трафика:
docker service update \
--image nginx:1.26 \
--update-parallelism 1 \ # обновлять по 1 реплике
--update-delay 10s \ # ждать 10 сек между репликами
--update-failure-action rollback \ # откатить при ошибке
webБыло: [v1.25] [v1.25] [v1.25]
Шаг 1: [v1.26] [v1.25] [v1.25] ← обновили 1-ю, ждём 10 сек
Шаг 2: [v1.26] [v1.26] [v1.25] ← обновили 2-ю, ждём 10 сек
Шаг 3: [v1.26] [v1.26] [v1.26] ← готово
docker service rollback web # откатить к предыдущей версииPlacement constraints
Куда Swarm может планировать задачи:
# Только на нодах с меткой env=prod
docker service create \
--constraint 'node.labels.env==prod' \
--name api myapp:latest
# Только менеджеры (осторожно — нагружает управляющие ноды)
--constraint 'node.role==manager'
# Только воркеры
--constraint 'node.role==worker'
# Только конкретная нода
--constraint 'node.hostname==worker-2'# Навесить метку на ноду
docker node update --label-add env=prod worker-1
docker node update --label-add role=db worker-2Глобальный режим
Вместо N реплик — по одной на каждую ноду (мониторинг, логи):
docker service create \
--mode global \
--name node-exporter \
prom/node-exporterIngress и балансировка
Swarm встроенно балансирует нагрузку. Routing mesh: любой запрос на любую ноду кластера попадает к одной из реплик сервиса — даже если реплика не на этой ноде.
Запрос → worker-1:80 → Swarm routing mesh → реплика на worker-2:80
# Публикация порта
--publish published=8080,target=3000 # routing mesh (все ноды)
--publish published=8080,target=3000,mode=host # только ноды с репликойВ следующем уроке — Stack deploy: запуск всего приложения одной командой.