[AI生成] 通过bird模拟calico打通容器网络
本文基于 Docker + Bird 2 模拟 Calico 的 BGP 网络原理,使用 3 个容器作为节点,通过 Bird 建立 BGP 全互联(node-to-node mesh),模拟 Calico 的 Pod 网络路由宣告与学习过程。
一、架构概述
拓扑结构:3 个节点(node1 / node2 / node3)组成一个 BGP 全互联 mesh,模拟 Calico 的 node-to-node BGP 模式。每个节点运行 bird2 作为 BGP 路由守护进程,有一个 dummy 接口模拟本节点的 Pod CIDR,通过 bird 将本机 Pod 网段宣告给其他节点,学到的路由直接写入内核路由表,实现 Pod 跨节点互通。
节点网络(共享同一 docker 网络,模拟物理交换机):
| 节点 | 节点 IP | AS 号 | Pod CIDR |
|---|---|---|---|
| node1 | 10.0.0.11 | 64512 | 10.244.1.0/24 |
| node2 | 10.0.0.12 | 64512 | 10.244.2.0/24 |
| node3 | 10.0.0.13 | 64512 | 10.244.3.0/24 |
二、与 Calico 的对应关系
| 组件 | Calico 真实环境 | 本模拟 |
|---|---|---|
| 节点 | 物理机 / 虚拟机 | Docker 容器 |
| BGP 守护进程 | BIRD / GoBGP | Bird 2 |
| Pod 接口 | veth pair | dummy 接口 pod0 |
| Pod CIDR | IPAM 分配 | 手动分配 /24 |
| 本地路由生成 | felix 写内核路由 | static 协议 + pod0 |
| 路由宣告 | bird 从内核学路由 → BGP 宣告 | bird 直接宣告 static 路由 |
| 路由学习 | bird 学 BGP 路由 → 写内核表 | kernel protocol 同步 |
| BGP 模式 | node-to-node mesh | iBGP 全互联(AS 64512) |
三、跨节点 Pod 通信数据流
Pod A (node1, 10.244.1.10)
|
v
node1 内核路由表
10.244.2.0/24 via 10.0.0.12 dev eth0 ← bird 从 BGP 学到写入内核
|
v
node2 (10.0.0.12)
|
v
node2 内核路由表
10.244.2.0/24 dev pod0 ← 本机 Pod CIDR
|
v
Pod B (node2, 10.244.2.10)
四、环境搭建
4.1 目录结构
calico-bird-test/
├── Dockerfile # bird2 + iproute2 + ping 镜像
├── docker-compose.yml # 3 节点编排
├── init-node.sh # 节点初始化脚本
├── verify.sh # 一键验证脚本
├── node1/bird.conf # node1 BGP 配置
├── node2/bird.conf # node2 BGP 配置
└── node3/bird.conf # node3 BGP 配置
4.2 Dockerfile
基于本地已有 redis 镜像(Debian 12),安装 bird2、iproute2 和 iputils-ping:
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/redis:8.4.0
RUN apt-get update && apt-get install -y bird2 iproute2 iputils-ping \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir -p /etc/bird
EXPOSE 179
CMD ["bird", "-d", "-c", "/etc/bird/bird.conf"]
4.3 docker-compose.yml
3 个节点共享一个 bridge 网络,每个节点挂载自己的 bird.conf 和 init-node.sh:
services:
node1:
build: .
container_name: bird-node1
hostname: node1
privileged: true
volumes:
- ./node1/bird.conf:/etc/bird/bird.conf
- ./init-node.sh:/init-node.sh
networks:
calico-net:
ipv4_address: 10.0.0.11
cap_add:
- NET_ADMIN
- SYS_ADMIN
entrypoint: ["/bin/sh", "-c"]
command:
- |
sh /init-node.sh 10.244.1.1/24 &&
bird -d -c /etc/bird/bird.conf
# node2 / node3 类似,IP 和 Pod CIDR 不同
4.4 init-node.sh 节点初始化
容器启动时执行,做三件事:创建 /run/bird 目录、创建 dummy 接口 pod0 并配置 IP、启用 IP 转发。
#!/bin/sh
POD_CIDR=$1
# 创建 bird 运行时目录(控制 socket 路径)
mkdir -p /run/bird
# 启用 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 创建 dummy 接口(模拟 Calico 的 veth + 路由模式)
ip link add pod0 type dummy 2>/dev/null || true
ip link set pod0 up
# 配置 IP
ip addr add $POD_CIDR dev pod0 2>/dev/null || true
4.5 bird.conf 配置说明
以 node1 为例,每个节点的 bird.conf 包含 6 个协议:
| 协议 | 作用 |
|---|---|
| kernel | Bird 与内核路由表同步。import none 不导入内核路由,export all 把 bird 的路由写入内核 |
| device | 扫描网络接口状态(UP/DOWN) |
| direct | 从接口 IP 生成直连路由,用于 BGP 下一跳递归查找 |
| static | 静态宣告本机 Pod CIDR(模拟 Calico felix 生成的路由) |
| bgp node2 | 与 node2 建立 iBGP 邻居,交换 Pod CIDR 路由 |
| bgp node3 | 与 node3 建立 iBGP 邻居,交换 Pod CIDR 路由 |
完整配置(node1/bird.conf):
router id 10.0.0.11;
log syslog all;
log stderr all;
filter accept_pod_cidr {
if net.len = 24 then accept;
reject;
}
protocol kernel {
kernel table 0;
ipv4 {
import none;
export all;
};
scan time 2;
}
protocol device {
scan time 2;
}
protocol direct {
ipv4;
interface "eth0", "pod0";
}
protocol static {
ipv4;
route 10.244.1.0/24 via "pod0";
}
protocol bgp node2 {
local as 64512;
neighbor 10.0.0.12 as 64512;
ipv4 {
import filter accept_pod_cidr;
export filter accept_pod_cidr;
next hop self;
};
}
protocol bgp node3 {
local as 64512;
neighbor 10.0.0.13 as 64512;
ipv4 {
import filter accept_pod_cidr;
export filter accept_pod_cidr;
next hop self;
};
}
五、关键配置踩坑记录
5.1 为什么需要 protocol direct?
BGP 路由的下一跳需要是可达的,bird 才会把路由标记为 unicast(可用)。如果没有 direct 协议,bird 不知道 10.0.0.0/24 是直连网段,无法递归下一跳,BGP 学到的路由会变成 unreachable。
protocol direct 自动从接口配置的 IP 生成直连路由,解决下一跳递归问题。这是踩的第一个坑——配置完 BGP 邻居后路由都是 unreachable,排查了很久才发现是 bird 自己的路由表里没有直连网段。
5.2 为什么用 next hop self?
本机的 Pod CIDR 路由的下一跳是 pod0(接口名),对端收到后无法解析这个接口名。next hop self 让 bird 在宣告路由时把下一跳改成自己的 BGP 源 IP(即节点 IP),对端收到后就能正确转发。
5.3 为什么是 iBGP(同一个 AS)?
Calico 的 node-to-node mesh 默认使用同一个 AS(通常是 64512),所有节点之间建立 iBGP 对等关系,是最简单的全互联模式。生产环境中节点数量多时,通常会引入 Route Reflector(路由反射器)来减少 BGP 连接数。
5.4 Bird 1.x 与 Bird 2.x 语法差异
| Bird 1.x | Bird 2.x |
|---|---|
| protocol kernel { import none; export all; } | protocol kernel { ipv4 { import none; export all; }; } |
| protocol static { route ... } | protocol static { ipv4; route ... } |
| protocol bgp { import ...; export ...; } | protocol bgp { ipv4 { import ...; export ...; }; } |
| show protocols bgp | show protocols(直接看) |
| 直接指定下一跳接口名 | 需要 next hop self + direct 协议配合 |
六、验证结果
6.1 BGP 邻居状态
Name Proto Table State Since Info
direct1 Direct --- up 00:19:44.376
node2 BGP --- up 00:19:48.364 Established
node3 BGP --- up 00:19:48.613 Established
两个 BGP 邻居都是 Established 状态,说明 BGP 会话建立成功。
6.2 BGP 路由表
Table master4:
10.244.1.0/24 unicast [direct1] ! (240) dev pod0
unicast [static1] (200) dev pod0
10.244.2.0/24 unicast [node2] ! (100) [i]
via 10.0.0.12 on eth0
10.244.3.0/24 unicast [node3] ! (100) [i]
via 10.0.0.13 on eth0
10.0.0.0/24 unicast [direct1] ! (240) dev eth0
node1 学到了 node2 的 10.244.2.0/24(via 10.0.0.12)和 node3 的 10.244.3.0/24(via 10.0.0.13),路由状态是 unicast(可用)。
6.3 内核路由表
10.0.0.0/24 dev eth0 scope link metric 32
10.244.1.0/24 dev pod0 scope link metric 32
10.244.2.0/24 via 10.0.0.12 dev eth0 metric 32
10.244.3.0/24 via 10.0.0.13 dev eth0 metric 32
4 条 bird 路由全部写入内核路由表(proto bird),包括直连路由和学到的 BGP 路由。
6.4 跨节点 ping 测试
| 源 | 目标 | 结果 |
|---|---|---|
| node1 | 10.244.2.1 (node2 Pod 网关) | 2/2 包,0% 丢包 |
| node1 | 10.244.3.1 (node3 Pod 网关) | 2/2 包,0% 丢包 |
| node2 | 10.244.1.1 (node1 Pod 网关) | 2/2 包,0% 丢包 |
所有跨节点 ping 全部通过,说明 BGP 学习到的路由在内核中生效,流量可以正确转发。


七、常用操作命令
# 启动环境
cd calico-bird-test
docker compose up -d --build
# 查看 BGP 邻居状态
docker exec bird-node1 birdc show protocols
# 查看 BGP 路由表
docker exec bird-node1 birdc show route
# 查看某条路由的详细属性
docker exec bird-node1 birdc show route 10.244.2.0/24 all
# 查看从某个邻居学到的路由
docker exec bird-node1 birdc show route protocol node2
# 查看内核路由表(bird 学到的)
docker exec bird-node1 ip route show proto bird
# 软重载配置
docker exec bird-node1 birdc configure soft
# 查看节点接口
docker exec bird-node1 ip addr
# 停止环境
docker compose down
八、总结
通过 Docker + Bird 2 模拟了 Calico 的 BGP 网络核心原理:
- 每个节点运行 BGP 守护进程(bird),与其他节点建立 iBGP 邻居
- 每个节点将本机 Pod CIDR 通过 BGP 宣告给其他节点
- 学到的 BGP 路由写入内核路由表,实现跨节点 Pod 通信
- 整个过程不需要 overlay 网络(如 VXLAN),性能更好,但依赖底层网络支持 BGP
这个实验清晰地展示了 Calico BGP 模式的工作原理——本质就是在节点之间通过 BGP 交换路由,让每个节点都知道所有 Pod 网段的下一跳,从而实现纯三层的容器网络。
浙公网安备 33010602011771号