现象
部分节点间歇性变成 NotReady,每次持续1-3分钟后自动恢复。未恢复的节点上运行的Pod会被驱逐并重建,导致业务出现瞬断。我们用监控看到,每天这种NotReady事件有5-10次,频率不高但影响面很广
定位
-
看节点状态
kubectl describe node <node-name>发现节点状态在
Ready和NotReady之间来回跳 -
查看节点日志
journalctl -u kubelet -f --since "1 hour ago"发现
"PLEG is not healthy: pleg was last seen active 3s ago; threshold is 3s"。这是kubelet的**PLEG(Pod Lifecycle Event Generator,Pod生命周期事件生成器)**健康检查失败了。 -
追查PLEG不健康的原因
# 检查容器运行时
systemctl status containerd
crictl ps # 发现这个命令卡住,无响应
执行 `crictl ps` 时**命令hang住**,说明容器运行时和kubelet之间的通信出现了问题,导致kubelet无法获取Pod状态,从而将节点标记为NotReady。
4. 定位根因
```sh
# 查看容器运行时日志
journalctl -u containerd -f --since "1 hour ago"
发现了大量超时和context deadline exceeded错误,最终定位到是CNI(容器网络接口,Container Network Interface)插件(我们用的是Calico)在处理网络策略时,因为IPVS连接表满了导致调用超时,阻塞了容器运行时的响应。
# 验证IPVS表状态
ipvsadm -L -n | wc -l # 发现连接数达到几十万,远超正常值根因分析
根本原因是:kubelet每10秒会通过CRI(Container Runtime Interface,容器运行时接口)调用运行时来获取Pod状态,而运行时需要调用CNI插件获取网络信息。 当IPVS连接表满时,CNI查询超时,导致整个调用链被阻塞。kubelet的PLEG在3秒内收不到状态更新,就认为节点不健康,标记为
NotReady。等超时恢复后,节点又自动变回Ready。
深层原因是: 节点上
nf_conntrack表的默认timeout设置过长(默认5天),加上短连接服务带来的大量TIME_WAIT连接,导致nf_conntrack表被填满。这反过来阻塞了IPVS的连接处理,最终引发kubelet的CRI调用超时,节点NotReady。
解决方法
临时
- 直接执行
ipvsadm --clear清理连接表,节点立即恢复(治标) - 调整kubelet参数
--node-status-update-frequency=4s和--node-monitor-grace-period=20s,让节点NotReady的判断更宽容一点(减少抖动)
长期
- 增大IPVS连接表大小:
net.ipv4.ip_vs_conn_tab_size=524288/net.netfilter.nf_conntrack_max=524288(从默认的65536调大) - 增加监控告警:监控IPVS连接数,超过阈值时提前告警
监控
# 1. nf_conntrack 使用率(核心告警项)
node_ipvs_connections_total # IPVS连接总数
node_nf_conntrack_entries # 当前连接跟踪表项数
node_nf_conntrack_entries_limit # 连接跟踪表上限
# 告警规则示例:
# 当 nf_conntrack 使用率 > 80% 时告警
(node_nf_conntrack_entries / node_nf_conntrack_entries_limit) > 0.8