Flannel 是一个专为 Kubernetes 设计的轻量级 Overlay 网络解决方案,它通过在现有主机网络之上创建虚拟二层网络,使分布在不同节点上的 Pod 能够像处于同一个局域网内一样直接通信。在 Ubuntu 这类主流 Linux 发行版上部署 Flannel 并不复杂,但需要理解其背后的数据封装机制以及各组件之间的协作关系,否则容易在 MTU 设置、防火墙放行或 Pod 网段规划上踩坑。

本文将以 Ubuntu 20.04/22.04 作为基础环境,介绍 Flannel 的核心工作原理、完整安装步骤以及验证与排错方法。无论你是正准备初始化一套 Kubernetes 集群,还是想在现有集群中更换 CNI 插件,都可以通过本文的演示快速完成任务。
Flannel Overlay 网络核心原理
Flannel 的设计目标非常简单:为每个节点分配一个独立的子网,然后通过某种封装或路由技术将这些子网连接起来。默认情况下,Flannel 使用 VXLAN(Virtual eXtensible LAN)作为数据平面,它把 Pod 发出的以太网帧封装在 UDP 数据包中进行传输,从而跨越底层物理网络。VXLAN 报文的结构是:物理网络层(IP + UDP)承载 VXLAN 头部和原始二层帧,物理网络中的交换机或路由器只看到 UDP 流量,完全感知不到 Overlay 的存在。
在控制平面方面,Flannel 可以依赖 etcd 或者 Kubernetes 的 API Server 来存储每个节点的子网分配信息。当一个新的节点加入集群时,Flannel 守护进程(flanneld)会从后端存储中获取全局配置,并为自己分配一个未使用的子网,例如 10.244.1.0/24。随后,flanneld 会修改本机的路由表和 ARP 表,使得发往其他节点 Pod 的流量被引导到对应的 VXLAN 隧道接口上。以 VXLAN 模式为例,每个节点会创建一个名为 flannel.1 的虚拟网络设备,它的作用类似于一个网关,负责将原始二层帧封装后发送到目标节点的物理 IP 地址。
除了 VXLAN,Flannel 还支持 Host-GW、UDP、IPIP 等后端模式。Host-GW 模式直接利用主机路由表进行三层转发,不进行报文封装,因此性能最好,但要求所有节点必须位于同一个二层网络内。在 Ubuntu 部署时,如果网络环境允许二层互通,建议优先考虑 Host-GW 模式;若跨网段部署或底层不支持二层广播,则使用 VXLAN 模式。
Ubuntu 环境准备与 Flannel 安装
在安装 Flannel 之前,需要确保 Ubuntu 节点已经完成以下准备工作。首先,所有节点必须安装 Docker 或 containerd,因为 Flannel 生成的 CNI 配置文件需要与容器运行时配合使用。以 Docker 为例,可以通过官方脚本或 apt 仓库进行安装:
# 安装 Docker Engine sudo apt update sudo apt install -y docker.io sudo systemctl enable --now docker # 检查 Docker 版本 docker version
接下来,初始化 Kubernetes 集群。如果你使用 kubeadm 进行部署,需要在主节点上执行 kubeadm init 命令,并确保在初始化时指定 Pod 网络网段,使其与 Flannel 的默认配置一致。例如:
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
初始化完成后,需要配置 kubectl 的访问权限,并将其他节点加入集群。当集群处于 Ready 之前,CoreDNS 等系统组件会一直处于 Pending 状态,因为它们等待 CNI 插件安装完成。此时就可以安装 Flannel 了。最直接的方法是下载 Flannel 官方提供的 YAML 清单文件,然后使用 kubectl apply 命令部署:
# 下载 Flannel YAML 文件 wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml # 应用配置 kubectl apply -f kube-flannel.yml
默认情况下,kube-flannel.yml 假定 Pod 网段为 10.244.0.0/16,并且使用 VXLAN 后端。如果你的集群规划不是该网段,需要编辑该文件,将 net-conf.json 中的 Network 字段修改为实际值。同时,如果希望使用 Host-GW 模式,可以将 Backend 字段的 Type 改为 host-gw。需要注意的是,修改后端模式时,所有节点上的 flanneld 必须保持一致,否则会导致网络割裂。
Flannel 配置验证与通信测试
部署完成后,首先要检查 Flannel 相关 Pod 是否正常运行。执行以下命令:
kubectl get pods -n kube-system -l app=flannel
正常情况下应该看到每个节点都有一个 flannel Pod 处于 Running 状态。如果某些 Pod 一直处于 CrashLoopBackOff,可以通过 kubectl logs 命令查看 flanneld 的日志,常见错误包括:etcd 连接失败、后端存储权限不足、网络接口名称不匹配等。接下来,验证 CNI 配置文件是否成功生成。每个节点的 /etc/cni/net.d/ 目录下应该出现 10-flannel.conflist 文件,其内容定义了 Flannel 作为 CNI 插件使用的相关参数。
为了测试跨节点的 Pod 通信,可以创建两个 Deployment,并通过节点选择器强制它们调度到不同的节点上。例如:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test-a
spec:
replicas: 1
selector:
matchLabels:
app: nginx-a
template:
metadata:
labels:
app: nginx-a
spec:
nodeSelector:
kubernetes.io/hostname: node1
containers:
- name: nginx
image: nginx:1.21
对应的另一个 Deployment 调度到 node2 上。然后通过 kubectl exec 进入其中一个 Pod,使用 curl 或 ping 访问另一个 Pod 的 IP 地址。这里注意,Flannel 分配的 Pod IP 是虚拟的二层地址,通信时数据包会经过 flannel.1 接口进行 VXLAN 封装。可以使用 tcpdump 抓取物理网卡上的流量来验证封装是否生效:
sudo tcpdump -i eth0 udp port 8472 -nn -vv
如果抓包结果中出现了许多 UDP 8472 端口的数据包,说明 VXLAN 封装正常工作。同时也可以在节点上查看路由表,确认去往其他节点子网的路由指向 flannel.1 接口:
ip route show | grep flannel
输出中的 10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink 这类条目表示路由配置正确。
Flannel 部署常见问题与性能调优
在 Ubuntu 上部署 Flannel 时,最常遇到的问题之一是 Pod 之间无法连通,而 flanneld 日志却显示正常。这种情况往往是防火墙规则阻止了 VXLAN 使用的 UDP 8472 端口,或者节点之间的物理网络不允许该端口的通信。可以通过在每台节点上执行以下命令来临时放行:
sudo iptables -I INPUT -p udp --dport 8472 -j ACCEPT sudo iptables -I OUTPUT -p udp --sport 8472 -j ACCEPT
如果是使用 ufw 防火墙的 Ubuntu 桌面版,还需要执行 sudo ufw allow 8472/udp。另一个容易被忽略的问题是 MTU 不匹配。因为 VXLAN 封装会增加 50 字节的头部开销,如果物理网络的 MTU 为 1500,那么 Pod 接口的 MTU 应该设置为 1450,否则大数据包会被分片,严重降低通信效率。Flannel 默认会自动计算 MTU,但如果发现性能异常,可以手动指定 --iface 和 --mtu 参数。
在性能敏感的场景下,推荐使用 Host-GW 模式。该模式不需要任何封装,直接通过主机路由表转发数据包,延迟和吞吐量接近原生网络。但 Host-GW 要求所有节点位于同一个二层广播域内,否则无法直接路由。对于跨区域或公有云环境,VXLAN 是更通用的选择。此外,Flannel 还支持 WireGuard 后端,它可以在 Overlay 网络之上提供加密传输,适合对安全性有较高要求的场景。启用 WireGuard 后端需要在 kube-flannel.yml 中添加相关配置,并在所有节点上安装 WireGuard 内核模块。