Docker Swarm 0.3: трёхнодовый кластер без внешних зависимостей
Собираем трёхнодовый Docker Swarm 0.3/0.4, запускаем сервисы через стандартный Docker CLI. Оцениваем зрелость для stateless-задач и сравниваем с Mesos.
Docker Swarm 0.3/0.4 развивается как нативная кластеризация Docker без внешних зависимостей - управление кластером через стандартный Docker CLI
На прошлой неделе выкроили время и собрали нормальный Swarm-кластер - не наспех на тестовой коробке, а три реальных ноды, реальная нагрузка, реальный разбор полётов. Поводом стал запрос от интеграционного проекта: клиент хочет запускать stateless-сервисы в контейнерах и спрашивает, есть ли что попроще Mesos. Docker Swarm выглядел как очевидный кандидат для ответа.
Что такое Swarm в версии 0.3
Swarm - это нативная кластеризация Docker. Идея простая: несколько Docker-демонов объединяются в один виртуальный хост, которым управляешь через обычный docker CLI. Никакого нового синтаксиса, никаких дополнительных абстракций - docker run на Swarm-мастере раскидывает контейнеры по нодам по стратегии планировщика.
В отличие от Mesos, Swarm не требует ZooKeeper, отдельного планировщика Marathon, Java-стека и команды специалистов для первоначального поднятия. Это его главный аргумент на сегодня.
Как собирали кластер
Три CentOS 7 сервера, Docker 1.6, Swarm 0.3. Открытие master на 2375 порту с TLS - обязательно, иначе любой в сети дёрнет ваш Docker API.
Базовая схема такая:
# На каждой ноде - регистрация в Consul (использовали как discovery backend)
docker run -d swarm join --addr=<NODE_IP>:2375 consul://<CONSUL_IP>:8500/swarm
# На мастере - Swarm manager
docker run -d -p 4000:4000 swarm manage \
--strategy spread \
consul://<CONSUL_IP>:8500/swarm
После этого docker -H tcp://<MASTER_IP>:4000 info показывает все три ноды и суммарные ресурсы. docker run автоматически выбирает ноду по стратегии.
Вместо Consul можно использовать встроенный token-based discovery через Docker Hub - но это облачная зависимость, для изолированного окружения не годится. Consul уже стоял у нас в инфраструктуре, поэтому его и взяли.
Стратегии планировщика
Swarm 0.3 даёт три стратегии размещения:
- spread - раскидывает контейнеры по нодам равномерно, стараясь занять каждую хотя бы по одному контейнеру. Для нашего сценария оптимально.
- binpack - набивает одну ноду до отказа, потом переходит к следующей. Логика экономии ресурсов.
- random - случайный выбор. Для тестов удобно, для продакшна нет смысла.
Кроме стратегий есть constraints - метки на ноды и фильтры при запуске. Например:
docker run -e constraint:storage==ssd nginx
Пометили одну ноду storage=ssd, и контейнеры с таким constraint пойдут только на неё. Это закрывает базовые кейсы с разными типами железа.
Что работает нормально
Стандартный CLI. Главный плюс - ты не переучиваешься. Тот же docker ps, docker logs, docker exec. Контейнер запущен на удалённой ноде, но команды выглядят одинаково. Для команды, которая уже умеет Docker, порог входа в Swarm минимальный.
Docker Compose поверх Swarm. Взяли существующий docker-compose.yml от одного проекта, подняли через docker-compose -H tcp://<MASTER>:4000 up -d - заработало без изменений. Контейнеры разъехались по нодам по стратегии spread. Это приятно - переиспользуешь то, что уже написано для локальной разработки.
Автоматическая публикация портов. Swarm при запуске контейнера с -p публикует порт именно на той ноде, куда поместил контейнер. docker port показывает правильный адрес.
Где трещит по швам
Нет балансировки на уровне Swarm. Если запустил три реплики nginx - каждая сидит на своей ноде со своим портом. Клиент должен сам знать, куда ходить, или нужен внешний балансировщик. Mesos + Marathon умеют service discovery через HAProxy из коробки; здесь это ваша забота.
Планировщик примитивный. Spread раскидывает контейнеры по количеству, не по реальной нагрузке CPU/RAM. Можно получить ситуацию когда на одной ноде три тяжёлых контейнера, а рядом три лёгких - и Swarm доволен, у него по три штуки везде.
Нет health checks на уровне Swarm. Контейнер упал - Swarm его не перезапустит и не перенесёт на другую ноду. Максимум что есть - Docker restart policy на самом контейнере. Если нода недоступна, Swarm перестаёт отправлять туда контейнеры, но уже запущенные не мигрируют. Mesos + Marathon здесь выигрывает принципиально.
Состояние в discovery backend. При использовании Consul (или etcd) Swarm хранит там список нод. Это дополнительная зависимость, которую нужно мониторить и бэкапить. С token-based discovery зависимость уходит, но появляется требование наличия внешней сети.
Swarm vs Mesos: честное сравнение
На сегодняшний день это не совсем конкуренты - разный уровень зрелости и разный масштаб задач.
Mesos сложнее в развёртывании и требует отдельной экспертизы. Зато он умеет нормальный scheduling по ресурсам, health checks, rolling updates через Marathon, work с произвольными задачами - не только контейнерами. Если у вас десятки сервисов и требование отказоустойчивости - это разговор про Mesos.
Swarm закрывает другой сценарий: небольшой кластер (три-пять нод), stateless сервисы без сложных требований по планированию, команда уже в Docker и не хочет тратить неделю на онбординг в новый оркестратор. Для тестовых сред или небольших проектов аргумент про «просто docker run» реально работает.
Для нашего клиентского кейса Swarm оказался достаточным: несколько stateless API-сервисов, балансировщик снаружи уже есть (HAProxy), требования по HA минимальные. Mesos здесь был бы избыточен по операционной стоимости.
Итог
Swarm 0.3 работает. Для простых stateless-сценариев без жёстких требований к планированию ресурсов и автовосстановлению - вполне. Главный его козырь - нулевой порог входа для тех, кто уже использует Docker.
Принципиальные ограничения - отсутствие нормального scheduling по загрузке и отсутствие встроенного health check с перезапуском - это архитектурные решения, которых в Swarm нет. Для сложных production-сценариев это не замена Mesos.
Мы планируем погонять кластер ещё пару недель под реальной нагрузкой клиентского проекта - посмотрим, что всплывёт.
- Docker Machine 0.2: создаём Docker-хосты в облаке одной командой · 3 марта 2015
- Docker Compose для локального стенда: web + db + cache в одном файле · 13 января 2015