ADG Оставить заявку
Блог Интеграции 4 мин чтения

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 - не просто замену, а постепенный переход с одновременной работой обоих режимов. Это позволяет откатиться, если что-то пошло не так.

Схема примерно такая:

  1. Разворачиваем KRaft-контроллеры - отдельные ноды (или выделяем часть брокеров под роль controller). Назначаем process.roles=controller, настраиваем controller.quorum.voters.

  2. Запускаем контроллеры в режиме миграции - они подключаются к ZooKeeper и начинают читать метаданные. zookeeper.metadata.migration.enable=true в конфигурации. В этот момент ZooKeeper ещё остаётся источником истины.

  3. Переключаем брокеры - один за другим добавляем process.roles=broker и controller.quorum.voters в конфигурацию брокеров, рестартуем. Брокеры начинают работать с KRaft-контроллерами. ZooKeeper при этом ещё жив.

  4. Финализируем миграцию - после того как все брокеры перешли, запускаем kafka-features.sh для завершения: метаданные копируются из ZooKeeper в KRaft-топик, ZooKeeper отключается.

  5. Останавливаем 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 достаточно предсказуемая, главное - грамотно разобраться с окружением вокруг кластера до старта.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.