Skip to content

Практикум: группа central в Docker

Резервирование объясняет, как устроена группа central, а Группа central на нескольких серверах — как её развернуть. Эта страница — про то, чтобы увидеть её работу своими глазами: на одной машине, из контейнеров, за десять минут и без единого арендованного сервера.

Стенд одноразовый. На нём можно и нужно делать то, чего не делают на работающей инсталляции: гасить процессы посреди работы и смотреть, что из этого выйдет.

Что понадобится

  • Docker с compose — больше ничего ставить не нужно.
  • Ключ лицензии. Он нужен каждому процессу: и обоим central, и обоим стримерам.
  • Образ с группой central. Практикуму нужна сборка, в консоли которой есть раздел Кластер → Central. Если раздела нет, образ старше группы central, и стенд не соберётся.
  • Свободные порты 8081 и 8082 на локальной машине.

Из чего собран стенд

Пять контейнеров:

  • postgres — одна база на всю группу.
  • central-a и central-b — два инстанса управления над этой базой, консоли на портах 8081 и 8082.
  • streamer-1 и streamer-2 — два стримера, разведённые по разным инстансам: первый ходит в central-a, второй — в central-b.

Разведение стримеров по инстансам — не украшение стенда, а его смысл. Картина «прямо сейчас» одна на всю группу, и весь парк обязан быть виден с любого из двух адресов, хотя отчитываются машины в разные.

Скачайте docker-compose.yaml и положите в пустой каталог. Ниже — те его куски, ради которых он написан; остальное в нём — обычная обвязка.

Первый инстанс заявляет все четыре роли, включая migrate:

central:
  admin_keys:
    - lab-admin-key
  roles: [run, migrate, layouter, stats]
  advertise_url: http://central-a

Второй — то же самое без migrate: схему накатывает один процесс, иначе два погонят миграции наперегонки.

central:
  admin_keys:
    - lab-admin-key
  roles: [run, layouter, stats]
  advertise_url: http://central-b

Роли layouter и stats заявлены у обоих, и это не двойной запуск: роль — притязание, а исполнителя выбирает мандат.

Стример получает не адрес инстанса, а список адресов группы; порядок — порядок предпочтения:

managed_by:
  name: streamer-1
  url:
    - http://central-a
    - http://central-b
  join_token: ${JOIN_TOKEN}

У второго стримера тот же список в обратном порядке.

Подъём

Стенд не собирается одним docker compose up: окно присоединения открывает живой central, и join-токен появляется только после его старта.

Сначала база и оба инстанса управления:

export CATENA_VERSION=latest
export LICENSE_KEY='ваш ключ'
docker compose up -d postgres central-a central-b

Дождитесь, пока консоль откроется на http://127.0.0.1:8081, и войдите как admin с паролем pass. При первом входе консоль попросит завести именную учётную запись — заведите.

Откройте Кластер → Стримеры, нажмите Разрешить присоединение и скопируйте join-токен. Поднимите стримеры с ним:

JOIN_TOKEN=jt-... docker compose up -d streamer-1 streamer-2

Обе машины появятся в списке стримеров за несколько секунд. Окно присоединения после этого закройте — парк собран.

Заведите несколько стримов, чтобы в кластере было что раскладывать. Вход syntetic — встроенный генератор, внешний источник стенду не нужен:

for i in 1 2 3 4 5 6; do
  curl -s -X PUT -H 'Authorization: Bearer lab-admin-key' \
    -H 'Content-Type: application/json' \
    -d '{"inputs":[{"syntetic":{}}]}' \
    "http://127.0.0.1:8081/central/api-v4/streams/configs/cam$i"
done

Группа целиком

Откройте Кластер → Central.

Инстансы central: притязания и мандаты

В таблице две строки — вся группа, и её одинаково показывает любой инстанс: реестр лежит в общей базе.

  • Притязания у обоих почти одинаковы: migrate заявлен только у central-a, всё остальное — у обеих машин.
  • Держит мандаты заполнено только у одной. Это и есть ответ на вопрос «кто в группе главный»: главного нет, есть держатели отдельных мандатов.
  • У второй строки написано нет — только обслуживает запросы. Такой инстанс не запасной и не спящий: он полноценно отвечает консоли, API и стримерам, просто фоновую работу сейчас делает не он.

На вашем стенде мандаты могут лежать иначе — оба у одной машины или по одному у каждой. Мандаты независимы, и их расстановка зависит от того, кто успел первым; неправильной расстановки здесь не бывает.

Парк виден с любого адреса

Не уходя с инстанса, откройте Кластер → Стримеры.

Оба стримера в эфире

Обе машины в эфире, хотя отчитывается в этот инстанс только одна из них. Вторая шлёт синхронизацию соседу, а видна здесь потому, что картина «прямо сейчас» одна на группу: инстанс без мандата stats ходит к ней по сети — по тому самому объявленному адресу.

Откройте ту же страницу на http://127.0.0.1:8082 — увидите то же самое. Это и есть проверка, ради которой стримеры разведены по разным инстансам.

Гасим держателя мандата

Теперь то, ради чего стенд одноразовый. Погасите инстанс, который держит мандаты, — на снимках выше это central-b:

docker compose stop central-b

Вернитесь на Кластер → Central живого инстанса и подождите несколько секунд.

Мандаты перешли, строка соседа погасла

Три вещи изменились:

  • Строка погашенного инстанса не исчезла, а помечена: «молчит — процесс, скорее всего, умер». Группа помнит свой состав, а не только живых.
  • Мандаты перешли к живому инстансу. Никто их не передавал: мандат живёт на отдельном соединении с PostgreSQL и освобождается вместе со смертью сессии, а сосед приходит за освободившимся сам.
  • Номер эпохи вырос. Он растёт при каждой смене держателя и едет вместе с каждой записью: инстанс, очнувшийся уже не держателем, получит отказ на записи, а не испортит размещение задним числом.

Переезд занимает секунды. Руками подтверждать его не нужно и нечем.

Эфир этого не заметил

Откройте Стримы.

Все стримы по-прежнему в эфире

Все шесть стримов идут. Половина из них живёт на стримере, который отчитывался в погашенный инстанс: он ушёл на второй адрес из своего списка за один неудавшийся запрос, и central даже не успел счесть его пропавшим.

Ровно из-за этого второй адрес в списке обязателен. Уберите его, повторите опыт — и через полторы минуты увидите, как лейаутер уводит стримы с живой машины, потому что она перестала подавать признаки жизни.

Возвращаем инстанс

docker compose start central-b

Строка снова загорается, но обратного переезда не происходит — и это не недоделка, а решение.

  • Мандаты остаются у живого инстанса. Отбирать их незачем: держатель работает, а смена держателя стоит новой инкарнации картины «прямо сейчас».
  • Стример остаётся на том адресе, куда ушёл. Пока адрес отвечает, менять его незачем; порядок в списке — стартовое предпочтение, а не постоянная привязка.

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

Убираем стенд

docker compose down -v

Ключ -v сносит и тома: база, состояние стримеров и их идентичность в кластере. Без него следующий подъём получит наполовину чужое состояние.

Чего этот стенд не показывает

  • Отказ базы. Здесь она одна и без реплики: погасите её — и управление встанет целиком, а эфир продолжится. Это правда, но резервирование базы — задача самой базы.
  • Сеть. Все контейнеры в одной docker-сети, потерь и задержек между ними нет.
  • Нагрузку. Шесть синтетических стримов не говорят ничего о том, как группа ведёт себя на настоящем парке.
  • Точку входа оператора. На стенде их две — по адресу на инстанс; в бою нужен один адрес с переключением.