Docker Swarm: встроенная оркестрация

Рейтинг: 62.3% · 11 голосов
Практический курс по Docker: образы, контейнеры, тома, сети, Compose и продакшен. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
Marina_DevOps
Сообщения: 54
Зарегистрирован: 11 май 2026, 05:31

Docker Swarm: встроенная оркестрация

Сообщение Marina_DevOps »

Оглавление курса (46)
  1. Что такое Docker и какие задачи он решает
  2. Установка Docker и запуск первого контейнера
  3. Образы: слои, теги и реестр Docker Hub
  4. Пишем свой Dockerfile
  5. Тома и хранение данных: volumes и bind mounts
  6. Сети в Docker: связываем контейнеры между собой
  7. Переменные окружения и конфигурация контейнеров
  8. Docker Compose: поднимаем многоконтейнерное приложение
  9. Оптимизация образов: multi-stage сборка, размер и кэш слоёв
  10. Логи, отладка и мониторинг контейнеров
  11. Базовая безопасность контейнеров
  12. Подготовка к продакшену: что важно учесть
  13. Dockerfile глубже: ENTRYPOINT и CMD, HEALTHCHECK, .dockerignore, запуск не от root
  14. Реестры образов: приватные registry, push и pull, теги и digest, imagePullSecrets
  15. BuildKit и buildx: multi-arch сборки, секреты сборки, экспорт кэша
  16. Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация
  17. Итоговый проект и куда расти: от Dockerfile до прода, обзор оркестрации (Kubernetes, Podman, OCI)
  18. Архитектура Docker: dockerd, containerd, runc и OCI
  19. Как работает изоляция: namespaces и cgroups
  20. Образы изнутри: слои, OverlayFS и storage driver
  21. Жизненный цикл контейнера и политики перезапуска
  22. Отладка контейнеров: exec, attach, nsenter, debug
  23. Сети Docker глубже: bridge, overlay, macvlan и iptables
  24. Docker Compose глубже: profiles, healthcheck-зависимости, override
  25. Данные и тома глубже: драйверы, бэкап, права
  26. Секреты и конфигурация: как не светить пароли
  27. Ограничение ресурсов: CPU, память, OOM и cgroups
  28. Здоровье и автозапуск: HEALTHCHECK, init и сигналы
  29. Логирование контейнеров: драйверы, ротация, сбор
  30. Мониторинг контейнеров: stats, cAdvisor, Prometheus
  31. Безопасность глубже: rootless, user namespaces, seccomp, capabilities
  32. Supply chain: сканирование, SBOM и подпись образов
  33. Глубокая оптимизация образов: distroless, scratch, кэш
  34. Multi-arch и сборка под ARM: buildx и эмуляция
  35. Реестры в продакшене: Harbor и облачные registry
  36. Docker без Docker: Podman, containerd, nerdctl, Buildah
  37. От Compose к оркестрации: когда контейнеров становится много
  38. Docker Swarm: встроенная оркестрация (вы здесь)
  39. Сборка образов в CI без демона: kaniko, BuildKit, Buildah
  40. Траблшутинг Docker: типичные ошибки и как чинить
  41. Производительность и эксплуатация Docker-хоста
  42. Docker Desktop, WSL2 и альтернативы на Windows и Mac
  43. Контейнеризация приложений: бэкенд, фронтенд, БД
  44. Docker и Kubernetes: containerd, миграция, kompose
  45. Лучшие практики и антипаттерны Docker
  46. Сквозной проект: production-ready стек и путь дальше
Зачем вообще оркестратор, если есть compose

У тебя на одном сервере крутится compose-стек, и все хорошо. Пока сервер один. А теперь представь: трафик вырос, нужен второй и третий узел, надо чтобы при падении машины контейнеры переехали сами, чтобы релиз катился без даунтайма, чтобы пароль к БД не валялся в открытом виде в переменной окружения. Руками это превращается в ад: ssh на каждую ноду, ручной запуск, ручной перезапуск упавшего. Оркестратор - это робот-диспетчер, который держит в голове желаемое состояние ("хочу 5 реплик этого сервиса на кластере") и сам приводит реальность к нему. Упала нода - он поднимает реплики на живых. Ты сказал "обнови" - он катит новую версию по одной, проверяя, что не сломалось.

docker swarm - это оркестратор, встроенный прямо в Docker Engine. Не отдельный продукт, не лишний бинарник: тот же демон dockerd, который у тебя уже запускает контейнеры, умеет работать в режиме кластера. Это его главная фишка и главная причина, почему он до сих пор жив. Внутри сидит библиотека SwarmKit, и весь твой опыт работы с docker run и compose переносится почти один в один - меняются только глаголы: вместо docker run появляется docker service create, вместо docker compose up - docker stack deploy. В этом уроке разберем docker оркестрация изнутри: как устроен кворум, как пакеты летают между узлами через overlay-сети, как работает балансировка, секреты, обновления и откаты. И честно поговорим, где Swarm сегодня уместен, а где его давно вытеснил Kubernetes.

Изображение

Архитектура: менеджеры, воркеры и raft

swarm кластер состоит из узлов (nodes) двух ролей. Manager - мозг: хранит состояние кластера, принимает API-команды, планирует, куда ставить контейнеры. Worker - руки: просто запускает то, что ему назначили. Менеджер тоже может быть воркером (по умолчанию он и работу тянет), но в проде менеджеры обычно разгружают.

Состояние кластера (какие сервисы есть, сколько реплик, где они) надо хранить надежно и согласованно на всех менеджерах. Для этого SwarmKit использует алгоритм консенсуса Raft. Если на пальцах: менеджеры голосуют и выбирают одного лидера, который принимает все записи, а остальные реплицируют его лог. Чтобы кластер мог принимать решения, нужен кворум - большинство (N/2 + 1) живых менеджеров. Отсюда железное правило: менеджеров должно быть нечетное число.
  • 1 менеджер - кворум 1, переживает 0 падений (тестовый стенд).
  • 3 менеджера - кворум 2, переживает падение 1 (минимум для прода).
  • 5 менеджеров - кворум 3, переживает падение 2 (крупный кластер).
Почему нечетное и почему не "чем больше тем лучше": 4 менеджера дают тот же кворум 3, что и 5, но переживают только 1 падение вместо 2 - лишняя нода без пользы, зато больше Raft-трафика. А если кворум потерян (упало большинство менеджеров), кластер становится read-only: запущенные контейнеры продолжают работать, но ты не можешь ничего создать, обновить или отмасштабировать, пока кворум не восстановится. Воркеров может быть сколько угодно - они кворум не образуют.

Поднимаем кластер: init и join

Инициализируем первый менеджер. Если на хосте несколько IP (а в облаке это норма), обязательно указывай --advertise-addr, иначе Swarm может выбрать не тот интерфейс и воркеры не достучатся.

Код: Выделить всё

docker swarm init --advertise-addr 192.168.10.11
Вывод даст готовую команду для подключения воркеров:

Код: Выделить всё

Swarm initialized: current node (k7p2...) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-49nj1...xyz 192.168.10.11:2377

To add a manager to this swarm, run 'docker swarm join-token manager'.
Разберем: 2377 - порт control plane (Raft, управление кластером). Это не тот порт, где живут твои приложения. Токен SWMTKN несет в себе хэш CA-сертификата кластера - это и аутентификация, и защита от того, что чужой узел вотрется в кластер. Токены для воркера и менеджера разные, так что воркер не сможет случайно стать менеджером. Если токен утек - не паникуй, его ротируют командой docker swarm join-token --rotate worker.

На воркере выполняем ту самую join-команду, затем на менеджере смотрим список:

Код: Выделить всё

docker node ls
ID            HOSTNAME   STATUS  AVAILABILITY  MANAGER STATUS
k7p2x * ...   node-1     Ready   Active        Leader
m3v9q ...     node-2     Ready   Active        Reachable
a1b8t ...     node-3     Ready   Active
Звездочка - текущий узел. MANAGER STATUS=Leader - тот самый Raft-лидер, Reachable - менеджер-реплика, пустое поле - воркер. AVAILABILITY можно переключать: drain выводит ноду из-под нагрузки (для обслуживания), и Swarm переселяет с нее задачи на другие.

Порты, которые должен пропускать файрвол между узлами: TCP 2377 (управление), TCP+UDP 7946 (обнаружение узлов, gossip), UDP 4789 (трафик данных overlay, VXLAN). Забыл открыть 4789 - получишь самый коварный баг Swarm: кластер собрался, сервисы стартовали, а контейнеры на разных нодах не видят друг друга.

Сервисы: docker service вместо docker run

Контейнер в Swarm не запускают напрямую. Ты объявляешь сервис - желаемое состояние, а планировщик раскидывает его задачи (tasks) по узлам. Задача - это обертка вокруг одного контейнера; если контейнер умер, Swarm создаст новую задачу, а не "перезапустит" старую.

Код: Выделить всё

docker service create \
  --name web \
  --replicas 3 \
  --publish published=8080,target=80 \
  nginx:1.27-alpine
docker service create поднимает 3 реплики nginx и публикует порт 8080 наружу через routing mesh (про него ниже). Смотрим, как разъехались задачи:

Код: Выделить всё

docker service ps web
ID        NAME    NODE    DESIRED STATE  CURRENT STATE
9fb2...   web.1   node-1  Running        Running 2 minutes ago
3ac7...   web.2   node-2  Running        Running 2 minutes ago
77de...   web.3   node-3  Running        Running 2 minutes ago
DESIRED STATE - чего хочет планировщик, CURRENT STATE - что есть на самом деле. Когда они расходятся (например, Desired=Running, Current=Failed) - это сигнал смотреть логи. Масштабирование в одну команду:

Код: Выделить всё

docker service scale web=5
Планировщик по умолчанию использует стратегию spread - размазывает реплики по узлам максимально равномерно, чтобы падение одной ноды забрало минимум задач. Управлять размещением можно через --constraint (например, node.labels.disk==ssd) и --placement-pref. Это не выдуманные, а реальные рычаги: ими ты, скажем, прибиваешь сервис с состоянием к ноде, где лежит его том.

Overlay-сети, ingress mesh и балансировка

Самое интересное под капотом docker swarm - сеть. Контейнеры на разных физических узлах должны общаться так, будто они в одной локалке. Это делает overlay-сеть поверх VXLAN: пакет L2 между контейнерами на разных хостах заворачивается (инкапсулируется) в UDP-датаграмму и летит на порт 4789 к нужной ноде, где разворачивается обратно. Снаружи это обычный UDP-трафик между серверами, внутри - изолированная виртуальная сеть твоих сервисов. Связку с физической сетью хоста обеспечивает служебный мост docker_gwbridge, который Swarm создает автоматически.

Код: Выделить всё

docker network create -d overlay --attachable backend
docker service create --name api --network backend ...
Внутри overlay работает встроенный DNS: обращаешься к сервису по имени (http://api), и Swarm резолвит его в виртуальный IP (VIP). За этим VIP сидит балансировщик на уровне ядра - IPVS (IP Virtual Server, L4), который раскидывает соединения по живым задачам. Тебе не нужен отдельный nginx для балансировки между репликами - это уже встроено.

Теперь про ingress routing mesh - вторую магию. Когда ты опубликовал порт 8080, он слушается на каждой ноде кластера, даже если реплики сервиса там нет. Прилетел запрос на node-3, а реплики только на node-1 и node-2 - IPVS на node-3 сам перешлет запрос на узел с задачей. Практический смысл: можно повесить внешний L4-балансировщик на любой набор нод и не думать, где именно крутится сервис. Цена - лишний хоп между нодами и потеря реального IP клиента (на L4 он не виден). Если IP клиента критичен (логи, гео, антифрод) - публикуй порт в режиме host (--publish mode=host,...), он минует routing mesh, но тогда сервис слушает только на нодах со своими репликами.

Один нюанс безопасности: трафик данных overlay по умолчанию не шифруется. Если ноды в одной доверенной приватной сети - норм. Если между ними публичный сегмент - включай шифрование при создании сети: docker network create -d overlay --opt encrypted backend. Это поднимет IPSec на VXLAN, заплатив за это процессором.

Стеки: docker stack deploy из compose

docker service create удобен для одного сервиса, но реальное приложение - это пачка сервисов, сетей и томов. Их описывают в знакомом compose-файле и катят как стек. Тот же синтаксис, что и в обычном compose, плюс ключевая секция deploy - именно она оживает только в Swarm (обычный docker compose ее почти всю игнорирует).

Код: Выделить всё

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"
    networks: [front]
    deploy:
      replicas: 4
      update_config:
        parallelism: 1
        delay: 10s
        order: start-first
      rollback_config:
        parallelism: 2
      restart_policy:
        condition: on-failure
      placement:
        constraints: [node.role == worker]
networks:
  front:
    driver: overlay
Деплоим (compose-файл уже без устаревшего ключа version:):

Код: Выделить всё

docker stack deploy -c compose.yaml shop
docker stack services shop
В secret-режиме реальной эксплуатации deploy-секция и есть твой контракт с оркестратором: сколько реплик, как обновлять, куда ставить, что делать при падении. order: start-first означает "сначала подними новую реплику, потом гаси старую" - так держится мощность во время релиза (по умолчанию stop-first - наоборот, экономит ресурсы, но на секунды просаживает емкость).

Rolling update и откат

Обновление образа без даунтайма - то, ради чего люди и приходят в оркестрацию.

Код: Выделить всё

docker service update \
  --image nginx:1.27.4-alpine \
  --update-parallelism 1 \
  --update-delay 10s \
  --update-order start-first \
  web
--update-parallelism 1 значит "обновляй по одной задаче за раз", --update-delay 10s - пауза между пачками (даешь сервису прогреться и пройти healthcheck). Swarm катит новую версию реплика за репликой; если у сервиса задан --health-cmd и контейнер не проходит проверку, обновление встает. Поведение при сбое задается --update-failure-action: по умолчанию pause (встать и ждать тебя), но можно поставить rollback - тогда Swarm сам откатится на прежний образ. Ручной откат - отдельная команда, она возвращает предыдущую спецификацию сервиса целиком:

Код: Выделить всё

docker service rollback web
Грабли: Swarm хранит только одну предыдущую версию. Сделал два обновления подряд - откатишься лишь на шаг назад, а не на два. Поэтому "версионируй" через тэги образов и git compose-файла, а не надейся на бесконечный undo.

Секреты и конфиги Swarm

Пароль к БД в переменной окружения - это утечка, ждущая своего часа: его видно в docker inspect, в логах, в истории. Swarm дает secrets - первоклассный механизм. Секрет хранится в зашифрованном Raft-логе, доставляется только на ноды, где реально крутится потребляющая его задача, и монтируется в контейнер как файл в tmpfs (в памяти, /run/secrets/имя), а не в переменную и не на диск.

Код: Выделить всё

printf 'S3cr3t' | docker secret create db_password -
docker service create --name db \
  --secret db_password \
  -e POSTGRES_PASSWORD_FILE=/run/secrets/db_password \
  postgres:16
Рядом живут configs - то же самое, но для нечувствительных данных (nginx.conf, конфиг приложения): хранятся в Raft, монтируются файлом, не требуют пересборки образа ради смены конфига. Секреты и конфиги в Swarm иммутабельны - чтобы поменять значение, создаешь новую версию (db_password_v2) и обновляешь сервис на нее. Звучит неудобно, но это осознанный дизайн: так у тебя всегда четкая привязка "какой сервис какую версию секрета использует".

Грабли и антипаттерны из практики
  • Закрытый UDP 4789. Самый частый и самый мутный баг: кластер собран, сервисы Running, а межнодовая связь молчит. Всегда проверяй файрвол на 2377/tcp, 7946/tcp+udp, 4789/udp.
  • Четное число менеджеров. 2 или 4 менеджера - худшее из решений: при сплите кластер целиком уходит в read-only. Только нечетное (1, 3, 5).
  • Состояние без привязки. Запустил БД с локальным volume без constraint - после переезда задачи на другую ноду данные "пропали" (они остались на старой). Stateful-сервисы прибивай к ноде или выноси на сетевое хранилище.
  • Надежда на routing mesh там, где нужен реальный IP клиента. L4-mesh прячет источник. Нужен IP - mode=host или внешний L7-прокси.
  • Незашифрованный overlay через публичную сеть. По умолчанию данные идут в открытую. Между датацентрами - только --opt encrypted или VPN.
  • latest в образах. В Swarm это вдвойне опасно: разные ноды могут вытянуть разные сборки одного тэга. Только конкретные версии и желательно digest.
Мини-лаба

Нужны 2-3 машины (или VM/мультипас). Делаем руками:
  • На первой: docker swarm init --advertise-addr <IP>. Скопируй join-команду.
  • На остальных выполни docker swarm join .... Проверь docker node ls с менеджера - все Ready.
  • docker network create -d overlay app, затем docker service create --name web --replicas 3 --network app --publish 8080:80 nginx:1.27-alpine.
  • Открой http://<IP-любой-ноды>:8080 - работает с любой, благодаря routing mesh. Останови docker на одной ноде - смотри docker service ps web, как Swarm пересоздает задачи.
  • Создай секрет, прокинь в сервис, зайди в контейнер и убедись, что он лежит файлом в /run/secrets, а не в env.
  • Обнови образ с --update-parallelism 1 --update-delay 10s и параллельно крути docker service ps web - увидишь rolling update вживую. Затем docker service rollback web.
Где Swarm жив в 2026 и почему его вытеснил Kubernetes

Честно: Swarm сегодня в режиме поддержки (maintenance mode). Он по-прежнему едет вместе с Docker Engine, получает патчи безопасности, и Mirantis официально пообещала поддержку как минимум до 2030 года. Но активной разработки новых фич почти нет, а экосистема и рынок труда давно ушли в Kubernetes - его выбирает большинство enterprise-нагрузок, и управляемый k8s есть у каждого облака, тогда как управляемого Swarm нет нигде.

Почему так вышло. Swarm выигрывает в одном - простоте: поднять кластер из коробки, без отдельных компонентов, на знакомых командах. Для маленькой команды, одного-двух приложений, домашнего сервера или периметра (edge) на пяток нод это до сих пор разумный и быстрый выбор. Но как только нужны автоскейлинг по метрикам, сложные сетевые политики, операторы, богатый ecosystem (Helm, service mesh, CRD, GitOps), тонкий контроль над планированием - Swarm упирается в потолок, а Kubernetes именно для этого и сделан. K8s сложнее в эксплуатации, зато его расширяемость и сообщество несравнимы. Симптоматично, что сам Kubernetes еще в 2022-м выпилил dockershim и больше не использует Docker как среду исполнения - индустрия стандартизировалась на containerd и OCI, а оркестрацию забрал k8s.

Практический вывод: учить Swarm стоит - он отлично объясняет концепции оркестрации (желаемое состояние, реплики, rolling update, секреты, overlay) на минимуме сложности, и эти идеи один в один переносятся на Kubernetes. Запускать в Swarm новый большой прод в 2026-м - спорно: скорее всего, тебе нужен k8s. А поддерживать уже работающий Swarm-кластер - совершенно нормально, паники "все срочно мигрировать" нет.

Контрольные вопросы
  • Сколько менеджеров нужно, чтобы кластер пережил падение двух из них, и почему именно нечетное число?
  • Что произойдет с запросом на порт 8080, который прилетел на ноду, где нет ни одной реплики сервиса? Опиши путь пакета.
  • Чем secret отличается от обычной переменной окружения с точки зрения хранения и доставки в контейнер?
  • В чем разница update-order start-first и stop-first, и когда какой выбрать?
Итог

docker swarm - встроенный в движок оркестратор: менеджеры держат состояние через Raft, воркеры крутят задачи, overlay-сети по VXLAN связывают узлы, а ingress mesh и IPVS дают балансировку и публикацию портов на весь кластер. docker service и docker stack заменяют docker run и compose, добавляя реплики, rolling update, откат, секреты и конфиги. В 2026-м Swarm - простой, надежный, но "замороженный" инструмент: идеален, чтобы понять оркестрацию и закрыть небольшие задачи, но для серьезного масштаба индустрия выбрала Kubernetes - и следующие уроки логично ведут именно туда.
👍2 ❤️6 🔥2 😄 🤔2
Аватара пользователя
martin2000
Сообщения: 1
Зарегистрирован: 13 май 2026, 05:48

Re: Docker Swarm: встроенная оркестрация

Сообщение martin2000 »

Открыл порты 2377 и 7946, а контейнеры на разных нодах все равно друг друга не видели час бился. Оказалось забыл UDP 4789, как ты и написал в граблях. Спасибо что прям выделил это, сэкономил бы мне вечер если б прочел заранее.
👍 ❤️ 🔥 😄 🤔2
Аватара пользователя
elixirmain
Сообщения: 1
Зарегистрирован: 08 июн 2026, 14:10

Re: Docker Swarm: встроенная оркестрация

Сообщение elixirmain »

Вопрос по откату: если у меня прод на свежем проде на swarm катать уже не стоит, а старый кластер живет нормально - правильно ли я понял что migrate в k8s можно не срочно? Просто начальство пугает что swarm мертв, а по уроку выходит что до 2030 поддержка есть.
👍 ❤️2 🔥1 😄 🤔
Ответить
← Предыдущая глава
От Compose к оркестрации: когда контейнеров становится много
Следующая глава →
Сборка образов в CI без демона: kaniko, BuildKit, Buildah

Все главы курса «Docker: контейнеризация от основ до продакшена»

Поделиться темой: ✈ Telegram VK
Похожие запросы: как установить docker на ubuntu и linuxdocker команды шпаргалка для новичкаdocker run как запустить контейнер с флагамиdocker images как посмотреть и удалить образыdocker desktop и wsl2 на windows как настроитьdocker контейнер падает сразу после запуска как найти причину

Вернуться в «Docker с нуля»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость