Docker环境下如何配置Kafka broker实现节点互通并解决连接报错
该报错90%以上不是leader与follower的直接连通故障,是Kafka监听器配置不匹配导致的:Kafka需要区分容器内部集群通信、外部客户端(宿主机/其他机器)访问两类场景的监听地址,如果对外广播的访问地址配置为localhost,其他容器内的broker访问localhost时会解析到自身容器,而非目标broker,就会触发连通失败提示。
报错原文:WARN [AdminClient clientId=adminclient-1] Connection to node -2 (localhost/127.0.0.1:29092) could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
1. 修正docker-compose.yml的broker核心配置
每个broker节点都需要配置三类监听器相关的环境变量,以节点名为kafka1、对外端口29092的broker为例,配置如下:
services: kafka1: image: confluentinc/cp-kafka:latest environment: # 定义容器内监听的所有端口,0.0.0.0表示监听容器所有网卡 KAFKA_LISTENERS: INTERNAL://0.0.0.0:9092,EXTERNAL://0.0.0.0:29092 # 广播给客户端和其他broker的访问地址,内部通信填broker的容器服务名,外部访问填宿主机IP/localhost KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:9092,EXTERNAL://localhost:29092 # 定义两类监听器的安全协议 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT # 指定broker之间集群通信走内部监听器,避免走localhost地址 KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL # Zookeeper连接地址填三个zk节点的容器服务名+端口 KAFKA_ZOOKEEPER_CONNECT: zk1:2181,zk2:2181,zk3:2181
另外两个broker只需对应修改KAFKA_ADVERTISED_LISTENERS里的服务名、对外端口即可,比如kafka2的对外端口可设为29093,配置为INTERNAL://kafka2:9092,EXTERNAL://localhost:29093。
2. 修正端口映射配置
每个broker的端口映射要和外部监听器的端口一一对应,不要重复:
# kafka1的端口映射 ports: - "29092:29092" # kafka2的端口映射 ports: - "29093:29092" # kafka3的端口映射 ports: - "29094:29092"
3. 验证集群内部连通性
重启集群后进入任意一个kafka容器,执行以下命令检查集群状态:
# 查看所有broker的接口信息,正常会返回3个broker的记录 kafka-broker-api-versions.sh --bootstrap-server kafka1:9092,kafka2:9092,kafka3:9092
如果返回正常说明集群内部通信已经恢复。
4. 修正外部客户端访问配置
在宿主机执行创建topic、生产消费命令时,bootstrap-server参数需要填写所有broker的对外地址:
# 创建topic示例 kafka-topics.sh --create --topic test-topic --bootstrap-server localhost:29092,localhost:29093,localhost:29094 --partitions 3 --replication-factor 3
不要只填单个broker地址,避免该节点不是controller导致请求失败。
- 确认所有broker和zookeeper节点在同一个docker网桥下,没有跨网络隔离
- 不要在
KAFKA_ADVERTISED_LISTENERS的内部通信地址里填127.0.0.1/localhost,否则容器之间无法正常寻址 - 检查zookeeper集群状态,确保三个zk节点都正常选主运行
内容的提问来源于stack exchange,提问作者Chenphop Chanphum

