在 Kubernetes 中安装与配置 Flannel 网络插件:从 vxlan 到 host-gw 的完整实践
2026/9/23 12:39:35 网站建设 项目流程

在 Kubernetes 中安装与配置 Flannel 网络插件:从 vxlan 到 host-gw 的完整实践

【免费下载链接】kubernetes-handbookKubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook

Flannel 是 Kubernetes 中最常用的容器网络插件之一,它以 etcd 为存储后端为每个 Node 分配独立的 Pod 子网,并通过 vxlan 或 host-gw 等后端实现跨主机 Pod 互通。本文基于 kubernetes-handbook 的 安装 flannel 网络插件 一文,完整讲解在所有 Node 节点上通过 yum 安装、配置、启动并验证 flannel 的每一步操作,同时结合仓库中的 flanneld.service、flanneld 环境变量配置、docker.service 等真实配置文件,深入剖析 flannel 与 etcd、Docker 之间的协作机制,帮助你一次上手即可部署出可用的扁平化 Pod 网络。

为什么每个 Node 节点都需要网络插件

Kubernetes 集群中运行着三类 IP,理解它们之间的区别是配置网络插件的前提:

  • Node IP:宿主机的物理 IP 地址;
  • Pod IP:由网络插件(如 flannel)分配的虚拟 IP,用于让跨主机的 Pod 相互连通;
  • Cluster IP:Service 的虚拟 IP,通过 kube-proxy 注入的 iptables 规则访问。

Kubernetes 本身并不实现网络方案,而是通过 CNI(Container Network Interface)规范对接各类插件(详见 容器网络接口(CNI))。只有所有 Node 节点都安装了网络插件,集群中的所有 Pod 才能加入同一个局域网,这也是安装 flannel 的出发点。按照本手册的部署顺序,Node 节点上的进程遵循flannel -> docker -> kubelet -> kube-proxy的启动次序,flannel 是整个链路的第一环。

从架构上看,运行在每个 Node 上的 flanneld 进程承担两个核心职责:

  1. 为每个 Node 分配独立的 subnet:容器启动后自动从该子网中获取 IP;
  2. 维护跨节点路由:当有新的 Node 加入网络时,为每个 Node 增加指向远端子网的路由条目。

安装前准备:etcd 集群与 TLS 证书

flannel 以 etcd 作为配置和租约存储后端,因此安装前必须保证:

  • 有一个可访问的 etcd 集群(本文示例为三节点172.20.0.113/114/115:2379,TLS 加密通信);
  • 每个 Node 上已准备好与 etcd 通信所需的证书文件:ca.pemkubernetes.pemkubernetes-key.pem(位于/etc/kubernetes/ssl/目录,与 kube-apiserver 使用的证书一致,etcd 集群安装可参考 etcd 集群安装)。

使用 yum 安装 flanneld

建议直接使用 yum 安装 flanneld,除非对版本有特殊需求:

yum install -y flannel

在本文写作时默认安装的是0.7.1 版本的 flannel。安装完成后会在系统内生成两个关键文件:

文件作用
/usr/lib/systemd/system/flanneld.serviceflanneld 的 systemd 单元文件,定义了启动参数与依赖关系
/etc/sysconfig/flanneldflanneld 的环境变量配置文件(endpoints、prefix、TLS 等)

配置 flanneld:service 单元文件解析

仓库中完整保存了该单元文件,见 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 \ -etcd-endpoints=${FLANNEL_ETCD_ENDPOINTS} \ -etcd-prefix=${FLANNEL_ETCD_PREFIX} \ $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 与系统各组件的关系:

  • After=etcd.service/Before=docker.service:声明 flanneld 必须在 etcd 之后启动、在 docker 之前启动。这正是"先有子网分配、后有 Docker 接入"的编排保证;
  • RequiredBy=docker.service:将 docker 反向依赖 flannel,确保 docker 启动前 flanneld 已经就绪;
  • Type=notify:flanneld 启动完成后会主动向 systemd 发送通知,避免过早认为服务就绪;
  • EnvironmentFile/etc/sysconfig/flanneld提供核心变量;-/etc/sysconfig/docker-network前面的-表示该文件允许不存在;
  • ExecStartflanneld-start从环境变量中读取 etcd endpoints 与配置前缀(key),$FLANNEL_OPTIONS用于透传额外的命令行参数(如 TLS 证书、指定网卡);
  • ExecStartPost:flanneld 启动后立即执行/usr/libexec/flannel/mk-docker-opts.sh,它基于 flannel 生成的子网信息生成 Docker 所需的启动参数文件,这是 flannel 与 Docker 协作的关键一环,下文会展开说明;
  • Restart=on-failure:进程异常退出时自动拉起。

配置 /etc/sysconfig/flanneld 环境变量

仓库中的 etc/sysconfig/flanneld 完整呈现了该配置文件的典型内容:

# Flanneld configuration options # 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_ENDPOINTSetcd 集群地址列表,多个地址用逗号分隔;此处使用 https 表明开启 TLS
FLANNEL_ETCD_PREFIXflannel 在 etcd 中使用的配置键前缀,本文统一使用/kube-centos/network
FLANNEL_OPTIONS追加的 flanneld 命令行参数。本示例为与启用 TLS 的 etcd 通信指定 CA、客户端证书与私钥

多网卡场景:如果宿主机有多个网卡(例如 vagrant 环境),flannel 可能选错出口网卡导致子网无法互通,此时需要在FLANNEL_OPTIONS中显式指定对外网卡,例如-iface=eth2

注意:FLANNEL_ETCD_ENDPOINTSFLANNEL_ETCD_PREFIX这两个变量仅供 flanneld 使用,而 flannel 生成的 Docker 参数会单独落到/run/flannel/目录(见下文)。

在 etcd 中初始化网络配置

flannel 从 etcd 中的配置键读取整个集群的网络规划(大网段、子网掩码、后端类型)。首先创建配置目录,然后写入网络配置:

etcdctl --endpoints=https://172.20.0.113:2379,https://172.20.0.114:2379,https://172.20.0.115:2379 \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ mkdir /kube-centos/network etcdctl --endpoints=https://172.20.0.113:2379,https://172.20.0.114:2379,https://172.20.0.115:2379 \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ mk /kube-centos/network/config '{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}'

该 JSON 配置中的三个字段共同决定了整个集群的 Pod 网络形态:

  • Network:整个集群的 Pod 大网段(CIDR),所有 Node 的子网都从该网段中划分;
  • SubnetLen:每个 Node 获得的子网掩码长度,示例为24,即每个 Node 最多可容纳 254 个 Pod(172.30.0.0/16可划分出 256 个/24子网);
  • Backend.Type:数据面封装/转发模式。示例为vxlan(Overlay 隧道);如果希望改用host-gw模式,直接将vxlan改为host-gw即可,例如:
etcdctl --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ mk /kube-centos/network/config '{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"host-gw"}}'

关于 vxlan 与 host-gw 的取舍,可参考 网络和集群性能测试 一节,该节最终采用了host-gw 模式,两者差异详见本文后面的"模式选择"部分。

启动 flannel 并验证

配置完成后即可启动 flanneld:

systemctl daemon-reload systemctl enable flanneld systemctl start flanneld systemctl status flanneld

启动成功后,每个 Node 的 flanneld 会向 etcd 注册自己分配到的子网。查询 etcd 可以看到类似如下的内容:

$etcdctl --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ ls /kube-centos/network/subnets /kube-centos/network/subnets/172.30.14.0-24 /kube-centos/network/subnets/172.30.38.0-24 /kube-centos/network/subnets/172.30.46.0-24 $etcdctl --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ get /kube-centos/network/config { "Network": "172.30.0.0/16", "SubnetLen": 24, "Backend": { "Type": "vxlan" } } $etcdctl --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ get /kube-centos/network/subnets/172.30.14.0-24 {"PublicIP":"172.20.0.114","BackendType":"vxlan","BackendData":{"VtepMAC":"56:27:7d:1c:08:22"}} $etcdctl --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ get /kube-centos/network/subnets/172.30.38.0-24 {"PublicIP":"172.20.0.115","BackendType":"vxlan","BackendData":{"VtepMAC":"12:82:83:59:cf:b8"}} $etcdctl --endpoints=${ETCD_ENDPOINTS} \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ get /kube-centos/network/subnets/172.30.46.0-24 {"PublicIP":"172.20.0.113","BackendType":"vxlan","BackendData":{"VtepMAC":"e6:b2:fd:f6:66:96"}}

以上输出中的每一条 subnet 记录都是一个 Node 的"租约":

  • PublicIP:该 Node 对外的物理 IP(示例中 3 个 Node 分别为 114、115、113);
  • BackendType:当前使用 vxlan 后端;
  • BackendData.VtepMAC:该 Node 上创建的 VTEP(虚拟隧道端点)网卡的 MAC 地址,vxlan 模式下正是通过这张网卡完成跨主机封包转发。

如果能够查询到上述内容,说明 flannel 已经安装并运行成功。下一步就可以在该 Node 上安装和配置 docker、kubelet、kube-proxy 等组件,完整流程参见 部署 node 节点。

深入理解:flannel 如何与 Docker 协同工作

flannel 安装完成的标志不只是 flanneld 进程运行,更关键的是它能否把 Pod 子网信息"传导"给 Docker。这一过程由单元文件中的ExecStartPost完成:

ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker

mk-docker-opts.sh的作用是Generate Docker daemon options based on flannel env file(根据 flannel 环境文件生成 Docker 守护进程参数)。flanneld 启动后它会自动生成两个文件:

1./run/flannel/docker—— 给 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"

2./run/flannel/subnet.env—— flannel 向 etcd 注册的子网信息

FLANNEL_NETWORK=172.33.0.0/16 FLANNEL_SUBNET=172.33.68.1/24 FLANNEL_MTU=1500 FLANNEL_IPMASQ=false

其中--bip=172.33.68.1/24指定了该 Node 上 docker0 网桥的地址(也就是 Pod 子网的网关),--mtu与 vxlan 隧道 MTU 相匹配,--ip-masq=true则允许容器访问外部网络时进行地址伪装。

为了让 Docker 读取这些参数,需要修改/usr/lib/systemd/system/docker.service,加入环境变量引用。仓库中的 systemd/docker.service 完整保留了推荐配置(兼容 yum 与二进制两种安装方式):

EnvironmentFile=-/run/flannel/docker EnvironmentFile=-/run/docker_opts.env EnvironmentFile=-/run/flannel/subnet.env EnvironmentFile=-/etc/sysconfig/docker EnvironmentFile=-/etc/sysconfig/docker-storage EnvironmentFile=-/etc/sysconfig/docker-network EnvironmentFile=-/run/docker_opts.env

并且ExecStart中显式拼接了 flannel 生成的三个变量:

ExecStart=/usr/bin/dockerd \ --exec-opt native.cgroupdriver=systemd \ $DOCKER_OPT_BIP \ $DOCKER_OPT_IPMASQ \ $DOCKER_OPT_MTU \ -s=overlay \ --log-driver=json-file \ ...

这样一来,只要通过 systemctl 先启动 flannel 再启动 docker,docker0 就会自动落在 flannel 分配的子网内。实际启动后的 docker 进程参数会呈现为:

--bip=172.33.68.1/24 --ip-masq=true --mtu=1500

ip addr查看宿主机网卡即可印证:docker0的地址正是172.33.68.1/24,同时存在veth设备将 Pod 容器与 docker0 相连;用docker network inspect也能看到 bridge 网络的Subnet/Gateway与 flannel 分配的子网完全一致。这些都是 flannel 与 Docker 成功协同的直接证据。

注意:无论使用 yum 还是二进制方式安装 flannel,向 docker.service 注入上述EnvironmentFile都是必不可少的步骤,否则 Docker 无法加入 flannel 创建的虚拟网络。若二进制方式安装(tar 包方式),还需从 flannel release 中取出mk-docker-opts.sh脚本并执行./mk-docker-opts.sh -i生成环境文件。

验证跨节点 Pod 互通

flannel 的另一项核心工作是维护宿主机的路由表。Node 节点启动 flannel 后,路由表中会出现类似下面的条目(示例来自 扁平网络 Flannel):

172.33.68.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0 172.33.96.0 172.30.118.65 255.255.255.0 UG 0 0 0 eth2
  • 第一条是本机子网路由,指向 docker0;
  • 第二条是 flannel 自动添加的远端 Node 子网路由——当有新的 Node 加入集群后,每个 Node 的路由表都会同步增加对应条目,这也是"新增节点即插即用"的原因。

使用traceroute访问另一台 Node 上的 Pod(如172.33.96.3),可以看到流量先到达对端 Node 的物理 IP,再一跳进入目标 Pod:

1 172.30.118.65 (172.30.118.65) 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

iptables -L中也能看到 kube-proxy 注入的KUBE-SERVICESKUBE-FORWARD等 Service 转发规则链,说明 Pod 网络与 Service 网络已协同工作。

vxlan 与 host-gw 模式如何选择

flannel 支持的两种主流后端在数据面实现上差异显著,直接决定集群网络的性能上限:

  • vxlan 模式:Overlay 隧道方案,跨主机流量通过 VTEP 封包/解包转发,与底层物理网络解耦,部署最省心,但封装/解封装过程带来明显性能损耗;
  • host-gw 模式:纯路由方案,flannel 直接在宿主机路由表中写入"远端 Pod 子网 -> 对端 Node IP"的路由,跨节点流量直接走物理网络转发,没有封包开销。

两种模式的架构可分别参考下图理解(左为 host-gw 路由模型,右为 flannel 总体架构):

仓库中的 网络和集群性能测试 使用 iperf 对同一集群做过对比测试(测试命令:服务端iperf -s -p 12345 -i 1 -M,客户端iperf -c ${server-ip} -p 12345 -i 1 -t 10 -w 20K),结果如下:

场景vxlan 带宽host-gw 带宽
宿主机之间(基准)5.37 Gbits/sec5.37 Gbits/sec
不同主机的 Pod 之间3.30 Gbits/sec4.88 Gbits/sec
Node 与跨主机 Pod 之间3.42 Gbits/sec4.94 Gbits/sec

结论是:vxlan 模式相对宿主机直连约有 30%~40% 的性能损耗,而 host-gw 模式损耗仅约 10%。因此,如果你的集群位于二层可达的同一网段(host-gw 依赖 Node 间三层路由可达且无需跨子网隔离),优先选择host-gw模式;如果 Node 分布跨网段、物理网络不可直连,再退而使用 vxlan。更多关于 Kubernetes 网络模型与 flannel 模式的讨论可参考 Kubernetes 中的网络模式解析 与 CNI 接口说明。

常见问题排查

  1. etcd 中没有 subnets 租约:检查FLANNEL_ETCD_ENDPOINTS与 TLS 证书(-etcd-cafile/-etcd-certfile/-etcd-keyfile)是否正确,并用etcdctl手工读取/kube-centos/network/config确认配置键已写入;
  2. Pod 子网与外网网段冲突Network字段务必选择不与任何 Node 物理网段重叠的私有网段;
  3. 多网卡选错出口导致跨 Node 不通:在FLANNEL_OPTIONS中追加-iface=<对外网卡名>(如 vagrant 环境中的eth2);
  4. Docker 未使用 flannel 子网:确认docker.service已包含EnvironmentFile=-/run/flannel/docker等环境变量引用,并检查systemctl status -l docker中是否出现--bip=... --ip-masq=true --mtu=...参数;
  5. 更换后端模式:只需更新 etcd 中/kube-centos/network/configBackend.Typevxlanhost-gw,然后依次重启各 Node 的 flanneld 与 docker。

完成 flannel 安装后,请继续按照 部署 node 节点 安装 Docker、kubelet 与 kube-proxy,使 Node 正式加入 Kubernetes 集群。

【免费下载链接】kubernetes-handbookKubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询