☰
Calico 在 OpenStack 中的实现原理:Linux 路由、BGP 与 DHCP Agent 设计解析
2026/9/29 3:20:01 网站建设 项目流程
  • 网络
  • 云原生
  • 网络安全

【免费下载链接】calico

Cloud native networking and network security

项目地址:https://gitcode.com/gh_mirrors/cal/calico
点击查看免费下载

Calico(本项目 networking-calico 子项目)在 OpenStack/Neutron 云环境中的核心实现思路是:放弃桥接与隧道模拟 L2,转而使用标准 Linux 路由转发 VM 流量,用 iptables 施加安全策略,并用 BGP(BIRD)在计算节点之间扩散路由。本文基于 networking-calico 实现笔记 展开,结合仓库源码说明默认地址作用域下的连通性机制、路由表象、DHCP 服务的实现细节,以及与之配套的 Calico DHCP Agent 的整体架构。读完本文,你将能理解 Calico 作为 Neutron 后端时"不做二层、只做三层"的具体落地方式,以及其 DHCP agent 如何从 etcd 拉取数据、复用 Dnsmasq 完成地址下发。

与 Neutron 其他后端的关键差异

Calico 与大多数 Neutron 后端(依赖 Linux bridge、Open vSwitch 或隧道封装来模拟 L2 连通性)的根本不同,是它直接在L3 层工作。networking-calico 的文档索引页(networking-calico/doc/source/index.rst)明确列出了这一选择带来的三方面 API 语义约束:

  • 单一扁平地址空间:Calico 只支持一个扁平 IP 地址空间,不支持网段重叠(overlapping IP ranges)或 BYOIP("bring your own addressing")。在 Neutron API 术语中,所有 Calico 网络子网必须属于同一个地址作用域(address scope)。
  • 无 L2 邻接:即使在同一 Neutron 子网内,Calico 也不提供二层邻接,因此裸二层协议和广播流量无法工作。在 Neutron API 术语中,所有 Calico 网络的l2_adjacency必须为False。
  • 默认跨网络互联:Calico 默认提供不同网络之间的连通性,网络隔离与细粒度安全限制依赖 security group 配置与策略实现。这意味着 Calico 网络要么是外部 provider 网络,要么是通过 Neutron 路由器连接到外部网络的租户网络。

这三条约束直接决定了实现笔记中描述的数据通路:既然不做二层,VM 之间的数据转发自然落到 Linux 路由层。

默认地址作用域下的连通性实现

从 TAP 到路由:宿主机上的数据通路

对默认地址作用域的 endpoint,所有转发都发生在计算节点的默认网络命名空间(default namespace)中,由标准 Linux 路由转发 VM 数据,由 iptables 实现配置的安全策略。具体过程如下:

  1. VM 通过宿主上的TAP 设备接入,TAP 的宿主端不做桥接、不配置任何 IP 地址(仅保留 link-local IPv6)。
  2. 宿主机被配置为通过该 TAP响应任何 ARP 或 NDP 请求,且应答自己的 MAC 地址。因此经 TAP 到达的数据在 L2 层总是以宿主机为目的地址,随后被交给 Linux 路由层处理——这正是"以 L3 方式接管 L2 流量"的关键技巧。
  3. 对每个本地 VM,宿主机编程一条指向对应 TAP 设备的路由,目标为该 VM 的 IP 地址。
  4. 宿主机运行BGP 客户端(BIRD),将这些路由导出给其他计算节点,同时也从其他节点学习远端 VM 的路由。

计算节点上的路由表形态

文档给出了一张计算节点路由表的真实样例(命令route -n的输出):

user@host02:~$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.18.203.1 0.0.0.0 UG 0 0 0 eth0 10.65.0.21 172.18.203.126 255.255.255.255 UGH 0 0 0 eth0 10.65.0.22 172.18.203.129 255.255.255.255 UGH 0 0 0 eth0 10.65.0.23 172.18.203.129 255.255.255.255 UGH 0 0 0 eth0 10.65.0.24 0.0.0.0 255.255.255.255 UH 0 0 0 tapa429fb36-04 172.18.203.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

这张表直观展示了 Calico 的路由模型:

  • 本机 VM10.65.0.24的路由是UH(主机路由,经 TAP),下一跳为空(直接连接),出口设备为tapa429fb36-04;
  • 远端三台 VM(.21、.22、.23)分别落在两台计算节点(172.18.203.126与.129)上,路由表现为UGH(经网关的主机路由),出口为 eth0——这些路由正是由 BIRD 通过 BGP 从其他计算节点学习而来;
  • 每台远端 VM 都是一条独立的/32主机路由,而不是聚合网段路由,这体现了 Calico"每 endpoint 一条路由"的精确路由风格。

对比典型的 Neutron 后端(如 VXLAN + Linux bridge / OVS),这里没有 br-int、没有 VXLAN 隧道接口、没有 namespace 隔离,所有流量直接走宿主 eth0 转发。

DHCP 服务:在路由网络里如何下发地址

在无桥接、无 namespace 的路由式网络里,DHCP 服务不能沿用 Neutron 的默认设计。实现笔记明确指出:DHCP 服务由运行在每个计算节点上的 DHCP agent 提供,agent 调用Dnsmasq 并使用其--bridge-interface选项。

--bridge-interface的语义

该选项的效果是:Dnsmasq 把所有 TAP 接口当作ns-XXX接口(Dnsmasq 的 DHCP 上下文定义所在的接口)的别名,具体表现为两个行为:

  • 若在某个 TAP 接口上收到 DHCP(v4 或 v6)或 Router Solicit 报文,Dnsmasq按在ns-XXX接口上收到一样处理,然后把应答报文从对应的 TAP 发回;
  • 当 Dnsmasq 平时会在ns-XXX接口上主动发送无请求的路由通告(unsolicited Router Advertisement)时,此时改为在全部 TAP 接口上发送。

网关 IP 复用而非独立分配

为了适配路由式网络,DHCP agent 使用一个 Calico 特有的接口驱动,其行为与标准 Neutron DHCP agent 有本质区别:

  • 它把ns-XXX创建为Linux dummy 接口(而不是桥接接口);
  • 它使用子网网关 IP 作为ns-XXX的 IP 地址,而不是从 Neutron 为每个 DHCP 端口分配一个独立的 IP。

这样做的直接后果是:DHCP 端口不再占用 Neutron 数据库中的独立 IP 地址,从而消除了大规模部署中 IP 分配与端口同步的巨大开销。实现笔记还提到,支持该行为的补丁已分别合入Dnsmasq 2.73 之前的版本和Neutron Liberty 之前的版本。

源码佐证:驱动与 Dnsmasq 配置的落地实现

RoutedInterfaceDriver:创建 dummy 接口

文档描述的"Calico 特有接口驱动"在仓库中对应 networking_calico/agent/linux/interface.py 的RoutedInterfaceDriver:

  • use_gateway_ips属性返回True:注释说明路由式网络不跨计算节点或网络节点桥接,因此 DHCP 端口可以使用每个子网的网关 IP 地址,而不必申请新的 Neutron 分配地址;
  • plug_new()通过ip_lib.IPWrapper().add_dummy(device_name)创建 dummy 接口(位于默认命名空间),并设置 MAC、可选 MTU 后将其 up;
  • init_l3()在超类逻辑之外,删除 Linux 自动为该 CIDR 创建的子网路由(device.route.delete_onlink_route)——这是路由式 DHCP 的关键修正,避免 dummy 接口上的网关地址引入多余的直接路由;
  • bridged属性为False。

DnsmasqRouted:组装桥接式 Dnsmasq 命令行

Dnsmasq 驱动在 networking_calico/agent/linux/dhcp.py 的DnsmasqRouted中实现,它组合出与实现笔记完全对应的命令行参数:

dnsmasq --no-hosts --except-interface=lo --pid-file=... \ --dhcp-hostsfile=... --addn-hosts=... --dhcp-optsfile=... \ --dhcp-leasefile=... --dhcp-match=set:ipxe,175 \ --bind-dynamic --interface=<ns-XXX> \ --interface=tap* --bridge-interface=<ns-XXX>,tap*

关键点在于--bridge-interface=<ns-XXX>,tap*与--bind-dynamic的组合:前者正是文档所述"把 TAP 当作 ns-XXX 别名"的机制,后者使 Dnsmasq 动态绑定各 TAP 接口,从而避免在计算节点上创建额外的桥接 namespace。文件开头的注释还说明其使用 Calico 自己的CalicoDeviceManager。

配套组件:Calico DHCP Agent 架构与 etcd 数据模型

实现笔记侧重"宿主如何转发数据",而 DHCP agent 的详细设计收录在同目录的 networking-calico/doc/source/dhcp-agent.rst 中,两者共同构成完整的实现图景。

复用 Neutron 架构、避免 RPC 风暴

Calico DHCP agent 大量复用现有 Neutron DHCP agent 架构(包括 Dnsmasq 的使用),但剔除掉导致 Neutron server 在 DHCP agent 超过数百个时负载过高的部分。改动集中在两点:

  • 移除DhcpAgentWithStateReport——它原本向 Neutron server 上报本 agent 的存在,导致 server 向其扇出(fan out)端口更新;
  • CalicoDhcpAgent替换DhcpAgent.run()——Neutron 的run()会在启动时及之后周期性地向 Neutron server 询问端口信息,Calico 版本直接停止这一行为。

作为替代,agent 通过 etcd 监视/calico/v1/host/<hostname>/workload子树中本主机的 endpoint 数据变化,把当前 endpoint 数据集转换为 Neutron DHCP 驱动期望的NetworkCache格式后交给 dhcp_driver。这一点在源码 networking_calico/agent/dhcp_agent.py 中得到印证:CalicoDhcpAgent继承 Neutron 的DhcpAgent,在__init__中强制enable_isolated_metadata=False、use_namespaces=False,将interface_driver覆盖为RoutedInterfaceDriver、将dhcp_driver_cls覆盖为DnsmasqRouted,并把 RPC 插件替换为本地FakePlugin(提供create_dhcp_port/release_dhcp_port/get_ports存根,MAC 使用硬编码的本地管理地址02:00:00:00:00:00,不占用 Neutron 数据库端口)。其run()直接启动CalicoEtcdWatcher完成 etcd 数据驱动。

etcd 数据模型扩展

为了从 etcd 供数给 DHCP agent,文档给出了在 Felix 已消费的数据之外新增的数据模型:

  • /calico/dhcp/v1:DHCP agent 所需信息的新子树;
  • /calico/dhcp/v1/subnet:子网信息目录;
  • /calico/dhcp/v1/subnet/<subnet-id>:JSON dict 形式的内容:
{ 'cidr': <cidr>, # Mandatory. For example: "192.168.1.0/24". 'gateway_ip': <gateway IP>, # Mandatory. For example: "192.168.1.1". 'dns_servers': [ <ip1>, <ip2>, ... ] # Optional. For example: [ '172.18.10.55', '172.18.10.74' ] }
  • 每个 endpoint 的 JSON dict 中新增字段:
{ 'ipv4_subnet_ids': [ <subnet-id>, ... ] # Subnet IDs for each corresponding IPv4 address in 'ipv4_nets'. 'ipv6_subnet_ids': [ <subnet-id>, ... ] # Subnet IDs for each corresponding IPv6 address in 'ipv6_nets'. 'fqdn': <fqdn> # Optional. E.g. 'calico-vm17.datcon.co.uk' }

当前仓库源码中,子网路径与注解键的实现在 datamodel_v1.py(SUBNET_DIR)与 datamodel_v3.py(注解键openstack.projectcalico.org/fqdn、openstack.projectcalico.org/network-id)中可查。

两个关键细节

  • 子网前缀长度必须正确:对每个子网,网关 IP 与前缀长度会以ifconfig <device> <gateway IP>/<prefix length>的形式配置在 Dnsmasq 监听的 Linux 接口上;且 Dnsmasq 只会在关联 Linux 接口定义的子网范围内下发 IP。若前缀长度错误,Dnsmasq 将无法下发地址。
  • VM 主机名(fqdn):Neutron 通过端口字段dns_name(可写,简单名如calico-vm17)与dns_assignment(服务端生成的只读字段,形如{'hostname': 'calico-vm17', 'ip_address': '10.65.0.4', 'fqdn': 'calico-vm17.datcon.co.uk'})向 DHCP agent 传递主机名信息;agent 将其交给 dhcp_driver 并写入 Dnsmasq 配置。在 Calico 模型中,endpoint 数据只新增单个fqdn字段,hostname由在第一个.处拆分派生。从源码看,CalicoEtcdWatcher.on_endpoint_set正是从 endpoint 注解读取 fqdn、按fqdn.split(".")[0]得到 hostname,并组装进dns_assignment。

调用方式

DHCP agent 的调用方式与标准 Neutron DHCP agent 相同,使用 neutron 配置文件;区别在于 Calico agent 额外消费calicooption group下的设置(例如 etcd 集群连接信息)。一个典型调用示例:

calico-dhcp-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini

由于 calico ml2 插件配置文件已包含全部所需设置,它本身也可作为该 option group 的配置来源。源码入口见 dhcp_agent_main.py(setup.py中注册的calico-dhcp-agent命令入口,负责在导入模块前完成 eventlet monkey_patch)。

总结:一条贯穿数据面与控制面的完整链路

把实现笔记与配套文档、源码合起来看,Calico 在 OpenStack 中的实现是一条清晰的链路:

  1. 数据面:VM 经无桥接 TAP 接入宿主默认命名空间 → 宿主应答 ARP/NDP 把流量引入路由层 → 本地 VM 走 TAP 主机路由、远端 VM 走 BGP 学习到的/32主机路由(见 实现笔记 中的路由表示例);
  2. 策略面:iptables 承载 security group 等安全策略,不做 L2 隔离;
  3. 控制面:BIRD(BGP)负责计算节点间路由扩散;Calico DHCP agent 以 etcd 为数据源(/calico/v1/host/<hostname>/workload与/calico/dhcp/v1/subnet),复用RoutedInterfaceDriver+DnsmasqRouted完成基于网关 IP 的 DHCP 地址下发,同时彻底绕开 Neutron server 的 RPC 扇出与端口 IP 分配负担。

理解这一实现,也就理解了为什么 Calico 要求 Neutron 网络满足"单一地址作用域、l2_adjacency False、网络默认互通"这三项约束——它们不是限制,而是整个三层路由方案的直接推论。

  • 网络
  • 云原生
  • 网络安全

【免费下载链接】calico

Cloud native networking and network security

项目地址:https://gitcode.com/gh_mirrors/cal/calico
点击查看免费下载
上一篇:macOS 窗口置顶工具 Topit 使用指南:从安装到进阶一次说清
下一篇:pixi 包依赖类型全解析:build / host / run 依赖、run-exports 与条件依赖实战

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询