Visitors have accessed this post 503 times.

Docker Swarm: знакомство

7
0
503
13 ноября 2020 9:42
Автор: Rebrain Me
Docker

Visitors have accessed this post 503 times.

Автор — Максим Рязанов

Всех приветствую! В этой статье я расскажу о Docker Swarm, его возможностях и основах взаимодействия с ним.

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

  • Построение кластера высокой доступности и управление кластером
  • Сервисы в Docker Swarm:
  1. Режимы Replicated и Global
  2. Файлы конфигурации и секреты
  3. Placements — места запуска
  • Docker Swarm. Stacks
  • Docker Swarm. Краткий разбор сети

Для примера будут использоваться три виртуальные машины под управлением Debian 10, развернутые на моем компьютере. Все команды, перечисленные в статье, будут выполняться от имени пользователя root, а управление виртуальными машинами — с помощью команд libvirt.

Эта статья подготовлена с использованием материалов c docs.docker.com и открытого практикума Rebrain Docker Swarm 09.04.2020.

Итак, что такое Docker Swarm и причем тут, собственно, рой (swarm — англ. рой)? В этом режиме Docker можно запустить контейнеры на нескольких хостах, объединив их в общем пуле вычислительных ресурсов. При этом наблюдать за контейнерами, распределять их и поднимать в случае необходимости будет сам Docker. По умолчанию docker swarm выключен.

Как создать кластер Docker-контейнеров с помощью Docker Swarm

Наше построение кластера начнем с изучения скромного количества понятий о кластере Docker Swarm. Как и в любом другом кластере, в кластере docker swarm должны быть ноды, из которых кластер и будет состоять. У нод в кластере может быть две роли:

  1. Роль worker: нода-исполнитель наших контейнеров, которые мы будем поднимать в кластере.
  2. Роль manager: обеспечивает управление кластером docker swarm. Как и worker, может выполнять запуск и работу контейнеров. Инициализация менеджера кластеров позволяет решить задачи:
  • поддержания состояния кластера;
  • планирования;
  • обслуживания конечных точек HTTP API в режиме Swarm.

Источник изображения — https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/

Приступим к знакомству на практике.

Для начала я разверну на своем компьютере виртуальные машины под управлением Debian 10 из заранее заготовленного шаблона с помощью libvirt. Libvirt — замечательный инструмент и помощник администратора виртуализации, который позволяет управлять множеством решений (поддерживает KVM, ESX, OpenVZ, lxc и т.д.) одними и теми же инструментами.

Развертка трех виртуальных машин будет состоять из трех последовательных команд:

virt-clone -o debian10template -n swr1 -f /storage/dataspace_sata/swr1.qcow2

virt-clone -o debian10template -n swr2 -f /storage/dataspace_sata/swr2.qcow2

virt-clone -o debian10template -n swr3 -f /storage/dataspace_sata/swr3.qcow2

В первой мы указываем утилите virt-clone взять за основу виртуальную машину debian10template, создать новую с именем swr1, в качестве файла диска для хранения данных скопировать существующий в /storage/dataspace_sata/swr1.qcow2. Остальные команды можно разобрать по аналогии.Для запуска используем следующие команды:

virsh start swr1

virsh start swr2

virsh start swr3

Далее я проверю IP-адреса, выданные этим виртуальным машинам. Они у меня находятся в изолированной локальной сети с именем locnet на хосте.

virsh net-dhcp-leases locnet

После на имеющемся у меня в сети powerdns сервере (с которым мы познакомились ранее в статье) я создам каждой ноде по доменному имени для удобства:

pdnsutil add-record rpulse.locnet swr1 A 600 192.168.100.86

pdnsutil add-record rpulse.locnet swr2 A 600 192.168.100.60

pdnsutil add-record rpulse.locnet swr3 A 600 192.168.100.40

pdnsutil rectify-zone rpulse.locnet

Затем выполним установку Docker Engine на эти три тестовые ноды, которые я буду использовать далее. Это можно сделать с помощью официальных инструкций для Ubuntu или Debian (они есть и для других дистрибутивов). Рекомендую ознакомиться с инструкцией под ваш дистрибутив, но для установки на 3 ноды сразу, абстрагируясь от дистрибутива, я подготовил универсальный playbook для ansible, который справится с установкой docker-ce из официального репозитория и на Debian, и на Ubuntu.

- name: Install Docker CE from official repo for supported versions of Debian or Ubuntu
  hosts: swr
  connection: local
  gather_facts: yes
  tasks:
  - name: Upgrade system
    apt:
      update_cache: yes
      upgrade: dist
  - name: Install pre-requrements
    apt:
      pkg:
      - apt-transport-https
      - ca-certificates
      - curl
      - software-properties-common
      - gnupg-agent
  - name: Add Docker GPG apt Key
    apt_key:
      url: https://download.docker.com/linux/{{ansible_distribution | lower | replace('"', "")}}/gpg
      state: present
  - name: Add Docker Repository
    apt_repository:
      repo: deb https://download.docker.com/linux/{{ansible_distribution | lower | replace('"', "")}} {{ansible_distribution_release | lower | replace('"', "")}} stable
      state: present
  - name: Install latest docker-ce
    apt:
      update_cache: yes
      pkg:
      - docker-ce
      - docker-ce-cli
      - containerd.io

Имейте в виду, что при развертке docker на VDS с публичными IP-адресами хорошей практикой настройка правил брандмауэра для разрешения трафика docker swarm (iptables, firewalld, ufw) на каждом сервере перед созданием кластера. Для успешного создания кластера необходимо, чтобы каждый VDS мог связаться друг с другом по следующим протоколам и портам:

  • TCP порт 2377 для обеспечения связи с целью управления кластером;
  • TCP и UDP порт 7946 для связи между нодами;
  • UDP порт 4789 для трафика overlay-сети.

Займемся наконец созданием swarm кластера.

Инициализация первого swarm manager-а:

docker swarm init --advertise-addr 192.168.16.86

Если advertise address не будет передан параметром, docker попытается определить адрес для использования самостоятельно. Если у вас более двух сетевых интерфейсов (не считая интерфейса-петли), укажите конкретный адрес, чтобы у вас с докером не возникло недопонимания.

После инициализации первого менеджера ниже увидим команду для подключения нод-воркеров в формате:

docker swarm join --token SWMTKN-1-24ksahgkdfjkgjlksfhgdfjkl... 192.168.16.86:2377

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

docker swarm join-token manager

Соответственно, для просмотра команды, которая позволит добавить еще одного воркера, выполним

docker swarm join-token worker

В демонстрационных целях все три ноды я сделаю менеджерами.

Команда ниже позволит посмотреть состояние кластера:

docker node ls

Я выполню эту команду на сервере swr2.rpulse.locnet, и мы разберем ее вывод:

ID                            HOSTNAME             STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION  
vshgjsytmp6e1zjm2zthvp1v2     swr1.rpulse.locnet   Ready               Active              Leader              19.03.12  
ft3m1g6rifmthcuurj6ocp1ii *   swr2.rpulse.locnet   Ready               Active              Reachable           19.03.12  
vf67frq4ee2bottzbcud8h19d     swr3.rpulse.locnet   Ready               Active              Reachable           19.03.12 

Все ноды готовы к обслуживанию (STATUS=Ready), доступны для выполнения на них контейнеров (AVAILABILITY=Active). Но лидером является только нода swr1.rpulse.locnet, в то время как остальные ноды просто доступны (MANAGER STATUS=Reacheble). Символом * отмечена нода, с которой мы выполнили команду.Команда

docker node update --availability drain swr1.rpulse.locnet

заставит ноду swr1.dev.rpulse.locnet не принимать на себя задачи по запуску и исполнению контейнеров (команду можно использовать для проведения техработ на ноде). При этом нода сохранит статус менеджера и продолжит выполнять соответствующие ее роли задачи.

Вернуть ноду к приему задач можно командой

docker node update --availability active swr1.rpulse.locnet

Docker Swarm Service

Что такое сервис в docker swarm? Попробую описать сущность сервиса в одном изображении.

Docker Swarm container — это изолированный процесс. В модели docker swarm каждая задача вызывает один контейнер. Задача аналогична «слоту», куда планировщик помещает контейнер. Когда контейнер активен, планировщик распознает, что задача находится в рабочем состоянии. Если контейнер не проходит проверку работоспособности или завершается, завершается и задача.

Режимы Replicated и Global

Существует два типа развертывания сервисов: replicated и global.

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

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

Давайте вновь перейдем к практике и потренируемся в деплое сервисов.

Команда

docker service create --name HelloWorld --replicas 2 alpine ping docker.com

создаст сервис HelloWorld из двух задач, контейнер базируется на образе alpine, где будет выполняться команда ping docker.com.

То же самое в расширенном режиме:

docker service create --name HelloWorld --mode replicated --replicas 2 alpine ping docker.com

Обе команды выше поднимают сервис в режиме replicated – в нем несколько задач может быть и на одной ноде, и на разных.

Осуществим запуск сервисов в docker swarm по 1 задаче на каждую ноду в кластере (в режиме global):

docker service create --name HelloWorld --mode global alpine ping docker.com

Команда

docker service ls

покажет нам состояние всех запущенных сервисов в кластере.

Команда

docker service logs HelloWorld

покажет нам логи сервисa.

Команда

docker service logs --tail=100 HelloWorld

покажет последние 100 записей из логов сервиса.

Если мы выводим ноду, на которой были запущены задачи сервиса, в режим drain, мы можем посмотреть, по каким нодам разъедутся задачи командой

docker service ps HelloWorld

Это актуально для режима replicated.

Команда

docker service update --replicas 5 HelloWorld

обновит сервис и запустит в нем больше задач в режиме replicated. При этом несколько задач может быть и на одной ноде, и на разных. Можно заскейлить обратно.

docker service update --replicas 2 HelloWorld

Команда

docker service rm HelloWorld

удаляет наш сервис.

Файлы конфигурации и секреты

Конфигурации и секреты хранятся на manager-е, и оттуда происходит их дистрибуция.

Команда

docker config create passwdfile /etc/passwd

создаст конфигурацию с именем passwdfile, которая будет осуществлять дистрибуцию файла /etc/passwd в контейнер.

Команда

docker config ls

покажет нам все созданные конфигурации.

Команда

docker secret create shadowfile /etc/shadow

создаст конфигурацию с именем shadowfile, хранящую sensitive данные.

Команда

docker secret ls

покажет нам все конфигурации с sensitive данными.

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

docker service create --name HelloWorld --replicas 1 --config passwdfile --secret shadow alpine ping docker.com

Посмотрим, на какой ноде запущен наш сервис:

docker service ps HelloWorld

Подключаемся к ноде и заходим в контейнер:

docker exec HelloWorld -it /bin/bash

Наш конфиг подмонтировался в /passwd. Наш secret подмонтировался в /var/run/secrets/shadow.

Placements — места запуска

docker node ls

покажет все ноды в кластере.

docker node inspect swr1.dev.rpulse.locnet

покажет информацию о ноде.

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

Посмотрим на примере — создадим две «площадки» с разными нодами, чтобы часть сервисов запускалась, скажем, на нодах, размещенных на площадке главного дата-центра (лейбл gdc), а другие — на резервной площадке (лейбл rp).

Предположим, что моя виртуальная машина swr1 размещена в главном дата-центре, а swr2 — на резервной площадке. Присвоим нодам лейблы.

docker node update --label-add placepoint=gdc swr1.rpulse.locnet

docker node update --label-add placepoint=rp swr2.rpulse.locnet

Мы можем добавить еще лейблов для каждой ноды:

docker node update --label-add env=prod swr1.dev.rpulse.locnet

docker node update --label-add env=dev swr1.dev.rpulse.locnet

docker node update --label-add env=dev swr2.dev.rpulse.locnet

Запустим наш сервис на dev площадке в главном дата-центре:

docker service create --name HelloWorld --replicas 5 --constraint node.labels.env==dev --constraint node.labels.place==gdc a

lpine ping docker.com
t8mupy3q3atv6rzk57c57ds6o  
overall progress: 5 out of 5 tasks   
1/5: running   [==================================================>]   
2/5: running   [==================================================>]   
3/5: running   [==================================================>]   
4/5: running   [==================================================>]   
5/5: running   [==================================================>]   
verify: Service converged

Сервис запущен. Проверим, запустился ли он там, где мы ожидали:

***Как говорится, где пруфы, Билли! Буквы каждый написать может, давай скрины!! Даю.***

docker service ps HelloWorld

Сервис не попал на резервную площадку. А давайте пустим его туда?

docker service update --constraint-rm node.labels.place==gdc HelloWorld


Задачам сервиса вполне уютно и на swr1 в gdc. Давайте заставим его оттуда уехать — переведем swr1 в «режим обслуживания»:

docker node update --availability drain swr1.rpulse.locnet

Задачи сервиса уехали на swr2, как и предполагалось. На скриншоте, сделанном сразу после вывода swr1 с приема задач, видно, что контейнеры еще подготавливаются. В скором времени сервис продолжит работу:

Ну и дабы набить руку, давайте все вернем взад!

docker node update --availability active swr1.rpulse.locnet

docker service update --constraint-add node.labels.place==gdc HelloWorld

docker service ps HelloWorld

Вот и вернулся наш сервер на площадку дата-центра.Но мы еще сломали не все, что можно! Давайте посмотрим, что будет, если наш лидер-менеджер с запущенными на нем задачами внезапно сломается.

Снова удалим label gdc или пересоздадим сервис, чтобы сервису было куда уехать. Я пересоздам для примера.

После чего принудительно завершим работу гостевой системы (виртуальной машины) swr1.rpulse.locnet, это симулирует ситуацию аварийного завершения.

C помощью libvirt «убиваем» наповал swr1:

virsh destroy swr1

Смотрим на сервис и кластер:

Во-первых, команда docker node ls показывает, что swr1 находится в статусе Unreachable (недоступен), а leader-ом стал swr3.

Вывод второй команды docker service ps HelloWorld показывает, что задачи 1 и 4 после пересоздания до симуляции падения лидера были запущены на swr2, так как он имел соответствующий label, а вот задачи 2, 3 и 5, запущенные изначально на swr1, переехали на swr2.

Поднимем обратно swr1 командой

virsh start swr1

Посмотрим, как там теперь обстоят дела.

swr1 стал доступен, но лидером остался swr3. Часть задач вернулись обратно на swr1.

Перед переездом команда задачи завершились с кодом 255 — и это нормально. Как правило, программы возвращают код -1 в случае аварийного завершения. По стандартам POSIX, наша оболочка имеет 256 значений поддерживаемых кодов возврата и возвращает нам код 255 тогда, когда был получен код, который не попадает в диапазон от 0 до 255. Код -1 в этот диапазон не попадает.

Docker Swarm. Stack


Файл формата docker-compose описывается для деплоя через docker stack, чтобы запустить несколько сервисов и управлять ими не как отдельными сервисами, а как единой системой в рамках одного стека. Проще говоря, в одном файле мы описываем все сервисы, необходимые для работы нашего приложения.

version: '3.2' 
services: 
  agent: 
    image: portainer/agent 
    volumes: 
      - /var/run/docker.sock:/var/run/docker.sock 
      - /var/lib/docker/volumes:/var/lib/docker/volumes 
    networks: 
      - agent_network 
    deploy: 
      mode: global 
      placement: 
        constraints: [node.platform.os == linux] 
 
  portainer: 
    image: portainer/portainer 
    command: -H tcp://portainer_agent:9001 --tlsskipverify 
    ports: 
      - "9000:9000" 
      - "8000:8000" 
    volumes: 
      - portainer_data:/data 
    networks: 
      - agent_network 
    deploy: 
      mode: replicated 
      replicas: 1 
      placement: 
        constraints: [node.role == manager] 

networks: 
  agent_network: 
    driver: overlay 
    attachable: true 

volumes: 
  portainer_data:

В данном стеке portainer присутствуют сервисы agent и portainer. Мы также описали здесь сеть и том.Для запуска стека portainer:

docker stack deploy -c ./portainer.yml portainer

где ./portainer.yml — путь до файла c конфигом portainer — имя стека.

Docker Swarm. Краткий разбор сети

Network host

Используется для открытия порта в пространстве имен (namespace) хоста:

docker service create --name HelloWorld --mode global -p published=2224,target=22,mode=host containous/whoami

Ключ -p = —publish (порт)

Host

Запускает контейнер, вынося всю сеть контейнера в пространство имен хоста.

docker service create --name HelloWorld --mode global --network host containous/whoami

Routing Mesh

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

docker service create --name HelloWorld --replicas 1 -p published=9000,target=80 containous/whoami # ingress port 9000

Routing Mesh Technologies — построены на:

  • IPTABLES
  • IPVS
  • Bridge
  • VXLAN


Cеть overlay в рамках swarm позволит создать внутреннюю сеть для контейнеров и опубликовать какой-либо порт на основе Routing mesh.

Хотите продолжить более подробный разбор полученных сегодня материалов с примерами? Обязательно отметьте свою заинтересованность и нажмите лайк слева от статьи. И до встречи в следующей части!

От редакции

Если вам интересно посещать бесплатные онлайн-мероприятия по DevOps, Kubernetes, Docker, GitlabCI и др. и задавать вопросы в режиме реального времени, подключайтесь к каналу DevOps by REBRAIN

*Анонсы мероприятий каждую неделю

Практикумы для специалистов по инфраструктуре и разработчиков — https://rebrainme.com.

Наш Youtube-канал — https://www.youtube.com/channel/UC6uIx64IFKMVmj12gKtSgBQ.

Агентство Fevlake, проектируем и поддерживаем IT-инфраструктуры с 2012 года — https://fevlake.com.

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

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

Лучшие книги по DevOps
array(1) { [0]=> object(WP_Term)#11157 (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(12) ["filter"]=> string(3) "raw" ["cat_ID"]=> int(7) ["category_count"]=> int(12) ["category_description"]=> string(0) "" ["cat_name"]=> string(6) "DevOps" ["category_nicename"]=> string(6) "devops" ["category_parent"]=> int(0) } } DevOps

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

1
0
25 мая 2020
Базовая работа с nix. Каналы
array(1) { [0]=> object(WP_Term)#10580 (16) { ["term_id"]=> int(6) ["name"]=> string(5) "Linux" ["slug"]=> string(5) "linux" ["term_group"]=> int(0) ["term_taxonomy_id"]=> int(6) ["taxonomy"]=> string(8) "category" ["description"]=> string(0) "" ["parent"]=> int(0) ["count"]=> int(23) ["filter"]=> string(3) "raw" ["cat_ID"]=> int(6) ["category_count"]=> int(23) ["category_description"]=> string(0) "" ["cat_name"]=> string(5) "Linux" ["category_nicename"]=> string(5) "linux" ["category_parent"]=> int(0) } } Linux

Автор — Юрий Изоркин

В предыдущей статье мы познакомились с ОС NixOS. Теперь рассмотрим возможности пакетного менеджера nix. Источником обновления пакетов для менеджера nix служат каналы.

Применение каналов позволяет:

зафиксировать ПО на определенной версии;
использовать устаревшее ПО, например, если какие-либо скрипты не...

1
0
27 ноября 2020
Обзор Kali Linux
array(1) { [0]=> object(WP_Term)#11155 (16) { ["term_id"]=> int(6) ["name"]=> string(5) "Linux" ["slug"]=> string(5) "linux" ["term_group"]=> int(0) ["term_taxonomy_id"]=> int(6) ["taxonomy"]=> string(8) "category" ["description"]=> string(0) "" ["parent"]=> int(0) ["count"]=> int(23) ["filter"]=> string(3) "raw" ["cat_ID"]=> int(6) ["category_count"]=> int(23) ["category_description"]=> string(0) "" ["cat_name"]=> string(5) "Linux" ["category_nicename"]=> string(5) "linux" ["category_parent"]=> int(0) } } Linux

Kali Linux – достаточно узкоспециализированный дистрибутив, платформа для тестирования на проникновения, созданная для проверки безопасности ИТ-систем. Он реализуется как проект с открытым кодом при финансировании компании Offensive Security, которая занимается обучением и предоставлением услуг по информационной защите.
Как появился и развивался...

1
0
25 мая 2020