Нататкі: ноды ў кластары Docker Swarm

Нататкі: ноды ў кластары Docker Swarm

Docker Swarm — гэта ўбудаваны аркестратар Docker аб'ядноўваючы некалькі сэрвероў у адзін кластар зь цэнтралізаваным кіраўніцтвам. Адна зь самых частых задач пры эксплуатацыі кластара — далучэньне і выдаленне нодаў. Разбярэм кожны крок падрабязна.

Тыпы нодаў у Swarm

У Docker Swarm ёсць два тыпы нодаў:

  • Manager — удзельнічае ў кіраванні кластарам (Raft consensus), можа выконваць каманды docker service, docker stack і гэтак далей. Таксама можа запускаць кантэйнеры (калі не абмежаваны).
  • Worker — толькі выконвае задачы (таскі), не мае доступу да кіравання кластарам.

Усе каманды кіравання кластарам выконваюцца на любой мэнэджар-нодзе.

Змяніць hostname перад далучэннем

Docker Swarm выкарыстоўвае hostname сэрверу як назву ноды. Калі ўсе сэрверы маюць аднолькавы дэфолтны hostname (напрыклад, ubuntu або localhost), гэта прывядзе да блытаніны.

Мяняем hostname да далучэння да кластара і дадаем радок да /etc/hosts (каб лакальнае імя рэзолвілася):

hostnamectl set-hostname host-endor
echo "127.0.1.1 host-endor" >> /etc/hosts

Змены ўступяць у сілу пасля перазапуску сесіі ці перазагрузкі. Пасля гэтага далучаемся да кластара — нода будзе адлюстравана з правільным іменем.

Калі нода ўжо ў кластары і трэба перайменаваць яе:

docker node update --label-add alias=new-name <NODE_ID>

Змяніць лэйбл (display label) ноды — НЕ мяняе фактычны hostname

Для рэальнага перайменавання — змяніць hostname на сэрверы і перазапусціць docker daemon:

hostnamectl set-hostname host-mustafar
systemctl restart docker

Ініцыялізацыя першага мэнэджара

Каб стварыць новы кластар, на першым сэрверы выконваем:

docker swarm init --advertise-addr <IP_АДРАС>

--advertise-addr — гэта IP, па якім іньшыя ноды будуць падключацца да гэтага мэнэджару. Выкарыстоўваецца зьнешні ці ўнутраны (адрас у прыватнай сетцы, дасяжны для ўсіх астатніх хастоў) сеткавы адрас сэрверу, а не 127.0.0.1.

Прасьцей за ўсё паглядзець адрас камандай

~$ hostname -I
21.127.43.17 172.18.0.1 172.17.0.1 2211:468:ccbb:dd77::1

Прыклад:

docker swarm init --advertise-addr 21.127.43.17

Пасля выканання каманды Docker вывядзе токен для далучэння воркераў і падказку, як атрымаць токен для даданьня дадатковых менеджараў:

Swarm initialized: current node (host-endor) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-xxx 21.127.43.17:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Цалкам магчымасьці каманды ініцыялізацыі выглядаюць так:

Usage:  docker swarm init [OPTIONS]

Initialize a swarm

Options:
      --advertise-addr string                  Advertised address (format: "<ip|interface>[:port]")
      --autolock                               Enable manager autolocking (requiring an unlock key to start a stopped manager)
      --availability string                    Availability of the node ("active", "pause", "drain") (default "active")
      --cert-expiry duration                   Validity period for node certificates (ns|us|ms|s|m|h) (default 2160h0m0s)
      --data-path-addr string                  Address or interface to use for data path traffic (format: "<ip|interface>")
      --data-path-port uint32                  Port number to use for data path traffic (1024 - 49151). If no value is set or is set to 0, the default port (4789) is used.
      --default-addr-pool ipNetSlice           default address pool in CIDR format (default [])
      --default-addr-pool-mask-length uint32   default address pool subnet mask length (default 24)
      --dispatcher-heartbeat duration          Dispatcher heartbeat period (ns|us|ms|s|m|h) (default 5s)
      --external-ca external-ca                Specifications of one or more certificate signing endpoints
      --force-new-cluster                      Force create a new cluster from current state
      --listen-addr node-addr                  Listen address (format: "<ip|interface>[:port]") (default 0.0.0.0:2377)
      --max-snapshots uint                     Number of additional Raft snapshots to retain
      --snapshot-interval uint                 Number of log entries between Raft snapshots (default 10000)
      --task-history-limit int                 Task history retention limit (default 5)

Порт 2377 — стандартны порт Swarm для міжнодавай камунікацыі. Яго трэба адкрыць у firewall паміж усімі нодамі.

📖 Дакументацыя: docker swarm init

Якія сеткавыя парты выкарыстоўвае Docker Swarm

Docker Swarm выкарыстоўвае тры парты для камунікацыі паміж нодамі. Важна разумець, якія з іх патрэбны толькі мэнэджарам, а якія — усім нодам без выключэння.

Порт 2377/TCP — кіраванне кластарам

Выкарыстоўваецца выключна для камунікацыі паміж мэнэджарамі і для далучэння новых нодаў (docker swarm join). Воркеры не камунікуюць па гэтым порце пасля далучэння.

  • Адкрыць толькі на мэнэджарах
  • Напрамак: усе ноды → мэнэджары

Для UFW:
ufw allow from 10.0.0.0/24 to any port 2377 proto tcp

Для iptables:

iptables -A INPUT -p tcp --dport 2377 -s 10.0.0.0/24 -j ACCEPT

Порт 7946/TCP і 7946/UDP — gossip-пратакол (discovery)

Выкарыстоўваецца для выяўлення нодаў і абмену станам кластара праз Serf gossip. Патрэбен усім нодам — і мэнэджарам, і воркерам.

  • Адкрыць на ўсіх нодах
  • Абодва пратаколы: TCP і UDP
  • Напрамак: двухбаковы, паміж усімі нодамі

Для UFW:
ufw allow from 10.0.0.0/24 to any port 7946 proto tcp
ufw allow from 10.0.0.0/24 to any port 7946 proto udp

Порт 4789/UDP — overlay-сеткі (VXLAN)

Выкарыстоўваецца для трафіку ўнутры overlay-сетак (docker network create --driver overlay). Патрэбен усім нодам, на якіх запускаюцца кантэйнеры з overlay-сеткамі.

  • Адкрыць на ўсіх нодах
  • Толькі UDP
  • Напрамак: двухбаковы, паміж усімі нодамі

Для UFW:
ufw allow from 10.0.0.0/24 to any port 4789 proto udp

Важна: порт 4789 выкарыстоўваецца ядром Linux для VXLAN-інкапсуляцыі. Калі сервер знаходзіцца за знешнім фаерволам (напрыклад, у хостэра), правілы трэба дадаваць і там.

Рэзюмэ:

2377: [TCP] Мэнэджары - Кіраванне кластарам, swarm join
7946 [TCP + UDP] Усе ноды - Gossip (выяўленне нодаў, стан кластара)
4789 [UDP] Усе ноды - Overlay-сеткі (VXLAN)

📖 Дакументацыя: firewall configuration for Docker Swarm

Калі ўсе ноды звязаны паміж сабой прыватнай сеткай — часам прасцей дазволіць увесь трафік унутры падсеткі замест адкрыцьця партоў паасобку. Але калі ноды раскіданы па розных сэрверах/правайдарах/датацэнтрах і зносіны адбываюцца паверх публічных сетак - правілы па партах абавязковыя.

Дадаць воркер ноду

На новым сэрверы выконваем каманду, якую выдаў swarm init (ці атрымоўваем яе зноўку на мэнэджары):

docker swarm join-token worker

Затым на новым сэрверы:

docker swarm join --token SWMTKN-1-xxx 21.127.43.17:2377

Пасля далучэння праверыць спіс нодаў можна на мэнэджэр хасце:

docker node ls

Вывад будзе прыкладна такім:

ID                          HOSTNAME       STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
l6dccl2z3gi8z2jnurssh5xr2*  host-endor     Ready     Active         Leader           28.5.2
ucx5iyh1orschlhnxe9n0ve45   host-tatooine  Ready     Active                          28.5.2

📖 Дакументацыя: docker swarm join

Дадаць дадатковы мэнэджар

Колькі мэнэджараў трэба і чаму

Docker Swarm выкарыстоўвае алгарытм Raft для дасягнення кансэнсусу ў кластары. Гэта азначае, што для прыняцця любога рашэння (разгортванне сэрвісу, змена канфігурацыі) патрэбна большасць мэнэджараў — кворум.

Формула кворуму: ⌊N/2⌋ + 1, дзе N — агульная колькасць мэнэджараў.

Колькасьць мэнэджэраў Кворум Дапушчальная страта
1 1 0
2 2 0
3 2 1
4 3 1
5 3 2
7 4 3

Рэкамендацыі:

  • 1 мэнэджар — для dev асяродку і тэставых стэндаў. Страта адзінага менеджара == страта кластара.
  • 3 мэнэджары — мінімум для prod асяродку. Кластар перажыве страту аднаго.
  • 5 мэнэджараў — добры выбар для буйных інсталяцый. Перажыве страту двух адначасова.
  • Больш за 7 — не рэкамендуецца. Накладныя выдаткі на Raft-камунікацыю расцуць, а надзейнасць ужо не павялічваецца значна.
Заўвага: Заўсёды выкарыстоўваць няцотную колькасць мэнэджэраў. 2 або 4 мэнэджары не даюць ніякай перавагі перад 1 і 3 адпаведна, але патрабуюць той жа кворум.

Кворум: чаму гэта важна

Кворум — гэта мінімальная колькасць мэнэджараў, якія павінны быць даступны, каб кластар мог прымаць рашэнні. Калі кворум губляецца:

  • Новыя сэрвісы не могуць быць разгорнуты.
  • Бягучыя сэрвісы працягваюць працаваць (таскі ужо запланаваны і выконваюцца воркерамі).
  • Ніякія змены канфігурацыі кластара немагчымы.
  • Каманды кшталту docker service update, docker stack deploy будуць вяртаць памылку.

Гэта значыць, калі з 3 мэнэджэраў 2 упалі — кластар "замарожваецца" у бягучым стане. Нічога нельга змяніць, пакуль не будзе адноўлены кворум.

Калі кворум усё ж страчаны і аднавіць мэнэджары немагчыма — ёсць аварыйная працэдура аднаўлення:

docker swarm init --force-new-cluster

ТОЛЬКІ ў аварыйнай сітуацыі — прымусовае аднаўленне кластара з аднаго вузла

📖 Дакументацыя: Raft кансэнсус і кворум

Далучэнне мэнэджэр-ноды

На бягучым мэнэджэры атрымоўваем токен:

docker swarm join-token manager

На новым сэрверы:

docker swarm join --token SWMTKN-1-yyy 21.127.43.17:2377

Даданне лэйбла (тэга) для новай ноды

Лэйблы выкарыстоўваюцца для прывязкі сэрвісаў да пэўных нодаў праз placement constraints. Напрыклад, базы дадзеных толькі на нодах з SSD, або фронтэнд толькі на нодах у пэўным датацэнтры.

# Дадаць лэйбл
docker node update --label-add role=database host-naboo

# Дадаць некалькі лэйблаў
docker node update --label-add dc=fra --label-add disk=ssd host-alderaan

# Паглядзець лэйблы ноды
docker node inspect --pretty node-endor

Выкарыстанне ў docker-compose.yml / стэку:

services:
  postgres:
    image: postgres:16
    deploy:
      placement:
        constraints:
          - node.labels.role == database

📖 Дакументацыя: node update

Выдаленне воркер-ноды з кластара

Выдаленне воркера — просты двухкрокавы працэс.

Крок 1: Перавесці ноду ў стан drain (усе таскі будуць перанесены на іньшыя ноды, выконваць на нодзе-мэнэджары):

docker node update --availability drain worker1

Пачакайце, пакуль усе кантэйнеры перамесцяцца на іньшыя ноды (паглядзець можна праз docker service ps <service-name>).

Крок 2: Выдаліць ноду з кластара:

docker swarm leave

Варыянт A: з самой ноды (перад выдаленнем з кластара)

docker node rm host-naboo
# або
docker node rm --force host-naboo

Варыянт B: прымусова з мэнэджару (калі нода недаступна)

Пасля docker swarm leave нода з'явіцца ў спісе са статусам Down. Яе трэба выдаліць з рэестру кластара:

docker node rm host-naboo

📖 Дакументацыя: docker node rm

Выдаленне мэнэджар-ноды з кластара

Выдаленне мэнэджару патрабуе дадатковай асцярожнасці, каб не страціць кворум.

Варыянт 1: Зніжэнне да воркера перад выдаленнем

Гэта самы бясьпечны спосаб:

docker node demote host-tatooine

Крок 1: Зніжаем мэнэджара да воркера

docker node update --availability drain host-tatooine

Крок 2: Далей як звычайны воркер

docker swarm leave

Крок 3: На самой выдаляемай нодзе

docker node rm host-tatooine

Крок 4: На адным зь застаўшыхся мэнэджэраў

Варыянт 2: Прамое выдаленне (калі нода недаступна)

docker node rm --force host-alderaan

Прымусовае выдаленне з мэнэджару

Перад выдаленнем мэнэджару заўсёды ўпэўніцеся, што кворум будзе захаваны. Калі маеце 3 мэнэджары і выдаляеце адзін — застаецца 2, кворум 2 з 2 — усё нармальна. Калі маеце 3 мэнэджары і хочаце выдаліць 2 — кластар страціць кворум.

📖 Дакументацыя: docker node demote


Калі лепей спачатку павысіць аднаго зь воркераў да мэнэджару

Ёсць сітуацыі, калі рэплейсмент мэнэджару правільней рабіць праз "спачатку дадаць, потым выдаліць":

  1. Міграцыя на новы сэрвер альбо выдаленьне хаста-мэнэджару цалкам

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

Правільны парадак:

docker node promote host-naboo

Крок 1: Для абранага воркеру падымаем узровень да мэнэджару

docker node ls

Крок 2: Пераконваемся, што былы воркер адлюстроўваецца ў сьпісе як мэнэджар

docker node demote host-endor
docker node update --availability drain host-endor
docker node rm host-endor

3. Толькі пасьля гэтага зьніжаем і выдаляем той, які зьбіраліся

  1. Колькасць мэнэджараў на мяжы кворуму (мінімальная). Калі маеце роўна 3 менеджары і хочаце замяніць адзін — спачатку дадайце 4-ы (хай часова колькасць парная), а потым выдаліце стары.
  2. Планавы перанос пры абнаўленні АС або міграцыі. Калі трэба зрабіць паслядоўную замену ўсіх нодаў (rolling replacement), не спыняючы кластар.
  3. Вы не ўпэўнены ў стане ноды. Калі мэнэджар паводзіць сябе дзіўна (памылкі Raft, нестабільнасць), лепей дадаць новы і толькі потым выдаліць праблемны.

Карысныя каманды для кіравання нодамі

docker node ls

Паглядзець усе ноды

docker node inspect host-tatooine --pretty

Падрабязная інфармацыя пра ноду

docker node ps host-naboo

Паглядзець таскі на пэўнай нодзе

docker node update --availability active host-mustafar

Зняць ноду з абслугоўвання (перавесці назад у Active)

docker swarm join-token worker
docker swarm join-token manager

Атрымаць токены для далучэння

docker swarm join-token --rotate worker
docker swarm join-token --rotate manager

Ратацыя токенаў (пры змене)


Кароткае рэзюмэ

Задача Каманда
Ініцыялізаваць кластар docker swarm init --advertise-addr <MANAGER_IP>
Далучыць воркера docker swarm join --token <WORKER_TOKEN> <MANAGER_IP>:2377
Далучыць мэнэджэра docker swarm join --token <MANAGER_TOKEN> <MANAGER_IP>:2377
Панізіць мэнэджэра да воркера docker node demote <NODE>
Павысіць воркера да мэнэджэра docker node promote <NODE>
Перавесці ў drain docker node update --availability drain <NODE>
Выдаліць ноду docker node rm <NODE>
Выйсці з кластара docker swarm leave
Дадаць лэйбл docker node update --label-add key=value <NODE>

Дадатковая дакументацыя