Группа central на нескольких серверах¶
Резервирование объясняет, из чего состоит инсталляция с резервом и что меняет второй инстанс. Эта страница — про то, как её собрать: какие настройки задать каждой машине, что написать стримерам и что проверить, когда всё поднялось.
Здесь описан парк из независимых серверов — по машине на инстанс. Попробовать то же самое на одном ноутбуке, не арендуя серверов, можно по практикуму в Docker: там та же группа собирается из контейнеров за несколько минут.
Что именно разворачивается¶
Инсталляция с резервом состоит из четырёх частей, и только одна из них — сама Catena:
- Один кластер PostgreSQL, доступный всем инстансам по одному адресу. Это единственное хранилище состояния и единственная часть, отказоустойчивость которой Catena на себя не берёт.
- Два и более инстанса central — отдельные машины с одинаковым конфигом, отличающиеся ролями и объявленным адресом.
- Стримеры — отдельные машины, которым задан не адрес одного инстанса, а список адресов группы.
- Точка входа оператора — один адрес, за которым живой инстанс: DNS-имя с переключением или балансировщик.
Правило, с которого начинается такая инсталляция: central и вещание живут на разных машинах. Локальный стример внутри процесса central здесь не годится — он разделяет судьбу процесса, и его стримы падают вместе с управлением.
Сколько чего нужно¶
| Часть | Сколько | Замечание |
|---|---|---|
| PostgreSQL | Один логический кластер | Два независимых сервера базы — это две разные инсталляции, а не резерв |
| Инстансы central | Два и больше | Третий добавляется тем же конфигом; переписывать существующие не нужно |
| Стримеры | Сколько требует эфир | Резервируются не здесь, а размещением |
| Точка входа оператора | Один адрес | Стримеры через него не ходят |
Конфиг инстанса central¶
Инстансы группы отличаются друг от друга ровно двумя строками — объявленным адресом и набором ролей. Всё остальное у них одинаково, включая строку подключения к базе.
Первый инстанс:
listeners:
http:
- port: 80
central:
database_url: postgres://central:пароль@db.example.com:5432/central
admin_keys:
- ключ-управления
roles: [run, migrate, layouter, stats]
advertise_url: http://central-a.example.com
api_auth:
login: admin
password: пароль-оператора
Второй — то же самое без роли migrate и со своим адресом:
central:
database_url: postgres://central:пароль@db.example.com:5432/central
admin_keys:
- ключ-управления
roles: [run, layouter, stats]
advertise_url: http://central-b.example.com
Роли — это притязания, а не назначения¶
Роль в конфиге означает «эта машина готова делать такую работу», а не «эта машина её делает». Кто из инстансов действительно исполняет работу, решает PostgreSQL, а не конфиг, — поэтому layouter и stats заявлены у обоих, и это не ошибка и не двойной запуск.
run— обслуживать запросы: консоль, management API, приём синхронизации со стримеров, выдачу метрик. Нужна каждому инстансу.migrate— накатить миграции схемы при старте.layouter— исполнять прогоны размещения.stats— держать картину «прямо сейчас» по всему кластеру.
Единственная роль, которую нельзя оставлять у всех, — migrate. Она не защищена мандатом: два процесса, стартовавшие одновременно, погонят миграции наперегонки. Поэтому схему накатывает один инстанс, а остальные стартуют после него.
Это же — причина не оставлять roles пустым на втором инстансе: пустой список означает не «никаких ролей», а все четыре, включая migrate.
Объявленный адрес¶
advertise_url — адрес, по которому до этой машины достучатся соседи по группе. Он нужен потому, что картину «прямо сейчас» держит один инстанс, а остальные ходят к ней по сети: держатель записывает свой адрес, соседи читают его оттуда.
Адрес балансировщика здесь не годится — он привёл бы соседа к самому себе. Адрес обязан быть адресом конкретной машины.
Настройку можно и не задавать: инстанс без объявленного адреса полноценно работает и даже может держать картину — но соседи до неё не дойдут и скажут об этом в лог. В консоли такая строка помечена отдельно, см. проверку после развёртывания.
Лицензия¶
Лицензия нужна каждому процессу central, а не одному на группу: без неё процесс не стартует вовсе. Ключ и объявленный продукт у инстансов одинаковые.
Кто что исполняет: мандаты¶
Работу, дубль которой вреден, в группе исполняет один инстанс — тот, который взял на неё мандат. Мандат живёт в PostgreSQL и выдаётся на отдельном соединении, поэтому гибель процесса освобождает его сама, без разбора зависших исполнителей по таймаутам: сессия умерла — мандат свободен.
Мандатов несколько, и они независимы. Единого лидера у central нет: layouter и stats могут оказаться на разных машинах, и это штатное состояние, а не перекос.
У каждой выдачи есть номер — эпоха. Она растёт при смене держателя и едет вместе с каждой записью: инстанс, очнувшийся после паузы уже не держателем, получает отказ на записи, а не портит размещение задним числом. Поэтому переход мандата безопасен и не требует ручного подтверждения.
Смена держателя занимает секунды — столько, сколько нужно PostgreSQL, чтобы заметить смерть сессии, а соседу — чтобы прийти за освободившимся мандатом.
Инстанс, не держащий ничего, — не запасной и не спящий: он полноценно обслуживает консоль, API и синхронизацию стримеров. Мандат касается только фоновой работы.
Конфиг стримера¶
Стример обращается к группе, а не к процессу, поэтому в его конфиге список адресов:
managed_by:
name: streamer-01
url:
- http://central-a.example.com
- http://central-b.example.com
join_token: токен-присоединения
Порядок в списке — это стартовое предпочтение, а не постоянная привязка. Стример держится текущего адреса, пока тот отвечает, и переходит к следующему после неудавшегося запроса. Обратно он сам не возвращается: пока новый адрес отвечает, менять его незачем, а перебор ради равномерности только размазал бы машину по группе.
Второй адрес обязателен, а не желателен. Разрыв петли синхронизации — единственный признак живости стримера, который есть у central. Стример, оставшийся без единственного адреса, через полторы минуты числится offline, после чего лейаутер честно уводит его стримы на другую машину — с живой и вещающей. Смерть одного инстанса управления превращается в переезд половины эфира.
Список удобно поделить по половинам парка: одной половине первым адресом задать первый инстанс, другой — второй. Тогда в спокойном состоянии нагрузка приёма синхронизации распределена, а при гибели любого инстанса на второй адрес уходит только его половина.
Точка входа оператора¶
Оператору нужен один адрес, который сам находит живой инстанс: DNS-имя с переключением или балансировщик перед группой. Состояния у обработчика запросов своего нет, поэтому на запрос оператора отвечает любой инстанс.
Стримеры через эту точку ходить не должны: у них свой список адресов, а лишний посредник на пути синхронизации только добавит точку отказа.
Порядок развёртывания¶
- Поднять PostgreSQL и создать базу.
- Запустить первый инстанс — тот, у которого есть роль
migrate. Дождаться, пока он ответит на запросы: схема накатывается до готовности. - Запустить остальные инстансы.
- Открыть окно присоединения и завести стримеры, задав каждому список адресов группы.
- Направить точку входа оператора на группу.
Пакет на машинах инстансов — catena-base, тот же, что и на стримерах: на вопрос установки о существующем PostgreSQL называется адрес общей базы, а роли и объявленный адрес задаются конфигом выше. Пакет catena здесь не нужен — он заводит базу на своей же машине, а группе она нужна отдельно от инстансов.
Порядок важен только на первом шаге: остальные инстансы не поднимутся раньше схемы, а стримеры не присоединятся раньше живого central.
Что проверить после развёртывания¶
Всё, что нужно посмотреть, лежит в консоли в разделе Кластер → Central.
- В таблице столько строк, сколько инстансов. Строка появляется через секунды после старта. Не появилась — инстанс не дошёл до базы.
- У каждой строки заполнен «Объявленный адрес». Пометка «не объявлен» означает, что соседи до этого инстанса не дойдут: ему не задан
advertise_url. - Столбец «Притязания» показывает заявленные роли. Убедитесь, что
migrateзаявлен ровно у одного. - Столбец «Держит мандаты» непустой хотя бы у одного инстанса. Пусто у всех — значит, ни один не заявил ролей
layouterиstats, и ни размещения, ни картины «прямо сейчас» в группе нет. - Столбец «Сборка» одинаков у всех строк. Разные версии в группе — штатное состояние только на время обновления.
- Раздел «Стримеры» показывает весь парк с любого инстанса. Половина парка, видимая с одного адреса, и другая половина — с другого, означают, что инстансы не видят картину друг друга: проверьте
advertise_url.
Проверять переключение руками не нужно и не стоит на работающей инсталляции — для этого есть практикум на одноразовом стенде.
Чего эта схема не делает¶
- Не резервирует базу. Отказоустойчивость PostgreSQL — задача самой базы: реплика с переключением или управляемый инстанс провайдера.
- Не заменяет бэкап. Резерв защищает от потери машины, но не от ошибочного удаления — см. Бэкап и восстановление.
- Не касается эфира. Стримы вещают и пишут архив без central; резервируется только управление, см. Автономия стримера.