"Алекс, у нас там проблемы с БД, которая у вас в кубере - приложение не подключается к нему, пишет всякое".
Не в первой диагностировать что-либо, но сперва вводные:
все базы у нас в кубернетисе, всё через оператора. в аргосиди репо в приложениях мы просто клеймим бд/юзера и приложением забирает адрес, логин и пароль из секретов кубера. Всё достаточно просто.
Лезу в тикет джиры, тред в слаке - коллеги разработчики жалуются, что в случайное время бизнес приложением не может писать в базу. Где-то ошибка, что не возможно подключится, где-то пишет, что база данных находится в ридонли.
Читаю поверхностно логи приложения, оператора, кластера БД - всё вроде ок.
Через разрешение рестартую приложение - проблема уходит.
Закрываю тикет, с лицом Дукалиса-солнышко объясняю деткам-разработчикам, что магии не бывает - у вас приложение говно, раз рестарт POD-a с бизнесовым приложением помогает. БД я не трогаю вообще.
Спустя несколько дней ситуация повторяется, но я, как умный синёр самоуверенный помидор, делаю рестарт пода приложения и снова снисходительно поясняю неразумным коллегам - проблема на вашей стороне.
Не, ну правда - если я вообще не трогаю БД и рестарт бизнес апп помогает - как я мог решить, что виновата инфра?
И потом ситуация ещё пару раз.
А при повторе на другом стеке, другого бизнес приложения подобной ошибки, у нас в команде начинают появляться подозрения, что мы не такие уж и синёры, а обычные мартышки.
В команде всего двое, кто любит нырять глубоко в траблшутинг, ныряю я.
Логи логи логи. Не буду тратить время на описание, но я бессмысленно потратил несколько дней - и ничего не нашёл. Не зная, что искать - ничего и не находишь.
Жалобы время от времени всё поступали и мы совсем сникли.
Для помощи самому себе так же подняли, не моими силами, сбор метрик не только PostgreSQL, но и Patroni.
Однако метрики ничем не помогли.
Просветление было однажды, когда я поймал и саму проблему и сумел увидеть в логе
demoting self because DCS is not accessible and I was a leader
Это была первая зацепка, и следом начал цепляться за всякое типа
20**/12/06 11:30:18 main.go:127: Connection stats - max: 200, used: 12, available: 185 (6.0% used)
20**/12/06 11:30:18 main.go:130: Connection states - active: 3, idle: 6, idle in transaction: 0
20**/12/06 11:30:18 main.go:274: Database in recovery mode: true
Зацепка, отписываем промежуточное мнение:
кластер делает свичовер но НЕ переключает на реплику(мы это видим по IP при ресолвинге)
наши бизнес приложения продолжают сидеть в том же пуле, их не выкидывает и не переключают на мастера
появляются новые пиды, у которых лайфсайкл времени идёт от времени свичовера.
Складывая в пул все найденные логи, какие-то новые для себя слова, я прихожу к
https://patroni.readthedocs.io/en/master/dcs_failsafe_mode.html
О, как это было похоже на то, что у нас происходило.
Не буду пояснять тут, в документации отлично всё расписано.
Проверяем: а есть ли у нас эта алупа:
root@test-db-2:/home/postgres# curl http://localhost:8008/config | jq
...
{
"failsafe_mode": false,
...
Бл, а оно у нас и не включено.
Иду у чарт
https://github.com/zalando/postgres-operator/blob/master/docs/reference/operator_parameters.md#patroni-options
https://github.com/zalando/postgres-operator/blob/master/manifests/configmap.yaml#L52
В общем обосратушки, в операторе это выключено.
Для теста включаю в чарте в отдельном теге.
Затем в dev контуре перевожу все аппликейшны на новый чарт.
Проверяем применилось ли это:
kubectl exec -it test-db-0 -- curl http://localhost:8008/config | jq .failsafe_mode
true
и
kubectl get postgresql test-db -o yaml | grep -A 2 patroni
patroni:
failsafe_mode: true
Где не применилось, там спасибо оператору, пилим костыль
kubectl rollout restart statefulset test-db
Пару недель тестов - ошибка больше не повторялось. Ура, победа!