Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Split brain: расщепление кластера и защита от него

Split brain: почему кластер делится надвое и как это предотвращать

Split brain: причины сетевого разделения, кворум и witness, fencing и STONITH, практические настройки для etcd, Patroni и Kubernetes.

Прямой ответ

Split brain — состояние, при котором кластер разделяется на две (или более) группы, каждая из которых считает себя работоспособной и продолжает принимать запись. Итог — расходящиеся версии одних и тех же данных, которые потом приходится разбирать вручную. Классическая причина — сетевое разделение (partition): узлы живы, но не видят друг друга.

Почему это вообще возможно:

  • Чётное число узлов. При N=2 каждая половина «думает», что она и есть большинство, либо блокируется полностью — отказоустойчивости нет.
  • Отсутствие кворума в решении. Если роль лидера определяется локально («я не получил heartbeat, значит я лидер»), разделение обязательно даст двух лидеров.
  • Опора только на TTL. Аренда без fencing не мешает «воскресшему» лидеру писать после того, как его роль уже передана.

Защиты, работающие в комплексе:

  1. Кворум (большинство). Любое решение требует подтверждения большинства узлов — при разделении победить может только одна сторона. Это основа Raft и Paxos.
  2. Нечётное число участников и witness. Три узла в трёх зонах; при потере одной зоны остаются два из трёх — кворум цел. Witness — лёгкий участник, который голосует, но не хранит данные.
  3. Fencing / STONITH. Изоляция бывшего лидера: отзыв доступа через токены, отключение сети или выключение узла. Без этого кворум защищает только решение, но не данные.
  4. Явная деградация меньшинства. Меньшая сторона обязана переходить в read-only или полностью отказывать в записи, а не «работать как ни в чём не бывало».

Практика: симптомы и быстрая диагностика

Как выглядит инцидент:

  • два узла сообщают role: leader одновременно;
  • клиент получает разные ответы в зависимости от того, на какой узел попал;
  • после «схлопывания» сети часть записей исчезает или конфликтует;
  • метрика смен лидера растёт лавинообразно.

Команды для etcd-кластера:

# состояние участников и лидерство
etcdctl endpoint status --cluster -w table

# кто сейчас лидер и какой терм
etcdctl endpoint status -w json | jq '.[].Status.leader, .[].Status.raftTerm'

# здоровье участников
etcdctl endpoint health --cluster

Если endpoint status --cluster отвечает только с части узлов, а остальные возвращают context deadline exceeded — это признак разделения, а не «медленного диска».

Для Patroni: patronictl list показывает лидера и lag реплик; отсутствие лидера при живых узлах обычно означает потерю связности с DCS. Разбор механики — в статье про failover PostgreSQL и Patroni.

Что проверить по порядку:

  1. Связность между узлами (не только «сеть вообще», а именно mesh между участниками).
  2. Время на узлах: рассинхронизация ломает TTL-аренды и логи с временными метками.
  3. Задержки диска: долгий fsync выглядит как потеря кворума и запускает перевыборы.
  4. Лимиты и CPU-throttling в Kubernetes: узел может «молчать» из-за троттлинга, а не из-за сети — про поды и ресурсы см. основы Kubernetes.

Практический сценарий: разделение зоны в PostgreSQL-кластере

Контекст: Patroni + etcd, три узла: два в зоне A, один в зоне B. Потеряна связность между зонами.

  1. Что происходит. В зоне A остаются два etcd-узла — кворум есть, лидер etcd сохраняется, текущий лидер PostgreSQL продолжает работу. Узел в зоне B теряет связь с DCS, его ключ лидера/реплики истекает, и он обязан уйти в read-only.
  2. Опасный сценарий. Если бы узлы были 2/2 (по одному в каждой зоне), обе стороны потеряли бы кворум etcd — кластер стал бы недоступен для записи, но зато без расхождения данных. Хуже вариант, когда promote выполняется «вручную» без DCS: тогда появляются два writable-узла.
  3. Действия дежурного. Убедиться, что меньшинство действительно read-only (pg_is_in_recovery() возвращает true), не выполнять ручной promote до восстановления связности, зафиксировать timeline.
  4. Восстановление. После возвращения сети узел B догоняет лидера; при расхождении timeline требуется pg_rewind или пересоздание реплики.
  5. Постмортем. Проверяем, что witness/третий узел живёт в третьей зоне, а не «для галочки» в той же стойке; добавляем алерт на потерю кворума и на pg_is_in_recovery() у неожиданного узла. Как оформлять разбор — в статье про incident management и runbook.

Результат: данные не разошлись, потому что меньшинство деградировало штатно. Вывод: защита от split brain — это топология (нечётное число, разные зоны) плюс явное поведение меньшинства плюс fencing, а не один параметр в конфиге.

Чек-лист перед тем, как объявить инцидент закрытым. Убедитесь, что в кластере ровно один лидер и его терм/ревизия совпадают на всех узлах; что реплики в меньшинстве действительно не принимали запись (проверьте счётчики записей и timeline); что после восстановления связности не осталось «сиротских» данных, которые придётся удалять вручную; и что изменения конфигурации, предотвращающие повтор, зафиксированы в коде инфраструктуры, а не только в чате дежурных. Без этих четырёх пунктов инцидент считается незакрытым, даже если сервис уже отвечает на запросы.

FAQ

Можно ли полностью исключить split brain? Нельзя исключить само разделение сети — оно физически возможно всегда. Можно сделать его безопасным: кворум гарантирует, что запись принимает только одна сторона, а fencing гарантирует, что бывший лидер не сможет испортить данные. Теоретическая рамка этого компромисса описана в статье про теорему CAP.

Почему не подходит чётное число узлов? Для четырёх узлов кворум равен трём: отказ одного узла оставляет три (работает), но устойчивость та же, что у трёх узлов, а задержка записи выше. При делении 2/2 обе стороны блокируются — доступность теряется без выигрыша в безопасности.

Что такое STONITH и нужен ли он в облаке? STONITH — «Shoot The Other Node In The Head», аппаратная изоляция узла. В облаке прямой аналог — принудительное выключение инстанса через API или отзыв сетевых правил. Суть та же: бывший лидер должен потерять физическую возможность писать, а не только «перестать считать себя лидером».

Как понять, что fencing действительно работает? Проведите учебный инцидент: остановите лидера на уровне процесса, дождитесь перевыборов, затем верните процесс и попробуйте записать данные. Запись должна быть отклонена. Механику лидерства и токенов см. в статье про выборы лидера.

Источники: etcd docs (failures), Patroni docs, Wikipedia (split-brain) — ссылки в шапке.