0%

K8S问题排查-安全策略导致Pod反复重启

问题背景

  1. 查看kube-system下的系统组件,发现harbor、influxdb、coredns等组件反复重启;
  2. 使用kubectl get pod -n kube-system命令查看pod列表,发现命令会稳定的卡15s

原因分析

先看第一点,这几个pod反复重启已经遇到过几次,看过前面的问题排查文章[1,2]的应该知道,在业务高并发场景下可能出现。先使用top命令看一下负载情况:

1
2
3
4
5
6
load average: 14.76  18.45  17.85
Tasks: 1998 total, 7 running, 1937 sleeping, 0 stopped, 54 zombie
%CPU: 15.2 us, 8.3 sys, 0.7 ni, 75.3 id

cat /proc/cpuinfo|grep MHz| wc -l
40

实际负载不高,排除这个可能(实际定位过程中,也依据前面的经验,做了相关内核参数的优化,问题确实没什么改善)。那就继续看,先describe看几个异常pod的错误信息:

1
2
3
kubelet     Liveness probe failed: Get "http://177.177.138.139:8885/api/health": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
kubelet Readiness probe failed: Get "http://177.177.138.139:8083/"": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
kubelet Back-off restarting failed container

错误基本一致,就是kubelet调用pod提供的健康检查接口超时了,所以被不断地kill再重启。为什么调不通?模拟kubelet的调用操作,在pod所在节点上使用curl命令调用,结果显示timeout,再ping一下看看pod通信有没有问题:

1
2
ping 177.177.212.186
^C

ping不通!这也就讲通了为啥健康检查不过,因为kubelet与所在节点上的Pod根本就无法通信。为啥会这样?通过一顿验证,发现一个规律:**集群各节点无法访问自己节点上的pod,但可以访问其他节点上的pod**;

这个现象是比较奇怪的,一般来说影响节点与自己节点上pod通信的原因不多,对于使用caliccni网络插件来说,可能的原因有:

  1. pod内的ip/arp/路由异常;
  2. calico网卡的arp配置异常;
  3. 请求被iptables拦截;

分别查看1,2相关配置,显示正常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@influxdb-847b74cbc5-ddxcd]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
3: eth0@if79: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 32:81:0e:f4:dd:3a brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 177.177.212.186/32 scope global eth0
valid_lft f

[root@influxdb-847b74cbc5-ddxcd]# arp
Address HWtype HWaddress Flags Mask Iface
gateway ether ee:ee:ee:ee:ee:ee C eth0

[root@influxdb-847b74cbc5-ddxcd]# ip rou
default via 169.254.1.1 dev eth0
169.254.1.1 dev eth0 scope link

[root@node]# cat /proc/sys/net/ipv4/conf/cali7acfda72e71/proxy_arp
1
[root@node]# cat /proc/sys/net/ipv4/conf/cali7acfda72e71/arp_ignore
0

对于第三点,通过iptables命令检查过,也没什么异常规则;

抓包看看啥情况:

  1. 在节点上ping本节点上的pod,同时在cali7acfda72e71上抓包,发现请求到了cali网卡,但没有响应;
  2. podping本节点ip,同时在cali7acfda72e71上抓包,发现cali网卡上有请求和响应,但依然无法ping通;

看起来像是请求被主动丢弃了,跟问题提出人确认问题环境的基本情况,发现该集群有额外安装EDR防病毒软件。为了确认该软件有没有影响,先停掉防病毒软件,观察一段时候后,发现环境恢复正常。重新启动防病毒软件,一段时间后问题复现;

与负责防病毒软件的技术沟通确认,该集群被设置到了防病毒软件的默认策略里,触发条件是默认策略组里面有防止端口扫描和流量阈值配置,结果触发了网络防护,导致节点ip被封了。经过软件提供方的调整,将该集群调整到单独的策略编组,问题解决;

问题解决后,现象1和现象2都消失了,但回过头想想,为什么会出现现象2?当时环境好了没有细究,后来自己的测试环境也出现过这个现象,通过debug日志发现,卡在了调用metric服务的接口上,根本原因就是访问metricpod不通,日志现象比较明显,这里就不贴了:

1
kubectl get pod -n kube-system -owide --v 10

解决方案

  1. 针对该集群环境,单独配置策略编组;
  2. 节点与Pod通信正常后,现象2消失;

参考资料

  1. https://lyyao09.github.io/2021/06/19/k8s/K8S%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5-%E4%B8%9A%E5%8A%A1%E9%AB%98%E5%B9%B6%E5%8F%91%E5%AF%BC%E8%87%B4Pod%E5%8F%8D%E5%A4%8D%E9%87%8D%E5%90%AF/
  2. https://lyyao09.github.io/2021/07/16/k8s/K8S%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5-%E4%B8%9A%E5%8A%A1%E9%AB%98%E5%B9%B6%E5%8F%91%E5%AF%BC%E8%87%B4Pod%E5%8F%8D%E5%A4%8D%E9%87%8D%E5%90%AF(%E7%BB%AD)/
  3. https://developer.aliyun.com/article/409634
  4. https://www.css3.io/31linuxxi-tong-diao-you.htmls