Kafka Kraft Docker Compose跨主机网络访问故障求助
Kafka Kraft (Docker Compose) 跨机器连接问题:无法解析节点ID为0的服务名称
问题描述
在Ubuntu服务器通过Docker Compose部署Kafka Kraft后,本地访问完全正常(可查询topic列表、生产消费消息),但同一局域网内其他机器用FastAPI+AIOKafka连接时出现异常:端口能通过telnet/nc连通,代码却报错无法解析节点ID为0的服务名称。已配置KAFKA_CFG_ADVERTISED_LISTENERS为服务器IP192.168.1.211:9092,防火墙也已放行9092端口,问题仍未解决。
相关配置与信息
Docker Compose 配置
version: '3.8' services: kafka: image: apache/kafka:latest environment: KAFKA_NODE_ID: 0 KAFKA_PROCESS_ROLES: controller,broker KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.1.211:9092 KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT KAFKA_CONTROLLER_QUORUM_VOTERS: 0@kafka:9093 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 ports: - "9092:9092" volumes: - kafka-data:/tmp/kraft-combined-logs volumes: kafka-data:
FastAPI + AIOKafka 测试代码
from fastapi import FastAPI from aiokafka import AIOKafkaProducer, AIOKafkaConsumer import asyncio app = FastAPI() KAFKA_BOOTSTRAP_SERVERS = "192.168.1.211:9092" TEST_TOPIC = "test-topic" @app.get("/produce") async def produce_message(): producer = AIOKafkaProducer(bootstrap_servers=KAFKA_BOOTSTRAP_SERVERS) await producer.start() try: await producer.send_and_wait(TEST_TOPIC, b"test message") return {"status": "success", "message": "Message sent"} finally: await producer.stop() @app.get("/consume") async def consume_message(): consumer = AIOKafkaConsumer(TEST_TOPIC, bootstrap_servers=KAFKA_BOOTSTRAP_SERVERS, group_id="test-group") await consumer.start() try: msg = await consumer.getone() return {"status": "success", "message": msg.value.decode()} finally: await consumer.stop()
报错信息
aiokafka.errors.NodeNotReadyError: Cannot resolve node id 0's hostname: kafka
测试结果
telnet 192.168.1.211 9092连通正常nc -zv 192.168.1.211 9092返回成功kcat -b 192.168.1.211:9092 -L显示节点信息中node id 0的主机名为kafka而非服务器IPnmap 192.168.1.211 -p 9092显示端口开放
解决方案
问题根源在于Kafka Kraft的controller配置使用了容器内部主机名kafka,导致Kafka返回给外部客户端的节点0地址是kafka,而客户端无法解析这个容器内部名称。
1. 修改Docker Compose环境变量
调整controller相关配置,确保所有广告地址使用服务器外部IP:
version: '3.8' services: kafka: image: apache/kafka:latest environment: KAFKA_NODE_ID: 0 KAFKA_PROCESS_ROLES: controller,broker KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 # 外部客户端使用的broker广告地址 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.1.211:9092 # controller的广告地址必须设置为服务器IP KAFKA_CONTROLLER_ADVERTISED_LISTENERS: CONTROLLER://192.168.1.211:9093 KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT # controller quorum voters 使用外部IP替代容器主机名 KAFKA_CONTROLLER_QUORUM_VOTERS: 0@192.168.1.211:9093 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 # 强制broker对外暴露的主机名是服务器IP KAFKA_ADVERTISED_HOST_NAME: 192.168.1.211 ports: - "9092:9092" - "9093:9093" # 开放controller端口,保证Kraft内部通信正常 volumes: - kafka-data:/tmp/kraft-combined-logs volumes: kafka-data:
2. 清理旧数据并重启容器
Kraft会将元数据存储在本地卷中,旧的节点信息会残留,必须删除卷后重新启动:
# 停止并删除现有容器 docker-compose down # 删除Kafka数据卷(替换<your-project-name>为你的Compose项目名) docker volume rm <your-project-name>_kafka-data # 重新启动容器 docker-compose up -d
3. 验证配置正确性
用kcat查看节点信息,确认节点0的主机名是服务器IP:
kcat -b 192.168.1.211:9092 -L
如果输出显示nodeId=0, host=192.168.1.211, port=9092,说明配置正确,此时运行FastAPI+AIOKafka代码即可正常连接。
额外排查点
- 确认客户端机器能正常ping通服务器IP
192.168.1.211 - 检查Docker容器的网络模式,若使用自定义网络,确保端口映射规则正确
- 验证AIOKafka版本与Kafka版本兼容(建议使用相同大版本,如Kafka 3.5对应AIOKafka 2.0+)
内容的提问来源于stack exchange,提问作者blopa
相关产品推荐
相关产品推荐

