В первой части мы остановились на том, что у нас есть отказоустойчивый кластер и теперь вроде бы все работает. Мы уже можем зайти в базу данных через лидера и что-нибудь туда записать. Последняя проблема, которую нужно решить — программно узнать, где находится лидер. Неужели нужно будет каждый раз делать эту проверку после падения, чтобы понять через какую ноду подключаться к базе? Это было бы настолько скверно, что испортило бы все решение. Но не беспокойтесь, с помощью HA Proxy вопрос решается довольно легко и незатейливо. Также как с Patroni, сначала сделаем отдельную директорию под билд/деплой файлы и начнем их там создавать: haproxy.cfg Это файл конфига, который мы положим в наш кастомный образ.  В этих строчках мы назначаем порты, по которым будет получать доступ:  А здесь мы просто перечисляем все сервисы Patroni, которые создали ранее:  И последнее. Эта строка нужна, если мы хотим проверять состояние кластера с помощью специальной утилиты из контейнера с HA Proxy:  Dockerfile  Dockerfile выглядит довольно просто и, думаю, не требует комментариев:   docker-compose-haproxy.yml Compose файл выглядит тоже достаточно просто:  Когда все файлы готовы, можно и задеплоить весь этот сет:  Когда HА Proxy запустится, можно будет в контейнере посмотреть статистику кластера специальной командой:  Выполнив эти три шага, мы увидим прямо в консоли красивый вывод статистики.  Сам я предпочитаю смотреть статистику через patronictl либо Patroni API, но HA Proxy тоже один из вариантов и почему бы не настроить и его заодно. А теперь немного о Patroni API. Я обещал показать три способа смотреть статистику кластера, и вот добрался-таки до последнего. Вывод статистики через API хорош тем, что он дает самую полную информацию о кластере (и вообще через него можно делать всё).  Более подробно почитать про API можно в доках, а здесь я покажу самые основные вещи: стандартные запросы и как их выполнить в нашем сетапе.  Также как с подключением к БД, мы не сможем обращаться к API, не находясь в сети ’patroni_patroni’. Так что нам придется слать все наши запросы из контейнера. Чтобы читать вывод json в приятном человеческому глазу формате, сделаем кастомный имейдж с curl’ом и jq.   И потом запустим контейнер с этим образом, подключив его к нужной сети:  Теперь мы можем обращаться к API Patroni нод по их именам и получать cтаты в таком вот виде:  Основная идея, что теперь мы можем ставить свои эксперименты с Patroni кластером так, как если бы это был кластер с тремя реальными серверами. Достаточно просто выключать и включать сервисы Patroni, чтобы сымитировать падения серверов. Если лидер у нас patroni3, то мы делаем:  И отключаем его, убивая его единственный контейнер. Теперь можно глянуть состояние кластера и убедиться, что лидер перешел на здоровую ноду:  Если сделать scale для patroni3 на ’1′, то он вернется в кластер и займет роль реплики.  Теперь вы можете запускать все тесты и проверять, как Patroni кластер будет реагировать на критические ситуации.  Как и обещал, ниже небольшой скрипт для тестов, а также инструкции как с ним работать. Так что, если вам нужно что-то уже готовое для быстрого теста, добро пожаловать. Если же у вас есть свои идеи и сценарии и вам не требуется готовое решение, просто пропустите спойлер.  Для тех читателей, кто хочет потестировать кластер Patroni на каком-то готовом примере прямо сейчас, я сделал вот этот скрипт. Он супер простой, и я уверен у вас не возникнет проблем с тем, чтобы понять, как он работает. По сути, он просто пишет в базу текущее время каждую секунду. Ниже я шаг за шагом покажу, как его запустить и какие результаты теста были у меня.  Шаг 1 Допустим, вы уже скачали скрипт и положили его где-то у себя на машине. Если нет, то проделайте эту подготовку. Теперь нам нужно запустить Docker контейнер с официальным образом Miscrosoft SDK такой командой:  Два момента. Первое, как и раньше мы хотим подключиться к сети ’patroni_patroni’ и второе, мы делаем mount к той директории, где уже лежит готовый скрипт. Таким образом мы сможем запускать его из контейнера.  Шаг 2 Теперь мы хотим, чтобы у нас появился единственный dll, который нужен чтобы скрипт взлетел. Заходим в контейнер и находясь в директории ’/home’ создаем папку ’patroni-test’ для консольного приложения. Заходим в нее и выполняем следующую команду:  И теперь мы можем добавить в проект нужный нам для работы пакет:  А потом просто упаковываем проект:  Если все прошло удачно, то мы получим ’Npgsql.dll’ по адресу: ’patroni-test/bin/Debug/net5.0/Npgsql.dll’. Этот путь мы и добавляем как референс в скрипте, так что если у вас он отличается от моего, то в скрипте это нужно подправить.  А дальше просто запускаем скрипт:  Важно не закрывать терминал со скриптом, пока идет тест. Шаг 3 Давайте посмотрим, где сейчас находится лидер, чтобы знать кого ронять. Можно использовать любой из трёх способов, я смотрел через patronictl:  Теперь нам нужно открыть новый терминал и «убить» лидера:  Через какое-то время в окне со скриптом мы увидим сообщения об ошибке:  Если мы проверим статус кластера, то можем заметить некоторую задержку — он всё ещё показывает patroni2 в качестве лидера. Но спустя n секунд он все-таки перестроится и, пройдя короткую стадию по выбору лидера, придет в такое состояние:  Если же вернемся к терминалу со скриптом, то увидим, что соединение наконец-то восстановлено и запись возобновилась:  Шаг 4 Теперь проверим, как там поживает сама база данных и всё ли с ней в порядке после падения лидера:  Из этого небольшого эксперимента мы можем заключить, что Patroni справился со своей задачей. После того, как лидера упал, произошли перевыборы, и мы смогли подсоединиться к базе. Все предыдущие данные также оказались в целости. Возможно, мы могли бы пожелать, чтобы восстановление произошло быстрее, чем за 42 секунды, но, в конце концов, это не так критично. Полагаю, на этом можно считать туториал завершенным. Надеюсь, он помог вам разобраться с основными моментами в настройке и работе с Patroni и в целом был полезен. Спасибо за внимание и да хранит Patroni ваши данные, отстреливаясь от багов и героически поднимаясь после падений! За помощь в настройке этого решения отдельное спасибо коллеге Андрею Юрченко. Без этого отзывчивого парня мои Patroni застряли бы в магазине/стволе и не убили бы ни одного врага. Все файлы использованные во второй части здесь. C# developer