Лучший опыт

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

Введение Раньше на рынке не было сложных управляемых служб Kafka. Поэтому мы в Zendesk построили с помощью Chef собственную инфраструктуру, развернув ее на экземплярах AWS EC2. Инфраструктура Kafka в виртуальной машине Кластер Kafka состоит из двух частей: набора брокеров Kafka и узлов Zookeeper. Брокер ― это сервер в кластере Kafka, в котором хранятся и контролируются данные, ведется работа по публикации сообщений и подписке на них. Кластер Zookeeper ― это квор?
Плавный переход: миграция кластера Kafka в Kubernetes...

Введение

Раньше на рынке не было сложных управляемых служб Kafka. Поэтому мы в Zendesk построили с помощью Chef собственную инфраструктуру, развернув ее на экземплярах AWS EC2.

Инфраструктура Kafka в виртуальной машине

Кластер Kafka состоит из двух частей: набора брокеров Kafka и узлов Zookeeper. Брокер ― это сервер в кластере Kafka, в котором хранятся и контролируются данные, ведется работа по публикации сообщений и подписке на них. Кластер Zookeeper ― это кворум, которым координируются и контролируются брокеры Kafka, выполняются задачи вроде выбора лидера, принадлежности к кластеру, поддержания метаданных.

Мы перенесли инфраструктуру с виртуальной машины в Kubernetes, или K8s. Поддержка инструментария Chef сократилась, поэтому потребовалась миграция инфраструктуры Kafka.

Определение плавной миграции

Плавная миграция для кластера Kafka ― прозрачный процесс с нулевым простоем, поддержкой целостности и согласованности данных, минимальными изменениями со стороны клиентов и минимальным ручным вмешательством.

Это репликация конфигурации и данных старого кластера, перевод клиентов на новый, обеспечение непрерывности работы и эквивалентной производительности.

Сложность плавной миграции напрямую связана с масштабом кластера и его клиентами. Миграция кластера, используемого нечасто или для обработки в основном автономных рабочих нагрузок, относительно проста. А вот миграция кластера, в котором обслуживаются серьезные рабочие нагрузки в реальном времени и значительный объем данных, намного сложнее.

Кластеры Kafka в Zendesk относятся ко второй категории. В них осуществляется управление существенным объемом данных более чем 100 служб.

Подробное состояние кластера Kafka:

  • 12 кластеров Kafka;
  • немногим менее 100 брокеров во всех средах;
  • 300 ТБ данных в хранилище;
  • 30 млрд сообщений в день;
  • более 1000 тем;
  • более 100 подключенных служб.

Основные проблемы

Миграцию такого большого и важного кластера требуется тщательно продумать, уделив внимание деталям, а главное, обеспечить:

  • целостность данных и доступность кластера на этапе репликации,
  • плавность перехода клиентов на этапе переключения.

Важно понимать: нет одномоментного переключения, когда после полной репликации всех данных клиенты массово перемещаются на новый кластер. Миграция потому и плавная, что на этапе переключения данные реплицируются непрерывно и одновременно с переходом клиентов.

Проект миграции

Однонаправленная миграция из кластера в кластер

Проект первой версии ― однонаправленная миграция из кластера в кластер. Здесь данные и конфигурации реплицируются из старого кластера в новый с помощью MirrorMaker2. После того как начальная загрузка данных перенесена между кластерами, данные остаются синхронизированными и каждый клиент осуществляет переходный процесс, отключаясь от старого кластера и подключаясь к новому:

Однонаправленная репликация конфигурации и данных с помощью Mirror Maker 2

Проблема: сложность миграции перекладывается на клиентов

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

Например, в простейшем сценарии, когда одна команда контролирует и отправителя, и получателя темы, сопровождаемый изменениями кода и неоднократными развертываниями перенос клиентов происходит так:

  • в новый кластер перемещаются все получатели;
  • отправка в старый кластер прекращается;
  • в новом кластере данные полностью синхронизируются;
  • запускается отправитель, указывая на новый кластер.

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

Дополнительные накладные расходы

Для этого конкретного проекта миграции имеются дополнительные накладные расходы:

  • Единая точка отказа ― кластер подключения MirrorMaker2. Когда все получатели темы мигрировали в новый кластер, но окончательные данные в процессе выполнения синхронизировать из старого кластера не удается из-за сбоя MirrorMaker2.
  • Косвенность в обнаружении сбоев и отработке отказа. Хотя сбой MirrorMaker2 неподконтролен каждой из команд, процесс отработки отказа клиента полностью зависит от них, поскольку при этом требуются изменения кода или повторное развертывание предыдущей версии.
  • Проблема длинного хвоста. Полное завершение миграции зависит от скорости самого медленного клиента. Из-за упомянутой выше сложности ряду клиентов требуется значительно больше времени на завершение миграции, в итоге реализация проекта в целом замедляется.
  • Затраты. На этом этапе затраты брокеров на вычисление и хранение удваиваются, а на передачу данных ― их перемещение от старых брокеров в кластер подключения, а затем к новым брокерам ― утраиваются.

Межкластерная миграция достижима, но мы стремимся к большему

Этот подход ― ни плавная миграция с точки зрения клиента, ни практическая реализация в таком масштабе по операциям и экономической эффективности.

Миграция на уровне брокеров в объединенном кластере Kafka

Основная проблема межкластерной миграции заключается в том, что в какой-то момент клиенты должны указывать на другой кластер. Время перехода ― для обеспечения целостности данных ― у получателей и отправителей различается.

Чтобы решить проблему, поставим вопрос радикальнее: «Могут ли клиенты не зависеть от переключения кластера?»

Повторим, миграция кластера ― это репликация конфигураций и данных из старого кластера в новый, а также переход клиентов.

Но что, если исключить из уравнения переход клиентов? Создадим не новый кластер, а набор брокеров в K8s и зарегистрируем их с имеющимся кластером. Так, клиентам уже не нужно менять кластеры. Остается только перенести данные от старых брокеров к новым в этом объединенном кластере Kafka.

В самом деле, новые брокеры присоединятся к имеющемуся кластеру, поэтому в переносе конфигурации нет необходимости. Нужные конфигурации уже в кластере, так что процесс упрощается.

Брокеры EC2 и K8s регистрируются в одном кластере, при этом данные переносятся от брокеров EC2 к брокерам K8s

Почему передача данных между брокерами приводит к переключению клиентов?

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

Когда данные тем переносятся от одного брокера к другому, фактически переносятся реплики. Как только реплика полностью перенесена и выбрана лидером, это изменение обнаруживается клиентом, и начинается взаимодействие с новой репликой-лидером. В итоге начинается взаимодействие клиента с новым брокером.

Реплика-лидер перенесена к новому брокеру для взаимодействия с ним клиента

Согласно этой схеме, как только все реплики перенесены к новым брокерам, все клиенты взаимодействуют с новыми брокерами, а старыми важных задач больше не выполняется.

Разложим этот подход на этапы

  • Разворачиваем столько же брокеров в K8s и регистрируем их в том же кластере Kafka в ZooKeeper. На этом этапе брокеры EC2 и K8s принадлежат одному кластеру, но в брокерах EC2 остаются все данные и обрабатывает весь клиентский трафик. Брокеры K8s неактивны, с ZooKeeper только поддерживается их работоспособность.
  • Реплики разделов тем начинают мигрировать из брокеров EC2 к брокерам K8s. Как только реплика полностью перенесена, брокеры K8s начинают обслуживать актуальные темы клиентов, исходя из того, имеется ли в них реплика-лидер.
  • Все реплики разделов тем перенесены от брокеров EC2 к брокерам K8s. В брокерах EC2 больше нет данных, и запросы клиентов не обрабатываются.
  • Количество брокеров EC2 сокращается, в кластере остаются лишь брокеры K8s. Миграция завершена.
Миграция на уровне брокеров в объединенном кластере Kafka

Следуя этапам миграции, мы избавились от необходимости перехода клиента. Поскольку клиенты все это время взаимодействуют с одним кластером, миграция становится для них абсолютно плавной.

Подробный разбор

От общей картины перейдем к конкретной настройке:

  • Настройка сети. Важно объединить два разных набора брокеров, облегчить их обнаружение клиентами в этом гибридном кластере Kafka.
  • Реализация и оркестрация миграции. Важна не только реализация переноса реплик к новым брокерам, но и эффективная оркестрация, которой должны учитываться и сценарии аварийного восстановления, например откаты.
  • Показатели и мониторинг. Эффективный мониторинг гибридного кластера  —  когда брокерами EC2 и K8s обрабатывается трафик  —  важен для выявления проблем, отладки и тонкой настройки производительности.
  • Контроль за перебоями в работе брокеров. Для высокой доступности нужны безостановочные брокеры или не допускать, чтобы брокеры из разных зон доступности отключались даже во время миграции.

Настройка сети для взаимодействия между брокерами, а также клиентом и брокером

Важная предпосылка миграции на уровне брокера ― взаимодействие обоих наборов брокеров с кластером ZooKeeper при относительно низкой задержке. А также возможность обнаружения клиентами обоих наборов брокеров и взаимодействия с ними при низкой задержке.

Первый вопрос решается сетевой архитектурой. Брокеры EC2, кластеры Zookeeper и K8s развернуты хоть и в разных подсетях, но взаимосвязанных, и в одной учетной записи AWS.

Чтобы брокеры EC2 и K8s обнаруживались клиентами, придется еще немного повозиться. Сначала разберемся в механизме обнаружения клиентами брокеров.

Механизм обнаружения брокеров клиентами

Для корректной работы, исходя из количества разделов в целевой теме и распределения реплик этих разделов, клиенту Kafka нужно «знать» почти каждого брокера. Типичный подход:

  1. Для извлечения метаданных о том, каким брокером какие разделы обслуживаются, клиентом выбирается брокер начальной загрузки.
  2. Клиентом запрашивается установка подключения с каждым из этих брокеров.
Модель обнаружения брокеров клиентами

Следовательно, клиентам должен быть доступен обратный прокси-сервер, определенный для брокеров EC2, и такой же для брокеров K8s. Поскольку все брокеры находятся в одном кластере, любым из них клиенту предоставляются полные метаданные ― будь то EC2 или K8s.

IP-адрес службы обратного прокси-сервера регистрируется в службе Consul

Службы обнаруживаются HashiCorp-службой Consul. Чтобы обнаружить оба набора брокеров, в имеющейся в Kafka службе Consul клиентами регистрируется новый IP-адрес службы обратного прокси-сервера. В K8s объявленный прослушиватель для каждого брокера и обратный прокси-сервер этих прослушивателей ― K8s Service.

Реализация и оркестрация миграции

Пока все хорошо, кластер Kafka со взаимосвязанными брокерами ― будь то EC2 или K8s ― настраивается. Клиентами обнаруживается любой брокер, они подключаются к нему. Но как реплики перемещаются от одного брокера к другому?

Перемещение реплики осуществляется с помощью Cruise Control, где имеются полнофункциональные API-интерфейсы для управления кластером Kafka в больших масштабах. remove_broker ― одна из конечных точек для перемещения реплик, в которой брокер сворачивается, а все его реплики перемещаются к целевому брокеру.

curl -X POST "$CRUISE_CONTROL_SERVICE/remove_broker?brokerid=11&concurrent_partition_movements_per_broker=25&destination_broker_ids=31&replication_throttle=100000000"

Это запрос к Cruise Control на перемещение всех реплик из «broker-11» в «broker-31». То, что нужно. Им также определяется что в каждый конкретный момент времени разрешено перемещение всего 25 одновременно выполняемых реплик, а общая скорость репликации ― ~100 Mбит/с.

Оркестрация

Вызывать конечную точку Cruise Control вручную нецелесообразно, небезопасно и неэффективно. Поэтому и создали систему оркестрации Kafka-Migration для:

  • Проверки условий миграции. Например, перед выполнением любых вызовов перемещения реплик ею проверяется, в работоспособном ли состоянии кластер и находятся ли цель и конечный брокер в одной зоне доступности.
  • Полнофункциональных режимов миграции. В системе имеются различные режимы миграции: в режиме конкретных брокеров данные перемещаются от конкретного набора брокеров к другому; в режиме зон доступности перемещение данных от имеющихся брокеров к целевым в пределах одной зоны доступности упрощается; в режиме полной миграции контролируется полное перемещением данных в новый набор брокеров, обеспечивается корректное присвоение реплик, оркестрируется перемещение в каждой зоне доступности. С установкой этих режимов и правил системой гарантируется перемещение реплики в безопасной и управляемой области. В итоге последствия минимизируются, а реакция на любые инциденты во время перемещения быстрая.
  • Детализированного контроля миграции. Кроме однонаправленной миграции, поддерживаются операции остановки, возобновления и отмены. Например, во время неожиданного всплеска, чтобы увеличить пропускную способность рабочего трафика, миграцию останавливают, а после затухания  —  возобновляют.

Показатели и мониторинг

Сбор показателей и создание инструментов важны для выявления проблем и понимания функционирования кластера во время миграции. Имеется три различных источника показателей, собираемых для Kafka: JMX-метрики брокера Kafka, метрики системного уровня брокера, метрики AWS EBS.

Метрики JMX и EBS в целом согласованы между EC2 и K8s, поэтому во время миграции остаются практически неизменными. Различаются они лишь тегами для метрик брокеров EC2 и K8s. Повторно сопоставить эти теги с имеющейся системой мониторинга несложно.

Метрики системного уровня брокера поинтереснее, ведь EC2  —  это виртуальная машина, а под K8s  —  группа контейнеров. Метрики виртуальных машин иногда не обнаруживаются в контейнерных метриках. Так, у показателя средней нагрузки, которым измеряется рабочая нагрузка на центральный процессор хоста с течением времени и указывается, насколько загружена система, нет прямого эквивалента на уровне контейнеров. Пожалуй, ближайший аналог  —  показатель регулируемой частоты процессора, но это не совсем то же.

Оптимальнее для выявления проблем высокоуровневые метрики. Скажем, JMX-метриками брокера Kafka неплохо указывается на проблему исчерпания ресурсов: задержка отправителя, емкость сетевого пула, емкость обработчика запросов, задержка репликации.

Контроль за перебоями в работе брокера

Наконец, во время миграции нужно тщательно контролировать перебои в работе брокера, то есть любые проблемы или события, из-за которых он функционирует некорректно или становится недоступным. Различают перебои непроизвольные, например из-за аппаратного сбоя, и произвольные, например из-за перезапуска брокеров без остановки.

Плохой контроль за перебоями чреват низкой доступностью

Для кластера Kafka, состоящего из брокеров трех зон доступности, где большинство тем настроены с тремя репликами и минимум двумя синхронизированными репликами, потеря брокеров в одной зоне доступности приемлема. А вот потеря двух брокеров из двух разных зон доступности чревата проблемами «отключенных разделов», так как минимальное количество синхронизированных реплик ― две:

Отключенные разделы при потере брокеров двух разных зон доступности

Нужно создать систему для максимально возможного предотвращения этого сценария. Непроизвольные перебои неизбежны, а значит, нужно предотвратить произвольные, которые случаются во время инцидента с непроизвольным перебоем.

Бюджет перебоев в работе подов со службой мониторинга Kafka

Чтобы отслеживать разворачиваемые в K8s поды брокеров, создан бюджет перебоев в работе подов на K8s. После обнаружения отключенного брокера бюджетом перебоев подов, чтобы предотвратить вытеснение других брокеров в K8s, бюджет перебоев нарушается.

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

Бюджет перебоев подов настраивается для мониторинга службы Kafka Monitoring Service и разворачиваемых в K8s брокеров. Им обнаруживаются отключенные брокеры K8s и EC2, первые ― непосредственным отслеживанием подов брокеров, вторые ― через службу мониторинга Kafka.

Чтобы предотвращать неожиданные перебои, бюджетом перебоев подов отслеживаются служба мониторинга Kafka и брокеры K8s

Миграция Zookeeper

Мы перенесли брокеры Kafka из экземпляров EC2 в K8s. Однако кластер Zookeeper по-прежнему запускается в экземплярах EC2.

Kafka в K8s, Zookeeper в EC2

Конечно, кластер Zookeeper переносится аналогично брокерам Kafka. Но имеется и другой способ. В Kafka версии 3.6 наконец стал общедоступным Kraft, с помощью которого Zookeeper заменяется брокерами с ролью контроллера. Брокеры уже запускаются в K8s, поэтому с ролью контроллера легко настроить новый набор брокеров.

Zookeeper переносится в контроллер Kraft

Заключение

Применив стратегию миграции на уровне брокеров в объединенном кластере Kafka, мы перенесли все кластеры Kafka на K8s. С точки зрения клиентов, этот процесс абсолютно плавный и без инцидентов, вызванных миграцией.

Управлять Kafka в K8s намного проще, чем на EC2, благодаря надежной, масштабируемой, гибкой платформе K8s, на которой автоматизируются многие рабочие задачи: от развертывания до мониторинга, масштабирования и самовосстановления. Благодаря четко определенным объектам K8s и определениям специальных ресурсов, на основе Kafka создаются операторы для дальнейшей автоматизации рабочих задач.

С усовершенствованной автоматизацией и уменьшенными накладными расходами работа команды в экосистеме Kafka ускоряется, время разработки высвобождается на новые задачи.