Восстановление кластера ETCD - с примером

Материал из support.qbpro.ru
Версия от 15:43, 9 октября 2025; Vix (обсуждение | вклад) (Новая страница: «==ВВЕДЕНИЕ== * Предполагаем несколько аварийных ситуаций где используется ETCD + Patroni + PostgreSQL/PRO * В данной статье рассматривается решение проблем конкретно ETCD, а Patroni + PostgreSQL/PRO - являются сопутствующим ПО. * Данные которые хранит ETCD - используются дальше в Patroni...»)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)

ВВЕДЕНИЕ

  • Предполагаем несколько аварийных ситуаций где используется ETCD + Patroni + PostgreSQL/PRO
  • В данной статье рассматривается решение проблем конкретно ETCD, а Patroni + PostgreSQL/PRO - являются сопутствующим ПО.
  • Данные которые хранит ETCD - используются дальше в Patroni + PostgreSQL/PRO для обмена и взаимодействия между участниками кластера.
  • Схема стенда кластера:


ClusterPG.png

РАБОТА С ПРОБЛЕМАМИ

1. Пример: Потеря одного участника в кластере, база данных etcd испорчена, бакапа - нет.

  • На арбитре делаем запрос состояния кластера:
ETCDCTL_API=2 etcdctl cluster-health
    • Результат:
member c410a7d6456910ab is healthy: got healthy result from http://ptrcs1.local.int:2379
member e59a90ef17ed6871 is healthy: got healthy result from http://ptrpg1.local.int:2379
member '''edbaafd55c6a0b67''' is healthy: got healthy result from http://ptrpg2.local.int:2379
  • Пояснение:
ptrcs1 - арбитр
ptrpg1 - нода1
ptrpg2 - нода2
  • Посмотреть историю обмена ключами:
ETCDCTL_API=2 etcdctl get /data/cspgpro/history|sed 's/\,/\n/g'|sed 's/\[//;s/\[//;s/\]]//;s/\]//'
    • Результат:
...
1
21133688
"no recovery target specified"
"2025-09-24T02:43:00.783823+03:00"
"ptrpg2"
2
50333648
"no recovery target specified"
"2025-09-24T03:03:11.812345+03:00"
"ptrpg1"
3
50333984
"no recovery target specified"
"2025-09-24T19:37:33.206983+03:00"
"ptrpg2"
...
  • Посмотреть все ключи кластера:
ETCDCTL_API=2 etcdctl ls  --recursive
    • Результат:
...
/data
/data/cspgpro
/data/cspgpro/config
/data/cspgpro/failover
/data/cspgpro/failsafe
/data/cspgpro/history
/data/cspgpro/initialize
/data/cspgpro/leader
/data/cspgpro/members
/data/cspgpro/members/ptrpg2
/data/cspgpro/members/ptrpg1
/data/cspgpro/status
...
  • Смотрим кто сейчас является Leader, так как любое внесение изменений делается от него:
ETCDCTL_API=2 etcdctl member list
    • Результат:
c410a7d6456910ab: name=ptrcs1 peerURLs=http://ptrcs1.local.int:2380 clientURLs=http://ptrcs1.local.int:2379 isLeader=true'
e59a90ef17ed6871: name=ptrpg1 peerURLs=http://ptrpg1.local.int:2380 clientURLs=http://ptrpg1.local.int:2379 isLeader=false
edbaafd55c6a0b67: name=ptrpg2 peerURLs=http://ptrpg2.local.int:2380 clientURLs=http://ptrpg2.local.int:2379 isLeader=false
  • ВЫВОД: Исходное состояние кластера - в рабочем состоянии, все участники присутствуют и идет обмен ключами.
  • Теперь создаем прецедент - вторая нода ptrpg2 - теряется из кластера etcd, архива базы нет:
    • на ноде ptrpg2 останавливаем patroni, etcd и удаляем базу etcd (/var/lib/etcd/default/member)
systemctl stop patroni
systemctl stop etcd
rm -r /var/lib/etcd/default/member/*
  • На арбитре ptrcs1 смотрим состояние кластера:
ETCDCTL_API=2 etcdctl cluster-health
    • Результат:
member c410a7d6456910ab is healthy: got healthy result from http://ptrcs1.local.int:2379
member e59a90ef17ed6871 is healthy: got healthy result from http://ptrpg1.local.int:2379
failed to check the health of member edbaafd55c6a0b67 on http://ptrpg2.local.int:2379: Get 
"http://ptrpg2.local.int:2379/health": dial tcp 10.9.9.175:2379: i/o timeout member edbaafd55c6a0b67 is unreachable: 
http://ptrpg2.local.int:2379] are all unreachable
...
    • Видно, что нода2 (ptrpg2) - стала недоступна...

Запуск etcd на ptrpg2 - ни чего не даст, кроме ошибок..
Поэтому для корректного восстановления нужно на арбитре, который сейчас является Leader - удалить ключ ptrpg2,
или попросту убрать ноду из кластера и после этого снова ее добавить, не трогая при этом patroni!

  • На арбитре (который сейчас Leader) ptrcs1 - удаляем ноду:
ETCDCTL_API=3 etcdctl --user="root" member remove edbaafd55c6a0b67
    • Команда выполняется с авторизацией и потребует сообщить пароль пользователя root (etcd)
  • Проверяем состояние кластера:
ETCDCTL_API=2 etcdctl cluster-health
    • Результат:
...
member c410a7d6456910ab is healthy: got healthy result from http://ptrcs1.local.int:2379
member e59a90ef17ed6871 is healthy: got healthy result from http://ptrpg1.local.int:2379
...
    • Видно что в списке нет ptrpg2!
  • Теперь нужно заново добавить ptrpg2 в кластер, перед выполнением добавления, на ptrpg2 - etcd должен быть выключен!
    • На ptrcs1 выполняем команду добавления:
ETCDCTL_API=3 etcdctl --user="root" --endpoints=ptrcs1.local.int:2379,ptrpg1.local.int:2379 member add ptrpg2 --peer-urls=http://ptrpg2.local.int:2380
    • Результат:
Member b10724c2f8e66abd added to cluster 85466bb104b9e4e5

ETCD_NAME="ptrpg2"
ETCD_INITIAL_CLUSTER="ptrpg2=http://ptrpg2.local.int:2380,ptrcs1=http://ptrcs1.local.int:2380,ptrpg1=http://ptrpg1.local.int:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://ptrpg2.local.int:2380"
ETCD_INITIAL_CLUSTER_STATE="existing" 
...
    • После этой команды, на ptrcs1 (который сейчас Leader) - etcd ждет подключения хоста ptrpg2
  • Запускаем третьего участника заново в кластер сначала в etcd:
systemctl start etcd
    • Проверяем что он в кластере, на ptrcs1 выполняем:
ETCDCTL_API=2 etcdctl cluster-health
    • Результат:
member b10724c2f8e66abd is healthy: got healthy result from http://ptrpg2.local.int:2379
member c410a7d6456910ab is healthy: got healthy result from http://ptrcs1.local.int:2379
member e59a90ef17ed6871 is healthy: got healthy result from http://ptrpg1.local.int:2379
cluster is healthy
...
    • Как видно все участники в кластере.
  • Теперь на ptrpg2 - запускаем patroni:
systemctl start patroni
    • Проверяем ptroni:
patronictl -c /etc/patroni/patronictl.yml list
    • Результат:
+ Cluster: cspgpro -----------+---------+---------+----+-----------+
| Member  | Host              | Role    | State   | TL | Lag in MB |
+---------+-------------------+---------+---------+----+-----------+
| ptrpg1 | ptrpg1.local.int | Leader  | running | 11 |           |
| ptrpg2 | ptrpg2.local.int | Replica | running | 11 |         0 |
+---------+-------------------+---------+---------+----+-----------+
...
    • Как видно кластер работает и идет синхронизация без ошибок.


ДОПОЛНИТЕЛЬНО