Режим отказоустойчивости DCS
Эта страница переведена при помощи нейросети GigaChat.
Проблема
Patroni в значительной степени полагается на распределенное хранилище конфигураций (DCS) для решения задачи выборов лидера и обнаружения разделения сети. То есть узлу разрешено запускать Postgres в качестве первичного только в том случае, если он может обновить блокировку лидера в DCS. В случае, если обновление блокировки лидера не удалось, Postgres немедленно понижается и запускается в режиме только для чтения. В зависимости от используемого DCS вероятность возникновения «проблемы» различается. Например, при использовании etcd, который применяется только для Patroni, вероятность близка к нулю, тогда как с K8s API (на базе etcd) это может наблюдаться чаще.
Причины текущей реализации
Сбой обновления блокировки лидера может быть вызван двумя основными причинами:
- Разделение сети;
- Недоступность DCS.
В общем случае невозможно различить эти две ситуации с точки зрения одного узла, и поэтому Patroni предполагает наихудший случай — разделение сети. В случае разделения сети другие узлы кластера Patroni могут успешно захватить блокировку лидера и повысить Postgres до первичного. Чтобы избежать ситуации split-brain, старый первичный узел понижается до истечения срока действия блокировки лидера.
Режим отказоустойчивости DCS
Введена новую специальную опцию — failsafe_mode. Она может быть включена только через глобальную динамическую конфигурацию, хранящуюся в ключе DCS /config. Если режим отказоустойчивости включен и обновление блокировки лидера в DCS не удалось по причинам, отличным от несоответствия версии/значения/индекса, Postgres может продолжать работать как первичный, если он может получить доступ ко всем известным участникам кластера через REST API Patroni.
Детали низкоуровневой реализации
- Введен новый постоянный ключ в DCS с именем
/failsafe. - Ключ
/failsafeсодержит всех известных участников данного кластера Patroni в данный момент времени. - Текущий лидер поддерживает актуальность ключа
/failsafe. - Участнику разрешено участвовать в выборах лидера и стать новым лидером только в том случае, если он присутствует в ключе
/failsafe. - Если кластер состоит из одного узла, ключ
/failsafeбудет содержать одного участника. - В случае «сбоя» DCS существующий первичный узел подключается ко всем участникам, представленным в ключе
/failsafe, через REST APIPOST /failsafeи может продолжать работать как первичный, если все реплики подтвердят это. - Если один из участников не отвечает, первичный узел понижается.
- Реплики используют входящие запросы REST API
POST /failsafeкак индикатор того, что первичный узел все еще активен. Эта информация кэшируется наttlсекунд.
Часто задаваемые вопросы
-
Почему текущий первичный узел ОБЯЗАН видеть ВСЕ остальные участники? Возможно ли полагаться на кворум здесь?
Это отличный вопрос! Проблема в том, что представление о кворуме может различаться с точки зрения DCS и Patroni. В то время как узлы DCS должны быть равномерно распределены по зонам доступности, для Patroni такого правила нет, и что еще важнее, нет механизма для введения и обеспечения соблюдения такого правила. Если большинство узлов Patroni окажется в проигравшей части разделенной сети (включая первичный), а узлы меньшинства — в выигравшей части, первичный узел должен быть понижен. Только проверка ВСЕХ остальных участников позволяет обнаружить такую ситуацию.
-
Что произойдет, если узел/pod будет завершен, пока DCS недоступен?
Если DCS недоступен, проверка «доступны ли ВСЕ остальные участники кластера?» выполняется каждый цикл цикла heartbeat (каждые
loop_waitсекунд). Если pod/узел завершен, проверка не пройдет, и Postgres будет понижен до режима только для чтения и не восстановится, пока DCS не будет восстановлен. -
Что произойдет, если все участники кластера Patroni будут потеряны, пока DCS недоступен?
Patroni можно настроить на создание новой реплики из резервной копии даже тогда, когда в кластере нет лидера. Но если новый участник отсутствует в ключе
/failsafe, он не сможет захватить блокировку лидера и стать первичным. -
Что произойдет, если первичный узел потеряет доступ к DCS, а реплики — нет?
Первичный узел выполнит код отказоустойчивости и свяжется со всеми известными репликами. Эти реплики будут использовать эту информацию как индикатор того, что первичный узел активен, и не начнут выборы лидера, даже если блокировка лидера в DCS истекла.
-
Как включить режим отказоустойчивости?
Перед включением
failsafe_modeубедитесь, что версия Patroni на всех участниках актуальна. После этого можно использовать либо REST APIPATCH /config, либоpatronictl edit-config -s failsafe_mode=true.