Kubernetes 网络方案:Flannel 插件全解析
Flannel 是 Kubernetes 生态中最广泛使用的 CNI (Container Network Interface) 插件之一,由 CoreOS 团队开发,专注于解决容器跨节点通信问题。
一、Flannel 核心架构
1.组件构成
-
flanneld 守护进程:运行在每个节点,负责网络配置管理
-
CNI 插件:实现 Kubernetes CNI 规范
-
后端引擎:支持多种网络传输模式
-
子网管理:通过 etcd 或 Kubernetes API 分配子网
2.平面架构
二、核心工作原理
1. 子网分配流程
-
节点启动时,flanneld 从 etcd 或 Kubernetes API 获取子网
-
分配结果存储到本地文件 /run/flannel/subnet.env
-
CNI 插件为每个 Pod 从节点子网分配 IP
2. 跨节点通信流程
-
源 Pod 发送数据包到目标 Pod IP
-
cni0 网桥根据路由表将包转发到 flannel.1
-
flanneld 通过 VXLAN/UDP 封装数据包
-
目标节点 flanneld 解封装并转发到目标 Pod
三、后端传输模式详解
1. VXLAN 模式
1.1 工作原理
-
将原始数据包封装在 UDP 包中(默认使用 8472 端口)
-
添加 VXLAN 头(VNI 通常为 1)
-
外层使用宿主机的 IP 进行通信
1.2 优点
-
支持三层网络,跨三层网络通信
-
MTU 需要调整(通常设为 1450)
-
对底层网络无特殊要求
1.3 缺点
-
约 10-20% 性能开销
1.4 使用场景
-
云环境或物理网络不支持 BGP/直接路由
-
节点位于不同子网
-
对网络性能要求不高的环境
2.host-gw 模式 (Host Gateway)
2.1 工作原理
直接使用宿主机的路由表,为每个节点添加路由条目(目标 Pod CIDR 指向对端节点 IP)
2.2 优点
-
接近裸机性能
-
零封装开销
2.3 缺点
-
要求节点间二层连通
-
不支持跨子网通信
2.4 适用场景
-
节点间在同一二层网络
-
物理机或私有云环境
-
对网络性能要求高的场景
3.DirectRouting 模式
3.1 工作原理
-
同子网通信:使用 host-gw 模式
-
跨子网通信:自动回退到 VXLAN 模式
-
配置示例:
{"Backend": {"Type": "vxlan","DirectRouting": true}
}
3.2 优点
-
同子网的高性能
-
跨子网的兼容性
3.3 缺点
-
配置略复杂
-
仍然有跨子网时的 VXLAN 开销
3.4 适用场景
-
混合网络环境(部分节点同子网,部分不同)
-
需要平衡性能和灵活性的场景
-
逐步迁移的网络架构
4.对比总结
特性 | VXLAN | host-gw | DirectRouting |
封装 | UDP+VXLAN | 无封装 | 条件性封装 |
性能 | 中 (~20%开销) | 高 (接近原生) | 同子网高,跨子网中 |
网络要求 | 仅需三层连通 | 需二层连通 | 混合要求 |
跨子网 | 支持 | 不支持 | 支持但性能下降 |
复杂度 | 中等 | 低 | 中等 |
5.选择建议
-
云环境/复杂网络:优先选择 VXLAN 或 DirectRouting
-
物理机/高性能需求:优先 host-gw(确保二层连通)
-
混合环境:DirectRouting 是最平衡的选择
四、部署模式对比
1.Kubernetes Manifest 部署
1.1 下载
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
1.2 修改配置一镜像地址
默认的镜像地址通常下载不下来,如何下载镜像清参考破解Docker镜像下载难题
# 修改前
image: ghcr.io/flannel-io/flannel-cni-plugin:v1.7.1-flannel1image: ghcr.io/flannel-io/flannel:v0.26.7#修改后,修改为自己的镜像仓库地址,我这里是将镜像存储到阿里云的
image: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel-cni-plugin:v1.7.1-flannel1image: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel:v0.26.7
1.3 修改配置二flannel网段
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","EnableNFTables": false,"Backend": {"Type": "vxlan"}}# "Network": "10.244.0.0/16" 修改为kube-controller-manager中设置的地址
#--cluster-cidr=10.244.0.0/16的地址或者etcd存储的flannel网段地址
1.4修改后完整配置
[root@master-1 ~]# cat kube-flannel.yml
---
kind: Namespace
apiVersion: v1
metadata:name: kube-flannellabels:k8s-app: flannelpod-security.kubernetes.io/enforce: privileged
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:labels:k8s-app: flannelname: flannel
rules:
- apiGroups:- ""resources:- podsverbs:- get
- apiGroups:- ""resources:- nodesverbs:- get- list- watch
- apiGroups:- ""resources:- nodes/statusverbs:- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:labels:k8s-app: flannelname: flannel
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: flannel
subjects:
- kind: ServiceAccountname: flannelnamespace: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:labels:k8s-app: flannelname: flannelnamespace: kube-flannel
---
kind: ConfigMap
apiVersion: v1
metadata:name: kube-flannel-cfgnamespace: kube-flannellabels:tier: nodek8s-app: flannelapp: 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","EnableNFTables": false,"Backend": {"Type": "vxlan"}}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:name: kube-flannel-dsnamespace: kube-flannellabels:tier: nodeapp: flannelk8s-app: flannel
spec:selector:matchLabels:app: flanneltemplate:metadata:labels:tier: nodeapp: flannelspec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/osoperator: Invalues:- linuxhostNetwork: truepriorityClassName: system-node-criticaltolerations:- operator: Existseffect: NoScheduleserviceAccountName: flannelinitContainers:- name: install-cni-pluginimage: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel-cni-plugin:v1.7.1-flannel1command:- cpargs:- -f- /flannel- /opt/cni/bin/flannelvolumeMounts:- name: cni-pluginmountPath: /opt/cni/bin- name: install-cniimage: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel:v0.26.7command:- cpargs:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.conflistvolumeMounts:- name: cnimountPath: /etc/cni/net.d- name: flannel-cfgmountPath: /etc/kube-flannel/containers:- name: kube-flannelimage: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel:v0.26.7command:- /opt/bin/flanneldargs:- --ip-masq- --kube-subnet-mgrresources:requests:cpu: "100m"memory: "50Mi"securityContext:privileged: falsecapabilities:add: ["NET_ADMIN", "NET_RAW"]env:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespace- name: EVENT_QUEUE_DEPTHvalue: "5000"volumeMounts:- name: runmountPath: /run/flannel- name: flannel-cfgmountPath: /etc/kube-flannel/- name: xtables-lockmountPath: /run/xtables.lockvolumes:- name: runhostPath:path: /run/flannel- name: cni-pluginhostPath:path: /opt/cni/bin- name: cnihostPath:path: /etc/cni/net.d- name: flannel-cfgconfigMap:name: kube-flannel-cfg- name: xtables-lockhostPath:path: /run/xtables.locktype: FileOrCreate
1.5 部署测试
[root@master-1 ~]# kubectl apply -f kube-flannel.yaml#查看
[root@master-1 ~]# kubectl get pods -n kube-flannel -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel-ds-mx8tp 1/1 Running 0 3h7m 192.168.91.21 node-1 <none> <none>
kube-flannel-ds-xp8p5 1/1 Running 0 3h7m 192.168.91.23 node-3 <none> <none>
kube-flannel-ds-xp9dh 1/1 Running 0 3h7m 192.168.91.22 node-2 <none> <none>#测试网络连通性
[root@master-1 ~]# cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-demo
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:latestimagePullPolicy: IfNotPresent[root@master-1 ~]# kubectl apply -f nginx.yaml[root@master-1 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-demo-68984b745f-jxn7c 1/1 Running 0 3h6m 10.244.1.2 node-2 <none> <none>
nginx-demo-68984b745f-pc4t2 1/1 Running 0 3h6m 10.244.0.2 node-1 <none> <none>
nginx-demo-68984b745f-rx76j 1/1 Running 0 3h6m 10.244.2.60 node-3 <none> <none>[root@node-1 ~]# curl -I 10.244.1.2
HTTP/1.1200 OK
Server: nginx/1.27.5
Date: Tue, 03 Jun 202505:35:17 GMT
测试发现node节点网络都是互通的
2.二进制部署
2.1 下载Flannel二进制包
wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
wget https://github.com/flannel-io/flannel/releases/download/v0.26.7/flannel-v0.26.7-linux-amd64.tar.gz
2.2 解压
[root@ master -1 ~]# tar xvf flannel-v0.11.0-linux-amd64.tar.gz
[root@ master -1 ~]# mv flanneld mk-docker-opts.sh /usr/local/bin/
2.3 配置Flannel文件,添加etcd信息
[root@node-1 ~]# mkdir -p /etc/flannel
[root@node-1 ~]# cat > /etc/flannel/flannel.cfg<<EOF
FLANNEL_OPTIONS="-etcd-endpoints=https://192.168.91.18:2379,https://192.168.91.19:2379,https://192.168.91.20:2379 -etcd-cafile=/etc/etcd/ssl/ca.pem -etcd-certfile=/etc/etcd/ssl/server.pem -etcd-keyfile=/etc/etcd/ssl/server-key.pem"
EOF
2.4 设置flannel网段存储到etcd中
[root@master-1 ~]# ETCDCTL_API=2 etcdctl \
--endpoints="https://192.168.91.18:2379,https://192.168.91.19:2379,https://192.168.91.20:2379" \
--ca-file=/etc/etcd/ssl/ca.pem \
--key-file=/etc/etcd/ssl/server-key.pem \
--cert-file=/etc/etcd/ssl/server.pem \
set /coreos.com/network/config '{ "Network": "10.244.0.0/16", "Backend": {"Type": "vxlan"}}'
#检查是否建立网段
[root@master-1 ~]# ETCDCTL_API=2 etcdctl \
--endpoints=https://192.168.91.18:2379,https://192.168.91.19:2379,https://192.168.91.20:2379 \
--ca-file=/etc/etcd/ssl/ca.pem \
--cert-file=/etc/etcd/ssl/server.pem \
--key-file=/etc/etcd/ssl/server-key.pem \
get /coreos.com/network/config#结果
{ "Network": "10.244.0.0/16", "Backend": {"Type": "vxlan"}}
2.5 配置flannel 启动配置文件
cat > /usr/lib/systemd/system/flanneld.service <<EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service[Service]
Type=notify
EnvironmentFile=/etc/flannel/flannel.cfg
ExecStart=/usr/local/bin/flanneld --ip-masq \$FLANNEL_OPTIONS
ExecStartPost=/usr/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
Restart=on-failure[Install]
WantedBy=multi-user.target
EOF#启动Flannel
[root@node-2 ~]# systemctl enable --now flanneld
[root@node-2 ~]# systemctl status flanneld
2.6 修改docker 配置文件,让docker使用flannel网段
[root@node-1 ~]# cat >/usr/lib/systemd/system/docker.service<<EOFL
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target[Service]
Type=notify
EnvironmentFile=/run/flannel/subnet.env
ExecStart=/usr/bin/dockerd \$DOCKER_NETWORK_OPTIONS
ExecReload=/bin/kill -s HUP \$MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s[Install]
WantedBy=multi-user.target
EOFL
#重启docker
[root@node-1 ~]# systemctl daemon-reload
[root@node-1 ~]# systemctl restart docker
五、总结
Flannel 作为 Kubernetes 网络生态的基石:简单可靠的 Overlay 网络,适用于中小集群、混合云环境,部署简单、社区支持好。