4、Calico架构与组件:Felix、BIRD、confd、etcd/kubernetes datastore、Calico CNI插件、IPAM与IP池管理

Calico 是云原生领域应用最广泛的 CNI 方案之一,其核心设计理念是“基于三层路由实现 Pod 互联”,而非依赖 Overlay 隧道。理解 Calico 的架构,关键在于厘清其控制平面与数据平面的分工:控制平面负责策略分发与路由计算,数据平面则依托 Linux 内核的 iptables/ipset 与路由表完成实际转发。本章将深入拆解 Calico 的六大核心组件——Felix、BIRD、confd、etcd/kubernetes datastore、Calico CNI 插件以及 IPAM 与 IP 池管理,并结合实战场景说明它们如何协同工作。

Calico 控制平面与数据平面架构 数据存储层(Datastore) etcd(独立部署) 或 Kubernetes API Server(KDD 模式) 存储:WorkloadEndpoint、NetworkPolicy、IPPool、BGPConfiguration、FelixConfiguration 控制平面组件(每节点运行) Felix 编程 iptables/ipset 维护路由表 BIRD BGP 路由分发 跨节点路由交换 confd 监听 datastore 生成 BIRD 配置 Calico CNI 插件 创建 veth 对 调用 IPAM 分配 IP 数据平面(Linux 内核) 路由表(FIB) 基于 BGP 学习到的路由 iptables / ipset 网络策略与安全组规则 veth pair / 路由转发 Pod 网卡与宿主机网卡 ● 控制平面:Felix 负责策略与路由编程,BIRD 负责 BGP 分发,confd 负责配置生成 ● 数据平面:纯内核态转发,无 Overlay 封装,性能损耗低 ● 关键接口:Felix 与 datastore 通过 watch 机制同步,BIRD 与 confd 通过文件系统交互 ● 排障入口:calicoctl node status、birdctl show route、iptables -L -n -v

4.1 核心原理:控制平面与数据平面的解耦设计

Calico 的架构设计遵循“控制与转发分离”的经典网络原则。控制平面由运行在每个节点上的代理进程组成,负责从数据存储中读取期望状态(Desired State),并将其转化为内核数据平面的实际配置。数据平面则完全依赖 Linux 内核的既有能力——路由表、iptables、ipset 和 veth 虚拟网卡——实现高性能的三层转发。

这种设计带来三个关键优势:性能高,因为数据包走内核原生路由路径,无隧道封装开销;可扩展性强,BGP 协议天然支持大规模路由分发;策略能力强,iptables 提供细粒度的五元组匹配能力。但同时也要求运维人员对 Linux 网络栈有较深理解,排障时需同时关注路由表、iptables 链和 BGP 会话状态。

关键理解:Calico 不是“一个二进制程序”,而是一组协同工作的进程集合。Felix 是“执行者”,BIRD 是“传播者”,confd 是“配置翻译器”,datastore 是“事实来源”。理解它们之间的数据流,是掌握 Calico 运维的基础。

4.2 组件详解与职责边界

4.2.1 Felix:节点代理与策略执行引擎

Felix 是运行在每个 Kubernetes 节点上的守护进程,它通过 watch 机制监听 datastore 中的资源变化(如 NetworkPolicy、WorkloadEndpoint、IPPool 等),并将这些期望状态翻译为内核配置。具体职责包括:

  • 编程 iptables 规则:为每个 WorkloadEndpoint 生成 INPUT/OUTPUT/FORWARD 链规则,实现 NetworkPolicy 的允许/拒绝逻辑。
  • 维护 ipset 集合:将 IP 地址、端口等匹配条件组织为 ipset,减少 iptables 规则数量,提升匹配效率。
  • 管理路由表:为本地 Pod 添加直连路由,并确保路由表与当前节点上的端点状态一致。
  • 接口监控:监听 veth 接口的创建与删除,动态调整策略。

Felix 的性能直接影响节点转发能力。在大型集群中,Felix 需要处理数千条 iptables 规则,因此 Calico 引入了 XDP 加速和 eBPF 数据面(可选)来优化性能。

4.2.2 BIRD:BGP 路由反射与分发

BIRD(BIRD Internet Routing Daemon)是 Calico 默认的 BGP 客户端,负责将本节点的 Pod 网段路由通告给其他节点。在集群内部,BIRD 运行在两种模式之一:

  • Node-to-Node Mesh(全互联模式):每个节点与所有其他节点建立 BGP 会话,适合节点数少于 50 的小型集群。
  • Route Reflector(路由反射模式):指定若干节点作为路由反射器,其他节点只与反射器建立会话,适合大规模集群。

BIRD 的配置由 confd 动态生成,当 Felix 更新路由表后,BIRD 会通过 BGP 协议将新的路由通告出去。运维人员可通过 birdctl show route 查看 BIRD 学习到的全部路由。

4.2.3 confd:模板驱动的配置生成器

confd 是一个轻量级的配置管理工具,它监听 datastore 中的键值变化,并根据预定义的模板(如 bird.cfg.template)重新生成 BIRD 配置文件。当配置变更时,confd 会触发 BIRD 重新加载配置,而无需重启进程。

confd 的存在使得 Calico 的配置管理变得声明式:用户只需修改 datastore 中的资源对象,confd 自动完成配置下发。这种模式避免了手工编辑配置文件的错误,也便于版本控制。

4.2.4 Datastore:etcd 与 Kubernetes API Server 双模式

Calico 支持两种数据存储方式:

特性etcd 模式Kubernetes datastore 模式(KDD)
存储位置独立 etcd 集群Kubernetes API Server 中的 CRD
适用场景非 Kubernetes 环境(如 OpenStack)Kubernetes 原生环境
运维复杂度需额外维护 etcd 集群复用 K8s 高可用能力
一致性etcd 自身保证依赖 K8s 的乐观锁机制
推荐度已逐步淘汰官方推荐,默认模式

在 KDD 模式下,Calico 将 WorkloadEndpoint、NetworkPolicy、IPPool 等资源定义为 CRD(Custom Resource Definition),通过 Kubernetes API 进行读写。这种方式简化了部署,但需要注意 CRD 的版本兼容性。

4.2.5 Calico CNI 插件:Pod 网络接入的“最后一公里”

Calico CNI 插件是 kubelet 调用的二进制文件,负责在 Pod 创建时完成网络接入。其工作流程如下:

  1. 创建 veth pair:一端放入 Pod 网络命名空间,另一端连接到宿主机 root 命名空间。
  2. 配置 Pod 侧 IP:调用 IPAM 插件从指定 IP 池分配 IP 地址。
  3. 设置路由:在 Pod 内添加默认路由指向 veth 对端。
  4. 通知 Felix:将新创建的 WorkloadEndpoint 信息写入 datastore,触发 Felix 编程策略。

CNI 插件本身不负责策略执行,它只做“连接”和“地址分配”,策略由 Felix 在后续异步完成。这种设计保证了 CNI 操作的快速响应。

4.2.6 IPAM 与 IP 池管理

Calico 的 IPAM(IP Address Management)模块负责从 IPPool 中分配和回收 IP 地址。IPPool 是 Calico 的核心资源对象,定义了可用的 CIDR 范围、是否允许重叠、是否启用 NAT 等属性。

# 查看当前集群的 IP 池
calicoctl get ippool -o yaml

# 创建新的 IP 池
calicoctl create -f - <<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: production-pod-cidr
spec:
  cidr: 10.244.0.0/16
  ipipMode: Always
  natOutgoing: true
  disabled: false
EOF

IPAM 支持两种分配策略:自动分配(按顺序从 IP 池中选取)和 手动指定(通过注解 cni.projectcalico.org/ipAddrs 指定)。生产环境建议为不同业务规划独立 IP 池,便于网络隔离和故障排查。

4.3 实战场景:跨节点 Pod 通信的完整链路

假设集群有两个节点:Node A(10.0.0.1)和 Node B(10.0.0.2),Pod A 运行在 Node A 上,IP 为 10.244.1.5;Pod B 运行在 Node B 上,IP 为 10.244.2.7。当 Pod A 向 Pod B 发送数据包时,完整链路如下:

  1. Pod A 发出数据包:目标 IP 为 10.244.2.7,源 IP 为 10.244.1.5,通过 veth 进入 Node A 的 root 命名空间。
  2. Node A 路由查询:内核查询路由表,发现 10.244.2.0/24 网段的路由下一跳为 10.0.0.2(Node B),出接口为 eth0。
  3. iptables 检查:数据包经过 FORWARD 链,Felix 预先配置的规则允许该流量(基于 NetworkPolicy 判断)。
  4. BGP 路由来源:Node A 的路由表由 Felix 写入,而 Node B 的 10.244.2.0/24 路由是通过 BIRD 从 Node B 学习到的。
  5. Node B 接收:数据包到达 Node B 的 eth0,内核查询路由表,发现 10.244.2.7 是本地直连路由,通过 veth 转发给 Pod B。
排障提示:如果跨节点通信失败,按以下顺序检查:
1. ip route 查看路由表是否存在目标网段路由;
2. birdctl show route 确认 BIRD 是否学习到该路由;
3. iptables -L -n -v | grep 10.244.2.7 检查是否有策略丢弃;
4. calicoctl node status 查看 Felix 与 BIRD 的健康状态。

4.4 常见误区与最佳实践

误区一:认为 Calico 必须依赖 etcd。实际上,Kubernetes 环境默认使用 KDD 模式,无需额外部署 etcd。
误区二:忽略 IP 池规划。如果多个集群共用同一 CIDR,会导致路由冲突。建议为每个集群规划独立的 IP 池,并预留扩展空间。
误区三:盲目调整 Felix 参数。例如,将 FelixChainInsertMode 改为 Append 可能导致策略被其他规则绕过。

最佳实践建议:

  • 生产环境启用 natOutgoing: true,确保 Pod 访问外部网络时源地址被正确转换。
  • 对于大规模集群(超过 100 节点),配置 BGP Route Reflector,避免全互联带来的会话数爆炸。
  • 定期使用 calicoctl get workloadendpoint 检查端点状态,确保与 Pod 实际状态一致。
  • 监控 Felix 的 iptables 规则数量,若超过 5000 条,考虑使用 ipset 或 eBPF 数据面优化。

总结而言,Calico 的架构设计体现了“简单、高效、可扩展”的理念。理解每个组件的职责边界与交互方式,是进行网络排障、性能调优和容量规划的基础。在实际运维中,建议结合 calicoctl 命令行工具和日志分析,逐步建立对集群网络状态的全局视图。