Pod 健康检查失败
- Kubernetes 健康检查包含就绪检查(readinessProbe)和存活检查(livenessProbe)
- pod 如果就绪检查失败会将此 pod ip 从 service 中摘除,通过 service 访问,流量将不会被转发给就绪检查失败的 pod
- pod 如果存活检查失败,kubelet 将会杀死容器并尝试重启
健康检查失败的可能原因有多种,除了业务程序BUG导致不能响应健康检查导致 unhealthy,还能有有其它原因,下面我们来逐个排查。
健康检查配置不合理
initialDelaySeconds
太短,容器启动慢,导致容器还没完全启动就开始探测,如果 successThreshold 是默认值 1,检查失败一次就会被 kill,然后 pod 一直这样被 kill 重启。
节点负载过高
cpu 占用高(比如跑满)会导致进程无法正常发包收包,通常会 timeout,导致 kubelet 认为 pod 不健康。参考本书 处理实践: 高负载 一节。
容器进程被木马进程杀死
参考本书 处理实践: 使用 systemtap 定位疑难杂症 进一步定位。
容器内进程端口监听挂掉
使用 netstat -tunlp
检查端口监听是否还在,如果不在了,抓包可以看到会直接 reset 掉健康检查探测的连接:
20:15:17.890996 IP 172.16.2.1.38074 > 172.16.2.23.8888: Flags [S], seq 96880261, win 14600, options [mss 1424,nop,nop,sackOK,nop,wscale 7], length 0
20:15:17.891021 IP 172.16.2.23.8888 > 172.16.2.1.38074: Flags [R.], seq 0, ack 96880262, win 0, length 0
20:15:17.906744 IP 10.0.0.16.54132 > 172.16.2.23.8888: Flags [S], seq 1207014342, win 14600, options [mss 1424,nop,nop,sackOK,nop,wscale 7], length 0
20:15:17.906766 IP 172.16.2.23.8888 > 10.0.0.16.54132: Flags [R.], seq 0, ack 1207014343, win 0, length 0
连接异常,从而健康检查失败。发生这种情况的原因可能在一个节点上启动了多个使用 hostNetwork
监听相同宿主机端口的 Pod,只会有一个 Pod 监听成功,但监听失败的 Pod 的业务逻辑允许了监听失败,并没有退出,Pod 又配了健康检查,kubelet 就会给 Pod 发送健康检查探测报文,但 Pod 由于没有监听所以就会健康检查失败。
SYN backlog 设置过小
SYN backlog 大小即 SYN 队列大小,如果短时间内新建连接比较多,而 SYN backlog 设置太小,就会导致新建连接失败,通过 netstat -s | grep TCPBacklogDrop
可以看到有多少是因为 backlog 满了导致丢弃的新连接。
如果确认是 backlog 满了导致的丢包,建议调高 backlog 的值,内核参数为 net.ipv4.tcp_max_syn_backlog
。