angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

От Docker-Composer к Docker Swarm: Configs

Docker Configs давайте Docker Swarm управлять нашей (статической) конфигурацией, хранение на общем томе не требуется.

29 августа 2023 Обновленный 29 августа 2023
В Docker
post main image

У вас есть приложение, состоящее из нескольких проектов Docker-Compose, и вы используете Docker-Compose для сборки, запуска и развертывания.

Теперь вы хотите сделать еще один шаг вперед и переместить некоторые из проектов Docker-Compose на другой сервер. Наиболее очевидным выбором для этого, который стоит попробовать в первую очередь, является Docker Swarm. Вы изучаете еще несколько команд Docker - и все готово. Действительно ли это так просто?

Предупреждение о спойлерах. Нет, это не так просто, если у вас есть контейнеры, использующие тома, например, для конфигурационных данных, высокопроизводительных данных, постоянных данных. Многие примеры в Интернете полностью обходят этот вопрос, либо вскользь упоминают об использовании общих хранилищ типа NFS (без шифрования) или GlusterFS, либо используют решения для хранения от облачных провайдеров. Все эти решения имеют одну и ту же особенность: Они работают по сети и очень медленны по сравнению с собственным хранилищем. Да, можно работать быстрее, но за это придется платить больше.

Прежде чем рассматривать Docker Swarm, я рекомендую прочитать об этом вопросе, чтобы понять, подходит ли ваш сценарий использования для Docker Swarm. Например, вот обсуждение этого вопроса, 'Data(base) persistence in docker swarm mode', см. ссылки ниже. А из этого Stackoverflow ответ "How does Docker Swarm implement volume sharing?", см. ссылки ниже:

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

Это означает, что можно подготовить структуру каталогов на рабочем узле и обеспечить запуск контейнера только на этом узле с помощью параметров deploy placement. Параметры ...

В этом посте мы используем Docker Swarm Configs для передачи (статических) конфигурационных данных контейнерам на рабочих узлах. Это немного антипаттерн, но хорошо то, что мы устраняем необходимость в хранении данных.

Как обычно, я работаю на Ubuntu 22.04. В данный момент я не использую Docker Desktop. Я использовал VirtualBox для создания Ubuntu сервера VM и использования его в качестве рабочего.

Docker Swarm не управляет данными тома!

Docker Swarm - это менеджер сервисов, а сервисы - это контейнеры (основанные на images), а не объемные данные. Это означает, что вы должны сами управлять данными тома.

В качестве примера рассмотрим контейнер DSN-сервера. По умолчанию он подключается к DNS-сервису A в Интернете, никаких внешних данных здесь нет. С помощью Docker Swarm мы можем развернуть этот контейнер, указать реплики, все просто.

Теперь мы хотим, чтобы тот же контейнер DSN-сервера подключался к DNS-сервису B в Интернете. Следуем инструкциям сопровождающего контейнера, создаем два (конфигурационных) файла, создаем сопоставление томов, и готово.

Часть файла Docker-Compose:

...
services:

  dns_service:
    image: ...
    volumes:
      - ./config/definitions1.conf:/opt/dns_server/config/definitions1.conf:ro
      - ./config/definitions2.conf:/opt/dns_server/config/definitions2.conf:ro
    ...

Но теперь у нас возникла проблема с Docker Swarm , поскольку он не управляет данными нашего тома! Если мы развернем службу на рабочем узле, то данных, конфигурационных файлов, там не будет!

'Запекание' конфигурационных данных в службу

При использовании Docker Swarm у нас нет данных в наших томах... если мы ничего не делаем. Существует способ обойти это, называемый 'Configs', недоступный в Docker-Compose. Мы можем использовать его для указания файлов, которые будут монтироваться в контейнер, подобно тому, как это делается с томами. Сначала мы рассмотрим решение Docker-Compose, а затем изменим его на Docker Swarm.

Использование Docker-Compose

При использовании Docker-Compose файл 'docker-compose.yml' для нашего проекта DNS-сервера, см. выше,
использует тома и выглядит примерно так:

# docker-compose.yml, using volumes

version: '3.7' 

services:
  app:
    image: busybox_volumes
    build: .
    volumes:
      - ./config/definitions1.conf:/opt/dns_server/config/definitions1.conf:ro
      - ./config/definitions2.conf:/opt/dns_server/config/definitions2.conf:ro
    command: sh -c "ls -l /opt/dns_server/config && cat /opt/dns_server/config/definitions*.conf && tail -f /dev/null"

Добавляем 'Dockerfile':

# Dockerfile
FROM busybox

И собираем образ:

docker-compose build

И запускаем его:

docker-compose up

На экран выводится текст:

app_1  | total 8
app_1  | -rw-rw-r--    1 1000     1000            14 Aug 29 08:06 definitions1.conf
app_1  | -rw-rw-r--    1 1000     1000            14 Aug 29 08:06 definitions2.conf
app_1  | definitions=1
app_1  | definitions=2

Как и ожидалось. Но если Docker Swarm развернет этот сервис на другом узле, рабочем, то наши файлы будут отсутствовать.

Использование Docker Swarm

Здесь мы удалим секцию 'volumes' и добавим новую секцию 'configs' :

# docker-compose.yml, using configs

version: '3.7' 

services:
  app:
    image: busybox_configs
    build: .
    configs:
      - source: definitions1
        target: /opt/dns_server/config/definitions1.conf
      - source: definitions2
        target: /opt/dns_server/config/definitions2.conf
    command: sh -c "ls -l /opt/dns_server/config && cat /opt/dns_server/config/definitions*.conf && tail -f /dev/null"

configs:
  definitions1:
    file: ./config/definitions1.conf
  definitions2:
    file: ./config/definitions2.conf

Собираем образ:

docker-compose build

И затем выполняем развертывание:

docker stack deploy -c docker-compose.yml configs

Результат команды deploy показывает создание 'configs':

Creating network configs_default
Creating config configs_definitions2
Creating config configs_definitions1
Creating service configs_app

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

docker service logs configs_app

Результат:

configs_app.1.vqumgq21leq8@myra    | total 8
configs_app.1.vqumgq21leq8@myra    | -r--r--r--    1 root     root            14 Aug 29 09:58 definitions1.conf
configs_app.1.vqumgq21leq8@myra    | -r--r--r--    1 root     root            14 Aug 29 09:58 definitions2.conf
configs_app.1.vqumgq21leq8@myra    | definitions=1
configs_app.1.vqumgq21leq8@myra    | definitions=2

Это означает, что менеджер Docker Swarm правильно добавил наши файлы.

В моем случае служба была развернута на узле менеджера Docker Swarm , а не на рабочем узле. Чтобы запустить его на рабочем узле, добавим в файл 'docker-compose.yml' следующее:

    deploy:
      placement:
        constraints:
          - node.role == worker
      replicas: 1

Пометить образ и поместить его в реестр Docker .

Только если вы используете частный реестр

Если вы используете частный, небезопасный реестр, вы должны сообщить всем узлам Docker , что он небезопасен, добавив эту информацию:

{
    "insecure-registries":[
        "<your registry ip address>:<your registry port>"
    ],
}

в файл:

/etc/docker/daemon.json

После этого перезапустите Docker :

sudo systemctl restart docker

Важно: это необходимо сделать на всех узлах.

Теперь отредактируйте файл 'docker-compose.yml', чтобы указать Docker Swarm , где он может получить ваш образ.

From:

...
services:
  app:
    image: busybox_configs:latest
    ...

To:

...
services:
  app:
    image: <registry host>:<registry port>/busybox_configs:latest
    ...

Разверните службу на рабочем узле

Удалите службу с этого узла, если она еще там находится:

docker stack rm configs_app

И разверните снова:

docker stack deploy -c docker-compose.yml configs

Теперь можно проверить, что служба запущена на рабочем узле:

docker service ps configs_app

Результат содержит узел, см. 'NODE':

ID             NAME            IMAGE     NODE         DESIRED STATE   CURRENT STATE           ERROR     PORTS
xotczxp65lub   configs_app.1   ...       vmubs2204a   Running         Running 9 minutes ago             

Более подробную информацию можно получить, например, с помощью команды:

docker service inspect --pretty configs_app

И самое главное, что же конкретно сделал наш сервис? На экран ничего не выводится, надо смотреть логи:

docker service logs configs_app

Результат точно такой же, как и раньше. Это означает, что Docker Swarm не только развернул наш сервис (контейнер), но и сделал наши файлы 'configs' доступными для нашего контейнера, запущенного на рабочем узле. Готово.

Резюме

В этой заметке мы использовали Docker Configs для передачи контейнерам (статических) конфигурационных данных. В файле 'docker-compose.yml' мы удалили секцию 'volumes' и заменили ее на секцию 'configs' . Теперь Docker Swarm управляет этими данными, и нам не нужен для этого общий том хранения. Неприятным моментом является то, что 'configs' не работает в Docker-Compose, что означает уход от единого 'docker-compose.yml', который может быть использован Docker-Compose и Docker Swarm.

Ссылки / кредиты

Data(base) persistence in docker swarm mode
https://forums.docker.com/t/data-base-persistence-in-docker-swarm-mode/20665

Deploy a stack to a swarm
https://docs.docker.com/engine/swarm/stack-deploy

Docker - configs
https://docs.docker.com/compose/compose-file/compose-file-v3/#configs

Docker Swarm Tutorial | Code Along | Zero to Hero under 1 Hour
https://takacsmark.com/docker-swarm-tutorial-for-beginners

How does Docker Swarm implement volume sharing?
https://stackoverflow.com/questions/47756029/how-does-docker-swarm-implement-volume-sharing

Подробнее

Docker Docker-compose

Оставить комментарий

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

Комментарии

Оставьте ответ

Ответьте анонимно или войдите в систему, чтобы ответить.