k8s的flannel网络pod之间不通 - Sun, Apr 12, 2020
k8s的flannel网络pod之间不通
k8s的flannel网络pod之间不通
在 Kubernetes 集群中,Flannel 是一个常用的网络插件,负责为集群提供跨主机的容器网络。当 Pod 之间无法通信时,通常与网络配置、防火墙规则、路由表等问题有关。本文将系统地介绍 Flannel 网络故障排查方法。
Flannel 网络基础
Flannel 工作原理
Flannel 通过以下方式实现跨主机容器通信:
- 为每个节点分配一个子网(如 10.244.0.0/16)
- 使用 VTEP(Virtual Tunnel End Point)设备封装网络数据包
- 支持多种后端网络模式:
- VxLAN(默认,性能较好)
- Host-GW(要求所有节点在同一二层网络)
- UDP(兼容性好但性能较差)
网络架构
Node A Node B
+--------+ +--------+
| Pod 1 | | Pod 2 |
| 10.244 | | 10.244 |
+--------+ +--------+
| |
v v
+--------+ +--------+
| cni0 | | cni0 |
+--------+ +--------+
| |
v v
+--------+ +--------+
| flannel| | flannel|
| .1 | | .1 |
+--------+ +--------+
| |
+----------+ |
| |
+-------+ |
| Switch| |
+-------+ |
| |
+----------+ v
+--------+ +--------+
| eth0 | | eth0 |
+--------+ +--------+
常见故障排查步骤
1. 检查 Pod 状态
# 查看 Pod 状态
kubectl get pods -o wide
# 查看 Pod 详情
kubectl describe pod <pod-name>
# 查看 Pod 日志
kubectl logs <pod-name>
2. 检查 Flannel Pod 状态
# 查看 kube-system 命名空间中的 Flannel Pod
kubectl get pods -n kube-system -l app=flannel
# 查看 Flannel 日志
kubectl logs -n kube-system -l app=flannel
# 查看特定节点的 Flannel 日志
kubectl logs -n kube-system flannel-xxxxx -c kube-flannel
3. 检查网络接口
# 查看网络接口
ip addr show
# 检查 cni0 接口
ip addr show cni0
# 检查 flannel.1 接口
ip addr show flannel.1
# 查看 VTEP 信息
bridge fdb show | grep flannel.1
4. 检查路由表
# 查看路由表
ip route
# 查看特定路由
ip route show | grep 10.244
# 跟踪数据包路径
traceroute <target-pod-ip>
5. 检查防火墙规则
# 查看 iptables 规则
iptables -L -n -v
# 查看 NAT 规则
iptables -t nat -L -n -v
# 查看 FILTER 规则
iptables -L FORWARD -n -v
# 清空防火墙规则(仅用于测试)
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -L -n
详细的故障排查命令
完整诊断脚本
#!/bin/bash
# Flannel 网络诊断脚本
echo "=== Flannel 网络诊断 ==="
echo ""
# 1. 检查 Flannel Pod 状态
echo "1. Flannel Pod 状态:"
kubectl get pods -n kube-system -l app=flannel
echo ""
# 2. 检查网络接口
echo "2. 网络接口状态:"
echo "cni0:"
ip addr show cni0 2>/dev/null || echo "cni0 接口不存在"
echo ""
echo "flannel.1:"
ip addr show flannel.1 2>/dev/null || echo "flannel.1 接口不存在"
echo ""
# 3. 检查路由表
echo "3. 路由表 (10.244.x.x):"
ip route show | grep 10.244
echo ""
# 4. 检查 iptables 规则
echo "4. iptables FORWARD 链:"
iptables -L FORWARD -n -v | head -20
echo ""
# 5. 检查 Flannel 日志
echo "5. Flannel 最近日志:"
kubectl logs -n kube-system -l app=flannel --tail=20 2>/dev/null || echo "无法获取日志"
echo ""
# 6. 测试 Pod 连通性
echo "6. 测试 Pod 连通性:"
pods=$(kubectl get pods -o wide --no-headers | awk '{print $6}')
for pod_ip in $pods; do
echo "测试连接到 $pod_ip:"
ping -c 2 $pod_ip 2>&1 | grep -E "PING|bytes from|unreachable"
done
echo ""
echo "=== 诊断完成 ==="
手动测试连通性
# 进入 Pod 测试
kubectl exec -it <pod-name> -- /bin/sh
# 在 Pod 内执行
ping <target-pod-ip>
traceroute <target-pod-ip>
curl http://<target-pod-ip>:<port>
常见问题和解决方案
1. 防火墙阻止通信
症状: Pod 之间无法 ping 通,其他服务正常
解决方案:
# 临时清空防火墙规则(测试用)
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
# 永久解决方案 - 添加 Flannel 规则
iptables -A INPUT -p udp --dport 8472 -j ACCEPT
iptables -A INPUT -p udp --dport 4789 -j ACCEPT
iptables -A FORWARD -i cni0 -j ACCEPT
iptables -A FORWARD -o cni0 -j ACCEPT
2. Flannel Pod 异常
症状: Flannel Pod 处于 CrashLoopBackOff 状态
排查步骤:
# 查看详细状态
kubectl describe pod -n kube-system flannel-xxxxx
# 查看日志
kubectl logs -n kube-system flannel-xxxxx -c kube-flannel
# 查看事件
kubectl get events -n kube-system --sort-by='.lastTimestamp'
常见原因:
- etcd 连接失败
- 配置文件错误
- 端口冲突
- 资源不足
3. 路由表错误
症状: 数据包无法正确路由到目标节点
检查路由表:
# 查看当前路由
ip route show
# 应该看到类似这样的路由
# 10.244.0.0/24 via 10.244.0.0 dev flannel.1 onlink
# 10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
修复方法:
# 重启 Flannel Pod
kubectl delete pod -n kube-system -l app=flannel
# 或者手动添加路由(不推荐)
ip route add 10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
4. MTU 问题
症状: 大数据包传输失败,小包正常
解决方案:
# 检查 MTU 设置
ip link show flannel.1
# 如果需要,调整 MTU
ip link set dev flannel.1 mtu 1450
# Flannel 配置中设置 MTU
# 在 ConfigMap 中添加:
# "net-conf.json": |
# {
# "Network": "10.244.0.0/16",
# "Backend": {
# "Type": "vxlan",
# "Port": 8472,
# "MTU": 1450
# }
# }
5. 主机防火墙冲突
症状: 部分节点间无法通信
解决方案:
# Ubuntu/Debian
sudo ufw allow 8472/udp
sudo ufw allow 4789/udp
sudo ufw reload
# CentOS/RHEL
sudo firewall-cmd --permanent --add-port=8472/udp
sudo firewall-cmd --permanent --add-port=4789/udp
sudo firewall-cmd --reload
6. CNI 插件冲突
症状: 网络配置混乱
解决方案:
# 检查已安装的 CNI 插件
ls /etc/cni/net.d/
# 确保只有一个 CNI 配置文件
# 如果有冲突,删除不需要的配置
# 重启 kubelet
sudo systemctl restart kubelet
配置优化
Flannel 配置示例
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
namespace: kube-system
labels:
tier: node
app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"SubnetLen": 24,
"Backend": {
"Type": "vxlan",
"Port": 8472,
"VNI": 1
}
}
使用 Host-GW 模式(性能更好)
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "host-gw"
}
}
注意: Host-GW 模式要求所有节点在同一个二层网络中。
防火墙规则详解
基本规则
# 1. 允许本地回环
iptables -A INPUT -i lo -j ACCEPT
# 2. 允许已建立的和相关的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 3. 允许 Flannel VxLAN 通信
iptables -A INPUT -p udp --dport 8472 -j ACCEPT
# 4. 允许 VTEP 通信(如果使用标准 VxLAN)
iptables -A INPUT -p udp --dport 4789 -j ACCEPT
# 5. 允许 Pod 网络通信
iptables -A INPUT -s 10.244.0.0/16 -j ACCEPT
# 6. 允许转发
iptables -A FORWARD -i cni0 -j ACCEPT
iptables -A FORWARD -o cni0 -j ACCEPT
# 7. 拒绝其他
iptables -A INPUT -j DROP
持久化防火墙规则
# Ubuntu/Debian - 使用 iptables-persistent
sudo apt-get install iptables-persistent
sudo netfilter-persistent save
# CentOS/RHEL - 使用 firewalld
sudo firewall-cmd --permanent --add-port=8472/udp
sudo firewall-cmd --permanent --add-port=4789/udp
sudo firewall-cmd --reload
网络故障排查工具
常用工具命令
# ping - 测试基本连通性
ping <target-ip>
# traceroute - 跟踪路由路径
traceroute <target-ip>
# mtr - 结合 ping 和 traceroute
mtr -r <target-ip>
# tcpdump - 抓包分析
tcpdump -i flannel.1 -n
tcpdump -i eth0 -n port 8472
# ip route - 查看路由
ip route get <target-ip>
# ip neigh - 查看 ARP 表
ip neigh show
# bridge fdb - 查看 VTEP 表
bridge fdb show | grep flannel
# ethtool - 查看网络接口统计
ethtool -S flannel.1
抓包分析示例
# 抓取 Flannel VxLAN 数据包
tcpdump -i eth0 -n 'udp port 8472' -w flannel.pcap
# 抓取 Pod 之间的数据包
tcpdump -i cni0 -n host <pod-ip-1> and host <pod-ip-2>
# 分析抓包文件
tcpdump -r flannel.pcap -v
性能优化
优化 VxLAN 性能
# 1. 启用 offload
ethtool -K eth0 tx-offload on
ethtool -K flannel.1 tx-offload on
# 2. 调整 conntrack 表大小
echo "net.netfilter.nf_conntrack_max = 1000000" >> /etc/sysctl.conf
echo "net.netfilter.nf_conntrack_buckets = 200000" >> /etc/sysctl.conf
sysctl -p
# 3. 优化 TCP 参数
echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_fin_timeout = 30" >> /etc/sysctl.conf
sysctl -p
监控和日志
# 监控 Flannel 性能
watch -n 1 'kubectl top pods -n kube-system -l app=flannel'
# 持续查看日志
kubectl logs -n kube-system -f -l app=flannel
# 查看网络统计
sar -n DEV 1 10
最佳实践
- 规划网络段: 合理规划 Pod 网络段,避免与物理网络冲突
- 选择合适的后端: 根据网络环境选择 VxLAN 或 Host-GW
- 监控网络状态: 定期检查网络接口、路由表和防火墙规则
- 备份配置: 备份 Flannel ConfigMap 和防火墙规则
- 测试恢复: 在测试环境中验证网络恢复流程
- 文档化: 记录网络配置和故障处理流程
- 使用网络策略: 配置 NetworkPolicy 控制网络流量
相关资源
- Flannel GitHub: https://github.com/flannel-io/flannel
- Kubernetes 网络: https://kubernetes.io/docs/concepts/cluster-administration/networking/
- iptables 教程: https://www.frozentux.net/iptables-tutorial/
- VxLAN 协议: https://tools.ietf.org/html/rfc7348