首页 > 解决方案 > 在 GKE 上进行 liveness/readiness 探测检查时,Kubelet 会定期失去与 Pod 的 TCP 连接

问题描述

我们在单个 GKE(google kubernetes 引擎)集群节点上部署了一个软件系统,该节点使用大约 100 个 pod,在每个 pod 中我们定义了 TCP 就绪探针,现在我们可以看到就绪探针Unable to connect to remote host: Connection refused在不同的 pod 上周期性地失败。

通过对集群节点和故障 pod 的 tcpdump 跟踪,我们发现从集群节点发送的数据包看起来是正确的,而 pod 没有收到 TCP 数据包,但故障 pod 仍然可以接收 IP 广播数据包。

奇怪的是,如果我们从失败的 Pod 中 ping/curl/wget 集群节点,无论集群节点是否有 http 服务,TCP 连接都会立即恢复,并且就绪检查会变得正常。

一个例子如下:

集群节点主机:10.44.0.1 失败的 pod 主机:10.44.0.92

集群节点 cbr0 接口上的 tcpdump

#sudo tcpdump -i cbr0  host 10.44.0.92

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on cbr0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:33:52.913052 ARP, Request who-has 10.44.0.1 tell 10.44.0.92, length 28
17:33:52.913181 ARP, Reply 10.44.0.1 is-at 0a:58:0a:2c:00:01 (oui Unknown), length 28
17:33:57.727497 IP 10.44.0.1.47736 > 10.44.0.92.mysql: Flags [S], seq 756717730, win 28400, options [mss 1420,sackOK,TS val 1084890021 ecr 0,nop,wscale 7], length 0
17:33:57.727537 IP 10.44.0.92.mysql > 10.44.0.1.47736: Flags [R.], seq 0, ack 756717731, win 0, length 0
17:34:07.727563 IP 10.44.0.1.48202 > 10.44.0.92.mysql: Flags [S], seq 2235831098, win 28400, options [mss 1420,sackOK,TS val 1084900021 ecr 0,nop,wscale 7], length 0
17:34:07.727618 IP 10.44.0.92.mysql > 10.44.0.1.48202: Flags [R.], seq 0, ack 2235831099, win 0, length 0
17:34:12.881059 ARP, Request who-has 10.44.0.92 tell 10.44.0.1, length 28
17:34:12.881176 ARP, Reply 10.44.0.92 is-at 0a:58:0a:2c:00:5c (oui Unknown), length 28

这些是从 Kubelet 发送的就绪检查数据包,我们可以看到失败节点的响应Flags [R.], seq 0, ack 756717731, win 0, length 0是 TCP 握手 ACK/SYN 回复,这是一个失败的数据包,不会建立 TCP 连接。

如果我们exec -it到失败的 pod 并从 pod ping 集群节点,如下所示:

root@mariadb:/# ping 10.44.0.1
PING 10.44.0.1 (10.44.0.1): 56 data bytes
64 bytes from 10.44.0.1: icmp_seq=0 ttl=64 time=3.301 ms
64 bytes from 10.44.0.1: icmp_seq=1 ttl=64 time=0.303 ms

然后让我们从 TCP 转储中查看集群节点端发生的情况:

#sudo tcpdump -i cbr0  host 10.44.0.92

17:34:17.728039 IP 10.44.0.92.mysql > 10.44.0.1.48704: Flags [R.], seq 0, ack 2086181490, win 0, length 0
17:34:27.727638 IP 10.44.0.1.49202 > 10.44.0.92.mysql: Flags [S], seq 1769056007, win 28400, options [mss 1420,sackOK,TS val 1084920022 ecr 0,nop,wscale 7], length 0
17:34:27.727693 IP 10.44.0.92.mysql > 10.44.0.1.49202: Flags [R.], seq 0, ack 1769056008, win 0, length 0
17:34:34.016995 ARP, Request who-has 10.44.0.1 tell 10.44.0.92, length 28
17:34:34.018358 ARP, Reply 10.44.0.1 is-at 0a:58:0a:2c:00:01 (oui Unknown), length 28
17:34:34.020020 IP 10.44.0.92 > 10.44.0.1: ICMP echo request, id 53, seq 0, length 64
17:34:34.020101 IP 10.44.0.1 > 10.44.0.92: ICMP echo reply, id 53, seq 0, length 64
17:34:35.017197 IP 10.44.0.92 > 10.44.0.1: ICMP echo request, id 53, seq 1, length 64
17:34:35.017256 IP 10.44.0.1 > 10.44.0.92: ICMP echo reply, id 53, seq 1, length 64
17:34:36.018589 IP 10.44.0.92 > 10.44.0.1: ICMP echo request, id 53, seq 2, length 64
17:34:36.018700 IP 10.44.0.1 > 10.44.0.92: ICMP echo reply, id 53, seq 2, length 64
17:34:37.019791 IP 10.44.0.92 > 10.44.0.1: ICMP echo request, id 53, seq 3, length 64
17:34:37.019837 IP 10.44.0.1 > 10.44.0.92: ICMP echo reply, id 53, seq 3, length 64
17:34:37.730849 IP 10.44.0.1.49666 > 10.44.0.92.mysql: Flags [S], seq 1304758051, win 28400, options [mss 1420,sackOK,TS val 1084930025 ecr 0,nop,wscale 7], length 0
17:34:37.730900 IP 10.44.0.92.mysql > 10.44.0.1.49666: Flags [S.], seq 1267340310, ack 1304758052, win 28160, options [mss 1420,sackOK,TS val 3617117819 ecr 1084930025,nop,wscale 7], length 0
17:34:37.730952 IP 10.44.0.1.49666 > 10.44.0.92.mysql: Flags [.], ack 1, win 222, options [nop,nop,TS val 1084930025 ecr 3617117819], length 0
17:34:37.731149 IP 10.44.0.1.49666 > 10.44.0.92.mysql: Flags [F.], seq 1, ack 1, win 222, options [nop,nop,TS val 1084930025 ecr 3617117819], length 0
17:34:37.731268 IP 10.44.0.92.mysql > 10.44.0.1.49666: Flags [P.], seq 1:107, ack 2, win 220, options [nop,nop,TS val 3617117819 ecr 1084930025], length 106
17:34:37.731322 IP 10.44.0.1.49666 > 10.44.0.92.mysql: Flags [R], seq 1304758053, win 0, length 0
17:34:47.728119 IP 10.44.0.1.50138 > 10.44.0.92.mysql: Flags [S], seq 502800802, win 28400, options [mss 1420,sackOK,TS val 1084940022 ecr 0,nop,wscale 7], length 0
17:34:47.728179 IP 10.44.0.92.mysql > 10.44.0.1.50138: Flags [S.], seq 4294752326, ack 502800803, win 28160, options [mss 1420,sackOK,TS val 3617127816 ecr 1084940022,nop,wscale 7], length 0

我们可以看到 ICMP 数据包是 Pod 发送的 ping 命令数据包,在 ICMP 数据包之后,readiness check 数据包现在立即变为正确,TCP handleshake 成功。

不仅 ping 可以让它工作,curl/wget 等其他命令也可以让它工作,只需要从失败的 pod 到达集群节点,之后集群节点到 pod 的 TCP 连接就会正确。

失败的 pod 会不时发生变化,它可能发生在任何 pod 上,因为节点上有 100 个 pod 正在运行,不确定它是否会触发某些系统限制,但是所有其他的都正常工作,我们没有看到巨大的 CPU 使用率,并且节点上还剩下几 GB 内存。

有谁知道问题可能是什么?

标签: kubernetes

解决方案


推荐阅读