Cilium 多播支持实战:启用、配置与 eBPF 数据面实现原理(Beta)

发布时间:2026/9/14 8:33:17
Cilium 多播支持实战:启用、配置与 eBPF 数据面实现原理(Beta) Cilium 多播支持实战启用、配置与 eBPF 数据面实现原理Beta【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/ciliumCilium 提供的多播Multicast能力允许用户应用以“一对多”的方式在 Kubernetes 集群内分发数据流例如行情推送、视频流分发、分布式计算中的组播通信等场景。本文基于 Cilium 官方文档Documentation/network/multicast.rst完整讲解如何开启多播功能、配置多播组地址与订阅者 IP、使用cilium-dbg与cilium multicast命令管理多播状态并深入到 eBPF 源码层面解析 IGMP 报文处理与数据包复制转发的底层实现。一、功能概述与适用前提多播能力让单个发送端sender的数据报文被 Cilium 在 eBPF 数据面内自动复制并分发到多个订阅者subscriber而不需要在用户态逐个复制流量。Cilium 的多播基于 eBPF 实现支持多种组播协议报文IGMPv2/v3 成员关系报告、离开报文在内核态直接处理。在动手配置之前必须确认以下前提条件源自文档 Prerequisites 章节Cilium 已正确安装可在集群中运行cilium status验证 Cilium 处于运行状态VXLAN 模式多播功能要求 Cilium 运行在 vxlan 隧道模式--tunnel-modevxlan。这是跨节点复制远端订阅者流量所必需的隧道封装能力内核版本多播仅支持 AMD64 平台内核 5.10、AArch64 平台内核 6.0。这是因为数据面大量使用了bpf_for_each_map_elem等较新的 eBPF 特性。从源码结构看该功能在代码中的开关是一个名为multicast-enabled的配置项定义在 pkg/maps/multicast/mcast.go 中默认值为falseconst ( // Multicast is the name of the flag to enable synthetic multicast. Multicast multicast-enabled ) type Config struct { MulticastEnabled bool mapstructure:multicast-enabled }同时eBPF 数据面代码通过编译期宏ENABLE_MULTICAST来控制多播相关函数的注入见 bpf/lib/mcast.h 中的#ifdef ENABLE_MULTICAST。也就是说配置项开启后Cilium Agent 会重新编译并挂载带多播逻辑的 BPF 程序。二、启用多播功能启用方式非常直接只需更新cilium-configConfigMap$ cilium config set multicast-enabled true ✨ Patching ConfigMap cilium-config with multicast-enabledtrue... ♻️ Restarted Cilium pods该命令对应 cilium-agent 的--multicast-enabled启动参数。设置后 Cilium pods 会被自动重启以加载带ENABLE_MULTICAST宏编译的 BPF 程序并初始化多播相关的 BPF map。三、配置多播组与订阅者 IP启用功能后还需要根据应用需求配置多播组组播地址和订阅者列表。这一步需要在每个cilium-agentPod 内执行cilium-dbg命令完成。配置完成后订阅者 Pod 即可发送 IGMP join 报文发送端 Pod 可以开始发送组播流。文档以组播组地址239.255.0.1为例演示完整流程。3.1 获取各节点的 CiliumInternalIP首先获取所有 CiliumNode 的内部 IP它们将作为多播订阅者地址$ kubectl get ciliumnodes.cilium.io NAME CILIUMINTERNALIP INTERNALIP AGE kind-control-plane 10.244.0.72 172.19.0.2 16m kind-worker 10.244.1.86 172.19.0.3 16m这里的CILIUMINTERNALIP是 Cilium 为每个节点分配的内部单播地址跨节点多播流量将通过 VXLAN 隧道发送到这里。3.2 添加多播组地址在每个cilium-agent中执行启用该节点的多播 BPF map### add multicast IP address $ cilium-dbg bpf multicast group add 239.255.0.1 ### check multicast IP address $ cilium-dbg bpf multicast group list Group Address 239.255.0.13.3 添加订阅者 IP继续在每个cilium-agent中设置订阅者地址注意订阅者 IP 是其他节点的 CiliumInternalIP而非本节点自身官方文档在此处有明确的 note 提醒### cilium-agent on kind-control-plane $ cilium-dbg bpf multicast subscriber add 239.255.0.1 10.244.1.86 $ cilium-dbg bpf multicast subscriber list all Group Subscriber Type 239.255.0.1 10.244.1.86 Remote Node ### cilium-agent on kind-worker $ cilium-dbg bpf multicast subscriber add 239.255.0.1 10.244.0.72输出中的Type列显示Remote Node表示这是一个远端节点订阅者通过 VXLAN 隧道转发如果是本地 Pod 通过 IGMP join 注册的订阅者则显示为Local Endpoint。3.4 使用 cilium multicast 命令批量管理推荐逐个节点操作繁琐Cilium CLI 提供了cilium multicast命令可以一次性让所有节点加入指定多播组并查看集群范围内的组与订阅者状态### make all nodes join the specified multicast group $ cilium multicast add --group-ip 239.255.0.1 ### confirm the multicast groups and subscribers $ cilium multicast list subscriber --all Node Group Subscriber Type cl-worker 239.255.0.1 10.244.0.196 Remote Node cl-control-plane 239.255.0.1 10.244.1.122 Remote Node这些命令的实现在 cilium-cli/multicast/multicast.go 中几个值得注意的实现细节自动跳过本节点AddAllNodescilium-cli/multicast/multicast.go#L437在遍历所有节点 IP 时通过if ip.IP ! pod.Name ! podName判断并跳过当前节点自身——这与手工操作时“订阅者 IP 不能是节点自身 IP”的约束一致CLI 在底层替你保证了正确性自动补建组如果目标节点上还不存在该多播组AddAllNodes会先执行cilium-dbg bpf multicast group add再添加订阅者并发执行命令通过 goroutine 并发在每个 cilium-agent Pod 内 execcilium-dbg命令底层调用见 getGroupList 与 AddAllNodes并对 “already exists”“does not exist” 这类幂等性错误做了容错处理集群视图ListGroups/ListSubscribers聚合所有节点的结果并以表格输出也支持-o json输出ListSubscribers要求--group-ip与--all二者必须且只能指定其一见 ListSubscribersIP 来源CLI 从 CiliumNode CR 的spec.addresses中筛选NodeCiliumInternalIP类型且为 IPv4 的地址getCiliumInternalIP。3.5 删除多播组与订阅者当不再需要某个多播组时在cilium-agent中执行删除命令$ cilium-dbg bpf multicast group delete 239.255.0.1 $ cilium-dbg bpf multicast subscriber delete 239.255.0.1 10.244.0.72对应的 CLI 批量删除命令为cilium multicast delete其实现DelAllNodescilium-cli/multicast/multicast.go#L537会在每个节点上执行cilium-dbg bpf multicast group delete并容忍“does not exist”这类幂等错误。四、eBPF 数据面实现原理以下原理部分基于 bpf/lib/mcast.h 的源码展开帮助理解上述配置最终作用于数据面的哪些环节。4.1 核心 BPF Map哈希套哈希结构多播状态由一个BPF_MAP_TYPE_HASH_OF_MAPS类型的外层 map 承载定义在 bpf/lib/mcast.h#L55-L70struct { __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); __type(key, mcast_group_v4); /* 32bit 大端组播组地址 */ __type(value, __u32); __uint(pinning, LIBBPF_PIN_BY_NAME); __uint(max_entries, MCAST_MAX_GROUP); /* 1024 */ __uint(map_flags, CONDITIONAL_PREALLOC); /* 内层该组的订阅者表 */ __array(values, struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(key_size, sizeof(__be32)); /* 订阅者 IPv4 地址 */ __uint(value_size, sizeof(struct mcast_subscriber_v4)); __uint(max_entries, MCAST_MAX_SUBSCRIBERS); /* 1024 */ __uint(map_flags, CONDITIONAL_PREALLOC); }); } cilium_mcast_group_outer_v4_map __section_maps_btf;即外层 map 以组播组地址为 key内层 map 以订阅者 IPv4 地址为 key。cilium-dbg bpf multicast group add就是创建外层条目同时创建内层 mapsubscriber add就是向内层 map 写入一条记录。容量上限为 1024 个组、每组 1024 个订阅者MCAST_MAX_GROUP/MCAST_MAX_SUBSCRIBERS。订阅者记录的结构体mcast_subscriber_v4bpf/lib/mcast.h#L32-L43包含saddr订阅者的 IPv4 源地址大端ifindex本地订阅者为接收接口索引远端订阅者带MCAST_SUB_F_REMOTE标志位见 bpf/lib/mcast.h#L21-L24则该字段为出接口索引配合saddr确定 VXLAN 隧道出口。4.2 IGMP 报文在内核态处理多播组并非只靠手工subscriber add维护——Cilium 数据面会直接解析 Pod 发出的 IGMP 报文并自动更新订阅表IGMPv3 成员关系报告mcast_ipv4_handle_v3_membership_reportbpf/lib/mcast.h#L125-L208以#pragma unroll展开的有界循环遍历报文中的 group records上限MCAST_MAX_GREC 24将CHANGE_TO_EXCLUDE视为“加入所有源”CHANGE_TO_INCLUDE视为“离开所有源”分别执行内层 map 的插入/删除IGMPv2 成员关系报告bpf/lib/mcast.h#L210-L241命中用户配置的多播组后直接把发送者加入订阅表离开报文mcast_ipv4_handle_igmp_leavebpf/lib/mcast.h#L243-L271从订阅表中移除该订阅者。处理完成后返回DROP_IGMP_SUBSCRIBED/DROP_IGMP_HANDLED表示 IGMP 报文已被数据面“消费”无需继续向上传递。这就是文档中“multicast subscriber pods can send out IGMP join”能够生效的机制——Pod 发出的 join 报文由 eBPF 直接翻译成订阅表项。4.3 报文复制与分发发送端 Pod 发出的组播报文由尾部调用tail call程序tail_mcast_ep_deliverybpf/lib/mcast.h#L397-L428完成复制分发用 IP 头的daddr查找cilium_mcast_group_outer_v4_map未命中则丢弃DROP_INVALID将二层目的 MAC 改写为组播组地址对应的 MAC——mcast_encode_ipv4_macbpf/lib/mcast.h#L310-L319按标准规则编码为01:00:0e:xx:xx:xx通过bpf_for_each_map_elem遍历该组的订阅者内层 map对每条订阅者记录调用回调__mcast_ep_deliverybpf/lib/mcast.h#L334-L390远端订阅者MCAST_SUB_F_REMOTE构造bpf_tunnel_key将sub-saddr填入remote_ipv4即目标节点的 CiliumInternalIP走ENCAP_IFINDEX出接口经 VXLAN 隧道发往远端节点。这也解释了为什么订阅者地址必须填节点的 CiliumInternalIP、且要求 vxlan 模式值得注意的是若当前程序运行在 overlay 路径IS_BPF_OVERLAY即远端节点已收到隧道包后本地分发则直接跳过远端投递避免环路——因为发送方节点已经负责向所有远端节点发了一份本地订阅者直接以sub-ifindex为目标接口执行clone_redirect把报文克隆投递到本地对应端点。最后通过send_drop_notify上报DROP_MULTICAST_HANDLED跟踪事件便于用cilium monitor/ Hubble 观测数据面行为。注以上为 IPv4 多播数据面的实现*_v4系列 map 与函数。仓库中的 pkg/multicast 包则是另一套工具函数提供 IPv6 组播地址的 join/leave/list基于 UDP socket 的ipv6.JoinGroup以及 solicited-node 组播地址ff02::1:ff00:0前缀、33:33:FF:xx:xx:xxMAC的构造主要服务于 NDP 等底层网络功能与本文讨论的应用层多播配置是不同层次。五、限制Limitations文档明确列出了两条使用限制实施前务必注意需要逐节点操作多播组/订阅者的配置需要在每一个使用多播的 CiliumNode 上执行或借助cilium multicast add --group-ip批量完成不兼容 IPsec该功能不支持 Cilium 管理的 Pod 之间的 IPsec 加密--enable-ipsec即开启 IPsec 加密后多播不可用两者不可同时启用。六、小结与相关文件索引步骤命令说明启用功能cilium config set multicast-enabled true更新 cilium-config 并重启 agent获取节点 IPkubectl get ciliumnodes.cilium.io读取 CILIUMINTERNALIP 列添加组cilium-dbg bpf multicast group add 组播IP在每个 cilium-agent 中执行添加订阅者cilium-dbg bpf multicast subscriber add 组播IP 节点IP订阅者须为其他节点 IP批量加入cilium multicast add --group-ip 组播IP全节点自动配置集群查询cilium multicast list subscriber --all查看各节点组与订阅者清理cilium-dbg bpf multicast group delete 组播IP在每个 cilium-agent 中执行关键源码与文档入口官方文档Documentation/network/multicast.rst配置项定义pkg/maps/multicast/mcast.gomulticast-enabled默认falseeBPF 数据面bpf/lib/mcast.hmap 定义、IGMP 处理、tail call 分发CLI 批量管理cilium-cli/multicast/multicast.go命令行参考cilium-dbg bpf multicast、cilium multicast需要再次强调适用前提该功能目前为Beta状态仅支持 vxlan 隧道模式要求内核 AMD64 5.10 / AArch64 6.0且不能与 IPsec 加密同时使用。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考