积累约300个完成Job后单节点Kubernetes集群不稳定问题排查
Kubernetes单节点集群因大量已完成Job出现不稳定的成因与排查方向
这个问题其实在旧版本Kubernetes里并不少见,结合你提供的现象和复现步骤,我们可以从几个核心角度来拆解成因和排查方向:
核心成因分析
你遇到的http2: no cached connection was available错误,本质是kubelet与apiserver之间的HTTP/2连接池被耗尽了,结合你的场景(300个挂载独立ConfigMap的已完成Job),主要触发点有两个:
- Reflector资源过载:每个Job对应的Pod挂载了唯一的ConfigMap,kubelet的reflector组件会为每个ConfigMap创建独立的监听(watch)来跟踪资源变化——哪怕Job已经完成,只要ConfigMap还存在,reflector就不会停止监听。300个ConfigMap就意味着300个并发的watch连接,直接打满了默认的HTTP/2连接池。
- 旧版本的已知缺陷:你用的Kubernetes v1.12.1是2018年的老版本,虽然Go仓库里的相关HTTP/2连接问题被修复,但这个版本的Kubernetes并没有合并对应的修复,甚至自身在reflector的连接管理上存在资源泄漏的问题——比如连接没有被及时回收,或者连接池的默认上限设置过低。
具体排查方向
- 验证连接池状态
- 在kubelet节点上执行
netstat -anp | grep kubelet | grep 6443,查看与apiserver的连接数,如果接近甚至超过几百个,基本可以确认连接池耗尽。 - 查看apiserver的日志,有没有类似
http2: stream closed或者连接过载的警告,这也能佐证连接池的问题。
- 在kubelet节点上执行
- 检查Reflector数量
- 执行
kubectl get --raw /metrics | grep reflector,统计针对ConfigMap的reflector数量,如果数量和你创建的Job/ConfigMap数量一致,说明每个ConfigMap都在被单独监听。
- 执行
- 测试资源清理的影响
- 尝试批量删除已完成Job对应的ConfigMap(而不只是Job),观察kubelet的错误是否消失,节点状态是否恢复——如果恢复,说明残留的ConfigMap是核心诱因。
- 调整HTTP/2相关参数
- 给apiserver添加启动参数
--http2-max-streams-per-connection=1000(默认可能是100),给kubelet添加--kube-api-qps=100和--kube-api-burst=200,提升连接池和请求并发的上限,看是否能缓解问题。
- 给apiserver添加启动参数
- 升级Kubernetes版本
- v1.12.1已经停止维护多年,后续版本(比如1.16+)不仅合并了Go的HTTP/2修复,还优化了reflector的资源管理(比如共享监听、自动清理无用的reflector),这是解决这类问题最彻底的方案。
临时优化建议
- 避免为每个Job创建独立的ConfigMap:改用共享ConfigMap,或者直接把配置通过
env字段注入Pod,减少kubelet需要监听的资源数量。 - 启用Job自动清理:在v1.12.1中可以开启
TTLAfterFinished特性门控,给Job添加spec.ttlSecondsAfterFinished字段,让已完成的Job自动被删除,同时可以写个简单脚本联动删除对应的ConfigMap。
内容的提问来源于stack exchange,提问作者Frederik Carlier
相关产品推荐
相关产品推荐

