Docker Swarm: практическое использование
6
12760
20 ноября 2020 9:37
20/11/2020
Visitors have accessed this post 12760 times.
Автор — Максим Рязанов
Всех приветствую! В этой статье мы познакомимся с преимуществами overlay-сети, а также попрактикуемся с деплоем сервисов и приложений. Будет интересно!
Замечание к статье: для примера будут использоваться три виртуальные машины под управлением Debian 10, развернутые на моем компьютере. Все команды, перечисленные в статье, будут выполняться от имени пользователя root, а управление виртуальными машинами — с помощью команд libvirt.
Перед прочтением статьи рекомендую ознакомиться с предыдущей статьей про Docker Swarm.
Напомню условия: в моих примерах используется три ноды docker swarm, все с ролью менеджера и разрешением на запуск и исполнение контейнеров. В примере используется домен в локальной сети, настроенный на Powerdns, находящемся там же.
Я обещал рассмотреть overlay-сеть в docker swarm. А так как я очень люблю практические занятия, давайте рассмотрим ее работу на практике!
Практиковаться будем сразу с использованием docker stack, чтобы сократить количество шагов деплоя нашего сервиса. Возьмем за основу данный файл:
version: '3.2'
services:
postgres-server:
image: postgres:11-alpine
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: PostSwarm77
POSTGRES_DB: ryazanov
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- postgres-network
deploy:
mode: replicated
replicas: 1
networks:
postgres-network:
driver: overlay
attachable: true
volumes:
postgres-data:
В нем описан сервис postgres-server в блоке services, который будет основан на образе postgres:11-alpine, трафик, поступающий на порт 5432 любого хоста, в swarm будет перенаправляться в контейнер на порт 5432.Environment задаст переменные окружения, из которых Postgres получит данные конфигурации (пароль к пользователю БД postgres, имя базы данных, каталог хранения данных).
Volumes позволит пробросить для ноды локальный том postgres-data.
В deploy мы указываем режим replicated и одну реплику.
В networks создаем нашу overlay сеть, если она еще не создана. Указываем, что она может использоваться службами swarm или автономными контейнерами для связи с другими автономными контейнерами на других нодах docker (attachable).
Объявляем под networks в volumes том postgres-data. Он будет доступен с исполняемой ноды /var/lib/docker/volumes/.
Задеплоим стек первой командой.
docker stack deploy -c ./postgres-11.yml training
-c — путь до файла конфигурации стека.
Смотрим на результат.
docker stack ps training
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
npw3n4usnw8f training_postgres-server.1 postgres:11-alpine swr2.rpulse.locnet Running Running about a minute ago
У нас запустился сервис training_postgres-server на ноде swr2.rpulse.locnet.Теперь, чтобы объяснить преимущество overlay сети, я выполню подключение postgres клиентом через ноду swr3.rpulse.locnet и swr1.rpulse.locnet.
Итак, первое преимущество overlay сети заключается в том, что мы можем подключиться к контейнеру через любую ноду, несмотря на то, на какой ноде он работает фактически.
Мы также можем подключить к этой сети другой сервис, чтобы связать его внутри нее с уже существующим. Сервис может находиться вне стека. Можно даже воспользоваться standalone-контейнером (как я и сделаю в примере ниже). Главное, подключить его к сети (в нашем случае — postgres-network).
docker run -it --network training_postgres-network postgres:11-alpine psql -h training_postgres-server -U postgres -W
Обратите внимание, что аргументом для ключа -h (—host, к которому необходимо подключиться) я указал не внешний IP хоста и не внутренний IP работающего контейнера, а имя нашего сервиса training_postgres-server. У docker swarm есть своя реализация внутреннего DNS-сервера, которая создает для сервиса в сети DNS-имя = имени сервиса.
Таким образом, если вы захотите реализовать кластер не на уровне swarm, а на уровне сервисов — у вас есть такая возможность, благодаря реализации внутреннего DNS docker.
Создаем стек
Давайте попробуем еще кое-что интересное и приближенное к серьезному приложению. Мы создадим стек, в котором будет два сервиса: traefik и whoami.
version: "3.3"
services:
traefik:
image: traefik:v2.2
ports:
- "80:80"
- "8080:8080"
- "443:443"
command:
- --api.insecure=true
- --api.dashboard=true
- --api.debug=true
- --log.level=DEBUG
- --providers.docker=true
- --providers.docker.swarmMode=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=traefik_external
- --entrypoints.web.address=:80
- --entrypoints.web-secured.address=:443
- --providers.file.filename=/traefik.toml
volumes:
- cert:/ssl
- /var/run/docker.sock:/var/run/docker.sock
configs:
- traefik
networks:
- external
deploy:
mode: global
placement:
constraints: [node.role == manager]
whoami:
image:
containous/whoami
networks:
- external
deploy:
mode: replicated
replicas: 4
labels:
- "traefik.enable=true"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
- "traefik.http.routers.whoami.rule=Host(whoami.rpulse.locnet
)"
- "traefik.http.routers.whoami.entrypoints=web"
- "traefik.http.routers.whoami-https.rule=Host(whoami.rpulse.locnet
)"
- "traefik.http.routers.whoami-https.entrypoints=web-secured"
networks:
external:
driver: overlay
attachable: true
configs:
traefik:
file: traefik.toml
volumes:
cert:
Traefik будет запускаться в режиме global (на каждой ноде) с сетью external. В этой же сети будет находиться сервис whoami в режиме replicated, реплик будет 4. В Traefik будет проброшен docker.sock, через который будут просматриваться все сервисы в swarm. Когда traefik будет находить новый сервис и принадлежащие ему лейблы, начинающиеся на traefik., он будет их считывать и изменять свою конфигурацию динамически. В конфигурации будут указаны доменные имена. В зависимости от того, по какому доменному имени обратится клиент, traefik будет перенаправлять трафик в тот или иной контейнер. В этом примере traefik будет перенаправлять на контейнер whoami все запросы, которые придут по доменному имени whoami.rpulse.locnet.
Я также сделал volume certs и конфиг traefik, чтобы в будущем была возможность добавить wildcard-сертификат.
version: "3.3"
services:
traefik:
image: traefik:v2.2
ports:
- "80:80"
- "8080:8080"
- "443:443"
command:
- --api.insecure=true
- --api.dashboard=true
- --api.debug=true
- --log.level=DEBUG
- --providers.docker=true
- --providers.docker.swarmMode=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=traefik_external
- --entrypoints.web.address=:80
- --entrypoints.web-secured.address=:443
- --providers.file.filename=/traefik.toml
volumes:
- cert:/ssl
- /var/run/docker.sock:/var/run/docker.sock
configs:
- traefik
networks:
- external
deploy:
mode: global
placement:
constraints: [node.role == manager]
whoami:
image:
containous/whoami
networks:
- external
deploy:
mode: replicated
replicas: 4
labels:
- "traefik.enable=true"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
- "traefik.http.routers.whoami.rule=Host(whoami.rpulse.locnet
)"
- "traefik.http.routers.whoami.entrypoints=web"
- "traefik.http.routers.whoami-https.rule=Host(whoami.rpulse.locnet
)"
- "traefik.http.routers.whoami-https.entrypoints=web-secured"
networks:
external:
driver: overlay
attachable: true
configs:
traefik:
file: traefik.toml
volumes:
cert:
Деплоим сервис
docker stack deploy -c ./webapp.yml webapp
Заходим из браузера по адресу http://whoami.rpulse.locnet/
Увидим результат вроде этого:
Попробуйте пообновлять страницу. Наверняка, вы заметите, что hostname, ip, RemoteAddr и другие связанные параметры могут меняться. И это правильно — у нас есть 4 разных контейнера whoami на разных нодах и пара — на одной, а traefik запущен в режиме global — по экземпляру на каждой ноде. Между traefik community edition трафик в этом примере балансируется через DNS.
Балансировка на уровне traefik доступна, если не ошибаюсь, только в enterprise edition.
У меня настроена возможность входа в traefik на порту 8080. Я заранее создал записи swr.ryazanov.locnet, которые ссылаются на все мои ноды docker swarm также, как и домен выше.
Давайте сразу посмотрим на сервисы (Services -> Explore).
Мы увидим, что сервис whoami в docker присутствует в этом списке:
Самостоятельно зайдите в Routers. Вы увидите, что есть http router, перенаправляющий запросы на traefik.
Обратите внимание, что в моей версии whoami https отсутствует. Но настройка такова, что traefik будет пересылать все https запросы, полученные на порт 443, в тот же порт на сервис с тем же типом соединения (https).
Теперь, спроектировав приложение с микросервисной архитектурой, вы сможете самостоятельно развернуть его в кластере docker swarm.
На данный момент это все, что я хотел рассказать. Если вам понравилась серия статей по Docker Swarm, обязательно отметте свою признательность и нажмите лайк. Остались вопросы — задавайте в комментариях! Я и сообщество постараемся ответить.
От редакции
Если вам интересно посещать бесплатные онлайн-мероприятия по DevOps, Kubernetes, Docker, GitlabCI и др. и задавать вопросы в режиме реального времени, подключайтесь к каналу DevOps by REBRAIN.
*Анонсы мероприятий каждую неделю
Практикумы для специалистов по инфраструктуре и разработчиков — https://rebrainme.com.
Наш Youtube-канал — https://www.youtube.com/channel/UC6uIx64IFKMVmj12gKtSgBQ.
Агентство Fevlake, проектируем и поддерживаем IT-инфраструктуры с 2012 года — https://fevlake.com.
Максим день добрый!
Попробовал повторить, и столкнулся с ошибкой.
При попытке задеплоить стек получаю ошибку «yaml: line 44: did not find expected ‘-‘ indicator»
Полагаю проблема в 44 и 46 стоке
— «traefik.http.routers.whoami.rule=Host(
whoami.rpulse.locnet
)»не заэкранированы кавычки.
Как правильно исправить стоку?
Заранее спасибо
извиняюсь не ту стоку указал
— «traefik.http.routers.whoami.rule=Host(
whoami.rpulse.locnet
)»