-
Оркестрация и конфигурирование кластера.
-
Децентрализованная архитектура. Нет главного узла, при падении которого отказывает вся система. Используется кворум между управляющими нодами. Упавший лидер заменяет один из его подчиненных.
-
Работает на основе docker-контейнеров. Кластеру без разницы, что в нем будет запускаться: frontend, backend, db и любые другие программные компоненты. Главное, чтобы они были упакованы в docker-образы.
-
Средства масштабирования. Каждому сервису можно указать необходимое количество реплик, которое будет автоматически поддерживаться в кластере.
-
Балансировка нагрузки "из коробки" с помощью перенаправления вызовов между репликами на основе публичного порта.
-
Управление и поддержание состояния кластера. Управляющие узлы следят за состоянием кластера (количество реплик, рабоющие узлы и прочее), и при необходимости меняют конфигурацию, чтобы она соответствовала исходным требованиям.
-
Внутренняя виртуальная сеть. Именование сервисов внутри сети с помощью DNS. Защищенный траффик внутри и между узлами на основе TLS.
-
Средства обновления компонентов кластера. Динамическое изменение настроек узлов и сервисов не требует остановки работы кластера.
-
Docker Swarm кластером называется некое множество физических и/или виртуальных хостов с установленным Docker Engine, работающим в режиме
swarm
. Хосты могут выполнять роль менеджера (manager) или воркера (worker), либо и то, и другое одновременно. По умолчанию все управляющие ноды также являются рабочими и могут запускать в себе сервисы (режим active), но их можно настроить на работу только в качестве управляющих (режим drain). -
Узлы деляться на 2 вида: управляющие (manager) и рабочие (worker). Управляющие узлы занимаются конфигурирование и оркестрацией кластера, именно они создают задачи для поддержания нужного количества реплик сервисов. Среди управляющих узлов всегда есть лидер (lead manager), остальные узлы являются его подчиненными (follow manager). При падении лидера, один из оставшихся узлов заменяет его. Рабочие узлы являются контейнерами для запуска docker-образов необходимых программных компонентов.
-
В кластере можно создать сервис (service) с необходимым количеством реплик (replicas), настройками виртуальной сети и доступными ресурсами (cpu, ram), а также портом для доступа из внешней сети и многое другое. Поддержкой работы необходимого количества реплик конкретного сервиса называется задачей (task). Задача назначается управляющим узлом определенному рабочему узлу в кластере. Запуск сервиса возможен в двух режимах: реплицированный (replicated), используемых по умолчанию, который запускает указанное количество реплик на свободных узлах, и глобальный (global), который запускает ровно по одной реплики на каждом узле (можно использовать для агентов мониторинга, антивирусных сканеров и прочего ПО, которое должно быть запущено на всех нодах, включая управляющие).
-
Для балансировки нагрузки между репликами используется ingress load balancing. Балансировка работает на основе заданного публичного порта и внутреннего DNS имени сервиса. Каждая из реплик по очереди обрабатывает запрос на указанный порт. Обращаться к сервису по его порту можно на любом узле кластера, он будет автоматически перенаправлен на нужный узел.
Кластер состоит из двух видов узлов: менеджеры (manager) и воркеры (worker). Менеджеры занимаются управлением кластера, отвечают за консенсус и непрерывную работу сервисов. Сервисы запускаются и работают на рабочих нодах (воркерах).
В кластере сервисом (service) называется программная компонента, которая должна быть запущена с определенным числом реплик. На изображение сервис nginx должен иметь 3 реплики в кластере. Обеспечение работы каждой реплики называется задачей (task). В данном примере сервис nginx должен иметь 3 реплики в кластере, соответственно мы имеем 3 задачи: nginx.1, nginx.2, nginx.3, которые отвечают за работу docker контейнера с образом nginx внутри.
Разработчики Docker Swarm рекомендуют держать нечетное количество менеджеров. Одного достаточно для тестовой среды. 3 достаточно для работы небольшого кластера. 5 оптимальный вариант для любой конфигурации. 7 и более менеджеров не имеет никакого смысла. Также для продакшен системы управляющие узлы должны располагаться на разных физических серверах.
Сервис в кластере создается командой docker service create
с указанием имени сервиса. Команда отправляется на управляющую ноду. Узел создает задачи на рабочих нодах в соответствии с нужным количеством реплик. Задачи на рабочих нодах создаются, подготавливаются и запускаются. У задач могут быть различные состояния (полный список доступен здесь). Просмотреть список задач конкретного сервиса можно с помощью команды docker service ps <service-name>
.
При создании кластера docker swarm init
текущий хост становиться управляющим узлом. И по умолчанию генерируется сертификат для защиты трафика по алгоритму TLS. Можно использовать собственный сертификат с использованием ключа --external-ca
. По умолчанию каждый узел в кластере обновляет свой сертификат каждые 3 месяца, возможно задать свое время жизни с помощью docker swarm update --cert-expiry <TIME PERIOD>
. Также ключ может быть заменен, если есть опасность компрометирования, с помощью команды docker swarm ca --rotate
.
Также первый управляющий узел генерирует 2 токена, с помощью которых можно подключать в кластер новые управляющие и рабочие узлы соответственно.
Инициализация режима кластера командой docker swarm init
:
-
Создается новый кластер с именем
default
по умолчанию. -
Текущий хост становится главным управляющим узлом (leader manager) и попадает в только что созданный кластер с именем по умолчанию совпадающим с именем хоста (hostname).
-
Управляющий узел начинает прослушивать порт 2377 по умолчанию.
-
Управляющий узел по умолчанию запускается в режиме
active
. Это означает, что он также выступает и в роли рабочего узла (worker) и может выполнять задачи (task) на запуск сервисов (service). -
Генерируются новые сертификаты безопасности и токены для подключения новых узлов в кластер.
-
Создается новая виртуальная сеть с именем
ingress
по умолчанию.
При инициализации следует указать IP адрес управлющей ноды, к которой будут обращаться остальные хосты, добавляемые в кластер, т.к. по умолчанию используется указанный в hosts
адрес (который может быть localhost
). Выполняется это с помощью команды docker swarm init --advertise-addr <MANAGER-IP>
. Для нашей локальной сети это может быть 192.168.0.123
. Для продакшен системы это будет внешей IPv4 адрес сервера в сети Интернет.
Добавление происходит с помощью выполнения специальных команд с секретными токенами на хостах, которые надо добавить в кластер. Для получения команд с токенами для добавления менеджеров и воркеров можно выполнить следующие команды соответственно: docker swarm join-token manager
и docker swarm join-token worker
.
Подключение текущего хоста в кластеру командой docker swarm join --token <TOKEN> <MANAGER-IP>:2377
:
-
Текущий хост с Docker Engine переходит в режим
swarm
. -
Хост запрашивает TLS сертификат с управляющего узла.
-
Новый узел в кластере получит имя своего хоста (hostname) по умолчанию.
-
Новый узел подключится к кластеру в качестве роли, которая ему была задана: manager или worker. По умолчанию
manager
запускается в режимеactive
, что означает, что также является иworker
. -
Новый узел по умолчанию добавляется в виртуальную сеть с именем
ingress
.
В случае страха компрометирования токенов, как и с сертификатами CA, их можно заменить с помощью команды swarm join-token --rotate
.
-
Просмотреть список всех узлов
docker node ls
. Полный список возможных состояний можно посмотреть здесь. -
Вывести подробную информацию по конкретному узлу
docker node inspect <NODE-ID> --pretty
. Без--pretty
вывод происходит в JSON формате. -
Переконфигурирование управляющего узла в режим
drain
, когда узел является только управляющим и не может выполнять задачи (task):docker node update --availability drain node-1
. -
Добавление мета-данных к конкретному узлу:
docker node update --label-add foo --label-add bar=baz node-1
. Мета-данные могут быть использованы в качестве специальной метки узла и прочее. -
У управляющих и рабочих узлов можно менять роли с помощью специальных команды: перевести 2 рабочие ноды в управляющие
docker node promote node-3 node-2
и перевести 2 управляющие ноды в рабочиеdocker node demote node-3 node-2
. -
Удалить текущую ноду из кластера
docker swarm leave
. После выхода хоста из кластера на управляющей ноде следует удалить ее из спискаdocker node rm node-2
.
- Создать сервис в кластере
docker service create nginx
. По умолчанию создает сервис со случайно сгенерированным именем с одной репликой без дополнительных конфигураций и внешнего порта для доступа извне. Доступ к такому сервису вне кластера невозможен. Чтобы создать сервис с именем необходимо указать ключ--name
, напримерdocker service create --name my_web nginx
. Также можно указать команду, которую должен выполнить контейнер сразу после запуска в концеdocker service create --name helloworld alpine:3.6 ping docker.com
.
# Типичное создание сервиса nginx с 3 репликами с доступом извне по порту 8080.
$ docker service create --name my_web \
--replicas 3 \
--publish 8080:80 \
nginx
-
В сервисе можно менять практически все параметры с помощью команды
docker service update
. Когда команда выполняется, старый контейнер уничтожается, на его место создается и запускается новый с обновленной конфигурацией. Например, укажем запущеному сервису внешний порт:docker service update --publish-add 80 my_web
. -
Удалить сервис из кластера можно командой
docker service remove
и указав его ID или имя. -
Вывести список сервисов на текущем узле можно командой
docker service ls
. -
При создании или обновлении сервиса можно указывать окружение:
--env
,--workdir
,--user
. Например,
$ docker service create --name helloworld \
--env MYVAR=myvalue \
--workdir /tmp \
--user my_user \
alpine ping docker.com
-
Также можно изменить команду, которая выполняется при запуске контейнера с помощью ключа
--args
:docker service update --args "ping docker.com" helloworld
. -
Внешний порт может быть указан 2 способами: 1) через
--publish <TARGET-PORT>:<SERVICE-PORT>
- этот способ позволяет маршрутизацию данного порта с любой ноды в кластере и использует встроенную балансировку нагрузки; 2) через--publish mode=host,target=<TARGET-PORT>,published=<SERVICE-PORT>
- данный способ не создает "глобального" порта сервиса на всем кластере и не балансирует запросы между нодами, обращаясь к конкретной ноде, Вы 100 % попадете на реплику сервиса именно этой ноды. -
В кластере можно создавать
overlay
сети и подключать к ним сервисы. Например, создадим сетьdocker network create --driver overlay my-network
. Все ноды после создания сети сразу же получают к ней доступ. Теперь добавим новый сервис в эту сеть:
$ docker service create \
--replicas 3 \
--network my-network \
--name my-web \
nginx
-
Можно также подключить к новой сети уже запущенные сервисы:
docker service update --network-add my-network my-web
, или удалить из сети:docker service update --network-rm my-network my-web
. -
При запуске сервиса можно указать доступное количество процессоров и памяти:
--reserve-memory
и--reserve-cpu
. Внимание, резервирование именно для сервиса, т.е. суммы его реплик, а не для каждой реплики отдельно. -
Тут можно почитать про разделение кластера на регионы и привязку отдельных сервисов к конкретным регионам.
-
Тут можно почитать про настройку поведения сервиса при обновлениях и их откатах.
-
Тут можно прочитать про
mount
инг внешнихvolume
ов. Важное замечание: маунтинг внешних источников очень сильно снижает производительность, следует избегать этого. -
Тут можно прочитать про использование шаблонов при создании сервисов. Очень удобно генерировать имена, например.
Docker Swarm позволяет хранить конфигурации вне контейнеров. Их можно создавать, обновлять и удалять. Конфигурации можно хранить в compose
файлах, которые поддерживаются как docker compose
, так и docker stack
. docker stack
по сути аналог docker compose
только в кластерной среде.
-
Создать новую конфигурацию можно командой
echo "This is a config" | docker config create my-config -
. Создется конфиг с именемmy-config
, который содержит строку "This is a config". -
Чтобы какому-то сервису был доступен конфиг, это необходимо указать явно при создании или обновлении сервиса:
docker service create --name redis --config my-config redis:alpine
. Тут создается сервис redis с доступом к конфигу, который был создан выше. Конфиг по умолчанию доступен внутри контейнера по пути/my-config
, т.е. в корне контейнера в каталоге с именем конфига в кластере. -
Чтобы отключить конфиги от сервиса, необходимо обновить сам сервис:
docker service update --config-rm my-config redis
. Теперь конфиг сервису недоступен, и каталог/my-config
не существует для контейнера. -
Чтобы удалить конфиг из кластера, необходимо выполнить команду
docker config rm my-config
. Удаление конфига из кластера возможно только, если ни один сервис его не использует. -
Для обновления конфига сначала создается новый конфиг с другим именем, например
my-config-2
. Старый конфиг заменятся на всех использующих его сервисах на новый черезdocker service update --config-rm my-config --config-add my-config-2 nginx
. После чего старый конфиг удаляется из кластераdocker config rm my-config
.
Простой пример с конфигом index.html
страницы:
Сама index-страница
<html>
<head><title>Hello Docker</title></head>
<body>
<p>Hello Docker! You have deployed a HTML page.</p>
</body>
</html>
Запускаем сервис, который будет использовать наш конфиг с домашней страницей
$ docker swarm init # Запускаем кластер
$ docker config create homepage index.html # Создаем конфиг с именем `homepage` с этой `index.html` страницей
$ docker service create # Запускаем сервис и передаем наш конфиг со страницей в него
--name my-iis
-p 8000:8000
--config src=homepage,target="\inetpub\wwwroot\index.html"
microsoft/iis:nanoserver
Открывает адрес http://localhost:8000
и видим нашу index.html
страницу.
Тут можно посмотреть более сложный пример с использованием конфигов для подключения сертификатов CA к nginx. Создается два secret
для хранения открытого и закрытого ключей, а также создается конфиг с настройками nginx для использования HTTPS с этими ключами. Очень хорошо описан, кстати, процесс генерации SSL ключей.
Для хранения секретов используется отдельный механизм, похожий на конфиги, но секреты в отличии от конфигов зашифровываются и не могут быть прочитаны в открытом виде. Для секретов идеально подходят: логины и пароли, TLS сертификаты и ключи, SSH ключи, другие конфеденциальные данные. Если конфиги доступны в корне контейнера в каталоге с именем конфига /<CONFIG-NAME>, то секреты доступны по пути
/run/secrets/<SECRET_NAME>. Секреты, как и конфиги работают как с
docker compose, так и с
docker stack`.
-
Для создания секрета используется команда
echo "This is a secret" | docker secret create my_secret_data -
, которая создаст секрет с именемmy_secret_data
и строкой внутри "This is a secret". -
Чтобы секрет был доступен в сервисе, сервису необходимо дать к нему доступ при создании или обновлении:
docker service create --name redis --secret my_secret_data redis:alpine
. -
Чтобы запретить конкретному сервису доступ к секрету, необходимо использовать команду
docker service update --secret-rm my_secret_data redis
. -
Чтобы удалить секрет из кластера, необходимо выполнить команду
docker secret rm my_secret_data
. Удаление секрета невозможно, пока есть хотя бы один сервис, который его использует. Сначала отключаем доступ у всех сервисов, потом удаляем сам секрет из кластера. -
Для обновления секрета сначала создается новый секрет с другим именем. Старый секрет заменятся на всех использующих его сервисах на новый. После чего старый секрет удаляется из кластера.
Простой пример с секретом index.html
страницы:
Сама index-страница
<html>
<head><title>Hello Docker</title></head>
<body>
<p>Hello Docker! You have deployed a HTML page.</p>
</body>
</html>
Запускаем сервис, который будет использовать наш секрет с домашней страницей
$ docker swarm init # Запускаем кластер
$ docker secret create homepage index.html # Создаем секрет с именем `homepage` с этой `index.html` страницей
$ docker service create # Запускаем сервис и передаем наш конфиг со страницей в него
--name my-iis
-p 8000:8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
microsoft/iis:nanoserver
Открывает адрес http://localhost:8000
и видим нашу index.html
страницу.
Тут можно посмотреть более сложный пример с использованием секретов для подключения сертификатов CA к nginx. Создается три secret
для хранения открытого и закрытого ключей, а также с настройками nginx для использования HTTPS с этими ключами. Очень хорошо описан, кстати, процесс генерации SSL ключей.
Пример использования секретов в docker-compose
файле:
version: '3.1'
services:
db:
image: mysql:latest
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_root_password
- db_password
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: db_password.txt
db_root_password:
file: db_root_password.txt
volumes:
db_data:
После инициализации кластера и подключения узлов к нему, система начинает работать. В процессе эксплуатации узлы могут выходить из строя, перезагружаться, отваливаться и прочее. После восстановления работы узел обратно подключается к кластеру. Данное подключение является возможной брешью в защите.
Для этого в Docker Swarm есть возможность запустить кластер в режиме авто-блокировки: docker swarm init --autolock
. Ключ --autolock
не позволит подключиться восстановившемуся узлу к кластеру, пока не будет выполнена команда docker swarm unlock
со специальным ключом разблокировки, сгенерированным при инициализации кластера. Так гарантируется, что подключается именно тот хост, который был до падения узла.
Ключ --autolock
оказывается влияние только на отвалившиеся узлы, при добавлении новых через docker swarm join
он не требуется.
Режим можно переключать в работающем кластере через команду docker swarm update --autolock=true
. Чтобы вывести ключ, необходимый для разблокировки кластера, требуется ввести команду docker swarm unlock-key
. Ключ также можно пересоздать командой docker swarm unlock-key --rotate
, если есть подозрения его компрометирования.
В кластере генерируется 2 вида трафика: служебный (управление состоянием кластера и поддержкание его работы) и апликационный (обмен данными между сервисами и с внейшей сетью).
Основные виды сетевого взаимодействия:
-
overlay - частная виртуальная сеть для общения docker-контейнеров между собой. Можно создавать и привязывать сервисы к своим overlay-сетям. Для создания новой overlay сети:
docker network create --driver overlay my-network
. Для просмотра информации о сети:docker network inspect my-network
. Overlay сеть по умолчанию не используется шифрование трафика, чтобы его влючить достаточно указать ключ--opt encrypted
, но шифрование трафика внутри кластера для overlay-сетей оказывается влияние на производительность. По умолчанию, сеть используется виртуальные ip-адреса для каждой реплики каждого сервиса. Можно перевести сеть на использование DNS имен с помощью ключа--endpoint-mode dnsrr
, который позволяет использовать свои собственные алгоритмы балансировки (DNS round-robin и прочие, основанные на доменных именах). -
ingress - специальная виртуальная сеть для реализации балансировки нагрузки между репликами одного сервиса. Когда в кластер на любой из узлов приходит запрос на определенный публичный порт, кластер перенаправляет этот запрос на нужную ноду, балансирую между репликами сервиса, который был назначен на этот порт. Эта сеть создается по умолчанию и в большинстве случаев (никогда) ее не стоит переконфигурировать.
-
docker_gwbridge - это мост между физически разделенными хостами кластера. Он создается автоматически при подключении нового хоста к кластеру. В большинстве случаев (никогда) его не стоит переконфигурировать.
Для вывода всех сетей можно выполнить команду docker network ls
.
При создании overlay сети можно задать различные настройки:
$ docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--gateway 10.0.9.99 \
my-network
Рекомендуется создавать сети только с ограничением в 24 блока (/24), который используется по умолчанию. Это позволяет создавать внутри сети 256 ip-адресов. Другие размеры блоков оказывают влияние на производительность кластера.
Для создания сервиса и добавления его в конкретную сеть используется команда:
$ docker service create \
--replicas 3 \
--name my-web \
--network my-network \
nginx
В Docker Swarm можно запускать группы контейнеров с помощью compose
файлов формата yml
. Для этого синтаксис docker-compose
был расширен для работы с кластером. Список команд можно посмотреть тут.
Добавить сервисы в кластер из compose
файла можно командой docker stack deploy -c <COMPOSE_FILE> <STACK_NAME>
. И также весь стек можно легко удалить командой docker stack rm <STACK_NAME>
. Вывести список стеков в кластере можно командой docker stack ls
.
Стеки очень удобны для объединения сервисов в группы. Например, стек микросервисов, стек инфраструктуры, стек средств мониторинга, стек утилит для работы с самим кластером и прочее.
Здесь можно посмотреть примеры.
- Никогда не стоит перезагружать управляющий узел, просто скопировав его кластерные настройки из
raft
каталога. Лучше всего удалить его из кластера и подключить снова:
$ docker node demote <NODE> ## Делаем узел обычным воркером
$ docker node rm <NODE> ## Удаляем узел из кластера
$ docker swarm join ## Подключаем хост как новый узел
-
Узел можно принудительно удалить с помощью специального ключа
--force
:docker node rm --force node9
. Это следует делать, когда узел недоступен или окончательно сломался и удалить его безопасным способом невозможно. -
Возможно создавать
backup
кластера, просто архивируя каталог/var/lib/docker/swarm
, в котором находятся все настройки, логи и данныеdocker swarm
. Для восстановления достаточно просто восстановить каталог и перезагрузить узел. Здесь более подробная инструкция. -
В
docker swarm
нет автоматической ребалансировки реплик сервисов между узлами, т.е. как они были созданы послеdocker service create
, т.к они и остануться. Но есть ключ--force
, который позволяет обновить сервис и заставить кластер пересмотреть физическое расположение реплик на нодах:docker service update --force
. -
Тут можно прочитать про настройку внешнего балансировщика (HAProxy).
Raft - алгоритм для решения задач консенсуса в сети ненадёжных вычислений. На данном алгоритме основана работа Docker Swarm.
-
2377 (tcp) - взаимодействие узлов для управления кластером
-
7946 (tcp/udp) - взаимодействие между всеми узлами
-
4789 (udp) - трафик внутри overlay сетей
-
ip protocol 50 (ESP)
- требуется для работы шифрованных overlay сетей (--opt encrypted
)
-
3 физически разделенных сервера (server1, server2, server3).
-
Доступность серверов друг к другу внутри одной сети (статические IP адреса).
-
Открыте порты на серверах для коммуникации по сети (список портов в разделе выше).
-
Ubuntu 16.04 LTS с установленным
Docker
версии 1.12+. Гайд по установке на Ubuntu тут.
-
server1 будет управляющим узлом manager1
-
server2 и server3 будут рабочими узлами worker1 и worker2
Заходим на server1 и выполняем команду: docker swarm init --advertise-addr <MANAGER-IP>
, где <MANAGER-IP>
- IP адрес server1 в локальной сети с server2 и server3. Например 192.168.0.62
.
Запустите команду docker info
, чтобы получить информацию о кластере, и команду docker node ls
, чтобы увидеть все узлы в кластере.
Чтобы подключать управляющие и рабочие узлы, используется специальные токены, которые выводятся при инициализации кластера и при выполнении команд:
docker swarm join-token manager
docker swarm join-token worker
Подключаем server2 и server3 как рабочие узлы к кластеру с помощью команды:
$ docker swarm join \
--token <WORKER_TOKEN> \
<MANAGER-IP>:2377
Где <WORKER_TOKEN>
- токен, который был сгенерирован при инициализации кластера для добавляения рабочих узлов.
Выполним на управлящей ноде manager1 на сервере server1 команду docker node ls
, чтобы увидеть список всех узлов в кластере.
На управляющем узле для создания сервиса необходимо выполнить команду:
docker service create --replicas 1 --name helloworld alpine ping docker.com
Для просмотра списка сервисов в кластере можно выполнить команду docker service ls
.
Для просмотра на каких узлах запущен конкретный сервис можно выполнить команду docker service ps <SERVICE-ID>
, где <SERVICE-ID>
- уникальный ID или имя сервиса.
Для вывода подробной информации о конкретном сервисе можно выполнить команду docker service inspect --pretty <SERVICE-ID>
.
Для просмотра запущенных контейнеров на текущем узле выполнить команду docker ps
.
Для масштабирования запущенного сервиса достаточно выполнить команду docker service scale <SERVICE-ID>=<NUMBER-OF-TASKS>
.
Для проверки работы масштабирования достаточно выполнить команду docker service ps <SERVICE-ID>
.
Для удаления севриса (всех его реплик) достаточно выполнить команду docker service rm <SERVICE-ID>
.
Для проверки, что сервис был удален можно использовать команду docker service inspect <SERVICE-ID>
.
Создадим новый сервис:
$ docker service create \
--replicas 3 \
--name redis \
--update-delay 10s \
redis:3.0.6
Проверим, что он создался docker service inspect --pretty redis
.
Теперь обновим версии образа внутри контейнера docker service update --image redis:3.0.7 redis
. Данная команда остановит каждую из реплик по отдельности, обновит образ используемого redis и запустит его.
Проверим, что redis обновился docker service inspect --pretty redis
.
По умолчанию управляющие ноды также являются воркерами (availability равно ACTIVE
).
Чтобы сделать ноду только управляющей достаточно обновить ее настройки: docker node update --availability drain <NODE-ID>
, где <NODE-ID>
- ID или имя узла кластера.
Чтобы сделать управляющую ноду опять способной запускать реплики, вновь обновляем настройки: docker node update --availability active <NODE-ID>
.
Для доступа к сервису внутри кластера требуется указать внешний порт с помощью специального ключа:
$ docker service create \
--name <SERVICE-NAME> \
--publish <PUBLISHED-PORT>:<TARGET-PORT> \
<IMAGE>
Например, для nginx:
$ docker service create \
--name my-web \
--publish 8080:80 \
--replicas 2 \
nginx
Можно добавить публичный порт уже запущенному сервису с помощью команды: docker service update --publish-add <PUBLISHED-PORT>:<TARGET-PORT> <SERVICE-ID>
.
Можно также публиковать только tcp или udp порты с помощью явного указания: 53:53/tcp
или 53:53/udp
.
-
Настраиваем 3 Ubuntu сервера в одной сети. Настраиваем SSH доступ и фаерволл (ssh и docker swarm порты). Устанавливаем Docker.
-
Инициализируем кластер на server1:
$ sudo docker swarm init --advertise-addr 192.168.0.62
$ sudo docker info
$ sudo docker node ls
- Добавляем server2 и server3 в кластер (команды запускается на server2 и server3):
$ sudo docker swarm join \
--token <WORKER_TOKEN> \
192.168.0.62.100:2377
- На управляющей ноде (server1) проверяем, что все подключились:
$ sudo docker node ls
- Запускаем первый сервис (подобные команды работают только на управляющих нодах):
$ sudo docker service create --replicas 1 --name helloworld alpine ping docker.com
$ sudo docker service ls
$ sudo docker service inspect --pretty helloworld
$ sudo docker service ps helloworld
- На каждой из нод можно посмотреть, что именно на ней запущено:
$ sudo docker ps
- Масштабируем сервис до 5 реплик:
$ sudo docker service scale helloworld=5
$ sudo docker service ps helloworld
$ sudo docker ps
- Удаляем сервис из кластера:
$ sudo docker service rm helloworld
$ sudo docker service inspect helloworld
$ sudo docker ps
- Создадим другой сервис для тестов обновления:
$ sudo docker service create \
--replicas 3 \
--name redis \
--update-delay 10s \
redis:3.0.6
$ sudo docker service inspect --pretty redis
$ sudo docker service ls
- Теперь попробуем обновить его:
$ sudo docker service update --image redis:3.0.7 redis
$ sudo docker service inspect --pretty redis
$ sudo docker service ls
- Перевод worker1 (server2) в неактивное (drain) состояние:
# До отлючения worker1
$ sudo docker node ls
$ sudo docker node inspect --pretty pmk-local-2
$ sudo docker service ps redis
# После отключения worker1
$ sudo docker node update --availability drain pmk-local-2
$ sudo docker node ls
$ sudo docker node inspect --pretty pmk-local-2
$ sudo docker service ps redis
# Активируем worker1 обратно
$ sudo docker node update --availability active pmk-local-2
$ sudo docker node ls
$ sudo docker node inspect --pretty pmk-local-2
$ sudo docker service ps redis
- Добавим еще один сервис для тестирования доступа извне:
$ sudo docker service create \
--name my-web \
--publish 8080:80 \
--replicas 2 \
nginx
$ sudo docker service ps my-web
Теперь с любого узла по порту 8080
доступен сервер nginx
:
Запустить панель управления кластером Portainer на порту 5000
на всех управляющий узлах:
$ sudo docker service create \
--name portainer \
--publish 5000:9000 \
--constraint node.role==manager \
--mode global \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
portainer/portainer \
-H unix:///var/run/docker.sock
Запустить простой GUI для мониторинга кластера на порту 5001
на всех управляющий узлах:
$ sudo docker service create \
--name swarm-visualizer \
--publish 5001:8080 \
--constraint node.role==manager \
--mode global \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
dockersamples/visualizer
Запустить простой GUI для мониторинга кластера на порту 5002
на всех управляющий узлах:
$ sudo docker service create \
--name dvizz \
--publish 5002:6969 \
--constraint node.role==manager \
--mode global \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
eriklupander/dvizz
$ sudo docker service create \
--name rabbitmq \
--publish 5672:5672 \
--publish 15672:15672 \
rabbitmq:3-management
$ sudo docker service create \
--name pgadmin4 \
-e "PGADMIN_DEFAULT_EMAIL=admin" \
-e "PGADMIN_DEFAULT_PASSWORD=password" \
--publish 5555:80 \
--replicas 1 \
dpage/pgadmin4