扁平网络 Flannel
Flannel 是 Kubernetes 集群中广泛使用的网络插件,它为集群提供了简单而有效的网络解决方案。本文将通过实际案例详细介绍 Flannel 的工作原理和配置方式。
集群网络概览
假设你有一个包含三个节点的 Kubernetes 集群,节点状态如下:
[root@node1 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
node1 Ready <none> 2d v1.24.0 <none> CentOS Linux 7 (Core) 3.10.0-693.11.6.el7.x86_64 containerd://1.6.6
node2 Ready <none> 2d v1.24.0 <none> CentOS Linux 7 (Core) 3.10.0-693.11.6.el7.x86_64 containerd://1.6.6
node3 Ready <none> 2d v1.24.0 <none> CentOS Linux 7 (Core) 3.10.0-693.11.6.el7.x86_64 containerd://1.6.6
集群中运行的 Pod 分布情况:
[root@node1 ~]# kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system coredns-6d4b75cb6d-sjqv9 1/1 Running 0 1h 172.33.68.2 node1
kube-system coredns-6d4b75cb6d-tkfrc 1/1 Running 1 1h 172.33.96.3 node3
kube-system metrics-server-684c7f9488-z6sdz 1/1 Running 0 1h 172.33.31.3 node2
kube-system kubernetes-dashboard-6b66b8b96c-mnm2c 1/1 Running 0 1h 172.33.31.2 node2
Kubernetes 网络类型
Kubernetes 集群内部存在三类重要的 IP 地址:
- Node IP:宿主机的物理网络 IP 地址,用于节点间通信
- Pod IP:由网络插件(如 Flannel)分配的容器 IP,实现跨节点 Pod 通信
- Cluster IP:Service 的虚拟 IP,通过 iptables/ipvs 规则提供服务访问
Flannel 网络架构
工作原理
Flannel 作为二进制程序部署在每个节点上,主要实现以下功能:
- 子网分配:为每个节点分配独立的子网段,确保 Pod IP 不冲突
- 路由管理:动态维护跨节点的路由信息,实现 Pod 间通信
- 网络封装:支持多种后端实现(VXLAN、host-gw、UDP 等)
网络拓扑
下图展示了使用 host-gw
后端的 Flannel 网络架构:

etcd 中的网络配置
Flannel 将网络配置信息存储在 etcd 中:
# 查看子网分配情况
[root@node1 ~]# etcdctl ls /kube-centos/network/subnets
/kube-centos/network/subnets/172.33.68.0-24
/kube-centos/network/subnets/172.33.31.0-24
/kube-centos/network/subnets/172.33.96.0-24
# 查看网络配置
[root@node1 ~]# etcdctl get /kube-centos/network/config
{"Network":"172.33.0.0/16","SubnetLen":24,"Backend":{"Type":"host-gw"}}
配置说明:
Network
:整个集群的网络段SubnetLen
:每个节点分配的子网掩码长度Backend
:网络实现方式(host-gw、vxlan、udp)
Flannel 配置详解
服务配置
Node1 上的 Flannel 服务配置:
[root@node1 ~]# cat /usr/lib/systemd/system/flanneld.service
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service
[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/flanneld
EnvironmentFile=-/etc/sysconfig/docker-network
ExecStart=/usr/bin/flanneld-start $FLANNEL_OPTIONS
ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure
[Install]
WantedBy=multi-user.target
RequiredBy=docker.service
环境变量配置
Flannel 主配置文件:
[root@node1 ~]# cat /etc/sysconfig/flanneld
# Flanneld configuration options
FLANNEL_ETCD_ENDPOINTS="http://172.17.8.101:2379"
FLANNEL_ETCD_PREFIX="/kube-centos/network"
FLANNEL_OPTIONS="-iface=eth2"
动态生成的配置
Flannel 启动后会生成以下配置文件:
Docker 网络配置 (/run/flannel/docker
):
[root@node1 ~]# cat /run/flannel/docker
DOCKER_OPT_BIP="--bip=172.33.68.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=true"
DOCKER_OPT_MTU="--mtu=1500"
DOCKER_NETWORK_OPTIONS="--bip=172.33.68.1/24 --ip-masq=true --mtu=1500"
子网环境变量 (/run/flannel/subnet.env
):
[root@node1 ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.33.0.0/16
FLANNEL_SUBNET=172.33.68.1/24
FLANNEL_MTU=1500
FLANNEL_IPMASQ=false
容器运行时集成
网络接口分析
查看节点的网络接口:
[root@node1 ~]# ip addr show
# 主要接口说明:
# lo: 回环接口 (127.0.0.1)
# eth0: NAT 网络接口
# eth1: 集群内部通信接口 (172.17.8.101/24)
# eth2: 外网访问接口
# docker0: Docker 网桥 (172.33.68.1/24)
# veth对: 连接容器与网桥的虚拟网卡对
网络接口类型说明:
- 物理接口:实际的网络硬件接口
- 虚拟网桥:软件实现的二层交换设备
- veth pair:成对出现的虚拟网络接口,用于连接不同的网络命名空间
容器网络检查
查看 Docker 网络配置:
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
940bb75e653b bridge bridge local
d94c046e105d host host local
2db7597fd546 none null local
# 检查 bridge 网络详情
[root@node1 ~]# docker network inspect bridge
# 输出包含子网配置、网关设置、连接的容器等信息
路由机制
路由表分析
Node1 的路由信息:
[root@node1 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.2.2 0.0.0.0 UG 100 0 0 eth0
172.17.8.0 0.0.0.0 255.255.255.0 U 100 0 0 eth1
172.33.68.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
172.33.31.0 172.17.8.102 255.255.255.0 UG 0 0 0 eth1
172.33.96.0 172.17.8.103 255.255.255.0 UG 0 0 0 eth1
路由规则说明:
- 本地子网(172.33.68.0/24)直接通过 docker0 网桥
- 远程子网通过对应节点的 IP 地址路由
- Flannel 自动维护这些路由规则
跨节点通信测试
测试从 node1 访问 node3 上的 Pod:
[root@node1 ~]# traceroute 172.33.96.3
traceroute to 172.33.96.3 (172.33.96.3), 30 hops max, 60 byte packets
1 172.17.8.103 (172.17.8.103) 0.518 ms 0.367 ms 0.398 ms
2 172.33.96.3 (172.33.96.3) 0.451 ms 0.352 ms 0.223 ms
通信流程:
- 数据包从 node1 发出
- 根据路由表转发到 node3(172.17.8.103)
- node3 接收后转发到目标 Pod
防火墙规则
Kubernetes 会在 iptables 中注入相关规则:
[root@node1 ~]# iptables -L -n
# 主要规则链:
# KUBE-SERVICES: Service 访问规则
# KUBE-FORWARD: 转发规则
# KUBE-FIREWALL: 防火墙规则
重要规则说明:
- KUBE-SERVICES:处理 Service 的负载均衡
- KUBE-FORWARD:允许 Pod 间的转发通信
- DOCKER 链:处理容器网络的 NAT 规则
最佳实践
性能优化
选择合适的后端:
host-gw
:性能最佳,要求节点在同一子网vxlan
:适用于复杂网络环境,有轻微性能损耗
MTU 设置:
- 根据底层网络调整 MTU 值
- 避免数据包分片导致的性能问题
故障排查
常见问题及解决方法:
Pod 无法跨节点通信:
- 检查路由表是否正确
- 验证防火墙规则
- 确认 Flannel 服务状态
网络性能问题:
- 检查 MTU 配置
- 监控网络接口状态
- 分析网络延迟和丢包