Visitors have accessed this post 9501 times.

Docker Swarm: практическое использование

4
2
9501
20 ноября 2020 9:37
Автор: Rebrain Me
Docker

Visitors have accessed this post 9501 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.

Комментарии (3)
Введено символов из возможных
Не отвечать
LavrovAP

Максим день добрый!
Попробовал повторить, и столкнулся с ошибкой.
При попытке задеплоить стек получаю ошибку «yaml: line 44: did not find expected ‘-‘ indicator»
Полагаю проблема в 44 и 46 стоке
— «traefik.http.routers.whoami.rule=Host(whoami.rpulse.locnet

не заэкранированы кавычки.
Как правильно исправить стоку?
Заранее спасибо

LavrovAP

извиняюсь не ту стоку указал
— «traefik.http.routers.whoami.rule=Host(whoami.rpulse.locnet

Вам также может понравится

7 шагов при выборе инструментов DevOps
array(1) { [0]=> object(WP_Term)#11569 (16) { ["term_id"]=> int(7) ["name"]=> string(6) "DevOps" ["slug"]=> string(6) "devops" ["term_group"]=> int(0) ["term_taxonomy_id"]=> int(7) ["taxonomy"]=> string(8) "category" ["description"]=> string(0) "" ["parent"]=> int(0) ["count"]=> int(19) ["filter"]=> string(3) "raw" ["cat_ID"]=> int(7) ["category_count"]=> int(19) ["category_description"]=> string(0) "" ["cat_name"]=> string(6) "DevOps" ["category_nicename"]=> string(6) "devops" ["category_parent"]=> int(0) } } DevOps

Перевод статьи — https://techbeacon.com/devops/7-steps-choosing-right-devops-tools

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

Почему? Количество и типы проблем сильно разнятся между собой. Типы процессов и инструментов, а также...

0
0
26 февраля 2021
Руководство по DevOps для начинающих: как попасть в IT-индустрию
array(1) { [0]=> object(WP_Term)#10975 (16) { ["term_id"]=> int(7) ["name"]=> string(6) "DevOps" ["slug"]=> string(6) "devops" ["term_group"]=> int(0) ["term_taxonomy_id"]=> int(7) ["taxonomy"]=> string(8) "category" ["description"]=> string(0) "" ["parent"]=> int(0) ["count"]=> int(19) ["filter"]=> string(3) "raw" ["cat_ID"]=> int(7) ["category_count"]=> int(19) ["category_description"]=> string(0) "" ["cat_name"]=> string(6) "DevOps" ["category_nicename"]=> string(6) "devops" ["category_parent"]=> int(0) } } DevOps

Перевод статьи — https://medium.com/slalom-build/beginners-guid-to-devops-how-to-make-it-into-the-industry-c1652d59807

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

8
0
25 декабря 2020
Команды Docker, которые вам точно пригодятся
array(1) { [0]=> object(WP_Term)#11568 (16) { ["term_id"]=> int(8) ["name"]=> string(6) "Docker" ["slug"]=> string(6) "docker" ["term_group"]=> int(0) ["term_taxonomy_id"]=> int(8) ["taxonomy"]=> string(8) "category" ["description"]=> string(0) "" ["parent"]=> int(0) ["count"]=> int(8) ["filter"]=> string(3) "raw" ["cat_ID"]=> int(8) ["category_count"]=> int(8) ["category_description"]=> string(0) "" ["cat_name"]=> string(6) "Docker" ["category_nicename"]=> string(6) "docker" ["category_parent"]=> int(0) } } Docker

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

8
2
23 октября 2020