十三、Docker容器网络与通信原理深度解析-4-flannel-cross-host-network-complete-guide
什么是 Flannel?Flannel = 简单的虚拟网络覆盖层由 CoreOS 开发(2015 年)现属 CNCF 项目目标:- 为容器提供简单的 Layer 3 网络- 支持多种后端(VXLAN, UDP, AWS VPC 等)- 易于部署和管理- 与 Kubernetes 深度集成│ Flannel vs Docker Overlay 对比 ││ 特性 Flannel Docker Over
Flannel 跨主机容器网络完全指南:从 ETCD 到 VXLAN 的生产级实践
作者:云原生架构师
技术栈:Flannel, ETCD, VXLAN, Kubernetes CNI, Linux Network
难度等级:★★★★★(专家级)
预计阅读时间:100 分钟
目录
- [引言:Flannel 项目概述](#1-引言 flannel-项目概述)
- Flannel 架构深度解析
- ETCD 分布式数据库详解
- 主机环境准备
- ETCD 集群部署
- Flannel 部署与配置
- Docker 网络集成
- 跨主机通信验证
- Flannel 后端详解
- Kubernetes CNI 集成
- 故障排查实战
- 性能优化与最佳实践
1. 引言:Flannel 项目概述
1.1 Flannel 项目背景
什么是 Flannel?
Flannel = 简单的虚拟网络覆盖层
由 CoreOS 开发(2015 年)
现属 CNCF 项目
目标:
- 为容器提供简单的 Layer 3 网络
- 支持多种后端(VXLAN, UDP, AWS VPC 等)
- 易于部署和管理
- 与 Kubernetes 深度集成
Flannel vs Docker Overlay:
┌─────────────────────────────────────────────────────┐
│ Flannel vs Docker Overlay 对比 │
├─────────────────────────────────────────────────────┤
│ 特性 Flannel Docker Overlay │
├─────────────────────────────────────────────────────┤
│ 复杂度 简单 中等 │
│ 依赖 ETCD Swarm │
│ 后端支持 多种 VXLAN only │
│ Kubernetes 集成 CNI 插件 需要额外配置 │
│ 性能 优秀 优秀 │
│ 加密 不支持 IPsec 支持 │
│ 适用场景 K8s 集群 Swarm 集群 │
└─────────────────────────────────────────────────────┘
1.2 Flannel 应用场景
场景 1:Kubernetes 集群网络
K8s 集群:
┌──────────┐ ┌──────────┐ ┌──────────
│ Master │ │ Node1 │ │ Node2 │
│ │ │ Pod:10.1 │ │ Pod:10.2 │
└──────────┘ └────────── └──────────┘
│ │ │
└───────────────┼───────────────┘
│
┌────────▼────────┐
│ Flannel │
│ VXLAN Backend │
└─────────────────┘
所有 Pod 可以直接通信
无需 NAT,无需端口映射
场景 2:多主机 Docker 容器
传统 Docker:
- 单机部署
- Bridge 网络
Flannel:
- 多机部署
- 统一网络
- 容器跨主机通信
2. Flannel 架构深度解析
2.1 Flannel 核心组件
架构图:
核心组件说明:
1. ETCD 集群
- 存储网络配置
- 存储子网分配
- 存储 VTEP 信息
2. flanneld(每个主机)
- 监听 ETCD 配置变化
- 分配本地子网
- 配置网络接口
- 设置路由表
3. 网络接口
- flannel.1: VXLAN 接口
- cni0: 容器网桥
- docker0: Docker 网桥(可选)
4. 后端(Backend)
- VXLAN(默认)
- UDP(已废弃)
- AWS VPC
- GCE
- Alibaba Cloud
2.2 Flannel 工作流程
初始化流程:
详细步骤:
步骤 1:注册网络配置
# 在 ETCD 中注册
etcdctl mk /coreos.com/network/config '{
"Network": "10.0.0.0/8",
"SubnetLen": 24,
"Backend": {
"Type": "vxlan"
}
}'
步骤 2-3:Host1 加入网络
# flanneld 启动
flanneld \
--etcd-endpoints=http://192.168.1.10:2379 \
--public-ip=192.168.1.10 \
--iface=eth0
# flanneld 行为:
1. 从 ETCD 获取网络配置
2. 检查可用子网
3. 分配 10.1.1.0/24
4. 在 ETCD 注册:
/coreos.com/network/subnets/10.1.1.0-24
{
"PublicIP": "192.168.1.10",
"BackendType": "vxlan",
"BackendData": {
"VtepMAC": "aa:bb:cc:dd:ee:01"
}
}
步骤 4-5:Host2 加入网络
# 类似 Host1
# 分配 10.1.2.0/24
# 在 ETCD 注册
步骤 6-7:ETCD 通知
# ETCD Watch 机制
# 当新子网注册时
# 通知所有已注册的 flanneld
# Host1 flanneld 收到通知:
# "新子网 10.1.2.0/24 在 192.168.1.20"
# Host2 flanneld 收到通知:
# "新子网 10.1.1.0/24 在 192.168.1.10"
步骤 8-9:配置路由
# Host1 配置路由
ip route add 10.1.2.0/24 via 192.168.1.20 dev flannel.1
# Host2 配置路由
ip route add 10.1.1.0/24 via 192.168.1.10 dev flannel.1
# 查看路由表
ip route show
# 输出:
# 10.1.1.0/24 dev cni0 proto kernel scope link src 10.1.1.1
# 10.1.2.0/24 via 192.168.1.20 dev flannel.1
3. ETCD 分布式数据库详解
3.1 ETCD 基础架构
什么是 ETCD?
ETCD = 分布式键值存储
特点:
- 强一致性(Raft 协议)
- 高可用(多节点集群)
- 高性能(万级 QPS)
- Watch 机制(实时通知)
用途:
- 服务发现
- 配置管理
- 分布式锁
- 网络状态存储(Flannel)
Raft 共识算法:
┌─────────────────────────────────────────────────────┐
│ ETCD Raft 集群 │
├─────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌────────── ┌──────────┐ │
│ │ Leader │ │ Follower │ │ Follower │ │
│ │ Node1 │ │ Node2 │ │ Node3 │ │
│ └──────────┘ └────────── └──────────┘ │
│ │ │
│ │ 1. Client Write │
│ ▼ │
│ 追加日志 │
│ │ │
│ │ 2. Replicate to Followers │
│ ▼ │
│ ┌──────────┐ ┌────────── │
│ │ Append │ │ Append │ │
│ └──────────┘ └──────────┘ │
│ │ │
│ │ 3. Commit when majority │
│ ▼ │
│ 应用到状态机 │
│ │ │
│ │ 4. Response to Client │
└─────────────────────────────────────────────────────┘
最少节点数:
- 生产:3 节点(容忍 1 故障)
- 高可用:5 节点(容忍 2 故障)
3.2 ETCD 集群部署
单节点部署(测试):
# 使用 Docker 运行 ETCD
docker run -d \
--name etcd \
-p 2379:2379 \
-p 2380:2380 \
-v /opt/etcd/data:/etcd-data \
-e ETCD_DATA_DIR=/etcd-data \
quay.io/coreos/etcd:v3.5.9 \
etcd \
--name etcd-single \
--data-dir /etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://localhost:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://localhost:2380 \
--initial-cluster etcd-single=http://localhost:2380 \
--initial-cluster-token my-etcd-token \
--initial-cluster-state new \
--auto-compaction-retention=1
# 验证
docker exec etcd etcdctl endpoint health
# 输出:http://localhost:2379: is healthy
三节点集群部署(生产):
# 节点 1 (192.168.1.10)
docker run -d \
--name etcd \
-p 2379:2379 \
-p 2380:2380 \
-v /opt/etcd/data:/etcd-data \
quay.io/coreos/etcd:v3.5.9 \
etcd \
--name etcd-node1 \
--data-dir /etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.1.10:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://192.168.1.10:2380 \
--initial-cluster etcd-node1=http://192.168.1.10:2380,etcd-node2=http://192.168.1.20:2380,etcd-node3=http://192.168.1.30:2380 \
--initial-cluster-token my-etcd-token \
--initial-cluster-state new \
--auto-compaction-retention=1 \
--quota-backend-bytes=8589934592 \
--heartbeat-interval=100 \
--election-timeout=1000
# 节点 2 (192.168.1.20)
# 修改 --name, --advertise-client-urls, --initial-advertise-peer-urls
# 节点 3 (192.168.1.30)
# 修改 --name, --advertise-client-urls, --initial-advertise-peer-urls
验证集群状态:
# 检查成员
docker exec etcd etcdctl member list
# 输出:
# 422a74f03b622b7d, started, etcd-node1, http://192.168.1.10:2380, http://192.168.1.10:2379
# 8a3f5e9c1d2b4a6f, started, etcd-node2, http://192.168.1.20:2380, http://192.168.1.20:2379
# c5d7e9f1a3b5c7d9, started, etcd-node3, http://192.168.1.30:2380, http://192.168.1.30:2379
# 检查健康
docker exec etcd etcdctl endpoint health
# 输出:
# http://192.168.1.10:2379: is healthy
# http://192.168.1.20:2379: is healthy
# http://192.168.1.30:2379: is healthy
# 检查 Leader
docker exec etcd etcdctl endpoint status --write-out=table
# 输出:
# +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
# | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
# +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
# | 192.168.1.10:2379 | 422a74f03b622b7d | 3.5.9 | 20 kB | true | false | 2 | 11 | 11 | |
# | 192.168.1.20:2379 | 8a3f5e9c1d2b4a6f | 3.5.9 | 20 kB | false | false | 2 | 11 | 11 | |
# | 192.168.1.30:2379 | c5d7e9f1a3b5c7d9 | 3.5.9 | 20 kB | false | false | 2 | 11 | 11 | |
# +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
3.3 ETCD 操作详解
基本操作:
# 写入数据
etcdctl put /key "value"
# 读取数据
etcdctl get /key
# 删除数据
etcdctl del /key
# 列出所有键
etcdctl get / --prefix --keys-only
Flannel 相关操作:
# 注册网络配置
etcdctl put /coreos.com/network/config '{
"Network": "10.0.0.0/8",
"SubnetLen": 24,
"SubnetMin": "10.0.1.0",
"SubnetMax": "10.255.255.0",
"Backend": {
"Type": "vxlan",
"VNI": 1,
"Port": 8472
}
}'
# 查看网络配置
etcdctl get /coreos.com/network/config
# 查看已分配子网
etcdctl get /coreos.com/network/subnets --prefix --keys-only
# 查看子网详情
etcdctl get /coreos.com/network/subnets/10.0.1.0-24
# 输出:
# {"PublicIP":"192.168.1.10","BackendType":"vxlan","BackendData":{"VtepMAC":"aa:bb:cc:dd:ee:01"}}
Watch 机制:
# 监听子网变化
etcdctl watch /coreos.com/network/subnets --prefix
# 当新子网注册时
# 输出:
# PUT
# /coreos.com/network/subnets/10.0.2.0-24
# {"PublicIP":"192.168.1.20","BackendType":"vxlan","BackendData":{"VtepMAC":"aa:bb:cc:dd:ee:02"}}
4. 主机环境准备
4.1 系统要求
硬件配置:
最低配置:
- CPU: 2 核
- 内存:4GB
- 磁盘:20GB
- 网络:1GbE
推荐配置:
- CPU: 4 核+
- 内存:8GB+
- 磁盘:50GB+ SSD
- 网络:10GbE
软件要求:
操作系统:
- Ubuntu 20.04/22.04 LTS
- CentOS 7/8
- Debian 10/11
内核版本:
- Linux 4.14+
- 推荐 5.10+
Docker 版本:
- Docker 20.10+
4.2 网络配置
禁用防火墙(测试):
# Ubuntu (ufw)
ufw disable
# CentOS (firewalld)
systemctl stop firewalld
systemctl disable firewalld
# 或者开放必要端口
# Ubuntu
ufw allow 2379/tcp
ufw allow 2380/tcp
ufw allow 8472/udp
ufw allow 4789/udp
# CentOS
firewall-cmd --permanent --add-port=2379/tcp
firewall-cmd --permanent --add-port=2380/tcp
firewall-cmd --permanent --add-port=8472/udp
firewall-cmd --permanent --add-port=4789/udp
firewall-cmd --reload
禁用 SELinux:
# 临时禁用
setenforce 0
# 永久禁用
sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
配置网络接口:
# 查看网络接口
ip addr show
# 确保 eth0 有正确 IP
# eth0: 192.168.1.10/24
# 测试连通性
ping 192.168.1.20
ping 192.168.1.30
4.3 安装必要工具
安装 Docker:
# Ubuntu/Debian
apt-get update
apt-get install -y docker.io docker-compose
# CentOS
yum install -y docker docker-compose
# 启动 Docker
systemctl start docker
systemctl enable docker
安装 ETCD 客户端:
# 下载 etcdctl
wget https://github.com/etcd-io/etcd/releases/download/v3.5.9/etcd-v3.5.9-linux-amd64.tar.gz
tar xzvf etcd-v3.5.9-linux-amd64.tar.gz
cp etcd-v3.5.9-linux-amd64/etcdctl /usr/local/bin/
chmod +x /usr/local/bin/etcdctl
安装 Flannel:
# 下载 flanneld
wget https://github.com/flannel-io/flannel/releases/download/v0.22.0/flannel-v0.22.0-linux-amd64.tar.gz
tar xzvf flannel-v0.22.0-linux-amd64.tar.gz
cp flanneld /usr/local/bin/
chmod +x /usr/local/bin/flanneld
5. ETCD 集群部署
5.1 单节点部署(快速测试)
使用 Docker 部署:
docker run -d \
--name etcd \
-p 2379:2379 \
-p 2380:2380 \
-v /opt/etcd/data:/etcd-data \
-e ETCD_DATA_DIR=/etcd-data \
quay.io/coreos/etcd:v3.5.9 \
etcd \
--name etcd-single \
--data-dir /etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.1.10:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://192.168.1.10:2380 \
--initial-cluster etcd-single=http://192.168.1.10:2380 \
--initial-cluster-token my-etcd-token \
--initial-cluster-state new \
--auto-compaction-retention=1
# 验证
etcdctl --endpoints=http://192.168.1.10:2379 endpoint health
5.2 三节点部署(生产)
节点 1 配置:
docker run -d \
--name etcd \
--restart=always \
-p 2379:2379 \
-p 2380:2380 \
-v /opt/etcd/data:/etcd-data \
-v /etc/localtime:/etc/localtime:ro \
quay.io/coreos/etcd:v3.5.9 \
etcd \
--name etcd-node1 \
--data-dir /etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.1.10:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://192.168.1.10:2380 \
--initial-cluster etcd-node1=http://192.168.1.10:2380,etcd-node2=http://192.168.1.20:2380,etcd-node3=http://192.168.1.30:2380 \
--initial-cluster-token my-etcd-token \
--initial-cluster-state new \
--auto-compaction-retention=1 \
--quota-backend-bytes=8589934592 \
--heartbeat-interval=100 \
--election-timeout=1000 \
--enable-v2=false
节点 2 配置:
docker run -d \
--name etcd \
--restart=always \
-p 2379:2379 \
-p 2380:2380 \
-v /opt/etcd/data:/etcd-data \
quay.io/coreos/etcd:v3.5.9 \
etcd \
--name etcd-node2 \
--data-dir /etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.1.20:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://192.168.1.20:2380 \
--initial-cluster etcd-node1=http://192.168.1.10:2380,etcd-node2=http://192.168.1.20:2380,etcd-node3=http://192.168.1.30:2380 \
--initial-cluster-token my-etcd-token \
--initial-cluster-state new \
--auto-compaction-retention=1 \
--quota-backend-bytes=8589934592 \
--heartbeat-interval=100 \
--election-timeout=1000
节点 3 配置:
# 类似节点 2,修改 IP 和名称
5.3 验证 ETCD 集群
检查集群健康:
# 设置 ETCDCTL_ENDPOINTS
export ETCDCTL_ENDPOINTS=http://192.168.1.10:2379,http://192.168.1.20:2379,http://192.168.1.30:2379
# 检查健康
etcdctl endpoint health
# 输出:
# http://192.168.1.10:2379: is healthy
# http://192.168.1.20:2379: is healthy
# http://192.168.1.30:2379: is healthy
检查集群状态:
# 检查成员
etcdctl member list
# 检查 Leader
etcdctl endpoint status --write-out=table
# 检查性能
etcdctl check perf
6. Flannel 部署与配置
6.1 在 ETCD 中注册网络
注册 Flannel 网络配置:
# 在所有节点执行
etcdctl --endpoints=http://192.168.1.10:2379 put /coreos.com/network/config '{
"Network": "10.0.0.0/8",
"SubnetLen": 24,
"SubnetMin": "10.0.1.0",
"SubnetMax": "10.255.255.0",
"Backend": {
"Type": "vxlan",
"VNI": 1,
"Port": 8472
}
}'
# 验证配置
etcdctl --endpoints=http://192.168.1.10:2379 get /coreos.com/network/config
# 输出:
# /coreos.com/network/config
# {"Network":"10.0.0.0/8","SubnetLen":24,"Backend":{"Type":"vxlan","VNI":1,"Port":8472}}
参数说明:
Network: 10.0.0.0/8
- Flannel 使用的全局网络
- 必须足够大以容纳所有容器
SubnetLen: 24
- 每个主机的子网掩码
- /24 = 256 个 IP(254 个可用)
SubnetMin/SubnetMax: 子网范围
- 限制子网分配范围
- 避免与其他网络冲突
Backend.Type: vxlan
- 使用 VXLAN 后端
- 其他选项:udp, host-gw, aws-vpc, gce
Backend.VNI: 1
- VXLAN 网络标识符
- 范围:0-16777215
Backend.Port: 8472
- VXLAN UDP 端口
- 默认 8472
6.2 部署 Flannel
使用 Systemd 部署:
# 创建 systemd 服务文件
cat > /etc/systemd/system/flanneld.service << EOF
[Unit]
Description=Flannel
Documentation=https://github.com/flannel-io/flannel
After=network.target
After=etcd.service
Wants=etcd.service
[Service]
Type=notify
ExecStart=/usr/local/bin/flanneld \\
--etcd-endpoints=http://192.168.1.10:2379 \\
--public-ip=192.168.1.10 \\
--iface=eth0 \\
--ip-masq=true \\
--subnet-file=/run/flannel/subnet.env
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
# 重新加载 systemd
systemctl daemon-reload
# 启动 flanneld
systemctl start flanneld
systemctl enable flanneld
# 查看状态
systemctl status flanneld
使用 Docker 部署:
docker run -d \
--name flanneld \
--net=host \
--privileged \
-v /run/flannel:/run/flannel \
-v /var/run/docker.sock:/var/run/docker.sock \
quay.io/coreos/flannel:v0.22.0 \
/opt/bin/flanneld \
--etcd-endpoints=http://192.168.1.10:2379 \
--public-ip=192.168.1.10 \
--iface=eth0 \
--ip-masq=true
# 查看日志
docker logs flanneld
6.3 验证 Flannel 部署
检查子网分配:
# 查看 ETCD 中的子网
etcdctl --endpoints=http://192.168.1.10:2379 get /coreos.com/network/subnets --prefix --keys-only
# 输出:
# /coreos.com/network/subnets/10.0.1.0-24
# /coreos.com/network/subnets/10.0.2.0-24
# /coreos.com/network/subnets/10.0.3.0-24
# 查看子网详情
etcdctl --endpoints=http://192.168.1.10:2379 get /coreos.com/network/subnets/10.0.1.0-24
# 输出:
# {"PublicIP":"192.168.1.10","BackendType":"vxlan","BackendData":{"VtepMAC":"aa:bb:cc:dd:ee:01"}}
检查网络接口:
# 查看 flannel.1 接口
ip -d link show flannel.1
# 输出:
# 3: flannel.1@NONE: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
# link/ether aa:bb:cc:dd:ee:01
# promiscuity 0
# vxlan id 1 remote 0.0.0.0 port 8472 \
# learn ageing 300 limit 1000 \
# srcport 0 0 dstport 0 \
# ttl 64 portrange [32768, 61000]
# 查看 cni0 网桥
ip addr show cni0
# 输出:
# 4: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
# link/ether 0a:58:0a:01:01:01
# inet 10.0.1.1/24 scope global cni0
检查路由表:
# 查看路由
ip route show
# 输出:
# 10.0.1.0/24 dev cni0 proto kernel scope link src 10.0.1.1
# 10.0.2.0/24 via 192.168.1.20 dev flannel.1
# 10.0.3.0/24 via 192.168.1.30 dev flannel.1
7. Docker 网络集成
7.1 配置 Docker 使用 Flannel
修改 Docker 配置:
# 加载 Flannel 环境变量
cat /run/flannel/subnet.env
# 输出:
# FLANNEL_NETWORK=10.0.0.0/8
# FLANNEL_SUBNET=10.0.1.1/24
# FLANNEL_MTU=1450
# FLANNEL_IPMASQ=true
# 修改 Docker daemon.json
cat > /etc/docker/daemon.json << EOF
{
"bip": "10.0.1.1/24",
"mtu": 1450,
"ip-masq": true
}
EOF
# 重启 Docker
systemctl daemon-reload
systemctl restart docker
验证 Docker 网络:
# 查看 docker0
ip addr show docker0
# 输出:
# 5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
# link/ether 02:42:ac:11:00:01
# inet 10.0.1.1/24 brd 10.0.1.255
7.2 运行容器测试
启动容器:
# 在 Host1 启动容器
docker run -d \
--name test1 \
--network bridge \
alpine sleep 3600
# 在 Host2 启动容器
docker run -d \
--name test2 \
--network bridge \
alpine sleep 3600
# 查看容器 IP
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' test1
# 输出:10.0.1.2
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' test2
# 输出:10.0.2.2
测试跨主机通信:
# Host1 容器 ping Host2 容器
docker exec test1 ping -c 3 10.0.2.2
# 输出:
# 64 bytes from 10.0.2.2: icmp_seq=1 ttl=64 time=0.5 ms
# 64 bytes from 10.0.2.2: icmp_seq=2 ttl=64 time=0.4 ms
# 64 bytes from 10.0.2.2: icmp_seq=3 ttl=64 time=0.4 ms
# 成功!跨主机通信正常
8. 跨主机通信验证
8.1 基础连通性测试
Ping 测试:
# 获取容器 IP
IP1=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' test1)
IP2=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' test2)
echo "Container 1: $IP1 (Host1)"
echo "Container 2: $IP2 (Host2)"
# Ping 测试
docker exec test1 ping -c 10 $IP2
# 输出:
# 10 packets transmitted, 10 received, 0% packet loss
# rtt min/avg/max/mdev = 0.4/0.5/0.6/0.1 ms
TCP 连接测试:
# 在容器 1 启动 TCP 服务器
docker exec -d test1 nc -l -p 8080
# 在容器 2 连接
docker exec test2 nc -vz $IP1 8080
# 输出:
# Connection to 10.0.1.2 8080 port [tcp/*] succeeded!
8.2 数据包路径验证
使用 tcpdump 抓包:
# 在 Host1 抓包
tcpdump -i eth0 -n udp port 8472
# 在 Host2 抓包
tcpdump -i eth0 -n udp port 8472
# 在容器 1 ping 容器 2
docker exec test1 ping $IP2
# 应该看到 VXLAN 封装的数据包
# 192.168.1.10:8472 > 192.168.1.20:8472
使用 tcptrace 分析:
# 安装 tcptrace
apt-get install tcptrace
# 抓包并分析
tcpdump -i any -s 0 -w flannel.pcap
# 使用 Wireshark 分析
wireshark flannel.pcap
9. Flannel 后端详解
9.1 VXLAN 后端(默认)
配置:
{
"Network": "10.0.0.0/8",
"Backend": {
"Type": "vxlan",
"VNI": 1,
"Port": 8472
}
}
特点:
优势:
- 性能好(内核级 VXLAN)
- 支持多播
- 广泛支持
劣势:
- 需要内核支持(3.12+)
- 50 字节开销
9.2 Host-GW 后端
配置:
{
"Network": "10.0.0.0/8",
"Backend": {
"Type": "host-gw"
}
}
特点:
优势:
- 无封装开销
- 性能最优
- 配置简单
劣势:
- 需要 Layer 2 连通性
- 不支持跨路由
9.3 UDP 后端(已废弃)
配置:
{
"Network": "10.0.0.0/8",
"Backend": {
"Type": "udp",
"Port": 8285
}
}
特点:
已废弃(v0.11.0)
性能差(用户空间封装)
仅用于测试
10. Kubernetes CNI 集成
10.1 CNI 插件安装
下载 CNI 插件:
# 下载 Flannel CNI
wget https://github.com/flannel-io/cni-plugin/releases/download/v1.2.0/flannel-cni-plugin-linux-amd64
mv flannel-cni-plugin-linux-amd64 /opt/cni/bin/flannel
chmod +x /opt/cni/bin/flannel
# 下载 CNI 配置工具
wget https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz
tar xzvf cni-plugins-linux-amd64-v1.2.0.tgz -C /opt/cni/bin/
配置 CNI:
# 创建 CNI 配置
cat > /etc/cni/net.d/10-flannel.conflist << EOF
{
"name": "cbr0",
"cniVersion": "1.0.0",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
EOF
10.2 Kubernetes 集成
部署 Flannel DaemonSet:
# kube-flannel.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds
namespace: kube-system
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
app: flannel
spec:
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.22.0
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
volumes:
- name: run
hostPath:
path: /run/flannel
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
---
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
namespace: kube-system
data:
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
应用配置:
kubectl apply -f kube-flannel.yml
11. 故障排查实战
11.1 常见问题
问题 1:子网分配失败
# 检查 ETCD 连接
etcdctl --endpoints=http://192.168.1.10:2379 endpoint health
# 检查网络配置
etcdctl --endpoints=http://192.168.1.10:2379 get /coreos.com/network/config
# 检查 flanneld 日志
journalctl -u flanneld -f
# 重启 flanneld
systemctl restart flanneld
问题 2:容器无法跨主机通信
# 检查 VXLAN 接口
ip -d link show flannel.1
# 检查路由表
ip route show
# 检查防火墙
iptables -L -n -v
# 抓包分析
tcpdump -i eth0 -n udp port 8472
问题 3:性能问题
# 检查 MTU
ip link show flannel.1
# 检查网络拥塞
ethtool -S eth0
# 检查 CPU 使用
top
12. 性能优化与最佳实践
12.1 MTU 优化
设置 MTU:
# Flannel 配置
{
"Network": "10.0.0.0/8",
"Backend": {
"Type": "vxlan"
}
}
# Docker 配置
{
"mtu": 1450
}
12.2 监控告警
Prometheus 监控:
# flannel-metrics.yaml
apiVersion: v1
kind: ServiceMonitor
metadata:
name: flannel
namespace: monitoring
spec:
selector:
matchLabels:
app: flannel
endpoints:
- port: metrics
interval: 30s
Grafana 仪表盘:
Flannel Dashboard:
- 网络流量(接收/发送)
- 数据包数量
- 错误包统计
- 延迟统计
12.3 最佳实践清单
✅ ETCD 集群:
- 生产环境使用 3 节点或 5 节点
- 使用 SSD 存储
- 定期备份
✅ Flannel 配置:
- 使用 VXLAN 后端(默认)
- 设置合理 MTU(1450)
- 启用 ip-masq(NAT)
✅ 网络规划:
- 使用私有地址(10.0.0.0/8)
- 预留足够地址空间
- 避免与其他网络冲突
✅ 监控告警:
- 监控 ETCD 健康状态
- 监控 Flannel 网络流量
- 设置告警阈值
版权声明:本文原创,转载请注明出处
参考资料:
- Flannel 官方文档
- ETCD 官方文档
- Kubernetes CNI 文档
- Linux 网络内核文档
如果本文对您有帮助,欢迎点赞、收藏、转发!
更多推荐

所有评论(0)