Восстановление KRaft-кворума в Kafka 4.x: инструкция после потери контроллеров

В Kafka 4.x метаданные управляются через KRaft, и потеря большинства контроллеров оставляет кластер без рабочего кворума. Разбираем, как диагностировать проблему и восстановить работу, опираясь на реальный баг-репорт Strimzi.

Восстановление KRaft-кворума в Kafka 4.x: инструкция после потери контроллеров

Представьте: все шесть подов в статусе 1/1 Running, Readiness зелёный, kafka-agent на брокерах отдаёт 204, а кластер мёртв. Оператор бесконечно крутит реконсайл и валится в TimeoutException: Timed out waiting for a node assignment. Call: describeMetadataQuorum. Если зайти на том контроллера, видно, что clustermetadata-0/quorum-state: leaderId выставлен, а appliedOffset в 0. Ни одна запись метаданных не применена. JVM живые, raft-лог на диске растёт, и при этом ни один под не написал в stdout ни строки следующие восемь часов. Это не выдумка, а реальный баг-репорт Strimzi от 25 мая 2026, и к нему мы ещё вернёмся.

В Kafka 4.x больше нет привычного «запасного выхода» в виде ZooKeeper: метаданные переехали внутрь самой Kafka (KRaft), и если кворум контроллеров теряет большинство, чинить приходится уже сам кластер Kafka, а не внешний сервис. Раньше для этого существовал ZooKeeper — отдельная система со своими инструментами, ансамблем и культурой восстановления. В версии 4.x его нет, и в документации от процедуры остался только линк на 3.9. Метаданные переехали внутрь самой Kafka (KRaft), и если кворум контроллеров теряет большинство, чинить приходится сам кластер Kafka, а не внешний сервис. В этой статье расскажем, что делать в такой ситуации и как восстанавливать этот кворум, чтобы не случилось ситуации, описанной выше.

Что такое KRaft-кворум и почему его потеря критична

KRaft — это протокол управления метаданными, который пришёл на смену ZooKeeper в Kafka. Вместо внешней системы координации Kafka теперь хранит все метаданные — топики, конфигурации, назначения партиций — в собственном журнале, который реплицируется между контроллерами. Кворум — это минимальное количество контроллеров, необходимое для выбора лидера и принятия решений. Если кворум теряет большинство, кластер не может выбрать лидера контроллера, и все операции записи метаданных блокируются. Брокеры продолжают работать, но не могут обрабатывать новые запросы на создание топиков, изменение конфигураций или перебалансировку.

В версии 4.x этот механизм стал ещё более критичным, потому что ZooKeeper больше не доступен как запасной вариант. Раньше можно было временно переключиться на ZooKeeper, но теперь всё завязано на внутренний кворум. Если потерять большинство контроллеров — например, из-за сбоя в дата-центре или ошибки при масштабировании, — кластер фактически замирает. При этом внешне он может выглядеть здоровым: поды запущены, проверки готовности проходят, но на самом деле никакие метаданные не обновляются. Это создаёт ложное чувство безопасности и затягивает решение проблемы.

Предыстория и контекст: как мы пришли к KRaft

Переход от ZooKeeper к KRaft начался ещё в Kafka 2.8, когда появилась ранняя версия внутреннего режима. В течение нескольких лет команда Kafka развивала этот протокол, добавляя новые функции и улучшая стабильность. В версии 3.3 KRaft стал production-ready, но ZooKeeper всё ещё поддерживался для обратной совместимости. Только в Kafka 4.0, вышедшей в 2025 году, поддержка ZooKeeper была полностью удалена. Это был логичный шаг — упростить архитектуру и убрать зависимость от внешней системы, но он также привёл к новым вызовам в области восстановления после сбоев.

В документации Kafka процедура восстановления после потери кворума описана очень кратко, и часто ссылается на старую версию 3.9, где ещё был ZooKeeper. Это создаёт путаницу: администраторы, привыкшие к старым методам, могут не найти актуальных инструкций. Именно поэтому важно понимать, как работает KRaft изнутри и какие инструменты доступны для диагностики и ремонта. Реальный баг-репорт Strimzi, упомянутый в начале, — отличный пример того, как легко пропустить признаки проблемы и как сложно её диагностировать без глубокого понимания внутренностей.

Как диагностировать потерю кворума

Первым признаком проблемы может быть то, что оператор не может выполнить reconcile, а в логах появляется ошибка Timed out waiting for a node assignment. Если вы используете Strimzi, вы увидите, что KafkaAssemblyOperator пытается получить информацию о кворуме через describeMetadataQuorum, но получает таймаут. Другой признак — на томе контроллера в файле clustermetadata-0/quorum-state leaderId выставлен, но appliedOffset равен нулю. Это означает, что контроллер не может применить ни одну запись метаданных, хотя лидер выбран. JVM при этом живы, raft-лог на диске растёт, но никакие изменения не фиксируются. В такой ситуации важно не перезапускать поды бездумно — это может усугубить проблему, если потеряно большинство.

Технические подробности: как работает восстановление

Для восстановления кворума необходимо пересобрать список контроллеров, исключив те, которые потеряны безвозвратно. В KRaft это делается через изменение конфигурации controllers в файле server.properties или через динамическую конфигурацию. Основная идея — сократить кворум до оставшихся живых контроллеров, чтобы они могли выбрать нового лидера и продолжить работу. Если у вас было три контроллера и один потерян, вы можете временно уменьшить кворум до двух, а затем добавить новый контроллер, чтобы вернуться к трём. Однако если потеряны два из трёх, кворум полностью разрушен, и потребуется специальная процедура.

В Kafka есть инструмент kafka-storage.sh, который позволяет управлять метаданными. Для восстановления кворума используется команда kafka-storage.sh format, но она не предназначена для ремонта существующего кластера. Более подходящий вариант — использовать kafka-reassign-partitions.sh или напрямую редактировать метаданные через kafka-metadata-shell.sh. Однако эти инструменты требуют работающего кворума, что создаёт замкнутый круг. В таких случаях приходится вручную менять конфигурацию контроллеров, останавливая один из них и изменяя список controllers, чтобы оставшиеся могли сформировать кворум. Этот процесс описан в документации, но требует осторожности и понимания рисков.

Кого затронет и как: практические последствия

Эта проблема касается в первую очередь DevOps-инженеров и администраторов Kafka-кластеров, которые работают с версией 4.x. Если вы используете Strimzi или другие операторы, потеря кворума может привести к длительному простою, как в баг-репорте, где кластер был мёртв восемь часов. Для бизнеса это означает недоступность критически важных данных, остановку пайплайнов и потерю доверия клиентов. Компании, которые мигрировали на Kafka 4.x, должны быть готовы к таким сценариям и иметь план восстановления. Особенно это актуально для России и СНГ, где Kafka широко используется в финансовых и телекоммуникационных компаниях.

Для разработчиков инструментов и операторов, таких как Strimzi, это также вызов: нужно улучшить обработку ошибок и предоставить более явные сигналы о проблемах с кворумом. В упомянутом баг-репорте оператор не мог корректно обработать ситуацию, и требовалось вмешательство вручную. Возможно, в будущих версиях Strimzi появится автоматическое восстановление, но пока администраторам приходится полагаться на свои знания и документацию.

Что будет дальше: прогноз и рекомендации

В ближайшее время стоит ожидать улучшения документации Kafka по восстановлению кворума, так как сообщество активно обсуждает эту проблему. Также возможны изменения в Strimzi, направленные на более явную диагностику и автоматическое восстановление. Однако пока администраторам рекомендуется заранее тестировать процедуры восстановления на тестовых кластерах, чтобы быть готовыми к реальным инцидентам. Важно также настроить мониторинг, который отслеживает состояние кворума и предупреждает о потере большинства контроллеров.

Если вы столкнулись с потерей кворума, не паникуйте. Сначала соберите максимум информации: проверьте логи контроллеров, состояние raft-лога и доступность узлов. Затем, следуя документации, сократите кворум до живых контроллеров и добавьте новые узлы для восстановления полного набора. Помните, что это сложная процедура, и лучше потратить время на подготовку, чем на долгий простой.

Итог

KRaft-кворум — это критический компонент Kafka 4.x, и его потеря может полностью остановить кластер. Важно понимать, как диагностировать проблему и какие шаги предпринять для восстановления. Реальный баг-репорт Strimzi показывает, что даже опытные команды могут столкнуться с такими ситуациями, поэтому подготовка и знание процедур — ключ к минимизации простоев. Следите за обновлениями документации и инструментов, чтобы быть готовыми к любым сценариям.