Cilium 与 Calico CNI 链式(Chaining)部署实战指南:eBPF 数据面叠加方案
2026/9/13 14:43:08 网站建设 项目流程

Cilium 与 Calico CNI 链式(Chaining)部署实战指南:eBPF 数据面叠加方案

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

导读

本指南讲解如何在已由 Calico 作为基础 CNI 的 Kubernetes 集群上,通过CNI Chaining(链式)配置叠加部署 Cilium:让 Calico 继续负责底层网络连通性与 IPAM,而由 Cilium 的 eBPF 程序附着在 Calico 创建的 veth 设备上,提供 L3/L4 网络可见性、安全策略执行与负载均衡等高级能力。读完本文,你将掌握如何编写链式 CNI 配置、以正确的 Helm 参数部署 Cilium,并通过cilium status与连通性测试验证整套链路是否工作正常,同时理解链式模式下各 CNI 插件在 ADD/DEL/CHECK 调用链中的协作机制。

什么是 CNI Chaining,为什么需要它

CNI chaining 允许 Cilium 与其他 CNI 插件在同一集群内协同工作。其核心分工模式是:

  • 基础 CNI 插件(本场景为 Calico)负责底层网络连通性与 IP 地址管理(IPAM),即它先创建容器网络命名空间、veth 设备并分配 IP;
  • Cilium作为链中的后续插件,不重新分配 IP 或重建网络设备,而是将 eBPF 程序附着到基础插件创建的网络设备上,以此提供 L3/L4 网络可见性、策略执行(Policy Enforcement)与其他高级特性。

在链式架构下,Cilium 的代理(Agent)依赖 Calico 已经完成的网络规划,自身则聚焦于数据路径上的 eBPF 逻辑。这种模式特别适合已经在生产环境使用 Calico、希望渐进式引入 Cilium 的 eBPF 能力(如策略与可观测性)而不必一次性迁移整个数据面的场景。

链式部署的已知限制

在与其他 CNI 插件链式使用时,Cilium 的部分高级特性会受到限制,官方文档明确列出:

  • Layer 7 策略(L7 Policy):HTTP/gRPC 等七层策略在链式模式下不可用;
  • IPSec 加密(encryption_ipsec:链式模式下无法启用基于 IPSec 的透明加密。

这些限制源于链式模式下 Cilium 不接管端点(Endpoint)的网络命名空间生命周期,且数据路径的编排方是基础插件。规划架构时需评估这两项能力是否属于硬性需求。

第一步:创建 CNI 链式配置(ConfigMap)

创建一个chaining.yaml文件,内容基于以下模板。该 ConfigMap 会被 Cilium 代理读取,用于生成/etc/cni/net.d/下的 CNI 链式配置:

apiVersion: v1 kind: ConfigMap metadata: name: cni-configuration namespace: kube-system data: cni-config: |- { "name": "generic-veth", "cniVersion": "0.3.1", "plugins": [ { "type": "calico", "log_level": "info", "datastore_type": "kubernetes", "mtu": 1440, "ipam": { "type": "calico-ipam" }, "policy": { "type": "k8s" }, "kubernetes": { "kubeconfig": "/etc/cni/net.d/calico-kubeconfig" } }, { "type": "portmap", "snat": true, "capabilities": {"portMappings": true} }, { "type": "cilium-cni" } ] }

对这份配置的逐段解读:

配置段作用关键字段
"name": "generic-veth"链式配置名。该名字与 Helm 的cni.chainingMode=generic-veth对应,是 Cilium 识别链式模式的依据name
"cniVersion": "0.3.1"CNI 规范版本,决定插件间传递PrevResult的格式cniVersion
第一个插件calico基础 CNI:负责建网与 IPAMtypeipam.type=calico-ipampolicy.type=k8skubernetes.kubeconfig
第二个插件portmap端口映射(HostPort 支持),snat: true启用 SNAT,通过capabilities声明对portMappings的支持typesnatcapabilities
第三个插件cilium-cniCilium 链式接入点,作为链的最后一环读取上游PrevResult并挂载 eBPFtype

说明mtu: 1440是模板中的默认取值,实际部署时应根据底层网络(如 VXLAN、云厂商 overlay 网络)的 MTU 情况调整,避免因分片影响吞吐。

应用该配置:

kubectl apply -f chaining.yaml

从源码实现看,cilium-cni在链式模式下会解析这份 JSON。在 plugins/cilium-cni/types/types.go 中,NetConfList结构体持有整个plugins数组,ReadNetConf会读取配置文件并调用LoadNetConf反序列化为 Cilium 可识别的网络配置结构,为后续判断是否进入链式模式做准备。

第二步:通过 Helm 部署 Cilium

首先配置 Helm 仓库。Cilium 官方 chart 可以通过 Helm 仓库或 OCI Registry 获取:

helm repo add cilium https://helm.cilium.io/

也可以使用 OCI 方式直接安装:helm install cilium cilium/cilium --version <VERSION> --namespace kube-system,OCI Registry(Quay.io 与 Docker Hub)无需额外配置。

接着使用以下参数部署 Cilium 到kube-system命名空间:

helm install cilium cilium/cilium --namespace kube-system \ --set cni.chainingMode=generic-veth \ --set cni.customConf=true \ --set cni.configMap=cni-configuration \ --set routingMode=native \ --set enableIPv4Masquerade=false \ --set enableIdentityMark=false

各参数的语义与配置要点:

Helm 参数含义为什么这样设置
cni.chainingMode=generic-veth启用 CNI 链式模式,模式名为generic-veth告诉 Cilium 它是链中的一环,且基础设备类型为通用 veth(与 ConfigMap 的name一致)
cni.customConf=true使用用户自定义的 CNI 配置让 Cilium 代理不去覆盖你手动提供的cni-configurationConfigMap
cni.configMap=cni-configuration指定承载链式 CNI 配置的 ConfigMap 名称指向第一步创建的chaining.yaml
routingMode=native路由模式设为原生(非隧道)模式与 Calico 的 underlay/直连路由架构匹配,避免再次封装
enableIPv4Masquerade=false关闭 Cilium 的 IPv4 地址伪装(Masquerade)伪装职责已由 Calico 数据面承担,避免双重 SNAT
enableIdentityMark=false关闭 Cilium 在数据包上打安全身份标记(Identity Mark)链式模式下由 Calico 处理转发路径,Cilium 不参与 mark 的消费

关于已有 Pod 的重要注意事项

链式配置不会自动应用到集群中已存在的 Pod。具体表现为:

  • 已存在的 Pod 依然可达,Cilium 可以对其做负载均衡(即新流量能被正确转发到这些 Pod);
  • 但策略执行(Policy Enforcement)不会作用于这些存量 Pod;
  • 从存量 Pod 发起的流量也不会经过 Cilium 的负载均衡。

因此,必须重启这些存量 Pod,让 kubelet 在重建容器时重新执行 CNI ADD 调用链,新的链式配置才会生效。常见的做法是对相关 Deployment/DaemonSet 做滚动重启(如kubectl rollout restart)。

第三步:验证安装

方式一:使用 Cilium CLI

先安装最新版 Cilium CLI(Linux 示例):

CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt) CLI_ARCH=amd64 if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum} sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}

检查 Cilium 各组件状态:

$ cilium status --wait /¯¯\ /¯¯\__/¯¯\ Cilium: OK \__/¯¯\__/ Operator: OK /¯¯\__/¯¯\ Hubble: disabled \__/¯¯\__/ ClusterMesh: disabled \__/ DaemonSet cilium Desired: 2, Ready: 2/2, Available: 2/2 Deployment cilium-operator Desired: 2, Ready: 2/2, Available: 2/2 Containers: cilium-operator Running: 2 cilium Running: 2 Image versions cilium quay.io/cilium/cilium:v1.9.5: 2 cilium-operator quay.io/cilium/operator-generic:v1.9.5: 2

运行完整的网络连通性测试:

$ cilium connectivity test ℹ️ Monitor aggregation detected, will skip some flow validation steps ✨ [k8s-cluster] Creating namespace for connectivity check... (...) --------------------------------------------------------------------------------------------------------------------- 📋 Test Report --------------------------------------------------------------------------------------------------------------------- ✅ 69/69 tests successful (0 warnings)

若连通性测试 Pod 因 "too many open files" 部署失败,可尝试提高宿主机的 inotify 资源限制后重试。

方式二:手动使用 kubectl

观察 Cilium 相关组件的启动过程:

$ kubectl -n kube-system get pods --watch NAME READY STATUS RESTARTS AGE cilium-operator-cb4578bc5-q52qk 0/1 Pending 0 8s cilium-s8w5m 0/1 PodInitializing 0 7s coredns-86c58d9df4-4g7dd 0/1 ContainerCreating 0 8m57s coredns-86c58d9df4-4l6b2 0/1 ContainerCreating 0 8m57s

等待数分钟后全部组件应进入Running状态。接着部署官方的 connectivity-check 测试套件(建议使用独立命名空间):

kubectl create ns cilium-test kubectl apply -n cilium-test -f examples/kubernetes/connectivity-check/connectivity-check.yaml

该套件会部署一系列 Deployment,覆盖多种连通性路径:有无 Service 负载均衡、多种网络策略组合等。Pod 名称标明其测试的连通性变体,其就绪(readiness)与存活(liveness)探针即代表测试成败:

$ kubectl get pods -n cilium-test NAME READY STATUS RESTARTS AGE echo-a-76c5d9bd76-q8d99 1/1 Running 0 66s echo-b-795c4b4f76-9wrrx 1/1 Running 0 66s echo-b-host-6b7fc94b7c-xtsff 1/1 Running 0 66s host-to-b-multi-node-clusterip-85476cd779-bpg4b 1/1 Running 0 66s pod-to-a-allowed-cnp-58b7f7fb8f-lkq7p 1/1 Running 0 66s pod-to-a-denied-cnp-6967cb6f7f-7h9fn 1/1 Running 0 66s ...

单节点集群上,检查多节点功能的 Pod 会一直处于Pending状态,这是预期行为(它们需要至少 2 个节点才能被调度)。

测试完成后清理命名空间:

kubectl delete ns cilium-test

源码视角:cilium-cni 如何识别并执行链式模式

理解链式配置的生效机制,需要回到cilium-cni插件的实现。在 plugins/cilium-cni/cmd/cmd.go 中,插件对 CNI ADD/DEL/CHECK 请求的处理逻辑清晰体现了链式设计的三个关键判断:

1. 通过PrevResult判断是否为链式调用。CNI 规范规定,链中的后续插件会收到前序插件(此处为 calico、portmap)产出的PrevResult。源码在 ADD 路径上会检查n.NetConf.RawPrevResult是否非空,若非空则说明本插件处于链式上下文中,进而构建chainingapi.PluginContext并委派给对应的链式实现;若没有配置链式模式却收到了PrevResult,会直接报错提示 "CNI PrevResult supplied, but not in chaining mode -- this is invalid, please set chaining-mode in CNI configuration"。

2. 依据ChainingMode查找链式插件。函数getChainedAction(plugins/cilium-cni/cmd/cmd.go#L1332)会通过chainingapi.Lookup(n.ChainingMode)按模式名查找已注册的链式实现,未知模式会返回 "invalid chaining-mode" 错误;DEL 与 CHECK 路径的处理逻辑与此对称,且注释特别说明 "DEL always has PrevResult set"(删除操作总是携带PrevResult),因此不能仅凭PrevResult判断是否链式。

3.generic-veth链式实现的实际动作。注册名为generic-veth的链式插件位于 plugins/cilium-cni/chaining/generic-veth/generic-veth.go,其Add方法先解析PrevResult获取前序插件(Calico)创建的网络结果,再打开容器网络命名空间(netns.OpenPinned),在命名空间内遍历网络链路,找到类型为veth的接口——这正是 Calico 已创建好的容器侧 veth——Cilium 随即基于该 veth 建立 Endpoint 模型并挂载 eBPF 程序,而不会重新配置 IP 或新建虚拟设备。这也从实现层面印证了"基础 CNI 负责连通性与 IPAM、Cilium 叠加 eBPF 能力"的分工。

与之对应,Agent 侧通过--cni-chaining-modeCNIChainingMode,见 pkg/option/config.go#L465-L466)接收链式模式配置,数据路径相关代码(如 iptables 处理)也会针对特定链式模式(如aws-cni)走不同的逻辑分支,说明链式模式是一个贯穿 CNI 插件与 Agent 数据面的全局配置。

常见问题排查

  • 存量 Pod 无策略保护:这是链式模式的预期行为,需重启 Pod 使新配置生效。
  • 双重 SNAT 导致连通性异常:检查是否设置了enableIPv4Masquerade=false;若同时开启 Cilium 与 Calico 的伪装功能,可能出现源地址被改写两次的问题。
  • invalid chaining-mode报错:确认 Helm 参数cni.chainingMode与 ConfigMap 中"name"字段一致,且 Agent 能读取到自定义 ConfigMap(cni.customConf=truecni.configMap必须同时正确设置)。
  • L7 策略 / IPSec 无法生效:链式模式的固有限制,需回归本指南开头列出的能力边界,重新评估方案选型。

后续可以做什么

验证通过后,可以基于这套链式部署进一步探索:

  • 部署 Hubble 以启用可观测性与 Service Map(参考仓库 Documentation/installation 下的 Hubble 相关指南);
  • 配置 ClusterMesh 实现多集群网络与策略互联;
  • 通过示例策略文件(examples/policies)验证链式模式下 L3/L4 策略的执行效果,确认策略 Enforcement 在新创建的 Pod 上按预期工作。

需要注意的是,链式模式中的 L7 策略与 IPSec 加密受限,若后续需要这些能力,应评估切换到 Cilium 独立接管数据面的部署形态。

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

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

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

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

立即咨询