K8s环境Kafka重部署报NOT_LEADER_OR_FOLLOWER错误排查咨询
根因定位
你遇到的永久NOT_LEADER_OR_FOLLOWER报错,本质是Kafka生产者持续向错误的节点发送生产请求,目标节点既不是对应分区的Leader也不是Follower,且客户端始终没有获取到最新的集群元数据,才会出现剩余重试次数高达2147483138(接近Integer.MAX_VALUE,即无限重试配置)、永远无法自恢复的现象。结合你描述的「本地连接集群正常、仅K8s内重部署后触发、销毁命名空间重建才恢复」的特征,核心原因集中在4类:
- Broker监听器配置错误:AWS环境部署Kafka时如果混用内外网访问地址,尤其是把K8s内部访问的
advertised.listeners配置为可变的Pod IP,重调度Broker后Pod IP变更,客户端缓存的旧地址被其他新启动的Pod占用,该节点不持有对应分区副本,就会持续抛错。 - DNS缓存配置不合理:JVM默认在开启SecurityManager时会永久缓存DNS解析结果,加上CoreDNS如果配置了过长的缓存TTL,重部署后Broker Pod IP变化,客户端始终解析到失效的旧IP,且因为访问的节点返回的错误不会触发全量元数据刷新,就会陷入死循环重试。销毁命名空间相当于重建所有客户端Pod清空了本地缓存,所以能临时恢复。
- K8s网络层规则残留:如果通过普通ClusterIP Service访问Kafka,重调度Broker时Service Endpoint更新延迟、iptables/IPVS规则残留,会持续把请求转发到已经下线的旧Broker节点;如果集群部署了Service Mesh,sidecar的长连接路由规则不随Pod重调度更新,也会出现同类问题。
- 客户端参数配置缺陷:仅调整
client.dns.lookup但没有同步缩短元数据自动刷新间隔,默认5分钟的元数据刷新周期加上错误触发刷新的逻辑失效,会导致客户端长期持有旧的集群拓扑信息。
本地连接集群正常是因为本地访问走的是AWS NLB固定地址,不存在IP可变、缓存残留的问题,所以不会触发该故障。
可落地解决方案
按以下优先级调整配置,可彻底解决该问题:
1. 修正Kafka Broker多监听器配置
AWS环境部署Kafka必须严格区分内外网监听器,禁止混用地址:
- 内部监听器绑定
0.0.0.0:9092,advertised.listeners统一配置为StatefulSet对应的无头Service(Headless Service)固定域名,格式参考INTERNAL://kafka-0.kafka-headless.<kafka所在命名空间>.svc.cluster.local:9092,不要用可变的Pod IP作为对外广播的地址。 - 外部监听器绑定
0.0.0.0:9094,advertised.listeners配置为AWS NLB的固定域名,供集群外的本地环境、跨VPC服务访问。 - 配置
listener.security.protocol.map匹配两个监听器的安全协议,设置inter.broker.listener.name=INTERNAL,保证Broker之间同步走内部域名,不绕外部负载均衡。
2. 调整客户端配置
- 给客户端应用的JVM加启动参数,修改DNS缓存TTL,禁止永久缓存解析结果:
-Dsun.net.inetaddr.ttl=30 -Dsun.net.inetaddr.negative.ttl=10
配置后JVM最多缓存30秒正向DNS结果、10秒负向解析结果,Broker IP变更后最多30秒就能拿到新的解析地址。
- 修正Kafka生产者参数,不要仅调整
client.dns.lookup:- 设置
client.dns.lookup=use_all_dns_ips - 把
metadata.max.age.ms从默认的300000(5分钟)调整为60000(1分钟),强制客户端每分钟主动全量刷新一次集群元数据,避免长期持有旧拓扑 - 设置
reconnect.backoff.ms=1000、reconnect.backoff.max.ms=10000,避免重连间隔过长导致恢复缓慢
- 设置
3. 排查K8s网络层配置
- 调整CoreDNS配置,把集群内域名的缓存TTL设置为30秒以内;给客户端Pod加
dnsConfig配置,把ndots从默认的5改成2,减少无效的域名搜索解析。 - 访问Kafka统一用无头Service地址,不要用开启了ClientIP会话保持的普通ClusterIP Service,避免iptables/IPVS规则残留导致流量转发错误。
- 如果集群部署了Istio、Linkerd等Service Mesh组件,先给Kafka Broker和客户端配置sidecar注入排除规则,验证是否为sidecar路由规则不更新导致的流量转发异常。
故障快速定位方法
下次故障复现时无需删除命名空间,按以下步骤可快速定位根因:
- 进入故障客户端Pod,用自带的
kafka-console-producer.sh脚本直接连接Broker无头Service地址发测试消息,如果发送正常,说明是业务应用本身的DNS缓存、客户端元数据缓存问题。 - 在客户端Pod内用
nslookup解析每个Broker的域名,对比返回的IP和Broker当前实际运行的Pod IP,如果不一致就是DNS缓存问题。 - 用
telnet连接解析到的Broker IP对应端口,核对返回的Broker ID和集群元数据内的Broker ID是否匹配,如果不匹配就是网络层规则残留导致的转发错误。
内容的提问来源于stack exchange,提问作者JimmyyW
相关产品推荐
相关产品推荐

