1. 故障背景
单节点Kubernetes集群升级操作系统内核版本、NVIDIA驱动与CUDA后重启服务器,引发容器云管理界面访问异常。核心环境如下:
- 组件版本:
- Ubuntu 5.19.0-40-generic
- Kubernetes 1.21.5, Docker 27.5.1
- 网络插件:Flannel(Pod网段 10.233.64.0/18、Svc网段10.233.0.0/18)
- 域名解析:CoreDNS + NodeLocalDNS
- 代理模式:Kube-Proxy ipvs模式
- 关键现象:
Pod可互访Pod IP,宿主机可访问Service IP与Pod IP,但Pod内部访问Service IP超时(如 10.233.36.146:6379)。
2. 问题排查
阶段一:基础状态检查
(1)防火墙确认:ufw status 显示inactive(排除防火墙拦截)
(2)核心组件状态:- kubectl get pods -n=kube-system # 所有组件Running
- kubectl get pods -n=容器云核心组件-system # 发现apiserver报错
复制代码 (3)日志线索定位:- kubectl logs -f -n=容器云核心组件-system apiserver-68654cdc5-gg88b
复制代码 关键报错:- Error: failed to connect to redis service, please check redis status, error: dial tcp 10.233.36.146:6379: i/o timeout
- 2025/07/29 17:22:08 failed to connect to redis service, please check redis status, error: dial tcp 10.233.36.146:6379: i/o timeout
复制代码 结论:DNS解析正常(域名→Service IP),但Service流量不通。
(4)排查redis服务运行情况:- kubectl get pods -n=容器云公共组件-system |grrp redis
复制代码 Redis容器运行状态正常,容器日志也正常,将Redis Svc改成NodePort模式,通过本地Redis客户端工具也能正常连接Redis服务,说明Redis服务是正常的。
阶段二:网络分层验证
- 客户端: bubybox容器或者宿主机
- 服务端: 集群里正常运行的Nginx服务
测试类型操作命令结果推断Pod→Pod IPkubectl exec -it busybox -- telnet 80✅ 成功Flannel底层网络正常 Pod→Service IPkubectl exec -it busybox -- telnet 80❌ 超时Service层异常宿主机→Servicetelnet 80✅ 成功kube-proxy规则对宿主机有效关键矛盾点:
- IPVS规则存在(ipvsadm -Ln | grep 显示正常DNAT)
- 但Pod流量无法穿透Service
注意: 如果使用的是iptables规则使用iptables-save | grep 命令排查Kube-Proxy组件是否生成了SvcIP转PodIP规则。
阶段三:抓包与内核层深挖
(1)抓包分析(Pod侧)
同时打开2个shell,都进入busybox容器内部,其中一个shell执行tcpdump命令进行抓包,另一个shell执行telnet nginx_svcIp(10.233.42.160) 80命令。- tcpdump -i any 'host 10.233.42.160 and tcp port 80' -w svc_capture.pcap
复制代码 抓包结束后使用kubectl cp或者docker cp命令将抓的包拷贝到宿主机上再使用sftp工具下载到本地用wireshark分析,发现源地址到不了目标svcIP。
结论:
持续发送SYN包 → 零响应(无RST/SYN-ACK),排除目标拒绝,指向中间层拦截。
源地址:Pod IP 10.233.64.250(发送方)
目标地址:Service IP 10.233.42.160
行为:
- 发送端发起TCP SYN请求(序号1)
- 连续6次重传SYN包(序号2-7),时间间隔指数级增长(1s → 3s → 7s → 15s → 31s → 64s)
关键缺失:零响应:无SYN-ACK(目标端确认)、无RST(目标拒绝)
(2)抓包分析(服务器侧)
同时打开2个shell,一个直接在服务器上执行tcpdump命令进行抓包(直接抓nginx_podIP),另一个进入busybox容器内部执行telnet nginx_svcIp(10.233.42.160) 80命令。- tcpdump -i any 'host 10.233.64.43 and tcp port 80' -w svc_capture.pcap
复制代码 抓包结束后使用kubectl cp或者docker cp命令将抓的包拷贝到宿主机上再使用sftp工具下载到本地用wireshark分析,根据包信息可以看到pod访问svcIp时也进行了DNAT将svcIP转成podIp了(说明kube-proxy正常),但是源Pod访问不通目标Pod。
(3)内核参数致命错误
这时候怀疑是Conntrack问题,使用sysctl -p命令检查内核参数配置,发现参数加载报错。
这三个关键内核参数配置没有加载成功,主要是net.bridge.bridge-nf-call-iptables = 1。- net.bridge.bridge-nf-call-arptables = 1
- net.bridge.bridge-nf-call-ip6tables = 1
- net.bridge.bridge-nf-call-iptables = 1
复制代码 net.bridge.bridge-nf-call-iptables = 1参数失效后果。- `net.bridge.bridge-nf-call-iptables=0`
- ↓
- 网桥流量**绕过iptables规则**
- ↓
- kube-proxy的IPVS DNAT规则**失效**
复制代码net.bridge.bridge-nf-call-iptables = 1
- 作用:控制通过 Linux 网桥的 IPv4 流量是否经过 iptables 规则链(如 FORWARD、INPUT)。
- 启用后(=1):
- 桥接流量(如 Pod 间通信、Service IP 访问)会被提交到 iptables 规则处理。
- 这是 Kubernetes 的必需配置,确保 kube-proxy 的 Service 负载均衡规则(DNAT)能生效。
- 禁用后(=0):
- 桥接流量绕过 iptables,导致 Service IP 的 DNAT 规则失效,Pod 访问 Service IP 必然失败。
net.bridge.bridge-nf-call-ip6tables = 1
- 作用:控制桥接的 IPv6 流量是否经过 ip6tables 规则链。
- 在 IPv6 环境中需启用,否则 IPv6 Service 无法正常工作。
net.bridge.bridge-nf-call-arptables = 1
- 作用:控制桥接的 ARP 流量是否经过 arptables 规则链。
- 启用后可防止 ARP 欺骗,但对 Service IP 通信影响较小。
3. 解决方案:修复内核隔离
步骤一:动态加载模块
加载内核模块:- modprobe br_netfilter # 临时加载
- modprobe nf_conntrack # 临时加载
- echo "br_netfilter" >> /etc/modules-load.d/k8s.conf # 永久加载
- echo "nf_conntrack" >> /etc/modules-load.d/k8s.conf # 永久加载
复制代码 步骤二:永久固化配置内核参数配置(实际这些参数之前都有,只不过上面那三行加载失败了)
[code]cat > /etc/sysctl.d/k8s.conf |