Вопрос или проблема
Я хочу создать кластер Kafka в режиме KRaft с двумя контроллерами и двумя брокерами. Я написал конфигурацию:
services:
kafka-controller-1:
image: 'bitnami/kafka:latest'
environment:
- KAFKA_CFG_NODE_ID=0
- KAFKA_KRAFT_CLUSTER_ID='4ea7fcb4a2fb4dc8a402d4103ee414eb'
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka-controller-1:9092,1@kafka-controller-2:9092
- KAFKA_CFG_PROCESS_ROLES=controller
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENERS=CONTROLLER://kafka-controller-1:9092
- KAFKA_CFG_ADVERTISED_LISTENERS=CONTROLLER://kafka-controller-1:9092
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT
kafka-controller-2:
image: 'bitnami/kafka:latest'
environment:
- KAFKA_CFG_NODE_ID=1
- KAFKA_KRAFT_CLUSTER_ID='4ea7fcb4a2fb4dc8a402d4103ee414eb'
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka-controller-1:9092,1@kafka-controller-2:9092
- KAFKA_CFG_PROCESS_ROLES=controller
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENERS=CONTROLLER://kafka-controller-2:9092
- KAFKA_CFG_ADVERTISED_LISTENERS=CONTROLLER://kafka-controller-2:9092
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT
kafka-broker-1:
image: 'bitnami/kafka:latest'
environment:
- KAFKA_CFG_NODE_ID=2
- KAFKA_KRAFT_CLUSTER_ID='4ea7fcb4a2fb4dc8a402d4103ee414eb'
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka-controller-1:9092,1@kafka-controller-2:9092
- KAFKA_CFG_PROCESS_ROLES=broker
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENERS=PLAINTEXT://kafka-broker-1:9092
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
kafka-broker-2:
image: 'bitnami/kafka:latest'
environment:
- KAFKA_CFG_NODE_ID=3
- KAFKA_KRAFT_CLUSTER_ID='4ea7fcb4a2fb4dc8a402d4103ee414eb'
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka-controller-1:9092,1@kafka-controller-2:9092
- KAFKA_CFG_PROCESS_ROLES=broker
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_LISTENERS=PLAINTEXT://kafka-broker-2:9092
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
kafka-ui:
container_name: kafka-ui
image: 'provectuslabs/kafka-ui:latest'
environment:
- KAFKA_CLUSTERS_0_NAME=test-local
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka-broker-1:9092
depends_on:
- kafka-controller-1
- kafka-controller-2
- kafka-broker-1
- kafka-broker-2
ports:
- '1354:8080'
Это работает, UI показывает мне два брокера, и один из них является контроллером. (Я не могу опубликовать изображение, нужно 10 репутации)
Мои вопросы:
- Почему я вижу только два брокера и ни одного из моих контроллеров?
- Почему один из брокеров является контроллером, если я настроил другие два контроллера?
Дополнительно:
-
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
настроен для брокеров, потому что без этого я получаю ошибку:Exception in thread “main” java.lang.IllegalArgumentException: requirement failed: controller.listener.names must contain at least one value when running KRaft with just the broker role
-
Если я подключу интерфейс к контроллеру
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka-controller-1:9092
, UI не может запросить METADATA:2025-02-08 00:18:21 2025-02-07 21:18:21,979 INFO [kafka-admin-client-thread | kafka-ui-admin-1738963090-1] o.a.k.c.a.i.AdminMetadataManager: [AdminClient clientId=kafka-ui-admin-1738963090-1] Metadata update failed
2025-02-08 00:18:21 org.apache.kafka.common.errors.UnsupportedVersionException: The broker does not support METADATA
Ответ или решение
Создание Kafka кластера в KRaft режиме с использованием Docker – задача, требующая тщательной настройки конфигураций для корректной работы всех компонентов. Рассмотрим подробно ваш случай для разъяснения ключевых моментов.
Теория
Apache Kafka в KRaft режиме (KRaft – это Kafka Raft metadata management mode) замещает необходимость использовать отдельный ZooKeeper для управления метаданными. В данном режиме контроллеры и брокеры работают в едином кластере, где контроллеры управляют метаданными, использованием Raft протокола для достижения консенсуса.
При настройке кластера в KRaft режиме важно правильно разграничить роли контроллеров и брокеров. Все узлы (или ноды) в кластере должны быть правильно сконфигурированы с учетом их специфических ролей для обеспечения стабильной и надежной работы.
Пример
В вашем примере конфигурации Kafka кластера через Docker Compose представлено четыре основных сервиса: два контроллера (kafka-controller-1 и kafka-controller-2) и два брокера (kafka-broker-1 и kafka-broker-2). Дополнительно вы включаете сервис для отображения пользовательского интерфейса – kafka-ui. Рассмотрим основные части вашей конфигурации более детально:
-
Узлы контроллеров:
- Каждый контроллер настраивается с уникальным идентификатором узла через переменную
KAFKA_CFG_NODE_ID
. - Кластерное решение поддерживается за счёт
KAFKA_KRAFT_CLUSTER_ID
– уникального идентификатора кластера. - Параметр
KAFKA_CFG_CONTROLLER_QUORUM_VOTERS
указывает на других участников кворума (контроллеров), обеспечивая консенсус.
- Каждый контроллер настраивается с уникальным идентификатором узла через переменную
-
Узлы брокеров:
- Брокеры также получают уникальные
KAFKA_CFG_NODE_ID
. - Они связываются с контроллерами через такие параметры, как
KAFKA_CFG_CONTROLLER_LISTENER_NAMES
, чтобы избегать ошибок, связанных с необходимостью конфигурации.
- Брокеры также получают уникальные
-
Общий момент:
- Все узлы разделают
KAFKA_KRAFT_CLUSTER_ID
, так как это один кластер. - Для сетевых соединений используется
PLAINTEXT
в параметреKAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP
, что может быть приемлемо для локальных или тестовых окружений, хотя для продакшн следует использовать TLS.
- Все узлы разделают
Применение
Причины проблем, которые вы наблюдаете, связаны с определенными нюансами конфигурации и пониманием, как компоненты взаимодействуют:
-
Почему видны только брокеры:
Пользовательский интерфейс Kafka, который вы используете, возможно, заточен под работу с брокерами и не отображает контроллеры, так как метаданные о контроллерах могут не приниматься брокерским API, к которому элемент управления подключается. -
Брокер выступает в роли контроллера:
Вероятно, это связано с тем, что в KRaft режиме каждый узел, выполняющий роль контроллера, также может администрировать некоторые брокерские операции для поддержки отказоустойчивости и избыточности. Однако это не значит, что брокер «становится» контроллером в функциональном смысле. -
Ошибка при подключении UI к контроллеру:
Контроллеры не обслуживают запросы клиента, такие как METADATA, поскольку напрямую работают только с внутренними данными кластера. Для получения метаданных и других данных о кластерной конфигурации инструменту UI необходимо подключиться к брокерам.
Ваш случай подчеркивает важность понимания роли каждого компонента в KRaft режиме и корректного отображения структурных особенностей конфигураций в связке Docker, что может предотвратить подобные нестыковки в дальнейшем.