Kafka 3.7: KRaft стал production-ready, ZooKeeper deprecated - мигрируем кластер клиента
Apache Kafka 3.7 официально выводит KRaft-режим в продакшн и объявляет ZooKeeper deprecated. Рассказываем процедуру миграции живого кластера и что проверить заранее.
Apache Kafka 3.7 выходит - KRaft режим без ZooKeeper объявлен production-ready, ZooKeeper официально deprecated
Kafka 3.7 вышла на прошлой неделе, и главное в этом релизе - не фичи брокера, а статус KRaft-режима. Apache Software Foundation официально объявил его production-ready. Одновременно ZooKeeper-режим получил статус deprecated. Это не просто ярлык: поддержка ZooKeeper-режима планово завершится в Kafka 4.0, и дата уже вполне реальная - 4.x в разработке.
Для нас это пришло в рабочий момент: у одного из клиентов кластер Kafka работает на ZooKeeper уже несколько лет. Никого особо не беспокоил. Но deprecation - это сигнал, что откладывать дальше не стоит, и мы с клиентом решили сделать миграцию сейчас, пока инструментарий свежий и документация актуальная.
Что такое KRaft и почему это важно
ZooKeeper в архитектуре Kafka всегда был некоторым архитектурным неудобством: отдельный ансамбль процессов, отдельная операционная логика, отдельные точки отказа. Kafka-брокеры хранили метаданные в ZooKeeper, и это создавало задержки при смене лидера и ограничивало количество партиций, которые кластер мог обслуживать без деградации.
KRaft (Kafka Raft) убирает ZooKeeper из уравнения. Метаданные хранятся внутри самого Kafka-кластера в специальном топике __cluster_metadata, а консенсус обеспечивается встроенной реализацией Raft. Контроллер становится частью брокеров - либо выделенные контроллер-ноды, либо совмещённые с брокерами (для небольших кластеров).
На практике это означает: один набор процессов вместо двух, проще мониторинг, быстрее failover, выше потолок на количество партиций.
Что смотреть перед миграцией
Прежде чем запускать любые процедуры - диагностика текущего состояния. У клиента кластер из нескольких брокеров, ZooKeeper-ансамбль из трёх нод, топики с репликацией 3. Несколько вещей, которые нужно проверить заранее.
Версия Kafka. Встроенный инструментарий миграции поддерживает переход только начиная с Kafka 2.8+. Если версия старше - сначала обновить до 3.x на ZooKeeper, потом мигрировать в KRaft. У клиента была 3.4, поэтому прямой путь.
Состояние ZooKeeper. Проверить, что ансамбль здоров: echo ruok | nc zk-host 2181 на каждой ноде, посмотреть mntr на лидере. Грязный ZooKeeper с несинхронизированными нодами - плохая отправная точка.
Отставание партиций. Перед миграцией в кластере не должно быть under-replicated partitions. kafka-topics.sh --describe --under-replicated-partitions должен дать пустой результат. Если есть - разобраться с причиной.
Клиенты. Все ли клиенты обновлены до версий, совместимых с KRaft? Старые клиенты (до 2.x) могут использовать ZooKeeper-зависимые API. В 3.x они всё ещё работают, но лучше убедиться заранее.
Мониторинг. Если мониторинг смотрит на метрики ZooKeeper напрямую - нужно заготовить замену. В KRaft часть метрик переехала или изменила имена.
Процедура миграции: как это устроено
Kafka 3.7 поддерживает bridged migration - не просто замену, а постепенный переход с одновременной работой обоих режимов. Это позволяет откатиться, если что-то пошло не так.
Схема примерно такая:
-
Разворачиваем KRaft-контроллеры - отдельные ноды (или выделяем часть брокеров под роль
controller). Назначаемprocess.roles=controller, настраиваемcontroller.quorum.voters. -
Запускаем контроллеры в режиме миграции - они подключаются к ZooKeeper и начинают читать метаданные.
zookeeper.metadata.migration.enable=trueв конфигурации. В этот момент ZooKeeper ещё остаётся источником истины. -
Переключаем брокеры - один за другим добавляем
process.roles=brokerиcontroller.quorum.votersв конфигурацию брокеров, рестартуем. Брокеры начинают работать с KRaft-контроллерами. ZooKeeper при этом ещё жив. -
Финализируем миграцию - после того как все брокеры перешли, запускаем
kafka-features.shдля завершения: метаданные копируются из ZooKeeper в KRaft-топик, ZooKeeper отключается. -
Останавливаем ZooKeeper - только после успешного завершения предыдущего шага.
Между шагами 3 и 4 кластер какое-то время работает в гибридном режиме. Kafka в это время полностью функциональна: продюсеры и консьюмеры работают без перерыва.
Что реально потребовало внимания
У клиента основная возня оказалась не с самой Kafka, а вокруг неё.
Мониторинг Zabbix смотрел на ZooKeeper через JMX и через four-letter words. Пришлось заранее добавить KRaft-метрики (контроллер, состояние кворума, lag метаданных) и отключить ZooKeeper-алерты уже после завершения миграции. Делали это параллельно с подготовкой - иначе после миграции получили бы ложные алерты «ZooKeeper недоступен».
Ansible-роль для развёртывания брокеров была написана под ZooKeeper-конфигурацию. Потребовала переработки шаблонов server.properties и добавления отдельного плейбука для контроллеров.
ACL. В ZooKeeper-режиме ACL хранятся в ZooKeeper. В KRaft они переносятся автоматически при миграции, но проверить после завершения - обязательно. У клиента был десяток ACL для сервисных аккаунтов, все перешли корректно, но мы проверяли явно.
Где сейчас
Кластер клиента работает на KRaft около недели. ZooKeeper-ноды остановлены, но пока не выведены из инвентаря - на всякий случай. По метрикам всё нормально: failover контроллера проверили искусственно (остановили лидирующий контроллер), выборы нового заняли меньше секунды.
Если у вас Kafka на ZooKeeper и вопрос миграции уже стоит в бэклоге - помогаем спроектировать и провести переход. Процедура в 3.7 достаточно предсказуемая, главное - грамотно разобраться с окружением вокруг кластера до старта.