- 云原生
- 教程
【免费下载链接】kubernetes-handbook
Kubernetes Handbook (Kubernetes指南) https://kubernetes.feisky.xyz
Flannel 是 Kubernetes 生态中最经典的 overlay 网络插件之一,它通过为每台宿主机分配独立子网的方式,为集群内的 Pod 提供跨节点的虚拟网络。本指南以本仓库 extension/network/flannel.md 为主线,结合仓库内 extension/network/README.md 的网络模型说明、extension/network/cni.md 的 CNI 机制以及etc/sysconfig/flanneld、manifests/systemd/flanneld.service等真实配置,系统讲解 Flannel 的控制面/数据面架构、核心配置参数、六大 Backend 的选型差异,以及 Docker、CNI、Kubernetes 三套集成方案。读完本文,你将能够独立完成 Flannel 的部署配置,并理解其底层数据转发路径。
Flannel 在 Kubernetes 网络模型中的定位
Kubernetes 采用 IP-per-Pod 的扁平网络模型:每个 Pod 都拥有独立 IP 地址,Pod 内所有容器共享一个网络命名空间;集群内所有 Pod 处于一个直接连通的扁平网络中,容器之间、Node 与容器之间无需 NAT 即可直接互访(见 extension/network/README.md)。
然而裸机或公有云环境下的宿主机网段通常不足以支撑大量 Pod IP,跨节点的容器通信也需要额外的路由或隧道机制。正如 extension/network/cni.md 指出的:Bridge 模式下,多主机网络通信需要额外配置主机路由,或使用 overlay 网络,此时可以借助 Flannel 或 Quagga 动态路由等来自动配置。
Flannel 正是为了解决这一跨节点连通性问题而生的 overlay 网络方案。它基于 Linux TUN/TAP 设备,使用 UDP 封装 IP 包来创建 overlay 网络,并借助 etcd 维护网络的分配情况。其核心思想是:把集群网段(如10.244.0.0/16)按宿主机划分成若干子网,每台宿主机独占一个子网(如10.244.0.0/24),Pod 的 IP 由宿主机本地的子网分配,跨宿主机的流量则通过封装隧道转发,从而既保证了 IP 不冲突,又实现了跨节点连通。
Flannel 工作原理:控制平面与数据平面
Flannel 的架构可以清晰地区分为控制平面与数据平面两个部分:
- 控制平面:宿主机上的
flanneld进程负责从远端的 etcd 集群同步本地和其他主机上的 subnet 信息,并为 Pod 分配 IP 地址。在 Kubernetes 集成模式下,flanneld 也可以改用--kube-subnet-mgr从 Kubernetes API 获取子网分配,而不再直接读写 etcd。 - 数据平面:Flannel 通过 Backend(如 UDP 封装)实现 L3 Overlay,既可以选用一般的 TUN 设备,也可以选用 VxLAN 设备完成封装与转发。
Flannel overlay 网络整体架构示意
这种"控制面集中协调、数据面分布式转发"的设计,使得 Flannel 在部署上非常轻量——每台宿主机只需运行一个 flanneld 守护进程,无需额外的控制节点。
核心配置详解:net-conf.json 参数
Flannel 的网络配置通常以 JSON 形式存放在 etcd 的指定 prefix(或通过 Kubernetes ConfigMap)下。原文档给出的典型配置如下:
{ "Network": "10.0.0.0/8", "SubnetLen": 20, "SubnetMin": "10.10.0.0", "SubnetMax": "10.99.0.0", "Backend": { "Type": "udp", "Port": 7890 } }各字段含义与作用:
| 参数 | 说明 |
|---|---|
Network | 整个集群的 overlay 网络 CIDR,flannel 将在此范围内为每台宿主机划分子网。上例为10.0.0.0/8 |
SubnetLen | 每台宿主机分配到的子网前缀长度。上例为 20,即在10.0.0.0/8内划分出若干个/20子网,每台主机独占其一 |
SubnetMin/SubnetMax | 宿主机子网的可分配范围边界,用于限定哪些子网可以被分配(上例限制在10.10.0.0到10.99.0.0之间),避免与机房内其他网段冲突 |
Backend.Type | 数据平面封装方式,取值如udp、vxlan、host-gw等,见下一节 |
Backend.Port | Backend 使用的端口。上例为 7890,是针对 udp 模式的自定义端口(默认 8285) |
仓库中的 etc/sysconfig/flanneld 展示了非 Kubernetes 模式下 flanneld 的进程级配置,与本 JSON 配置一一对应:
# etcd url location. Point this to the server where etcd runs FLANNEL_ETCD_ENDPOINTS="https://172.20.0.113:2379,https://172.20.0.114:2379,https://172.20.0.115:2379" # etcd config key. This is the configuration key that flannel queries # For address range assignment FLANNEL_ETCD_PREFIX="/kube-centos/network" # Any additional options that you want to pass FLANNEL_OPTIONS="-etcd-cafile=/etc/kubernetes/ssl/ca.pem -etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem -etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem"FLANNEL_ETCD_ENDPOINTS:flanneld 连接的 etcd 集群地址(此处为三个节点的高可用 etcd)。FLANNEL_ETCD_PREFIX:网络配置在 etcd 中的键前缀(/kube-centos/network),net-conf.json 即存放在该 prefix 之下。FLANNEL_OPTIONS:传递给 flanneld 的附加参数,典型场景是开启 etcd TLS 认证(CA、客户端证书与私钥)。
Backend 详解与选型
除了 UDP,Flannel 还支持多种 Backend,分别适用于不同的网络环境:
| Backend | 封装/转发方式 | 适用场景与注意事项 |
|---|---|---|
udp | 用户态 UDP 封装,默认使用 8285 端口 | 兼容性最好,但封装与解包都在用户态完成,性能损失较大,生产环境一般不推荐 |
vxlan | 内核态 VxLAN 封装 | 需要配置 VNI、Port(默认 8472)以及 GBP(Group Based Policy,即内核3511494ce2f3d3b77544c79b87511a4ddb61dc89提交引入的能力);相比 udp 性能更好,是生产环境的常用选择 |
host-gw | 直接路由,将容器网络路由信息直接写入主机路由表 | 无封装开销,性能最佳,但仅适用于二层直接可达的网络(如同一交换机/VLAN),无法跨三层路由 |
aws-vpc | 使用 Amazon VPC route table 创建路由 | 适用于 AWS 上运行的容器,利用云平台原生路由表,无额外隧道开销 |
gce | 使用 Google Compute Engine Network 创建路由 | 适用于 GCE 上运行的容器,所有 instance 需开启 IP forwarding |
ali-vpc | 使用阿里云 VPC route table 创建路由 | 适用于阿里云上运行的容器,与云厂商 VPC 路由表深度集成 |
选型要点:若集群运行在公有云 VPC 内且云平台支持路由表下发(AWS/GCE/阿里云),优先使用对应的 VPC Backend——这种方式没有额外的封装性能损失;若在自建机房且二层可达,host-gw最为高效;需要跨三层网络时,则回退到vxlan(内核态封装)或udp(用户态封装,兼容性优先)。
VxLAN 隧道模式下的跨节点 Pod 通信拓扑
仓库目录 network/flannel/flannel-flow.png 也存放了一张 Flannel VXLAN 隧道网络模型示意图,直观展示了两个节点各自的cni0网桥(网段分别为10.244.0.1/24与10.244.1.1/24)、flannel.1虚拟接口以及二者之间通过 VxLAN 隧道互联的结构,可作为理解上述转发路径的补充参考。
与 Docker 集成
在未使用 Kubernetes、仅用 Docker 的场景下,Flannel 通过环境变量文件将子网与 MTU 信息注入 Docker daemon:
source /run/flannel/subnet.env docker daemon --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU} &--bip=${FLANNEL_SUBNET}:将 docker0 网桥的 IP 设置为 flannel 分配给本机的子网(如10.244.0.1/24),使容器 IP 处于 Flannel 子网范围内。--mtu=${FLANNEL_MTU}:将 Docker 网络 MTU 设置为 Flannel 计算出的 MTU(通常为物理网卡 MTU 减去隧道封装开销,实际输出中常见 1410)。
在仓库的 systemd 部署方案中,这一步由 manifests/systemd/flanneld.service 的ExecStartPost自动完成:
ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/dockermk-docker-opts.sh脚本从/run/flannel/subnet.env读取子网与 MTU,生成DOCKER_NETWORK_OPTIONS环境变量文件(输出到/run/flannel/docker),供 docker.service 加载,从而把--bip、--mtu等参数自动传递给 Docker daemon。从服务单元依赖(Before=docker.service、RequiredBy=docker.service)可以看出,flanneld 必须在 Docker 启动前完成网络配置,这正是"先有 flannel 子网、再启动 docker0"的编排保证。
与 CNI 集成:flannel 插件如何委派给 bridge
Kubernetes 1.6+ 推荐使用 CNI 网络插件。CNI 的 flannel 插件并不自行实现网桥逻辑,而是将 flannel 网络配置转换为 bridge 插件配置,并调用 bridge 插件给容器 netns 配置网络。
比如下面的 flannel 配置:
{ "name": "mynet", "type": "flannel", "delegate": { "bridge": "mynet0", "mtu": 1400 } }会被 CNI flannel 插件转换为实际的 bridge 插件配置:
{ "name": "mynet", "type": "bridge", "mtu": 1472, "ipMasq": false, "isGateway": true, "ipam": { "type": "host-local", "subnet": "10.1.17.0/24" } }转换过程要点:
delegate字段用于向 flannel 插件传递希望覆盖的 bridge 参数(如自定义网桥名mynet0、期望 MTU 1400);- 转换后
type变为bridge,MTU 会被 flannel 修正为 overlay 网络实际可用的 MTU(上例 1472,即物理 MTU 减去 VxLAN/UDP 封装开销后得到的值),若用户未指定则使用 flannel 计算出的默认值; ipMasq: false表示本网段流量不做 SNAT(跨节点流量交给 flannel 隧道处理);isGateway: true使网桥成为 Pod 的默认网关;ipam使用host-local类型,subnet由 flannel 分配的本机子网(上例10.1.17.0/24)自动填充,保证 Pod IP 落在本机子网内且全局唯一。
与 Kubernetes 集成:完整部署流程
前置条件:为 kube-controller-manager 开启 CIDR 分配
使用 Flannel 前,需要让 kube-controller-manager 为每个 Node 分配独立的 PodCIDR,并指定集群 Pod CIDR:
kube-controller-manager --allocate-node-cidrs=true --cluster-cidr=10.244.0.0/16--allocate-node-cidrs=true:允许控制器为每个 Node 从集群 CIDR 中划分子网,并写入node.Spec.PodCIDR。--cluster-cidr=10.244.0.0/16:集群 Pod 网段,flannel 将以此作为整个 overlay 网络的范围(这也是 Flannel 官方部署清单中的默认网段)。
部署 flanneld DaemonSet
kubectl apply -f <coreos/flannel 官方仓库 Documentation 目录下的 kube-flannel.yml>该清单会创建一个 DaemonSet,在每台 Node 上启动 flanneld 容器,并自动完成 CNI 网络插件的配置(将 flannel 的 CNI 配置写入宿主机/etc/cni/net.d,同时把 CNI 插件二进制放入/opt/cni/bin)。部署完成后,可通过进程列表确认 flanneld 与 CNI 配置容器的状态:
$ ps -ef | grep flannel | grep -v grep root 3625 3610 0 13:57 ? 00:00:00 /opt/bin/flanneld --ip-masq --kube-subnet-mgr root 9640 9619 0 13:51 ? 00:00:00 /bin/sh -c set -e -x; cp -f /etc/kube-flannel/cni-conf.json /etc/cni/net.d/10-flannel.conf; while true; do sleep 3600; done- flanneld 以
--ip-masq(开启 IP 伪装/SNAT,用于访问集群外网络)和--kube-subnet-mgr(从 Kubernetes API 而非直接读 etcd 获取子网分配)两个关键参数运行; - 第二个进程是 CNI 配置容器,它把
/etc/kube-flannel/cni-conf.json拷贝为/etc/cni/net.d/10-flannel.conf,并以 sleep 循环保活。
生成的 CNI 配置文件内容如下:
{ "name": "cbr0", "type": "flannel", "delegate": { "isDefaultGateway": true } }该配置与前面 CNI 集成一节的结构一致:type: flannel的插件在运行时会读取 flanneld 写入的数据文件,把delegate中的参数(此处设置isDefaultGateway: true,使 bridge 成为 Pod 默认网关)合并进最终的 bridge 配置并委派执行。
flanneld 如何利用 PodCIDR 构建数据面
在--kube-subnet-mgr模式下,flanneld 自动连接 Kubernetes API,根据node.Spec.PodCIDR配置本地的 flannel 网络子网,并为容器创建 vxlan 设备(如 flannel.1)和相关的子网路由。
查看本地子网环境文件,可以看到 flannel 为本机生成的完整网络参数:
$ cat /run/flannel/subnet.env FLANNEL_NETWORK=10.244.0.0/16 FLANNEL_SUBNET=10.244.0.1/24 FLANNEL_MTU=1410 FLANNEL_IPMASQ=trueFLANNEL_NETWORK:集群 overlay 网段,即 kube-controller-manager 的--cluster-cidr;FLANNEL_SUBNET:本机分配到的子网及网关地址(此处10.244.0.1/24,对应node.Spec.PodCIDR为10.244.0.0/24);FLANNEL_MTU:overlay 网络实际 MTU(1410,即物理网卡 MTU 减去封装头开销);FLANNEL_IPMASQ:是否开启 IP 伪装,与进程参数--ip-masq对应。
查看内核态 VxLAN 设备,可以看到隧道端点的真实形态:
$ ip -d link show flannel.1 12: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1410 qdisc noqueue state UNKNOWN mode DEFAULT group default link/ether 8e:5a:0d:07:0f:0d brd ff:ff:ff:ff:ff:ff promiscuity 0 vxlan id 1 local 10.146.0.2 dev ens4 srcport 0 0 dstport 8472 nolearning ageing 300 udpcsum addrgenmode eui64vxlan id 1:VNI(VxLAN Network Identifier)为 1;local 10.146.0.2 dev ens4:本机隧道源地址为宿主机网卡ens4上的 IP;dstport 8472:VxLAN 封装目标端口为默认的 8472(与 Backend 一节中 vxlan 默认端口一致)。
至此,一条完整的跨节点数据路径已经建立:Pod 流量到达本机cni0网桥 → 依据主机路由表交给flannel.1虚拟设备 → 内核 VxLAN 封装后经物理网卡发往目标节点 → 目标节点解封装后经其flannel.1与cni0到达目标 Pod。
系统部署参考:systemd 下的 Flannel 启动流程
对于不使用 Kubernetes 自管理、而是通过 systemd 管理的场景,仓库提供了完整的参考单元文件 manifests/systemd/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关键点解读:
After=etcd.service+Before=docker.service:严格保证启动顺序——先有 etcd 与网络、再有 flanneld 完成子网分配、最后才启动 Docker;Type=notify:flanneld 就绪后会通过 sd_notify 通知 systemd,只有网络配置完成才视为服务启动成功;EnvironmentFile=/etc/sysconfig/flanneld:加载前文所述的 etcd 端点、prefix 与 TLS 选项($FLANNEL_OPTIONS);ExecStartPost:启动后立即调用mk-docker-opts.sh生成 Docker 所需的--bip/--mtu选项文件;Restart=on-failure:进程异常退出时自动拉起。
优点与局限
优点:
- 配置安装简单,使用方便:只需一份 net-conf.json 或官方 kube-flannel.yml,即可完成集群组网;
- 与云平台集成较好:
aws-vpc、gce、ali-vpc等 Backend 直接使用云厂商 VPC 路由表,VPC 方式没有额外的封装性能损失。
局限:
- VXLAN 模式对 zero-downtime restarts(零停机重启)支持不好。官方说明指出:当 Backend 不是 udp 时,内核承担数据通路、flanneld 仅作为控制平面,因此 flanneld 重启(甚至升级)不会干扰已有流量;但 vxlan Backend 下,重启需要在几秒内完成,否则 ARP 条目可能超时,需要 flannel 守护进程刷新它们。此外,为避免重启期间的中断,重启时配置不得变更(例如 VNI、
--iface等取值必须保持原样)。
总结
Flannel 以"控制面集中分配子网 + 数据面内核/用户态封装转发"的方式,为 Kubernetes 提供了简单可靠的 overlay 网络方案。无论是选择udp的兼容性、vxlan的性能,还是host-gw与云 VPC Backend 的无封装效率,都需要结合集群的网络环境权衡;而它与 Docker、CNI、Kubernetes 三种运行形态的集成方式,也使其成为理解容器网络抽象层的最佳切入点之一。
在本仓库中,Flannel 是 extension/network/README.md 网络插件体系中的一员,与之并列的还有 Weave Net、Calico、OVN、Contiv 等方案,其底层依赖的 CNI 机制详见 CNI 网络插件。如需在已有 Kubernetes 集群中快速体验,参照上文"与 Kubernetes 集成"一节,配置好--allocate-node-cidrs与--cluster-cidr后应用官方kube-flannel.yml即可。
- 云原生
- 教程
【免费下载链接】kubernetes-handbook
Kubernetes Handbook (Kubernetes指南) https://kubernetes.feisky.xyz
相关推荐
Kubernetes 网络模型与 CNI 插件深度解析:从 flannel、Calico 到 Cilium
Kubernetes 网络模型与 CNI 插件深度解析:从 flannel、Calico 到 Cilium Kubernetes 网络是构建集群时绕不开的核心话
教程云原生容器编排Kubernetes 网络插件全解析:网络模型、kubenet、CNI 与主流第三方插件实战指南
Kubernetes 网络插件全解析:网络模型、kubenet、CNI 与主流第三方插件实战指南 本篇指南以 Kubernetes Handbook 的「网络插
云原生教程5步构建高质量语音数据集:Audiblez新语言模型训练全指南
5步构建高质量语音数据集:Audiblez新语言模型训练全指南 你是否在为新语言训练TTS(Text to Speech,文本转语音)模型时遇到过这些问题:录音
云原生网络后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考