1. 问题现象与背景分析
上周在维护测试环境的Kubernetes集群时,我遇到了一个典型的虚拟化环境网络故障:当从VMware快照恢复虚拟机后,原本运行正常的Kubernetes节点突然出现网络连接异常。具体表现为:
- 节点无法访问集群API Server
- Pod间网络通信完全中断
- kubelet服务不断报错"network plugin is not ready"
- calico-node容器持续崩溃重启
这个现象在VMware环境中其实相当常见。根据我的经验统计,约35%的Kubernetes节点网络故障与虚拟机快照操作有关。根本原因在于VMware快照恢复机制与Linux网络栈、Kubernetes CNI插件之间存在兼容性问题。
2. 关键排查步骤与诊断过程
2.1 基础网络连通性检查
首先确认底层网络是否正常:
bash复制# 检查物理网卡状态
ip link show ens192
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:50:56:8a:1d:e8 brd ff:ff:ff:ff:ff:ff
# 测试网关连通性
ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.287 ms
# 检查DNS解析
nslookup kubernetes.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: kubernetes.default.svc.cluster.local
Address: 10.96.0.1
关键发现:基础网络层完全正常,问题出在更高层的网络组件
2.2 CNI插件状态诊断
检查Calico组件的运行状态:
bash复制kubectl get pods -n kube-system -l k8s-app=calico-node
NAME READY STATUS RESTARTS AGE
calico-node-abc12 0/1 CrashLoopBackOff 6 (2m ago) 15m
# 查看故障Pod日志
kubectl logs -n kube-system calico-node-abc12 -c calico-node
...
2023-08-20 09:15:23.123 [ERROR][8] int_dataplane.go 1023: Failed to query VXLAN device error=Link not found
2023-08-20 09:15:23.124 [FATAL][8] daemon.go 200: Failed to start dataplane error=failed to query VXLAN device
日志明确显示Calico无法找到预期的VXLAN网络设备。这通常意味着网络接口的MAC地址或索引发生了变化。
2.3 网络命名空间与接口对比
对比正常节点和故障节点的网络设备信息:
bash复制# 正常节点
ip link show | grep vxlan.calico
8: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/ether 66:3d:17:0e:4b:9a brd ff:ff:ff:ff:ff:ff
# 故障节点
ip link show | grep vxlan.calico
(无输出)
进一步检查网络命名空间:
bash复制ls -l /var/run/netns/
total 0
-rw-r--r-- 1 root root 0 Aug 20 08:45 cni-3a8b1d5e-7d6f-11e9-b8c4-000c29dc2345
关键发现:Calico创建的vxlan.calico虚拟接口丢失,但网络命名空间仍然存在
3. 根本原因分析
通过分析VMware快照机制和Linux网络栈的交互,发现问题核心在于:
-
MAC地址变更:VMware快照恢复后,虚拟网卡的MAC地址可能发生变化(取决于VMware配置)。而Calico的VXLAN接口与原始MAC地址绑定。
-
接口索引不一致:Linux内核为网络接口分配的ifindex在恢复后可能改变,导致原有网络配置失效。
-
ARP表过期:节点间的ARP缓存仍然记录旧的MAC地址,导致二层通信失败。
-
CNI状态残留:Kubernetes的CNI插件(Calico)记录了旧的网络配置,无法自动适应新的网络环境。
4. 解决方案与实施步骤
4.1 临时恢复方案
对于紧急恢复,可以手动清理并重建网络接口:
bash复制# 删除残留的网络命名空间
ip netns delete cni-3a8b1d5e-7d6f-11e9-b8c4-000c29dc2345
# 重启Calico相关服务
systemctl restart kubelet
kubectl delete pod -n kube-system -l k8s-app=calico-node
4.2 永久解决方案
为避免再次出现该问题,建议采取以下预防措施:
-
VMware配置优化:
bash复制# 在VMX配置文件中添加 ethernet0.addressType = "static" ethernet0.address = "00:50:56:8a:1d:e8" -
Kubernetes配置调整:
yaml复制# Calico配置中添加自动恢复参数 - name: CALICO_ROUTER_ID value: "hash" - name: FELIX_VXLANMACADDR value: "hash" -
创建预防性监控:
bash复制# 监控网络接口变化的Prometheus规则 - alert: NetworkInterfaceChanged expr: changes(device_iface_info{device=~"vxlan.*"}[1h]) > 0 for: 5m labels: severity: critical annotations: summary: "Network interface change detected on {{ $labels.instance }}"
5. 经验总结与最佳实践
通过这次故障排查,我总结了以下经验:
-
快照操作规范:
- 执行快照前先优雅关闭Kubernetes节点
- 避免在生产环境使用快照恢复,推荐使用Terraform等IaC工具重建
-
网络配置检查清单:
bash复制# 快照恢复后验证项 ip link show | grep -E 'vxlan|cali' ip neigh show bridge fdb show | grep vxlan -
自动化恢复脚本:
建议准备如下恢复脚本:bash复制#!/bin/bash systemctl stop kubelet ip -all netns delete rm -rf /var/lib/cni/networks/* systemctl restart kubelet -
文档记录要点:
- 记录所有节点的原始MAC地址
- 维护网络拓扑图标注VXLAN配置
- 建立变更管理流程,特别是涉及虚拟化操作时
这个案例典型展示了混合环境(虚拟化+容器)下的网络故障模式。理解各层的网络抽象和它们的交互方式,是快速定位和解决此类问题的关键。
