Перейти к содержанию

DCS Отказоустойчивый режим

DCS поведение, требования и эксплуатационные особенности отказоустойчивого режима.


Проблема

Patroni активно использует распределённое хранилище конфигурации (DCS) для решения задачи выбора лидера и обнаружения сетевых разделений. Узел может запускать PostgreSQL как первичный сервер только в том случае, если ему удаётся обновить блокировку лидера в DCS. В случае неудачи обновления блокировки лидера PostgreSQL немедленно понижается до режима только для чтения. Вероятность возникновения «проблемы» зависит от используемого DCS. Например, при использовании etcd, который применяется исключительно для Patroni, вероятность близка к нулю, тогда как при использовании K8s API (основанного на etcd) такая ситуация может возникать чаще.


Причины текущей реализации

Сбой обновления блокировки лидера может быть вызван двумя основными причинами:

  1. Разделение сети
  2. DCS недоступен

Вообще невозможно различить эти два случая на основе одного узла, поэтому Patroni исходит из худшего сценария — разделения сети. В случае разделения сети другие узлы кластера Patroni могут успешно получить блокировку лидера и повысить Postgres до первичного сервера. Чтобы избежать состояния split-brain, старый первичный сервер понижается в статусе до завершения срока действия блокировки лидера.


DCS Отказоустойчивый режим

Вводится новая специальная опция — failsafe_mode. Она может быть включена только через глобальную динамическую конфигурацию , хранящуюся в ключе DCS /config. Если включён отказоустойчивый режим и обновление блокировки лидера в DCS не удалось по причинам, отличным от несоответствия версии/значения/индекса, PostgreSQL может продолжать работу в качестве первичного сервера, если имеет доступ ко всем известным участникам кластера через Patroni REST API.


Детали низкоуровневой реализации

  • Вводится новый постоянный ключ в DCS, называемый /failsafe.
  • Ключ /failsafe содержит всех известных участников заданного кластера Patroni на данный момент.
  • Текущий лидер сохраняет ключ /failsafe.
  • Участник может участвовать в выборе лидера и стать новым лидером только в том случае, если он присутствует в ключе /failsafe.
  • Если кластер состоит из одного узла, ключ /failsafe будет содержать одного участника.
  • В случае DCS «сбоя» первичный сервер подключается ко всем участникам, перечисленным в ключе /failsafe, через REST API POST /failsafe REST API, и может продолжать работу как первичный сервер, если все реплики подтверждают его состояние.
  • Если один из участников не отвечает, первичный сервер понижается в статусе.
  • Реплики используют входящие запросы POST /failsafe REST API в качестве индикатора того, что первичный сервер всё ещё активен. Эта информация кэшируется на ttl секунд.

F.A.Q.

  • Почему MUST текущий первичный сервер видит ALL других участников? Разве здесь нельзя полагаться на кворум?

    Это отличный вопрос! Проблема в том, что взгляд на кворум может различаться с точки зрения DCS и Patroni. Хотя узлы DCS должны равномерно распределяться по зонам доступности, для Patroni такого правила не существует, и, что более важно, отсутствует механизм введения и обеспечения соблюдения такого правила. Если большинство узлов Patroni окажется в проигравшей части разорванной сети (включая первичный сервер), а меньшинство — в выигравшей, первичный сервер должен быть понижен. Только проверка ALL других участников позволяет выявить такую ситуацию.

  • Что будет, если узел/под будет завершён при недоступности DCS?

    Если DCS недоступен, проверка «доступны ли другие участники кластера ALL» выполняется каждый цикл цикла опроса состояния (каждые loop_wait секунд). Если под/узел завершается, проверка завершится неудачно, и PostgreSQL будет понижен до режима только для чтения и не восстановится до тех пор, пока DCS не будет восстановлен.

  • Что будет, если все участники кластера Patroni будут потеряны во время простоя DCS?

    Patroni может быть настроен на создание новой реплики из резервной копии даже тогда, когда кластер не имеет лидера. Однако, если новый участник отсутствует в ключе /failsafe, он не сможет получить блокировку лидера и произвести повышение.

  • Что произойдёт, если первичный сервер потеряет доступ к DCS, а реплики — нет?

    Первичный сервер выполнит код аварийной защиты и свяжется со всеми известными репликами. Эти реплики воспримут эту информацию как признак того, что первичный сервер работает, и не начнут выбор лидера, даже если блокировка лидера в DCS истекла.

  • Как включить отказоустойчивый режим?

    Перед включением failsafe_mode убедитесь, что версия Patroni на всех участниках обновлена. Затем вы можете использовать либо PATCH /config REST API , либо patronictl edit-config -s failsafe_mode=true