Calico 在 OpenStack 中的实现原理:Linux 路由、BGP 与 DHCP Agent 设计解析
网络云原生网络安全【免费下载链接】calicoCloud native networking and network security项目地址https://gitcode.com/gh_mirrors/cal/calico点击查看免费下载Calico本项目 networking-calico 子项目在 OpenStack/Neutron 云环境中的核心实现思路是放弃桥接与隧道模拟 L2转而使用标准 Linux 路由转发 VM 流量用 iptables 施加安全策略并用 BGPBIRD在计算节点之间扩散路由。本文基于 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或 BYOIPbring 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 实现配置的安全策略。具体过程如下VM 通过宿主上的TAP 设备接入TAP 的宿主端不做桥接、不配置任何 IP 地址仅保留 link-local IPv6。宿主机被配置为通过该 TAP响应任何 ARP 或 NDP 请求且应答自己的 MAC 地址。因此经 TAP 到达的数据在 L2 层总是以宿主机为目的地址随后被交给 Linux 路由层处理——这正是以 L3 方式接管 L2 流量的关键技巧。对每个本地 VM宿主机编程一条指向对应 TAP 设备的路由目标为该 VM 的 IP 地址。宿主机运行BGP 客户端BIRD将这些路由导出给其他计算节点同时也从其他节点学习远端 VM 的路由。计算节点上的路由表形态文档给出了一张计算节点路由表的真实样例命令route -n的输出userhost02:~$ 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 接口上收到 DHCPv4 或 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 的RoutedInterfaceDriveruse_gateway_ips属性返回True注释说明路由式网络不跨计算节点或网络节点桥接因此 DHCP 端口可以使用每个子网的网关 IP 地址而不必申请新的 Neutron 分配地址plug_new()通过ip_lib.IPWrapper().add_dummy(device_name)创建 dummy 接口位于默认命名空间并设置 MAC、可选 MTU 后将其 upinit_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-interfacelo --pid-file... \ --dhcp-hostsfile... --addn-hosts... --dhcp-optsfile... \ --dhcp-leasefile... --dhcp-matchset:ipxe,175 \ --bind-dynamic --interfacens-XXX \ --interfacetap* --bridge-interfacens-XXX,tap*关键点在于--bridge-interfacens-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_metadataFalse、use_namespacesFalse将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/v1DHCP agent 所需信息的新子树/calico/dhcp/v1/subnet子网信息目录/calico/dhcp/v1/subnet/subnet-idJSON 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.pySUBNET_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 主机名fqdnNeutron 通过端口字段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.pysetup.py中注册的calico-dhcp-agent命令入口负责在导入模块前完成 eventlet monkey_patch。总结一条贯穿数据面与控制面的完整链路把实现笔记与配套文档、源码合起来看Calico 在 OpenStack 中的实现是一条清晰的链路数据面VM 经无桥接 TAP 接入宿主默认命名空间 → 宿主应答 ARP/NDP 把流量引入路由层 → 本地 VM 走 TAP 主机路由、远端 VM 走 BGP 学习到的/32主机路由见 实现笔记 中的路由表示例策略面iptables 承载 security group 等安全策略不做 L2 隔离控制面BIRDBGP负责计算节点间路由扩散Calico DHCP agent 以 etcd 为数据源/calico/v1/host/hostname/workload与/calico/dhcp/v1/subnet复用RoutedInterfaceDriverDnsmasqRouted完成基于网关 IP 的 DHCP 地址下发同时彻底绕开 Neutron server 的 RPC 扇出与端口 IP 分配负担。理解这一实现也就理解了为什么 Calico 要求 Neutron 网络满足单一地址作用域、l2_adjacency False、网络默认互通这三项约束——它们不是限制而是整个三层路由方案的直接推论。赞分享网络云原生网络安全【免费下载链接】calicoCloud native networking and network security项目地址https://gitcode.com/gh_mirrors/cal/calico点击查看免费下载相关推荐Calico OpenStack 集成指南networking-calico 的路由连通性与 DHCP Agent 架构解析Calico OpenStack 集成指南networking calico 的路由连通性与 DHCP Agent 架构解析 networking calic网络云原生网络安全Calico DHCP 代理基于 etcd 数据驱动的 OpenStack Neutron DHCP 架构改造Calico DHCP 代理基于 etcd 数据驱动的 OpenStack Neutron DHCP 架构改造 Calico DHCP 代理Calico D网络云原生网络安全golang-jwt/jwt/v5 完全指南Go 语言 JWT 签发、解析与安全校验的权威实现golang jwt/jwt/v5 完全指南Go 语言 JWT 签发、解析与安全校验的权威实现 本指南以本仓库中 vendor 的 golang jwt/jw云原生操作系统容器编排上一篇macOS 窗口置顶工具 Topit 使用指南从安装到进阶一次说清下一篇pixi 包依赖类型全解析build / host / run 依赖、run-exports 与条件依赖实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考