Знакомство с Docker Swarm, Docker Stack

Установка Docker Swarm

Docker Swarm — это родная система кластеризации для Docker, которая превращает набор хостов Docker в один последовательный кластер, называемый Swarm.
Каждая/ый нода/хост, в составе такого кластера выступает в качестве либо управляющей(manager) либо рабочей ноды(worker).
В кластере должна быть, как минимум, одна управляющая нода(manager).
Технически физическое расположение машин не имеет значения, однако, желательно иметь все Docker-ноды внутри одной локальной сети, в противном случае — управление операциями (или
поиск консенсуса между несколькими управляющими нодами) может занять значительное количество времени.
Начиная с Docker 1.12, Docker Swarm уже интегрирован в Docker Engine как Swarm-режим
В более старых версиях необходимо было запускать swarm-контейнер на каждом из хостов для обеспечения функционала кластеризации.

Термины в Docker Swarm:
Service – запущенный образ ( в отличии от Docker Engine, где запущенный на Docker-хосте образ называется контейнером).
Одна service запускает определенное количество задач.
Задача — это атомная запланированная единица Docker Swarm, которая содержит информацию о контейнере и команду, которая должна запущена внутри контейнера.
Реплика – каждый контейнер, который запускается на ноде
Количество реплик — это ожидаемое число всех контейнеров для данной service

Запуск Docker Swarm происходит с указанием имени service, образа Docker, который нужно использовать для контейнеров и желаемого количества реплик.
Управляющая нода автоматически назначает задачи рабочим нодам.
Каждый реплицируемый контейнер запускается с одного и того же Docker-образа.
Docker Swarm может быть рассмотрен как слой поверх механизма Docker Engine, который отвечает за оркестрацию контейнеров

В данном изображения у нас есть три задачи, и каждая из них запускается на отдельной Docker-ноде.
Тем не менее, также может случиться так, что все контейнеры будут запущены на одной и той же Docker-ноде.
Все зависит от управляющей ноды, которая распределяет задачи для рабочих нод, используя стратегию планирования, которая будет описана в разделе
Стратегия планирования – распределения задач по рабочим нодам

Интересные возможности Docker Swarm:

Балансировка нагрузки: Docker Swarm отвечает за балансировку нагрузки и назначение
уникальных DNS-имен, чтобы приложение, развернутое в кластере, можно было использовать
так же, как и, если приложение было бы развернуто на одном Docker-хосте.
Другими словами, Docker Swarm может публиковать порты так же, как контейнер в Docker Engine, а затем управляющая нода распределяет запросы между service-ами в кластере.

Динамическое управление ролями: Docker-хосты могут быть добавлены Swarm-кластеру без необходимости перезапуска кластера. Более того, роль узла (управляющий или рабочий) также может динамически меняться.

Динамическое масштабирование сервисов: Каждая service может динамически масштабироваться как в сторону увеличения, так и в сторону уменьшения с клиентом Docker. Управляющая нода заботится о добавлении или удалении контейнеров на узлах.

Восстановление отказа: ноды постоянно контролируются управляющей нодой и, если
какая-либо нода сбоит, то новые задачи запускаются на других рабочих нодах с целью, чтобы обеспечивалось заявленное/желаемое количество реплик.
Docker Swarm также позволяет создавать несколько управлющих нод для предотвращения поломки кластера в случае выхода со строя единственной управляющей ноды

Rolling-обновления: обновление сервисов может применяться постепенно.
Например, если у нас есть 10 реплик, и мы хотим внести изменения, мы можем определить задержку между развертыванием для каждой реплики.
В таком случае, когда что-то пойдет не так, процесс обновления автоматически прерывается, тем самым защищая нас от ситуации, когда в кластере не останется рабочих реплик.

Режимы работы: Есть два режима, в которых можно запускать Docker Swarm:

Реплицированные service: указанное количество реплицируемых контейнеров
распределяются между узлами на основе стратегии планированния

Глобальные service: один контейнер запускается на каждом доступном узле в
кластере

Безопасность: Как и все в Docker, Docker Swarm обеспечивает TLS
аутентификации и шифрования связи. Также возможно использовать CA (или
самоподписанные) сертификаты.

 

Инициализация manager-ноды

Если хост имеет несколько интерфейсов,то можно определить IP-адрес, на котором нужно запускать Swarm-cluster

Проверяем состояние управляющей ноды

На всех нодах кластера в файрволле открываем следующие порты и протоколы
2377-tcp
7946-tcp/udp
4889-udp

 

Добавление рабочих нод
В выводе команды, выполненной на предыдущем этапе

Есть подсказка, как добавить рабочие ноды

Добавим пару нод

Проверим список нод в Swarm-кластере

Как видно, в даном случае 3 ноды в кластере, одна управляющая нода(lxc) и две рабочих ноды(ubuntu161 и ubuntu162)
По умолчанию в Docker Swarm контейнеры/службы/задачи могут запускаться,как на рабочих нодах(worker), так и на управляющих нодах(manager)
Для отключения запуска задач на управляющей ноде,чтобы она занималась только орекстрацией задач/контейнеров, а не их выполнением, установим для управляющей ноды дотупность в drain

Проверим,что статус управляющей ноды изменился с Active на Drain

Альтернативным вариантом для НЕ запуска задач на управляющей ноде используется параметр –constraint с указанным ниже значением

 

Запуск/деплой сервиса

Запуск приложения в кол-ве одной копии (—replicas 1) с именем tomcat(—name tomcat) из Docker-образа tomcat
Эта команда создает service и затем посылает задачу по запуску контейнера на одну из рабочих нод

Просмотр запущенных сервисов

Сервис tomcat запустился в одном контейнера

Для просмотра рабочей ноды,на которой был запущен контейнер с tomcat

Как видно из вывода команды,контейнер запустился на рабочей ноде ubuntu161

Для получения более детальной информации о созданном tomcat service используем

Проверим на рабочей ноде ubuntu161 наличие запущенного контейнера с tomcat

 

Масштабирование сервиса

Например, увеличим кол-во реплик(контейнеров) с 1-го до 3-х

Проверим,что на рабочей ноде ubuntu162 запущено два контейнера

 

Удаление сервиса
Удалим сервис tomcat

 

Публикация портов
Docker service подобно контейнерам используют port-forwarding механизм, заключающийся в перенаправлении портов с ноды на сервис/контейнер
Это достигается за счет использования опции

Например, запустим tomcat сервисы с публикацией наружу(на рабочей ноде) порта 8080, который внутренним механизмом docker swarm(routing mesh) пробрасывается на любой активный контейнер на любой worker-ноде

Провеяем,что с наружи доступен Tomcat-сервер на рабочей ноде ubuntu161

На самом деле на каждой ноде в кластере автоматически средствами Docker Swarm создается правило для проброса порта 8080 снаружи внутрь на все активные docker-контейнеры tomcat,запущенных на всех worker-нодах благодаря механизму routing mesh

Удобство Docker Swarm в том,что управляющая нода действует как лоадбалансер, распределяя входящие на нее запросы на порт 8080 на соответствующию ноды, на которых запущены контейнеры с tomcat. Этот внутренний механизм балансировки и используется по умолчанию
Управляющая нода следит за состоянием запущенных контейнеров на рабочих нодах, поддерживает всегда желаемое кол-во реплик, определяемых при запуске сервиса, перенаправляет запросы на действительно рабочие контейнеры tomcat
Поэтому достаточно все запросы адресовать на управляющую ноду, которая уже сама выберет подходящую рабочую ноду, на которой запущен контейнер, и перенаправит на такую рабочую ноду запрос
Однако также можно адресовать запросы на все worker-ноды(даже на те, на которых не запущены контейнеры, в таком случае внутренний механизмом routing mesh такие запросы буду перенаправлены на запущенные/активные контейнеры на другой ноде)

 

Полезные возможности Docker Swarm с точки зрения Continuous Delivery

1.Rolling-обновления
Возможность обновлять запущенный service без простоя (zero downtime)
Представляет собой автоматический метод замены реплики на реплики с новым/обновленным кодом/продуктом
Docker Swarm использует Rolling-обновления по умолчанию и они могут управляться с помощью двух параметров

– задержка между запуском одной реплики и остановки следующей реплики(по умолчанию 0 секунд)

– максимальное кол-во реплик обновляемых одновременно (по умолчанию 1)

Процесс rolling-обновления в Docker Swarm выглядит следующим образом

Значение параметра update-parallelism следует устанавливать исходя из кол-ва реплик, которое мы запускам. Если такое кол-во маленькое и загрузка сервиса происходит быстро, то разумно оставить значение по умолчанию — 1
Значение параметра update-delay следует устанавливать длинее/дольше, чем ожидаемое время загрузки приложения, т.к. это позволяет своевременно обнаружить возможные ошибки после старта приложения и не позволит продолжить процесс обновления, а поставит его на паузу

Запустим 3 реплики/контейнера с tomcat 8-й версии и установим задержку обновления в 10 секунд

Проверим значение различных параметров

Видно,что запущено 3 реплики контейнер tomcat:latest и задержка в обновлении составляет 10 секунд, кол-во одновременных обновлений-1

Обновим контейнер с tomcat с 8-й до 9-й версии

В процессе обновления одна реплика с tomcat8 будет остановлена, на ее место запущена одна реплика с tomcat9, после чего будет выдержана пауза в 10 секунд.
После чего следующая реплика с tomcat8 будет остановлена, на ее место запущена одна реплика с tomcat9, снова пауза в 10 секунд. Таким образом будут обновлены все реплики

Если,например, нам необходимо откатиться до предыдущей версии приложение, то достаточно выполнить команду

 

Draining nodes
Когда необходимо остановить рабочую ноду, например, для обслуживания или просто удалить ее с кластера, можно использовать Swarm draining-нод.
Перевод статуса ноды из состояния Active в состояние Drain приводит к тому, что управляющая нода перемещает все запущенные задачи/контейнеры с drain-ноды на остальные активне ноды путем остановки таких контейнеров на drain-ноде и запуске их на active-нодах
А также управляющая нода больше не посылает задачи на drain-ноду для запуска нових контейнеров.

В данный момент обе рабочие ноды находятся в статусе Active

C 2-я запущенными контейнерами на рабочей ноде ubuntu161 и 1-м — на ubuntu162

Переведем рабочую ноду ubuntu162 в статус Drain

Проверим,что запущенный контейнер на рабочей ноде ubuntu162 был перемещен на рабочую ноду ubuntu161

Для первода состояния рабочей ноды из Drain в Active используем команду

 

Несколько управляющих нод
Docker Swarm позволяет использовать 2-е и более упраляющие ноды
Для достижения отказоустойчивости в случае выхода со строя одной управляющей ноды рекомендуется использовать 2 или более управляющих нод

Для добавления второй управляющей ноды, выполним команду на действующей управляющей ноде

В результате выполнения предыдущей команды мы получаем команду, которую необходимо выполнить на ноде, которую нужно сделать управляющей

Другим вариантом добавление управляющей ноды может быть повышение роли одной из текущих рабочих нод до управляющей ноды

Например, переведем рабочую ноду ubuntu162 в статус управляющей

т.е. в данный момент текущая активная нода lxc, имеющая статус Leader, которая и выполняет все управление Swarm-кластером, а нода ubuntu162, которая также является управляющей( ее значение в колонке manager status либо остается пустым либо изменяется на Reachable) находится в режиме ожидания и готовности подхватить роль Leader в случае проблем с текущей Leader-нодой
Лидер нода выбирается из управляючих нод путем Raft согласованного алгоритма.
Сам Raft-алгоритм имеет ограничение на количество управляющих нод. Распределенные решения
должны быть одобрены большинством управляющих узлов, называемых кворумом. Это означает, что рекомендуется нечетное количество управляющих узлов.

Для перевода назад из управляющей в рабочую ноду выполняем

 

Стратегия планирования – распределения задач по рабочим нодам
Как Docker Swarm определяет на каких нодах какие задачи запускать?

Docker Swarm использует два критерия для выбора рабочей ноды
1.Доступность ресурсов – планировщик Docker Swarm имеет информацию о доступных ресурсах на рабочих нодах и запускает задачу на наименее загруженной рабочей ноде
2.Метки(labels) и ограничение(constrains)
Метки – это атрибут ноды. Некоторые метки назначаются автоматически(например, node.id или node.hostname), другие метки могут быть назначены администратором кластера(например, node.labels.segment)
Ограничения – применяется автором сервиса, например, для выбора конкретной ноды с определенной меткой

Метки разделяются на две категории

– добавляются администратором

– собираются Docker Engine

Например, запустим на рабочей ноде ubuntu162 новый сервис/контейнер с именем tomcat2
Для этого будем использовать

Добавим метку node.labels.segment со значением AA к ноде ubuntu162

Теперь можно использовать эту метку для запуска сервиса
Например, запустим на рабочей ноде ubuntu162 новый сервис/контейнер с именем tomcat23

 

Интеграция Docker Swarm и Docker Compose в Docker Stack
Docker Swarm запускает контейнеры на разных физических хостах не предоставляя связи между такими запущенными контейнерами(т.е. для того, чтобы контейнеры могли коммуницировать между собой необходимо вручную создавать такую сетевую связь)
Docker-compose, наоборот, запускает несколько взаимосвязанных между собой контейнеров, но в пределах одного физического сервера(т.е. горизонтальное масштабирование ограничено ресурсами одной физической ноды)
Docker Stack объединяет в себе обе технологи и позволяет запускать несколько связанных контейнеров на различных физических нодах(хостах Docker-кластера)
Возможность запуска нескольких контейнеров, описанных в Docker-compose на нескольких физических нодах кластера Dcocker-swarm реализуется с помощью Docker Stack

Создадим docker-compose.yaml файл, который будет запускать 3 контейнера с приложеним calculator и 1 контейнер с Redis размещая контейнеры на рабочих нодах ubuntu16{1..2}

При этом docker-образ mydocker.repo.servername/calculator:latest уже должен присутствовать на всех рабочих нодах Swarm-кластера(иначе на ноде, на которой нет этого образа, не запустится приложение calculator).  Альтернативным вариантом для получения рабочими нодами docker-образа mydocker.repo.servername/calculator:latest является использование параметра

при выполнении команды docker stack deploy(это позволит рабочим нодам аутентифицироваться в Docker-репозитарии и скачать этот образ)

Запуск такого стека приложений

Просмотр наличия docker stack с именем app

Просмотр списка задач в стеке app

Как видно, 2 контейнера с приложением запустились на рабочей ноде ubuntu162 и один – на ubuntu161.
Один контейнер с Redis запустился на рабочей ноде ubuntu161

Просмотр списка сервисов в стеке app

С управляющей ноды, а также с обоих рабочих нод, на которых запущено приложение калькулятор проверяем

Удаление docker stack

 

Источник: Книга Сontinuous delivery with Docker and Jenkins by Rafal Leszko

Комментирование и размещение ссылок запрещено.

Комментарии закрыты.

Яндекс.Метрика