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-flannel1
image: ghcr.io/flannel-io/flannel:v0.26.7
#修改后,修改为自己的镜像仓库地址,我这里是将镜像存储到阿里云的
image: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel-cni-plugin:v1.7.1-flannel1
image: 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-flannel
labels:
k8s-app: flannel
pod-security.kubernetes.io/enforce: privileged
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: flannel
name: flannel
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: flannel
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: flannel
name: flannel
namespace: kube-flannel
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-flannel
labels:
tier: node
k8s-app: flannel
app: 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-ds
namespace: kube-flannel
labels:
tier: node
app: flannel
k8s-app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
hostNetwork: true
priorityClassName: system-node-critical
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni-plugin
image: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel-cni-plugin:v1.7.1-flannel1
command:
- cp
args:
- -f
- /flannel
- /opt/cni/bin/flannel
volumeMounts:
- name: cni-plugin
mountPath: /opt/cni/bin
- name: install-cni
image: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel:v0.26.7
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
containers:
- name: kube-flannel
image: registry.cn-hangzhou.aliyuncs.com/liuxing666/flannel:v0.26.7
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: false
capabilities:
add: ["NET_ADMIN", "NET_RAW"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: EVENT_QUEUE_DEPTH
value: "5000"
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
- name: xtables-lock
mountPath: /run/xtables.lock
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni-plugin
hostPath:
path: /opt/cni/bin
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: 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: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: 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 网络,适用于中小集群、混合云环境,部署简单、社区支持好。