Запуск Apache Kafka с ZooKeeper

С выпуском версии 4.0 Apache Kafka лишится поддержки ZooKeeper, и единственным вариантом развёртывания кластера останется использование KRaft, о котором было рассказано в одной из предыдущих статей. Несмотря на это, я предлагаю в этой статье рассмотреть вариант развёртывания кластера Apache Kafka с кворумом Apache ZooKeeper.

Простой кластер для разработки

Простейший кластер для разработки можно запустить двумя командами, не внося изменений в конфигурации:

В результате будет запущен кластер из одного экземпляра ZooKeeper и одного экземпляра Kafka с настройками по умолчанию. Этого вполне достаточно для начала знакомства с Apache Kafka, но я советую разворачивать кластер из трёх экземпляров Kafka для более глубокого погружения в темы партиционирования и реплицирования, которым была посвящена предыдущая статья. Для этого достаточно сделать две копии файла config/server.properties и изменить идентификаторы брокеров, директории хранения данных и порты, на которых Kafka будет ожидать соединения.

Исходный файл server.properties

Файл с настройками второго экземпляра Kafka server_2.properties

Файл с настройками третьего экземпляра Kafka server_3.properties

Теперь осталось запустить 2 и 3 экземпляры Kafka как было показано выше:

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

Apache Kafka с ZooKeeper в Docker

Стандартный образ Apache Kafka не поддерживает запуск с Apache ZooKeeper, но если вы очень этого хотите, то исходный образ нужно немного изменить. Стандартный образ содержит файл /etc/kafka/docker/launch, в котором содержится команда на форматирование директории данных:

Необходимо скопировать этот файл, удалить указанный код и заменить получившимся файлом исходный в образе:

Dockerfile

Останется собрать модифицированный образ и запустить контейнер:

Ошибка UnknownHostException

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

Даже если вы используете ip-адрес в качестве адреса брокера, через который взаимодействуете с кластером, то внутри кластера всё равно используются названия хостов. И клиент, получив от брокера информацию о кластере, пытается взаимодействовать с кластером, используя названия хостов. В данном случае это внутренние для Docker названия хостов, о которых внешний клиент ничего не знает, что и приводит к ошибке.

Чтобы решить эту проблему, нужно правильно сконфигурировать параметры listeners и advertisedListeners (KAFKA_LISTENERS и KAFKA_ADVERTISED_LISTENERS в apache/kafka и KAFKA_CFG_LISTENERS и KAFKA_CFG_ADVERTISED_LISTENERS в bitnami/kafka).

Настройка собственного образа

В listeners нужно перечислить все адреса, которые сервис будет прослушивать для соединения с клиентами: первый — для взаимодействий внутри Docker (в т.ч. между разными контейнерами), второй — для внешних клиентов. В advertisedListeners нужно перечислить адреса, которые будут объявлены сервисом, как используемые: первый будет соответствовать первому адресу из listeners, а второй будет использовать порт из хост-системы, который будет прокинут на второй адрес из listeners. Важно: в кластере объявленные адреса должны быть уникальны.

Полностью все настройки приводить не буду, продемонстрирую только listeners и advertisedListeners:

Порт 19092 будет использован для взаимодействий внутри Docker, а 9092 будет прокинут на порт 29092 в хост-систему для внешних клиентов. Для остальных двух сервисов меняться будет только порт хост-системы: 39092 и 49092.

Описание процесса развёртывания кластера ZooKeeper я вынес в отдельную статью. Процесс демонстрируются, исходя из того, что кластер ZooKeeper запущен в контейнерах, а порты проброшены на следующие порты хост-системы (172.17.0.1): 21812182 и 2183.

Пример запуска контейнеров:

Использование bitnami/kafka

Аналогичного результата можно добиться и при помощи образа bitnami/kafka:

Apache Kafka и ZooKeeper в Docker Compose

Кластер Apache Kafka вместе с ZooKeeper можно описать при помощи Docker Compose, взяв за основу файл, описанный в статье, посвящённой ZooKeeper:

Так же можно использовать образ bitnami/kafka. Для запуска кворума Apache ZooKeeper и кластера Apache Kafka из трёх экземпляров в Docker Compose потребуется следующий файл: