Это перевод статьи из блога ByteByteGo, в которой собрана основная информация о крупном изменении инфраструктуры в Reddit — переносе Apache Kafka с Amazon на Kubernetes.
Команда инженеров Reddit провела одну из самых масштабных миграций инфраструктуры за всю историю компании. Весь парк Apache Kafka, насчитывающий более 500 брокеров и свыше петабайта «живых» данных, переехал с виртуальных машин Amazon EC2 на платформу Kubernetes.
Миграция прошла без простоя, при этом не пришлось менять настройки подключения к Kafka на стороне клиентов.
В этой статье мы разберём, как проходила миграция, с какими вызовами столкнулись инженеры и как им в итоге удалось успешно завершить переезд.
Дисклеймер: вся информация в посте взята из открытых источников, которыми поделились сами инженеры Reddit. Если увидите где-то ошибку — пишите в комментарии.
Какую роль Kafka играет в Reddit
Чтобы было понятнее, о чём речь, давайте для начала разберёмся, что такое Apache Kafka.
Apache Kafka — Open Source-платформа для стриминга сообщений. Одни приложения («продюсеры», producers) пишут сообщения в разделы Kafka («партиции»), а другие («консьюмеры», consumers) их оттуда читают. Kafka находится посередине и отвечает за надёжное хранение этих сообщений, даже если продюсер и консьюмер работают в совершенно разное время. Один сервер Kafka — это брокер; несколько брокеров, работающих вместе, — это кластер.

Apache Kafka в инфраструктуре Reddit — это не просто какой-то вспомогательный инструмент. Это фундамент для сотен критически важных сервисов, которые обрабатывают десятки миллионов сообщений в секунду. В случае сбоя Kafka значительная часть Reddit перестанет работать.
Почему Reddit решил отказаться от EC2
До миграции Reddit управлял брокерами Kafka на инстансах Amazon EC2 с помощью связки из Terraform, Puppet и кастомных скриптов. Инженеры выполняли апгрейды, вносили изменения в конфигурацию и заменяли машины, запуская команды со своих ноутбуков. До поры до времени это работало. Но с ростом числа машин процесс становился всё медленнее, дороже и рискованнее. Требовался более масштабируемый и надёжный способ управлять Kafka.
Решением стал Kubernetes в связке с инструментом под названием Strimzi.
Kubernetes — это платформа с открытым исходным кодом для запуска контейнеризированных приложений и управления ими. Вместо того чтобы вручную заказывать и поддерживать каждый сервер, разработчики просто описывают, что должно работать, а Kubernetes сам занимается развёртыванием, масштабированием и восстановлением после сбоев. Strimzi — проект Cloud Native Computing Foundation, который как раз и позволяет запускать Kafka на Kubernetes. С ним вы можете управлять кластерами Kafka декларативно. То есть разработчики описывают в конфигурационном файле то, что им нужно, а Strimzi сам всё развёртывает, обновляет и обслуживает. В теории это означает меньше ручной работы и более предсказуемую эксплуатацию.
Четыре ограничения, определившие стратегию миграции
В Reddit не стали бросаться и сразу же переносить брокеры. Прежде чем написать хоть строчку кода, они определили четыре жёстких условия, которые сразу отсекли целые классы возможных решений. Вот они:
Kafka должен был работать. Никаких «окон для техобслуживания». Даунтайм, потеря данных или необходимость менять что-то на стороне клиентов были неприемлемы. Это сразу отбросило варианты с плановым переключением, стратегиями двойной записи или миграцией через воспроизведение данных.
Метаданные Kafka невозможно пересоздать. Apache Kafka хранит подробную информацию о внутреннем состоянии (метаданные). Сюда входит информация о том, какие брокеры есть в кластере, какой из них за какие данные отвечает и где хранятся реплики этих данных. Всеми этими метаданными управлял внешний сервис ZooKeeper. Нет никакого официального способа пересоздать эти метаданные на чистом кластере, сохраняя при этом доступность системы. Поэтому новые брокеры должны были именно присоединиться к старому кластеру, а не заменить его.
Клиенты были жёстко привязаны к конкретным брокерам. Так уж повелось, что приложения в Reddit подключались напрямую к хостам определённых брокеров (как правило, к паре-тройке первых в кластере), а не использовали общий эндпоинт с балансировкой нагрузки. Выключение этих брокеров тут же поломало бы сотни сервисов. При этом команда Reddit не контролировала уровень, через который клиенты находили Kafka и подключались к нему.
Каждый шаг должен был быть обратимым. Ни одно действие в процессе миграции не должно было приводить систему в состояние, из которого невозможно восстановление. Это означало, что Reddit был готов долгое время жить в смешанном режиме, когда часть брокеров работала на EC2, а часть — в Kubernetes. Ну и самые рискованные изменения пришлось отложить до полной стабилизации системы.
Этап 1: контроль над DNS
Первый этап миграции вообще не касался Kafka.
Reddit внедрил так называемый DNS-фасад — набор DNS-записей, который работает как прослойка между клиентами и реальными брокерами Kafka. DNS — это система, которая превращает понятные человеку имена сайтов в IP-адреса серверов. Команда создала новые DNS-имена, которыми они могли управлять, и сначала нацелила их на старые EC2-брокеры. С точки зрения клиентских приложений при этом ничего не поменялось.
Затем они выкатили новые адреса подключения на более чем 250 сервисов с помощью автоматических инструментов, которые сами создавали пакеты пул-реквестов для обновления файлов конфигурации. После того как все клиенты стали ходить через этот DNS-слой, можно было перенаправить трафик с EC2 на Kubernetes, просто поменяв DNS-запись и не трогая код клиентов.
Этап 2: место для новых брокеров
У каждого брокера Kafka есть свой уникальный ID. Strimzi по умолчанию начинает нумерацию с нуля. Проблема была в том, что старые брокеры на ЕС2 уже занимали эти начальные номера.
Чтобы освободить их, команда удвоила размер кластера: добавили новые EC2-брокеры с высокими ID, а потом погасили старые брокеры с начальными ID. В результате все данные переехали на брокеры с новыми номерами, а ID 0, 1, 2 и так далее освободились для будущих брокеров, которыми будет управлять Strimzi.
Схема ниже помогает разобраться:

Этап 3: работа в смешанном режиме
Это был самый сложный этап с технической точки зрения.
Нужно было сделать так, чтобы новые Strimzi-брокеры на Kubernetes присоединились к тому же кластеру, где работали старые брокеры на EC2, и могли с ними напрямую общаться. Strimzi такое не умеет «из коробки», поэтому Reddit его форкнул. Все изменения были умышленно минимальными и точечными:
Межброкерные listeners настроили на использование plaintext, чтобы брокеры из EC2 и Kubernetes могли друг с другом общаться.
ZooKeeper использовали старый, который хостился на EC2. Так старые и новые брокеры могли видеть одни и те же метаданные и, по сути, выступать частями одного логического кластера.
Топик для Cruise Control сделали одинаковым для всех наборов брокеров, чтобы можно было с его помощью перекидывать данные между брокерами на EC2 и в Kubernetes. Cruise Control — это утилита для Kafka, которая автоматизирует процесс ребалансировки данных по брокерам. Она сыграла центральную роль в фактическом перемещении данных во время миграции.
Использование форкнутого оператора в продакшене несёт определенные риски. Поэтому изменения были сведены к минимуму. Reddit с самого начала планировал вернуться на ванильный Strimzi, как только миграция закончится.

Этап 4: постепенный перенос данных и трафика
Поскольку оба набора брокеров работали внутри одного кластера, можно было воспользоваться Cruise Control для постепенного переноса лидеров партиций и реплицированных данных с брокеров EC2 на брокеры Kubernetes.
Лидер партиции — это брокер, который отвечает за чтение и запись конкретного куска данных. Для надёжности Kafka хранит копии каждой партиции на нескольких брокерах. Это называется фактором репликации. Перенос данных предполагал последовательное переназначение лидеров и реплик на новую группу брокеров, по одной партиции за раз.
Reddit внимательно мониторил этот процесс: в течение недели количество лидеров на EC2 постепенно падало, а на Strimzi — синхронно росло. Точно так же перетекал и сетевой трафик (см. графики ниже). Если бы что-то пошло не по плану, миграцию в любой момент можно было поставить на паузу или откатить всё назад.

Этап 5: перенос управляющего слоя
Во время переезда брокеров метаданными Kafka управлял ZooKeeper. Инженеры осознанно решили не трогать управляющий слой, пока слой данных не начнёт стабильно работать в Kubernetes. Такое разделение зон ответственности снизило риск каскадных сбоев.
После того как все инстансы EC2 были остановлены, а данные и трафик переехали в Kubernetes, Reddit запустил миграцию с ZooKeeper на KRaft. KRaft — встроенная в Kafka система управления метаданными, которая устраняет необходимость в ZooKeeper.
Схема ниже помогает разобраться:

Поскольку у Strimzi и Kafka есть подробная документация для такой миграции, а вся остальная система уже прижилась на новом месте, этот финальный этап прошёл довольно гладко.
Этап 6: зачистка и переход на стандартный Strimzi
Когда управляющий слой и слой данных полноценно заработали в Kubernetes, инженеры убрали все переопределения конфигов, которые были зашиты в форк оператора Strimzi.
Управление кластерами передали стандартному, оригинальному оператору Strimzi. А старую инфраструктуру на EC2 вывели из эксплуатации.
Заключение
Миграция Reddit — отличный пример того, что большие инфраструктурные изменения не обязательно должны быть рискованными и непредсказуемыми. Разбив процесс на небольшие, обратимые и понятные этапы, а также учитывая имеющиеся системные ограничения, инженеры перенесли платформу петабайтного масштаба на Kubernetes без простоя.
Вот несколько ключевых уроков, которые можно вынести из этой миграции:
Внедрение управляемого слоя абстракции между клиентами и инфраструктурой — будь то DNS, прокси-сервер или API-шлюз — одно из самых рациональных решений во время миграции. Он «отвязывает» клиентов от железа и позволяет менять инфраструктуру, не заставляя каждую команду обновлять свой код.
Метаданные и логическое состояние почти всегда живут дольше, чем железо, на котором они работают. Планируя большой переезд, относитесь к логическому состоянию как к главной ценности, которую нужно сберечь, а к инфраструктуре — как к оболочке, которую вы просто меняете.
Продумывать каждый шаг так, чтобы его можно было отменить, — это не просто подстраховка. Это напрямую влияет на то, как уверенно и быстро можно двигаться вперёд, потому что всегда есть возможность откатиться, если что-то пойдёт не так.
Миграция, которая в середине процесса выглядит хаотично, но не нарушает работу production-среды, гораздо предпочтительнее, чем идеально спланированный переезд, в котором есть один рискованный момент без пути к отступлению.
Полезные ссылки
P.S.
Читайте также в нашем блоге: