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

Kafka ZooKeeper → KRaft в production: как прошла rolling migration без остановки топиков

Документируем production rolling migration Kafka-кластера клиента с ZooKeeper на KRaft: пошаговый процесс, что пошло не так и оценка рисков по итогу.

Контекст момента

Apache Kafka объявляет ZooKeeper deprecated в ветке 3.x, миграция на KRaft становится обязательной для новых кластеров

В ноябре мы описывали staging: подняли KRaft-контроллеры параллельно ZooKeeper, поймали проблему с NTP-drift, зафиксировали риски. С тех пор прошло несколько недель дополнительной подготовки - и в середине декабря провели production-миграцию. Рассказываем, как именно это выглядело в реальности, что пошло не совсем по плану и что думаем об этом процессе по итогу.

Контекст

Кластер на managed-сопровождении: пять брокеров, Kafka 3.3, ZooKeeper-ансамбль из трёх нод. Несколько сотен топиков, часть высоконагруженных. ZooKeeper deprecated начиная с 3.6, для новых кластеров уже нет смысла его поднимать - но у нас живой кластер с историей, и «просто пересоздать» не вариант.

Что сделали перед выездом в production

После ноябрьского staging добавили ещё один прогон - с реалистичным объёмом ACL и consumer groups. Замерили время каждого этапа до секунды. Обновили мониторинг: вывели KRaft-метрики контроллеров в Grafana рядом с существующими ZooKeeper-дашбордами, чтобы в процессе migration видеть оба источника одновременно.

Runbook вырос до двадцати с лишним шагов с явными go/no-go критериями между этапами. Это кажется избыточным, пока не наступает три часа ночи - тогда хочется именно такой документ.

Миграцию назначили на субботнее утро: нагрузка минимальная, все живые.

Как прошло: пошагово

Шаг первый - обновление брокеров до 3.6 было выполнено ещё за неделю до дня X, rolling по одному. Это отдельный шаг, который стоит не делать в один день с KRaft-migration - меньше переменных.

Шаг второй - деплой KRaft-контроллеров. Три новых процесса на отдельных хостах (не на брокерных нодах - осознанное решение, чтобы не смешивать роли). Отформатировали storage с новым cluster ID, подняли контроллеры в migration-режиме. На этом этапе они подключились к существующему ZooKeeper и начали вытягивать метаданные.

Синхронизация заняла около восьми минут - немного дольше, чем на staging, потому что в production ACL на самом деле больше, чем мы считали. Не критично, но приятно было заранее знать, что это нормально.

Шаг третий - переключение. Вот тут один момент нас напряг. После финализации migration один из пяти брокеров завис на переподключении к новому кворуму дольше ожидаемого - около двух минут без ответа на heartbeat. Остальные четыре уже работали с KRaft, топики обслуживались. Этот брокер в итоге поднялся сам, всё восстановилось - но эти две минуты были некомфортными. На мониторинге было видно временный рост under-replicated partitions по топикам, реплики которых жили на этом брокере.

Разобрались постфактум: на хосте был чуть выше обычного load average из-за параллельного запуска нескольких cron-задач - именно в это утро. Брокер просто медленнее обработал смену метаданных. Никакой системной проблемы KRaft, просто стечение обстоятельств.

Шаг четвёртый - вывод ZooKeeper. После того как все брокеры подтвердили работу с KRaft и under-replicated partitions вернулись к нулю, ZooKeeper-процессы остановили. Дождались пятнадцать минут, убедились что ничего не ломается. ZooKeeper выключен.

Что заняло больше времени, чем рассчитывали

Мониторинговые алерты. В ходе подготовки мы обновили дашборды, но алертинг в части ZooKeeper-специфичных метрик (zookeeper_outstanding_requests, сессионные метрики) не деактивировали заблаговременно. После выключения ZooKeeper они начали стрелять «нет данных» - не критично, но добавляет шум именно в тот момент, когда хочется тишины. Деактивировать такие алерты нужно до начала шага с переключением, а не после.

Это мелочь, но такие мелочи запоминаются.

Оценка рисков по факту

Перед миграцией мы выделили три основных риска.

Синхронизация метаданных - закрылась без проблем, с запасом по времени. Если кластер большой и ACL много - закладывайте время с коэффициентом два к staging.

Consumer group offsets - проверили после переключения несколькими независимыми командами: все группы восстановили offsets корректно, lag не изменился. Этот риск оказался наименее проблемным.

Поведение брокеров при переключении - вот тут сюрприз случился. Не катастрофический, но обратили бы внимание. Rolling migration позволяет одному брокеру задержаться с переключением - кластер при этом деградирует частично, а не падает. Это хорошее свойство, но его нужно учитывать в runbook: явный критерий «ждём до N минут, если брокер не поднялся - escalate».

Итог

Миграция прошла без даунтайма топиков и без потери данных. Общее время от старта KRaft-контроллеров до вывода ZooKeeper - около трёх часов с проверками. Если бы не алертный шум в финале и один медленный брокер - было бы совсем скучно.

Kafka's migration tool в 3.6 работает именно так, как описано в документации: без пересоздания кластера, с откатом до момента финализации. Это принципиально отличает ситуацию от того, что было год назад, когда переезд на KRaft означал новый кластер и ручной перенос данных.

ZooKeeper-кластер теперь истории. На одну движущуюся часть в инфраструктуре клиента стало меньше.

Контакт

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

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