Разверните службы на swarm

Службы Swarm используют декларативную модель, что означает, что вы определяете желаемое состояние службы и полагаетесь на Docker для поддержания этого состояния. Состояние включает такую информацию, как (но не ограничиваясь ею):

  • имя образа и тег, которые должны запускать сервисные контейнеры

  • сколько контейнеров участвует в обслуживании

  • открыты ли какие-либо порты для клиентов за пределами swarm

  • должна ли служба запускаться автоматически при запуске Docker

  • конкретное поведение, которое происходит при перезапуске службы (например, используется ли последовательный перезапуск)

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

Обзор режима swarm см. в статье Ключевые понятия режима Swarm. Обзор работы служб см. в статье Как работают сервисы.

Создаёт сервис

Чтобы создать службу с одной репликой без дополнительной настройки, достаточно указывает имя образа. Эта команда запускает службу Nginx со случайно сгенерированным именем и без опубликованных портов. Это наивный пример, т. к. вы не можете взаимодействовать с сервисом Nginx.

$ docker service create nginx

Служба запланирована на доступном узле. Чтобы убедиться, что служба создана и успешно запущена, используйте команду docker service ls:

$ docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE                                                                                             PORTS
a3iixnklxuem        quizzical_lamarr    replicated          1/1                 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268

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

Чтобы указывает имя для службы, используйте флаг --name:

$ docker service create --name my_web nginx

Как и в случае с автономными контейнерами, вы можете указывает команду, которую должны запускать контейнеры службы, добавив её после имени образа. В этом примере запускается служба с именем helloworld, которая использует образ alpine и выполняет команду ping docker.com:

$ docker service create --name helloworld alpine ping docker.com

Вы также можете указать тег образа для использования службой. Данный пример изменяет предыдущий для использования тега alpine:3.6:

$ docker service create --name helloworld alpine:3.6 ping docker.com

Дополнительные сведения о разрешении тегов образов см. в статье Указывает версию образа, которую должен использовать сервис..

gMSA для Swarm

Swarm теперь позволяет использовать конфигурацию Docker в качестве спецификации учетных данных gMSA — требование для приложений, прошедших проверку подлинности Active Directory. Это снижает нагрузку на распространение спецификаций учетных данных на узлы, на которых они используются.

В следующем примере предполагается, что gMSA и его спецификация учетных данных (называемая credspec.json) уже существуют и что развертываемые узлы правильно настроены для gMSA.

Чтобы использовать конфигурацию в качестве спецификации учетных данных, сначала создаёт конфигурацию Docker, содержащую спецификацию учетных данных:

$ docker config create credspec credspec.json

Теперь у вас должна быть конфигурация Docker с именем credspec, и вы можете создать службу, используя эту спецификацию учетных данных. Для этого используйте флаг –credential-spec с именем конфигурации, как здесь:

$ docker service create --credential-spec="config://credspec" <your image>

Ваша служба будет использовать спецификацию учетных данных gMSA при запуске, но в отличие от типичной конфигурации Docker (используемой путём передачи флага –config) спецификация учетных данных не будет монтироваться в контейнер.

Создаёт службу, используя образ в частном реестре

Если ваш образ доступен в частном реестре, который требует входа в систему, используйте флаг --with-registry-auth с docker service create после входа в систему. Если ваш образ хранится в registry.example.com, который является частным реестром, используйте команду, подобную следующей:

$ docker login registry.example.com

$ docker service  create \
  --with-registry-auth \
  --name my_service \
  registry.example.com/acme/my_image:latest

Это передает токен входа от вашего локального клиента на узлы swarm, где развернута служба, используя зашифрованные журналы WAL. С помощью этой информации узлы могут войти в реестр и получает образ.

Указывает спецификации учетных данных для управляемых учетных записей служб

В Enterprise Edition 3.0 безопасность повышена за счет централизованного распределения и управления учетными данными групповой управляемой учетной записи службы (gMSA) с использованием функций Docker Config. Swarm теперь позволяет использовать конфигурацию Docker в качестве спецификации учетных данных gMSA, что снижает нагрузку на распространение спецификаций учетных данных на узлы, на которых они используются.

Примечание

Данный параметр применим только к службам, использующим контейнеры Windows.

Файлы спецификаций учетных данных применяются во время выполнения, что устраняет необходимость в файлах спецификаций учетных данных на основе хоста или в записях реестра — учетные данные gMSA не записываются на диск на рабочих узлах. Вы можете сделать спецификации учетных данных доступными для Docker Engine, на котором запущены рабочие узлы комплекта swarm, до запуска контейнера. При развертывании службы с использованием конфигурации на основе gMSA спецификация учетных данных передаётся непосредственно среде выполнения контейнеров в этой службе.

--credential-spec должен быть в одном из следующих форматов:

  • file://<filename>: указанный файл должен находиться в подкаталоге CredentialSpecs в каталоге данных Docker, который по умолчанию имеет значение C:\ProgramData\Docker\ в Windows. Например, указание file://spec.json загружает C:\ProgramData\Docker\CredentialSpecs\spec.json.

  • registry://<value-name>: спецификация учетных данных считывается из реестра Windows на хосте демона.

  • config://<config-name>: имя конфигурации автоматически преобразуется в идентификатор конфигурации в интерфейсе командной строки. Используется спецификация учетных данных, содержащаяся в указанном config.

В следующем простом примере извлекается имя gMSA и содержимое JSON из экземпляра Active Directory (AD):

$ name="mygmsa"
$ contents="{...}"
$ echo $contents > contents.json

Убедиться, что узлы, на которых выполняется развертывание, правильно настроены для gMSA.

Чтобы использовать конфигурацию в качестве спецификации учетных данных, создаёт конфигурацию Docker в файле спецификации учетных данных с именем credpspec.json. Вы можете указывает любое имя для имени файла config.

$ docker config create --label com.docker.gmsa.name=mygmsa credspec credspec.json

Теперь вы можете создать службу, используя эту спецификацию учетных данных. Указывает флаг --credential-spec с именем конфига:

$ docker service create --credential-spec="config://credspec" <your image>

Ваша служба использует спецификацию учетных данных gMSA при запуске, но в отличие от типичной конфигурации Docker (используемой путём передачи флага –config) спецификация учетных данных не монтируется в контейнер.

Обновляет службу

Вы можете изменяет почти все в существующей службе с помощью команды docker service update. Когда вы обновляете службу, Docker останавливает свои контейнеры и перезапускает их с новой конфигурацией.

Поскольку Nginx — это веб-сервис, он будет работать намного лучше, если вы опубликуете порт 80 для клиентов за пределами swarm. Вы можете указывает это при создании службы, используя флаг -p или --publish. При обновлении существующей службы флаг --publish-add. Существует также флаг --publish-rm для удаления ранее опубликованного порта.

Предполагая, что служба my_web из предыдущего раздела все ещё существует, используйте следующую команду, чтобы обновить её, чтобы опубликовать порт 80.

$ docker service update --publish-add 80 my_web

Чтобы убедиться, что это сработало, используйте docker service ls:

$ docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE                                                                                             PORTS
4nhxl7oxw5vz        my_web              replicated          1/1                 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268   *:0->80/tcp

Дополнительные сведения о работе портов публикации см. в статье издательские порты.

Вы можете обновить почти все детали конфигурации существующей службы, включая имя образа и тег, который он запускает. См. Обновить образ службы после создания.

Удаляет службу

Чтобы удаляет службу, используйте команду docker service remove. Вы можете удаляет службу по её идентификатору или имени, как показано в выводе команды docker service ls. Следующая команда удаляет службу my_web.

$ docker service remove my_web

Детали конфигурации службы

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

См. справочники на командную строку для docker service create и docker service update или запускает одну из данных команд с флагом --help.

Настраивает среду выполнения

Вы можете настроить следующие параметры среды выполнения в контейнере:

  • переменные среды с использованием флага --env

  • рабочий каталог внутри контейнера с использованием флага --workdir

  • имя пользователя или UID с использованием флага --user

Контейнеры следующих служб имеют переменную среды $MYVAR, для которой задано значение myvalue, они запускаются из каталога /tmp/ и запускаются от имени пользователя my_user.

$ docker service create --name helloworld \
  --env MYVAR=myvalue \
  --workdir /tmp \
  --user my_user \
  alpine ping docker.com

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

Чтобы обновить команду, которую запускает существующая служба, вы можете использовать флаг --args. В следующем примере существующая служба с именем helloworld обновляется, чтобы она выполняла команду ping docker.com вместо любой команды, которая выполнялась ранее:

$ docker service update --args "ping docker.com" helloworld

Указывает версию образа, которую должен использовать сервис

Когда вы создаёте службу без указания каких-либо сведений о версии используемого образа, служба использует версию, помеченную тегом latest. Вы можете заставить службу использовать определенную версию образа несколькими способами, в зависимости от желаемого результата.

Версия образа может быть выражена несколькими различными способами:

  • Если вы укажете тег, менеджер (или клиент Docker, если вы используете контент траст) преобразует данный тег в дайджест. Когда запрос на создание контейнерной задачи поступает на рабочий узел, рабочий узел видит только дайджест, а не тег.

$ docker service create --name="myservice" ubuntu:16.04

Некоторые теги представляют отдельные релизы, например ubuntu:16.04. Подобные теги почти всегда со временем разрешаются в стабильный дайджест. Рекомендуется использовать данный тип тега, когда это возможно.

Другие типы тегов, такие как latest или nightly, могут часто разрешаться в новый дайджест, в зависимости от того, как часто автор образа обновляет тег. Не рекомендуется запускать службы с использованием тега, который часто обновляется, чтобы предотвратить использование разных версий образа разными задачами реплики службы.

  • Если вы вообще не указываете версию, по соглашению тег образа latest преобразуется в дайджест. Рабочие используют образ из этого дайджеста при создании сервисной задачи.

Таким образом, следующие две команды эквивалентны:

$ docker service create --name="myservice" ubuntu

$ docker service create --name="myservice" ubuntu:latest
  • Если вы укажете дайджест напрямую, именно эта версия образа всегда будет использоваться при создании сервисных задач.

$ docker service create \       --name="myservice" \       ubuntu:16.04@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1

Когда вы создаёте службу, тег образа преобразуется в конкретный дайджест, на который указывает тег во время создания службы. Рабочие узлы для этой службы всегда используют данный конкретный дайджест, если служба не обновляется явно. Данная функция особенно важна, если вы используете часто меняющиеся теги, такие как latest, поскольку она гарантирует, что все сервисные задачи будут использовать одну и ту же версию образа.

Примечание

Если контент траст включён, клиент фактически преобразует тег образа в дайджест, прежде чем связаться с менеджером swarm, чтобы убедиться, что образ подписано. Таким образом, если вы используете доверие к содержимому, диспетчер swarm получает предварительно разрешенный запрос. В этом случае, если клиент не может преобразовывает образ в дайджест, запрос завершается ошибкой.

Если менеджер не может преобразовывает тег в дайджест, каждый рабочий узел отвечает за преобразовывает тега в дайджест, и разные узлы могут использовать разные версии образа. В этом случае записывается предупреждение, подобное приведенному далее, с заменой реальной информации заполнителями.

unable to pin image <IMAGE-NAME> to digest: <REASON>

Чтобы просмотреть текущий дайджест образа, входит команду docker inspect <IMAGE>:<TAG> и найти строку RepoDigests. Далее приведён текущий дайджест для ubuntu:latest на момент написания этого контента. Вывод обрезан для ясности.

$ docker inspect ubuntu:latest
"RepoDigests": [
    "ubuntu@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1"
],

После создания службы её образ никогда не обновляется, если вы явно не запускает docker service update с флагом --image, как приведено далее. Другие операции обновления, такие как масштабирование службы, добавление или удаление сетей или томов, переименование службы или любой другой тип операции обновления, не обновляют образ службы.

Обновляет образ службы после создания

Каждый тег представляет собой дайджест, аналогичный хешу Git. Некоторые теги, такие как latest, часто обновляются, чтобы указывать на новый дайджест. Другие, такие как ubuntu:16.04, представляют собой выпущенную версию программного обеспечения, и не ожидается, что они будут часто обновляться, чтобы указывать на новый дайджест. Когда вы создаёте службу, она ограничена созданием задач с использованием определённого дайджеста образа, пока вы не обновляет службу, используя service update с флагом --image.

Когда вы запускаете service update с флагом --image, менеджер swarm запрашивает Docker Hub или ваш частный реестр Docker для получения дайджеста, на который в данный момент указывает тег, и обновляет сервисные задачи для использования этого дайджеста.

Примечание

Если вы используете контент траст, клиент Docker разрешает образ, а менеджер swarm получает образ и дайджест, а не тег.

Обычно менеджер может преобразовывает тег в новый дайджест, а служба обновится, повторно развернув каждую задачу для использования нового образа. Если менеджер не может разрешить тег или вызывается какая-либо другая проблема, в следующих двух разделах описывается, чего ожидать.

Если менеджер разрешает тег

Если диспетчер swarm может преобразовывает тег образа в дайджест, он предоставляет указание рабочим узлам повторно развернуть задачи и использовать образ в этом дайджесте.

  • Если рабочий процесс кэшировал образ в этом дайджесте, он использует его.

  • Если нет, он пытается получает образ из Docker Hub или частного реестра.

  • В случае успеха задача развертывается с использованием нового образа.

  • Если рабочему процессу не удается получает образ, служба не может быть развернута на этом рабочем узле. Docker снова пытается развернуть задачу, возможно, на другом рабочем узле.

Если менеджер не может разрешить тег

Если диспетчер swarm не может преобразовывает образ в дайджест, ещё не все потеряно:

  • Менеджер предоставляет указание рабочим узлам повторно развернуть задачи, используя образ с этим тегом.

  • Если рабочий процесс имеет локально кэшированное образ, которое разрешается в данный тег, он использует это образ.

  • Если у рабочего процесса нет локально кэшированного образа, который разрешается в тег, рабочий процесс пытается подключиться к Docker Hub или частному реестру, чтобы получает образ по этому тегу.

  • Если это удается, рабочий процесс использует это образ.

  • Если это не удается, задачу не удается развернуть, и диспетчер снова пытается развернуть задачу, возможно, на другом рабочем узле.

Опубликовать порты

Когда вы создаёте службу swarm, вы можете опубликовать порты этой службы на хостах за пределами swarm двумя способами:

  • Вы можете положиться на сетку маршрутизации. Когда вы публикуете порт службы, swarm делает службу доступной на целевом порту на каждом узле, независимо от того, есть ли задача для службы, работающей на этом узле, или нет. Это менее сложно и является правильным выбором для многих типов услуг.

  • Вы можете опубликовать порт задачи службы непосредственно на узле swarm, где работает эта служба. Это позволяет обойти сетку маршрутизации и обеспечивает максимальную гибкость, включая возможность разработки собственной структуры маршрутизации. Однако вы несете ответственность за отслеживание выполнения каждой задачи и маршрутизацию запросов к задачам, а также за балансировку нагрузки между узлами.

Продолжайте читать для получения дополнительной информации и вариантов использования для каждого из данных методов.

Опубликуйте порты службы, используя сетку маршрутизации

Чтобы опубликовать порты службы за пределами swarm, используйте флаг --publish <PUBLISHED-PORT>:<SERVICE-PORT>. swarm делает службу доступной через опубликованный порт на каждом узле swarm. Если внешний хост подключается к этому порту на любом узле swarm, сетка маршрутизации направляет его к задаче. Внешнему хосту не нужно знать IP-адреса или внутренние порты задач службы для взаимодействия со службой. Когда пользователь или процесс подключается к службе, любой рабочий узел, выполняющий задачу службы, может ответить. Дополнительные сведения о сети службы swarm см. в статье Управление сервисной сетью swarm работает.

Пример. Запускает службу Nginx с тремя задачами на 10 узлах swarm

Представьте, что у вас есть 10-узловой swarm, и вы развертываете службу Nginx, выполняющую три задачи на 10-узловом swarm:

$ docker service create --name my_web \
                        --replicas 3 \
                        --publish published=8080,target=80 \
                        nginx

Три задачи выполняются на трёх узлах. Вам не нужно знать, на каких узлах выполняются задачи; подключение к порту 8080 на любом из 10 узлов подключает вас к одной из трёх задач nginx. Вы можете проверяет это, используя curl. В следующем примере предполагается, что localhost является одним из узлов swarm. Если это не так или localhost не разрешается в IP-адрес вашего хоста, заменяет IP-адрес хоста или разрешаемое имя хоста.

Вывод HTML усекается:

$ curl localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...truncated...
</html>

Последующие соединения могут быть направлены на тот же или другой узел swarm.

Опубликуйте порты службы непосредственно на узле swarm

Использование сетки маршрутизации может быть неправильным выбором для вашего приложения, если вам нужно принимать решения о маршрутизации на основе состояния приложения или вам нужен полный контроль над процессом маршрутизации запросов к задачам вашего сервиса. Чтобы опубликовать порт службы непосредственно на узле, на котором она запущена, используйте параметр mode=host для флага --publish.

Примечание

Если вы публикуете порты службы непосредственно на узле swarm, используя mode=host, а также устанавливаете published=<PORT>, это создаёт неявное ограничение, заключающееся в том, что вы можете запускает только одну задачу для этой службы на данном узле swarm. Вы можете обойти это, указав published без определения порта, что заставит Docker назначать случайный порт для каждой задачи.

Кроме того, если вы используете mode=host и не используете флаг --mode=global для docker service create, трудно узнать, на каких узлах работает служба, чтобы направить на них работу.

Пример. Запускает службу веб-сервера nginx на каждом узле swarm

нгинкс — это обратный прокси-сервер с открытым исходным кодом, балансировщик нагрузки, кэш HTTP и веб-сервер. Если вы запускаете nginx как службу с использованием сетки маршрутизации, подключение к порту nginx на любом узле swarm показывает вам веб-страницу (фактически) случайного узла swarm, на котором запущена служба.

В следующем примере nginx запускается как служба на каждом узле в вашем swarm и предоставляет порт nginx локально на каждом узле swarm.

$ docker service create \
  --mode global \
  --publish mode=host,target=80,published=8080 \
  --name=nginx \
  nginx:latest

Вы можете подключиться к серверу nginx через порт 8080 каждого узла swarm. Если добавить ноду в swarm, на ней запускается задача nginx. Вы не можете запускает другую службу или контейнер на любом узле swarm, который привязан к порту 8080.

Примечание

Это наивный пример. Создание инфраструктуры маршрутизации на уровне приложений для многоуровневой службы является сложным и выходит за рамки этой темы.

Подключите службу к оверлейной сети

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

Сначала создаёт оверлейную сеть на узле менеджера с помощью команды docker network create с флагом --driver overlay.

$ docker network create --driver overlay my-network

После создания оверлейной сети в режиме swarm все узлы менеджера имеют доступ к сети.

Вы можете создать новую службу и передать флаг --network, чтобы подключить службу к оверлейной сети:

$ docker service create \
  --replicas 3 \
  --network my-network \
  --name my-web \
  nginx

swarm расширяет my-network на каждый узел, на котором работает служба.

Вы также можете подключить существующую службу к оверлейной сети, используя флаг --network-add.

$ docker service update --network-add my-network my-web

Чтобы отключить работающую службу от сети, используйте флаг --network-rm.

$ docker service update --network-rm my-network my-web

Дополнительные сведения об оверлейных сетях и обнаружении служб см. в статьях Присоединение сервисов к оверлейной сети и Модель сетевой безопасности с наложением режима Docker swarm.

Предоставьте сервису доступ к секретам

Чтобы создать службу с доступом к секретам, управляемым Docker, используйте флаг --secret. Дополнительные сведения см. в статье Управление конфиденциальными строками (секретами) для служб Docker

Настраивает режим изоляции службы

Docker позволяет указывает режим изоляции службы swarm. Данный параметр применяется только к хостам Windows и игнорируется для хостов Linux. Режим изоляции может быть одним из следующих:

  • default: используйте режим изоляции по умолчанию, настроенный для узла Docker, как настроено флагом -exec-opt или массивом exec-opts в daemon.json. Если демон не указывает технологию изоляции, process является значением по умолчанию для Windows Server, а hyperv — значением по умолчанию (и единственным) для Windows 10.

  • process: выполнение служебных задач как отдельного процесса на узле.

    Примечание

    Режим изоляции process поддерживается только в Windows Server. Windows 10 поддерживает только режим изоляции hyperv.

  • hyperv: выполнение задач службы как изолированных задач hyperv. Это увеличивает накладные расходы, но обеспечивает большую изоляцию.

Вы можете указывает режим изоляции при создании или обновлении новой службы, используя флаг --isolation.

Контроль размещения услуг

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

  • Вы можете указывает, должна ли служба запускать определённое количество реплик или она должна работать глобально на каждом рабочем узле. См. Реплицированные или глобальные службы.

  • Вы можете настроить Требования к процессору или памяти службы, и служба будет работать только на тех узлах, которые соответствуют этим требованиям.

  • Ограничения размещения позволяет настроить службу для запуска только на узлах с определенным (произвольным) набором метаданных и привести к сбою развертывания, если соответствующие узлы не существуют. Например, вы можете указывает, что ваша служба должна работать только на узлах, где для произвольной метки pci_compliant установлено значение true.

  • Настройки размещения позволяет применять произвольную метку с диапазоном значений к каждому узлу и распределять задачи службы по этим узлам с помощью алгоритма. В настоящее время поддерживается только алгоритм spread, который пытается разместить их равномерно. Например, если вы пометите каждый узел меткой rack со значением от 1 до 10, а затем укажете предпочтение размещения с ключом rack, тогда сервисные задачи будут размещены как можно более равномерно по всем узлам с меткой rack после принятия других ограничения размещения, предпочтения размещения и другие ограничения, характерные для узла.

В отличие от ограничений, предпочтения размещения являются максимальными усилиями, и служба обязательно развертывается, если ни один узел не может удовлетворить предпочтение. Если вы укажете предпочтение размещения для службы, узлы, соответствующие этому предпочтению, получат более высокий рейтинг, когда менеджеры swarm решат, какие узлы должны выполнять задачи службы. Другие факторы, такие как высокая доступность службы, также влияют на то, на каких узлах запланировано выполнение задач службы. Например, если у вас есть N узлов с меткой стойки (а затем некоторые другие), а ваша служба настроена на запуск реплик N+1, +1 планируется на узле, на котором ещё нет службы, если он есть, независимо от того, имеет ли данный узел метку rack или нет.

Реплицированные или глобальные службы

Режим Swarm имеет два типа служб: реплицированные и глобальные. Для реплицируемых служб вы указываете количество задач репликации, которые диспетчер swarm должен запланировать на доступные узлы. Для глобальных служб планировщик размещает одну задачу на каждом доступном узле, соответствующем ограничения размещения и требования к ресурсам службы.

Вы управляете типом службы, используя флаг --mode. Если вы не укажете режим, по умолчанию для службы используется replicated. Для реплицируемых служб вы указываете количество задач репликации, которые хотите запускает, используя флаг --replicas. Например, для запуска реплицируемого сервиса nginx с 3 задачами-репликами:

$ docker service create \
  --name my_web \
  --replicas 3 \
  nginx

Чтобы запускает глобальную службу на каждом доступном узле, передать --mode global в docker service create. Каждый раз, когда становится доступным новый узел, планировщик размещает задачу для глобальной службы на новом узле. Например, чтобы запускает службу, которая запускает alpine на каждом узле в swarm:

$ docker service create \
  --name myservice \
  --mode global \
  alpine top

Ограничения службы позволяют задать критерии, которым должен соответствовать узел, прежде чем планировщик развернет службу на узле. Вы можете применять ограничения к сервису на основе атрибутов узла и метаданных или метаданных механизма. Дополнительные сведения об ограничениях см. в статье docker service create Справка по интерфейсу командной строки.

Зарезервируйте память или ЦП для службы

Чтобы зарезервировать определённый объём памяти или количество ЦП для службы, используйте флаги --reserve-memory или --reserve-cpu. Если никакие доступные узлы не могут удовлетворить требование (например, если вы запрашиваете 4 ЦП, а ни один узел в swarm не имеет 4 ЦП), служба остаётся в состоянии ожидания до тех пор, пока соответствующий узел не будет доступен для выполнения её задач.

Исключения нехватки памяти (OOME)

Если ваша служба пытается использовать больше памяти, чем доступно узлу swarm, может возникнуть исключение нехватки памяти (OOME), а контейнер или демон Docker могут быть уничтожены убийцей OOM ядра. Чтобы этого не произошло, убедиться, что ваше приложение работает на хостах с достаточным объемом памяти и смотрите Понимание рисков нехватки памяти.

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

Ограничения по размещению

Используйте ограничения размещения для управления узлами, которым может быть назначен сервис. В следующем примере служба работает только на узлах с этикетка region, для которых задано значение east. Если нет доступных узлов с соответствующей маркировкой, задачи будут ожидать в Pending, пока они не станут доступными. Флаг --constraint использует оператор равенства (== или !=). Для реплицированных служб возможно, что все службы работают на одном узле, или на каждом узле работает только одна реплика, или что на некоторых узлах не выполняются никакие реплики. Для глобальных служб служба запускается на каждом узле, соответствующем ограничению размещения, и любому требования к ресурсам.

$ docker service create \
  --name my-nginx \
  --replicas 5 \
  --constraint node.labels.region==east \
  nginx

Вы также можете использовать ключ уровня обслуживания constraint в файле docker-compose.yml.

Если вы укажете несколько ограничений размещения, служба будет развернута только на тех узлах, где они все соблюдены. В следующем примере запуск службы ограничивается на всех узлах, где для region задано значение east, а для type не задано значение devel:

$ docker service create \
  --name my-nginx \
  --mode global \
  --constraint node.labels.region==east \
  --constraint node.labels.type!=devel \
  nginx

Вы также можете использовать ограничения размещения в сочетании с настройками размещения и ограничениями ЦП/памяти. Будьте осторожны, чтобы не использовать настройки, которые невозможно выполняет.

Дополнительные сведения об ограничениях см. в статье docker service create Справка по интерфейсу командной строки.

Настройки размещения

В то время как ограничения размещения ограничивает количество узлов, на которых может работать служба, предпочтения размещения пытаются размещать задачи на соответствующих узлах алгоритмическим способом (в настоящее время только равномерное распределение). Например, если вы назначите каждому узлу метку rack, вы можете установить предпочтение размещения для равномерного распределения службы по узлам с меткой rack по значению. Таким образом, если вы потеряете стойку, служба все ещё будет работать на узлах в других стойках.

Предпочтения по размещению строго не соблюдаются. Если ни один узел не имеет метки, которую вы указали в своих предпочтениях, служба развертывается, как если бы это предпочтение не было задано.

Параметры размещения игнорируются для глобальных служб.

В следующем примере задается предпочтение для распространения развертывания по узлам на основе значения метки datacenter. Если у одних узлов datacenter=us-east, а у других datacenter=us-west, служба развертывается как можно более равномерно на двух наборах узлов.

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  redis:3.0.6

Примечание

Отсутствующие или нулевые метки

Узлы, у которых отсутствует метка, используемая для распространения, по-прежнему получают назначения задач. Как группа, данные узлы получают задачи в равной пропорции с любой из других групп, идентифицированных определенным значением метки. В некотором смысле отсутствующая метка — это то же самое, что и метка с прикрепленным к ней нулевым значением. Если сервис должен работать только на узлах с меткой, используемой для параметра распространения, параметр должен быть объединен с ограничением.

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

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  --placement-pref 'spread=node.labels.rack' \
  redis:3.0.6

Вы также можете использовать настройки размещения в сочетании с ограничениями размещения или ограничениями ЦП/памяти. Будьте осторожны, чтобы не использовать настройки, которые невозможно выполняет.

На этой диаграмме показано, как работают настройки размещения:

placement preferences example

При обновлении службы с помощью docker service update --placement-pref-add добавляет новый параметр размещения после всех существующих параметров размещения. --placement-pref-rm удаляет существующее предпочтение размещения, соответствующее аргументу.

Настраивает поведение обновления службы

Когда вы создаёте службу, вы можете указывает поведение непрерывного обновления для того, как swarm должен применять изменения к службе при запуске docker service update. Вы также можете указывает данные флаги как часть обновления, как аргументы для docker service update.

Флаг --update-delay настраивает временную задержку между обновлениями сервисной задачи или множеств задач. Вы можете описать время T как комбинацию количества секунд Ts, минут Tm или часов Th. Таким образом, 10m30s указывает на задержку в 10 минут 30 секунд.

По умолчанию планировщик обновляет по 1 задаче за раз. Вы можете передать флаг --update-parallelism, чтобы настроить максимальное количество служебных задач, которые планировщик обновляет одновременно.

Когда обновление отдельной задачи возвращает состояние RUNNING, планировщик продолжает обновление, переходя к другой задаче, пока все задачи не будут обновлены. Если в любой момент обновления задача возвращает FAILED, планировщик приостанавливает обновление. Вы можете управлять поведением, используя флаг --update-failure-action для docker service create или docker service update.

В приведённом далее примере службы планировщик применяет обновления не более чем к 2 репликам одновременно. Когда обновленная задача возвращает либо RUNNING, либо FAILED, планировщик ждет 10 секунд, прежде чем останавливает следующую задачу для обновления:

$ docker service create \
  --replicas 10 \
  --name my_web \
  --update-delay 10s \
  --update-parallelism 2 \
  --update-failure-action continue \
  alpine

Флаг --update-max-failure-ratio определяет, какая часть задач может завершиться сбоем во время обновления, прежде чем обновление в целом будет считаться неудачным. Например, с --update-max-failure-ratio 0.1 --update-failure-action pause после сбоя 10% обновляемых задач обновление приостанавливается.

Обновление отдельной задачи считается неудачным, если задача не запускается или прекращает выполнение в течение периода мониторинга, указанного с помощью флага --update-monitor. Значение по умолчанию для --update-monitor — 30 секунд, что означает, что сбой задачи в первые 30 секунд после её запуска засчитывается в пороговое значение сбоя обновления службы, а сбой после этого не учитывается.

Откат к предыдущей версии службы

Если обновленная версия службы не работает должным образом, можно вручную выполняет откат к предыдущей версии службы, используя флаг docker service update --rollback. Это возвращает службу к конфигурации, которая была до последней команды docker service update.

Другие варианты можно комбинировать с --rollback; например, --update-delay 0s для выполнения отката без задержки между задачами:

$ docker service update \
  --rollback \
  --update-delay 0s
  my_web

Вы можете настроить службу для автоматического отката, если не удается развернуть обновление службы. См. Автоматический откат в случае сбоя обновления.

Ручной откат обрабатывается на стороне сервера, что позволяет вручную инициировать откат с учётом новых параметров отката. Обратите внимание, что --rollback нельзя использовать вместе с другими флагами до docker service update.

Автоматический откат в случае сбоя обновления

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

Флаг

По умолчанию

Описание

--rollback-delay

0s

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

--rollback-failure-action

pause

Когда не удается выполняет откат задачи, будь то pause или continue при попытке отката других задач.

--rollback-max-failure-ratio

0

Частота отказов, допустимая во время отката, заданная как число с плавающей запятой между 0 и 1. Например, учитывая 5 задач, коэффициент отказов .2 допускал бы отказ одной задачи откатиться. Значение 0 означает, что сбой не допускается, а значение 1 означает, что допустимо любое количество сбоев.

--rollback-monitor

5s

Продолжительность после каждого отката задачи для отслеживания сбоя. Если задача останавливается до истечения этого периода времени, откат считается неудачным.

--rollback-parallelism

1

Максимальное количество задач для параллельного отката. По умолчанию выполняется откат одной задачи за раз. Значение 0 вызывает параллельный откат всех задач.

В следующем примере служба redis настраивается на автоматический откат, если не удается развернуть службу docker service update. Две задачи можно откатывать параллельно. Задачи отслеживаются в течение 20 секунд после отката, чтобы убедиться, что они не завершатся, и допускается максимальный коэффициент отказа 20%. Значения по умолчанию используются для --rollback-delay и --rollback-failure-action.

$ docker service create --name=my_redis \
                        --replicas=5 \
                        --rollback-parallelism=2 \
                        --rollback-monitor=20s \
                        --rollback-max-failure-ratio=.2 \
                        redis:latest

Предоставьте сервису доступ к томам или привязка монтирования

Для лучшей производительности и переносимости вам следует избегать записи важных данных непосредственно в доступный для записи слой контейнера, а вместо этого использовать тома данных или привязку монтирования. Данный принцип распространяется и на услуги.

Вы можете создать два типа монтирований для служб: swarm монтирования, volume или bind монтирования. Независимо от того, какой тип монтирования вы используете, настраивает его с помощью флага --mount при создании службы или флага --mount-add или --mount-rm при обновлении существующей службы. По умолчанию используется том данных, если вы не укажете тип.

Объемы данных

Тома данных — это хранилища, которые существуют независимо от контейнера. Жизненный цикл томов данных в службах swarm аналогичен жизненному циклу контейнеров. Тома живут дольше задач и сервисов, поэтому их удалением нужно управлять отдельно. Тома можно создавать перед развертыванием службы или, если они не существуют на определенном хосте, когда там запланирована задача, они создаются автоматически в соответствии со спецификацией тома в службе.

Чтобы использовать существующие тома данных со службой, используйте флаг --mount:

$ docker service create \
  --mount src=<VOLUME-NAME>,dst=<CONTAINER-PATH> \
  --name myservice \
  <IMAGE>

Если том с тем же <VOLUME-NAME> не существует, когда задача запланирована для определённого хоста, то он создаётся. Драйвер тома по умолчанию — local. Чтобы использовать другой драйвер тома с этим шаблоном создания по требованию, указывает драйвер и его параметры с флагом --mount:

$ docker service create \
  --mount type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=<DRIVER>,volume-opt=<KEY0>=<VALUE0>,volume-opt=<KEY1>=<VALUE1>
  --name myservice \
  <IMAGE>

Дополнительные сведения о создании томов данных и использовании драйверов томов см. в статье Использовать тома.

Привязываемые монтирования

Связные монтирования — это пути к файловой системе от хоста, на котором планировщик развертывает контейнер для задачи. Docker монтирует путь в контейнер. Путь к файловой системе должен существовать до того, как swarm инициализирует контейнер для задачи.

В следующих примерах показан синтаксис монтирования привязки:

  • Чтобы смонтировать привязку чтения-записи:

$ docker service create \     --mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH> \     --name myservice \     <IMAGE>
  • Чтобы смонтировать привязку только для чтения:

$ docker service create \     --mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH>,readonly \     --name myservice \     <IMAGE>

Важно

Бинд-маунты могут быть полезны, но они также могут вызвать проблемы. В большинстве случаев рекомендуется проектировать приложение таким образом, чтобы пути монтирования с хоста не были нужны. К основным рискам относятся следующие:

  • Если вы привязываете путь узла монтирования к контейнерам службы, путь должен существовать на каждом узле swarm. Планировщик режима Docker swarm может планировать контейнеры на любом компьютере, который отвечает требованиям доступности ресурсов и удовлетворяет всем указанным вами ограничениям и предпочтениям размещения.

  • Планировщик режима Docker swarm может перепланировать ваши запущенные сервисные контейнеры в любое время, если они станут неработоспособными или недоступными.

  • Монтирования с привязкой к хосту не переносимы. Когда вы используете монтирование с привязкой, нет гарантии, что ваше приложение будет работать так же, как и в процессе разработки.

Создавать сервисы с помощью шаблонов

Вы можете использовать шаблоны для некоторых флагов service create, используя синтаксис, предоставляемый пакетом текст/шаблон Go.

Поддерживаются следующие флаги:

  • --hostname

  • --mount

  • --env

Допустимые заполнители для шаблона Go:

Заполнитель

Описание

.Service.ID

Идентификатор службы

.Service.Name

Наименование услуги

.Service.Labels

Сервисные этикетки

.Node.ID

Идентификатор узла

.Node.Hostname

Имя хоста узла

.Task.Name

Название задачи

.Task.Slot

Слот задачи

Пример шаблона

В этом примере задается шаблон созданных контейнеров на основе имени службы и идентификатора узла, на котором запущен контейнер:

$ docker service create --name hosttempl \
                        --hostname="{{.Node.ID}}-{{.Service.Name}}"\
                         busybox top

Чтобы увидеть результат использования шаблона, используйте команды docker service ps и docker inspect.

$ docker service ps va8ew30grofhjoychbr6iot8c

ID            NAME         IMAGE                                                                                   NODE          DESIRED STATE  CURRENT STATE               ERROR  PORTS
wo41w8hg8qan  hosttempl.1  busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912  2e7a8a9c4da2  Running        Running about a minute ago
$ docker inspect --format="{{.Config.Hostname}}" hosttempl.1.wo41w8hg8qanxwjwsg4kxpprj

Узнать больше