本地Docker Compose部署Kafka遇DNS解析故障求助
故障现象
本地通过Docker Compose部署Kafka集群时,Kafka UI的8080端口可正常访问,但无法显示Broker列表。日志报错显示DNS解析失败:
kafka-ui_1 | 2024-11-18 18:07:26,780 WARN [parallel-2] o.a.k.c.ClientUtils: Couldn't resolve server kafka-1:9092 from bootstrap.servers as DNS resolution failed for kafka-1
同时存在容器退出情况:
golang-kafka_kafka-3_1 exited with code 1
问题配置
version: '3' services: kafka-ui: image: provectuslabs/kafka-ui:latest ports: - 8080:8080 environment: KAFKA_CLUSTERS_0_NAME: local KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka-1:9092,kafka-2:9092 KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181 depends_on: - zookeeper zookeeper: image: zookeeper ports: - 2181:2181 environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka-1: image: wurstmeister/kafka ports: - "9095:9094" environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_LISTENERS: INTERNAL://kafka-1:9092,OUTSIDE://kafka-1:9094 KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-1:9092,OUTSIDE://localhost:9095 KAFKA_LOG_DIRS: /kafka/logs KAFKA_BROKER_ID: 500 KAFKA_offsets_topic_replication_factor: 2 volumes: - /var/run/docker.sock:/var/run/docker.sock - ./kafka_data/500:/kafka depends_on: - kafka-ui kafka-2: image: wurstmeister/kafka ports: - "9096:9094" environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_LISTENERS: INTERNAL://kafka-2:9092,OUTSIDE://kafka-2:9094 KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-2:9092,OUTSIDE://localhost:9096 KAFKA_LOG_DIRS: /kafka/logs KAFKA_BROKER_ID: 501 KAFKA_offsets_topic_replication_factor: 2 volumes: - /var/run/docker.sock:/var/run/docker.sock - ./kafka_data/501:/kafka depends_on: - kafka-ui
正常运行的配置
services: zookeeper: image: confluentinc/cp-zookeeper ports: - "2181:2181" environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 ZOOKEEPER_SYNC_LIMIT: 3 kafka1: image: wurstmeister/kafka ports: - 9095:9094 depends_on: - zookeeper environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_LISTENERS: INTERNAL://kafka1:9092,OUTSIDE://kafka1:9094 KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:9092,OUTSIDE://localhost:9095 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT KAFKA_BROKER_ID: 500 KAFKA_offsets_topic_replication_factor: 3 volumes: - /var/run/docker.sock:/var/run/docker.sock - ./kafka_data/500:/kafka kafka2: image: wurstmeister/kafka ports: - 9096:9094 depends_on: - zookeeper environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_LISTENERS: INTERNAL://kafka2:9092,OUTSIDE://kafka2:9094 KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka2:9092,OUTSIDE://localhost:9096 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT KAFKA_BROKER_ID: 501 KAFKA_offsets_topic_replication_factor: 3 volumes: - /var/run/docker.sock:/var/run/docker.sock - ./kafka_data/501:/kafka kafka3: image: wurstmeister/kafka ports: - 9097:9094 depends_on: - zookeeper environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_LISTENERS: INTERNAL://kafka3:9092,OUTSIDE://kafka3:9094 KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka3:9092,OUTSIDE://localhost:9097 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT KAFKA_BROKER_ID: 502 KAFKA_offsets_topic_replication_factor: 3 volumes: - /var/run/docker.sock:/var/run/docker.sock - ./kafka_data/502:/kafka kafka-ui: image: provectuslabs/kafka-ui:latest ports: - 8080:8080 environment: KAFKA_CLUSTERS_0_NAME: local KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka1:9092,kafka2:9092,kafka3:9092 KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181 depends_on: - zookeeper
故障原因分析
对比两个配置的差异,DNS解析失败的核心原因如下:
1. 服务名称的DNS兼容性问题
问题配置中Kafka服务名使用kafka-1、kafka-2(包含连字符),而正常配置使用kafka1、kafka2(纯字母数字)。虽然Docker网络理论上支持带连字符的服务名,但Kafka UI使用的Java Kafka客户端对包含连字符的主机名可能存在DNS解析兼容问题——早期Java版本的DNS解析逻辑对这类特殊字符的主机名处理存在bug,部分镜像的DNS配置也可能对这类名称的解析支持不佳,导致无法解析kafka-1这类服务名。
2. 容器启动依赖顺序完全倒置
问题配置中,kafka-1、kafka-2的depends_on设置为依赖kafka-ui,这会导致Kafka UI先启动,此时Kafka Broker容器尚未启动,对应的服务名还未注册到Docker网络的DNS服务器中。当Kafka UI尝试连接kafka-1:9092时,自然无法解析到对应的容器IP,触发DNS解析错误。
正常配置则遵循正确的依赖顺序:Kafka Broker依赖Zookeeper,Kafka UI依赖Zookeeper(实际应优先依赖Broker),保证Broker在UI之前启动并完成DNS注册。
3. 缺失Kafka监听器安全协议映射
问题配置的Kafka服务未设置KAFKA_LISTENER_SECURITY_PROTOCOL_MAP参数,而正常配置明确指定了INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT的映射关系。该参数是Kafka监听器配置的核心,缺失会导致Broker无法正确初始化监听器,进而无法正常注册到Zookeeper,最终Broker容器启动失败或异常退出,服务名从DNS中消失,导致UI无法解析。
4. 副本因子与Broker数量的潜在冲突
问题配置中KAFKA_offsets_topic_replication_factor设置为2,同时只有2个Broker,虽然理论上副本因子可以等于Broker数量,但如果Broker启动时无法成功创建offsets topic(比如网络延迟或Zookeeper未就绪),会导致Broker容器异常退出,进一步加剧DNS解析问题。正常配置中3个Broker对应副本因子3,避免了这类潜在冲突。
内容的提问来源于stack exchange,提问作者lara

