calico 可以使用 cilium 作为 secondary cni 么?

73 阅读14分钟

非常好的问题——这是在 CNI 迁移或多网络(Multus)部署 场景下经常被问到的。
我们来深入分析一下:


🧩 问题核心

“Calico 可以使用 Cilium 作为 secondary CNI 吗?”

理论上可以通过 Multus 或自定义 CNI chaining 实现,但在 实际生产环境中极不推荐,除非你非常清楚 CNI 插件链路的原理与约束。
原因在于 Calico 与 Cilium 都是 完整的 L3 网络堆栈 + Policy Engine + BPF dataplane,而不是简单的 “插件式 CNI” —— 它们都期望对 Pod 的主网络命名空间拥有完全控制权。


🚧 一般架构对比

项目CalicoCilium
网络模式IPIP / VXLAN / BGPGeneve / VXLAN / Direct-Routing / BGP
控制层Felix + TyphaCilium Agent + BPF Maps
数据平面iptables / eBPF全 eBPF
Policy 实现iptables / eBPFeBPF
Service 实现kube-proxy 或 eBPF kube-proxy-replacement自带 kube-proxy-replacement

这意味着:

  • 它们都要管理 Pod veth pair / route / policy / conntrack / service NAT
  • Secondary CNI 无法“简单插进去”而不冲突。

⚠️ 如果强行用作 secondary,会出现的问题

假设你通过 Multus 或 CNI chaining,让 Calico 做 primary(主网络接口 eth0),Cilium 做 secondary(例如 net1):

1️⃣ IP 分配冲突

  • Calico 与 Cilium 各自有 IPAM(IP Address Management),默认都管理 PodCIDR。
  • 如果不严格隔离(不同 subnet / 不同 CIDR),可能会分配重复 IP,造成 ARP 混乱。

2️⃣ 路由冲突

  • 两者都在容器命名空间内配置默认路由。
  • 结果是默认路由被覆盖,Pod 出站路径混乱。
  • 同时 Host 上的 veth 接口路由表也可能被两个 CNI 修改。

3️⃣ Policy 冲突

  • Cilium 会在内核 BPF Hook 点(TC / XDP)挂载过滤逻辑;
  • Calico 若启用 eBPF 模式,也会在相同点挂载;
  • 两者 hook 同一个接口时,TC ingress/egress chain 会竞争,后加载的会覆盖前者。

4️⃣ kube-proxy / Service NAT 冲突

  • 如果两个都启用 kube-proxy replacement,会双重 NAT;
  • 或者如果一个使用 kube-proxy,一个不用,也可能出现流量被错误拦截。

5️⃣ Multus 插件顺序问题

  • Multus 会将 primary CNI 的网络命名空间设置为主接口;
  • Secondary 的添加通常不修改默认路由;
  • 导致 secondary 网络(Cilium)不能直接访问 kube-dns、Service、或跨节点 Pod。

✅ 如果你真的需要二者共存,有两种合理方式:

✅ 方案 A:Calico primary + Cilium secondary (strictly isolated network)

要求:

  • 每个 CNI 使用独立 CIDR,例如:

    Calico PodCIDR: 10.244.0.0/16
    Cilium PodCIDR: 10.245.0.0/16
    
  • 禁用 Cilium kubeProxyReplacement 和 Policy enforcement;

  • 仅将 Cilium 用作 “数据平面实验网络”,比如 SRv6、Geneve overlay、或 service mesh。

用途:

  • 测试、观测用,不推荐生产。

✅ 方案 B:逐步迁移:CNI migration(Calico → Cilium)

官方推荐的方式:

  1. 安装 Cilium(但不接管现有 Pod);
  2. 使用 cilium-cli 提供的 “CNI migration tool”;
  3. 滚动替换节点;
  4. 删除 Calico。

这个是 安全迁移路径,不会造成 CNI 冲突。


🧠 总结

场景可行性风险建议
Multus: Calico + Cilium❌ 理论可行,实践极不推荐仅限实验环境
Calico → Cilium 迁移✅ 官方支持推荐生产
Calico primary, Cilium for special net⚠️ 可行但复杂限制用途(例如自定义 overlay)

如果你能告诉我你希望 Cilium secondary 的目的(例如:增强网络性能、实验 eBPF、特定 Pod 用新网络等),我可以帮你设计一个更稳定、安全的组合方案。
是否要我帮你画一个 Calico + Cilium 混合网络拓扑图来说明冲突点?

方案 B:逐步迁移:CNI migration(Calico → Cilium) 官方推荐的方式: 安装 Cilium(但不接管现有 Pod);

下面我整理了一个较为 详细但通用 的流程,介绍如何将 Calico 迁移到 Cilium(即 方案 B:逐步迁移),并在过程中尽可能 避免中断。在具体操作前,你还需要结合自身集群环境(Pod CIDR 、路由、网络策略、是否使用 BGP、是否有宿主机端口 HostPort 工作负载、是否是裸金属/云环境等)做适当调整。


🧰 准备阶段

在迁移开始之前,需要做好扎实的准备工作,以降低风险。主要包括以下几个方面:

  1. 确认当前环境状态

    • 检查当前 Calico 所使用的 Pod CIDR 范围、Overlay/Underlay 模式、是否开启 BGP、是否使用 IPIP/VXLAN 等。参见官方文档:迁移指南第一步即“检查现有集群”。(isovalent.com)
    • 检查网络策略 (NetworkPolicy) 使用情况:是否大量依赖 Calico 自定义 CRD(如 GlobalNetworkPolicy)或 Calico 特有功能。因为迁移后可能需要将这些策略转为 Cilium 可识别形式。(Reddit)
    • 确认节点、Pod、Service 运行状态稳定,且业务有可回滚方案。
  2. 规划新的 Cilium 配置

    • 为 Cilium 指定一个新的、与 Calico 不重叠的 Pod 池 (Pod CIDR) 。例如如果 Calico 用的是 10.244.0.0/16,那么 Cilium 可用 10.245.0.0/16。这样做是为了让旧 CNI 与新 CNI 共存期间,IP 路由能清晰区分。(Medium)

    • 配置 Cilium 使用 dual-overlay / 混合模式(即使 Calico 仍然运行期间,Cilium 也被部署,但暂时不作为 primary CNI)。“迁移”模式关键参数包括:

      • ipam.mode: cluster-pool 并配置 clusterPoolIPv4PodCIDRList 为上面规划的新 CIDR。(Cilium 文档)
      • cni.customConf: true(或者类似设置,确保 Cilium 不马上接管 /etc/cni/net.d),让 Calico 仍作为 primary。(Samsung Ads)
      • bpf.hostLegacyRouting: true(允许 Cilium 节点能够路由到旧 Calico 管理的 Pod 网络)(Medium)
      • 可能还需为 Cilium Overlay 设置 不同的隧道端口/协议(如 VXLAN 或 Geneve 的不同 UDP 端口),以避免与 Calico 的隧道冲突。(DEV Community)
    • 在写好这些值后,准备部署 Cilium(但暂不替换 Calico)。

  3. 部署 Cilium(但暂时为辅助状态)

    • 首先在集群安装 cilium-cli 工具,用于后续状态检查、迁移辅助操作。(Samsung Ads)
    • 使用 Helm 或 manifest 安装 Cilium,使用上文中准备的 “迁移模式” 配置。此时 Calico 仍在正常运行,Pod 仍由 Calico 管理。Cilium 处于被动状态。(Cilium 文档)
    • 验证 Cilium 是否部署成功(如 cilium status、节点上 Cilium DaemonSet 是否 Ready);同时验证与现有 Calico 网络兼容性(例如新 Pod 是否能正常部署,但因为仍使用 Calico,所以要确认 Cilium 不干扰现有流量)。
  4. 验证新的 Pod 网络可达性/路由

    • 在这一阶段,你需要验证 Cilium 所负责的新 Pod CIDR 网络与旧 Calico 网络之间的互通。也就是:旧 Pod (Calico 管理)能否访问新 Pod (Cilium 网络)/新 Pod 能否访问旧 Pod。若不能,需要检查路由、主机路由表、节点配置。迁移文档中提到这一步非常关键。(Samsung Ads)
    • 使用像 kubectl exec, ping, cilium connectivity test(或类似工具)来确认网络连通性。

🔄 节点逐一迁移阶段

在准备阶段完成后,就进入真正的 “逐节点切换” 阶段。核心思路是:节点滚动迁移,保持集群整体可用,每次切换少量节点/少量 Pod,从而降低风险。

  1. 选择一个节点迁移

    • 标记一个节点为切换目标。例如将该节点 cordon(禁止新 Pod 调度)并 drain(迁出 Pod)。
    • 在这个节点上,将其配置从 Calico 迁移为 Cilium 管理。具体操作包括:移除 Calico DaemonSet 或在该节点上停止 Calico 网络组件;并让 Cilium 成为该节点的 primary CNI。
    • 在迁移过程中,该节点上运行的 Pod 可能要重新调度或重建,使其获得新的 Pod IP(新 CIDR)由 Cilium 分配。
  2. 更新该节点的 CNI 配置

    • 更改 /etc/cni/net.d/ 配置,将默认 CNI 指向 Cilium(或更改 node-selector 让 Cilium 接管)。
    • 确保该节点上 Pod 分配的 IP now 来自 Cilium 的新 CIDR。
    • 验证该节点上所有新部署的 Pod 是通过 Cilium 网络,并且依然能与尚未迁移节点的 Pod(仍由 Calico 管理)通信。
  3. 重复迁移其他节点

    • 每次迁移完成一个节点就移开一个节点,验证网络和服务状态正常后,再迁移下一个节点。
    • 在大量节点/Pod 的集群中,建议分批次迁移(例如每次 10–20% 节点)以降低风险。
  4. 确认所有节点迁移完成

    • 全部节点都迁移到 Cilium 管理后,节点上旧 Calico 组件基本空闲,只剩下旧 Pod 网络(如果还没被重新调度)可能还在旧 CIDR。
    • 此时可以关闭 Calico 的 IPAM、路由、Policy enforcement 等功能。

🧹 清理与切换为完全 Cilium 模式

当所有节点都迁移并验证无误后,就进入清理旧 CNI 并让 Cilium 成为唯一的 CNI 管理网络阶段。

  1. 切换为 Cilium 为 primary CNI

    • 修改集群中 CNI 配置,使所有节点默认使用 Cilium。
    • 确保 /etc/cni/net.d 中只剩下 Cilium 的 .conf/.conflist 文件。
    • 更新 Cilium 配置,将 policyEnforcementMode 从 “never” 或暂时关闭状态变为 “default” 或 “always”,开启 Cilium NetworkPolicy 生效。(Medium)
    • 如果你还启用了 kube-proxy replacement (Cilium 支持)或其他高级功能,可视情况开启。文档中提到在迁移完成后可启用这些特性。(cilium.io)
  2. 删除 / 收回 Calico 相关资源

    • 删除 Calico DaemonSets、Deployments、CRDs(如 GlobalNetworkPolicy、NetworkPolicy 等旧格式)以及旧的 routing 和 IPAM 组件。 (Samsung Ads)
    • 移除旧 Pod 网络池(旧 CIDR)从安全/网络文档中,并清理主机上的旧路由、ip tables 规则等。文中提到在迁移过程后期需清理 iptables 的 Calico 规则。(Samsung Ads)
    • 如果原有 Calico 网络策略需要迁移至 Cilium,确认所有已有策略在 Cilium 中生效。
  3. 验证与监控

    • 执行全量连通性测试:Pod ↔ Pod 跨节点、Pod ↔ Service ↔ 外部。使用像 cilium connectivity test 或 Goldpinger 等工具。(Samsung Ads)
    • 验证网络策略生效、业务日志正常、无异常延迟或错误。
    • 监控节点负载、网络带宽/延迟是否出现异常。Cilium 的 Hubble 可用于可视化网络流量。(cilium.io)
  4. 关闭迁移模式标记

    • 如果之前为迁移设定了标签、特定配置(例如 cni.customConf=true, bpf.hostLegacyRouting=true),根据需求可以将其恢复至生产模式。
    • 减少遗留配置复杂度,确保集群网络配置简洁。

🧭 风险点 & 注意事项

虽然上述流程能最大程度降低中断风险,但在实践中仍需注意以下常见问题:

  • IP CIDR 冲突:如果新 CIDR 与旧网络重叠,会导致路由混乱。必须保证不重叠。

  • 跨 CNI 通信失败:在迁移期间,旧管理 Pod 与新管理 Pod 必须能互相通信,否则可能出现服务孤岛。这个是很多实践中的坑。(Samsung Ads)

  • 网络策略行为差异:Calico 与 Cilium 在网络策略语义、实现方式、基于 eBPF 或 iptables 的 enforcement 上可能有差别。迁移前需验证策略在 Cilium 上行为一致。来自 Reddit 的反馈:

    “I am in the process of migrating from Calico to Cilium … things don't seem to work like I think they work.” (Reddit)

  • 宿主机端口 (HostPort)、宿主网络 (HostNetwork)、Service Type=LoadBalancer 等特殊场景:如果你的应用使用了这些,需要确认 Cilium 对应功能开启(如 hostPort、hostServices)并且已验证。(Samsung Ads)

  • 回滚准备:虽然流程设计为滚动迁移,但仍建议在每步前有回滚路径(例如,如果节点切换后出现严重问题,可以把节点恢复为使用 Calico)。

  • 集群规模与资源:在大规模集群(数百节点、数万 Pod)中,迁移耗时、网络状态复杂度更高。实践中,有案例提到泸兼多个节点迁移流程并监控了数小时以上。(Samsung Ads)

  • 升级版本兼容性:建议使用 Cilium 官方支持的版本,并确认与你的 Kubernetes、Calico 版本兼容。官方文档也给出版本建议。(Cilium 文档)


📋 总结流程一览

  1. 确认当前 Calico 网络配置、Pod CIDR、网络策略、环境状态。
  2. 规划 Cilium 的 Pod CIDR、隧道协议、迁移模式参数。
  3. 安装 cilium-cli 与 Cilium (迁移模式,暂不接管 Pod )。
  4. 验证网络互通(旧 Pod ↔新 Pod )。
  5. 节点逐一滚动迁移:cordon → drain →切换节点到 Cilium→恢复。
  6. 所有节点迁移完成后,切换 Cilium 为唯一 CNI,开启 NetworkPolicy 等功能。
  7. 删除 Calico 相关资源,清理旧网络配置。
  8. 全面验证连通性、策略、性能;监控业务指标。
  9. 关闭迁移标识/配置,完成最终清理。

如果你愿意,我可以帮你 生成一个可执行的迁移清单(checklist + kubectl / helm 命令示例) ,并结合你的集群信息(如 K8s 版本、Calico 版本、是否使用 BGP 等)做 定制化建议。你看要不要?

太好了 👍 我来帮你生成一个 可执行的 CNI 迁移清单(Calico → Cilium)
这个清单遵循 官方推荐的安全迁移流程,并结合社区实践(如 Isovalent、DB Schenker、Samsung Ads 等案例)。


🧭 Calico → Cilium 迁移执行清单

🧩 前提假设

  • Kubernetes ≥ 1.24
  • Calico 当前运行模式:IPIP 或 VXLAN(非 BGP 模式也适用)
  • 计划使用 Cilium 1.18 或更高版本
  • 使用 Helm + cilium-cli
  • 集群暂时允许双 CNI 并存(过渡期)

✅ 阶段 1:准备阶段

1.1 确认现状

# 查看节点 PodCIDR
kubectl get nodes -o wide

# 查看 Calico 配置与 CIDR
kubectl get ippools.crd.projectcalico.org -A

# 检查 Calico 网络策略
kubectl get networkpolicies,globalnetworkpolicies -A

# 检查 CNI 配置文件
cat /etc/cni/net.d/*.conf

📋 记录结果,特别是:

  • Calico PodCIDR(例如 10.244.0.0/16)
  • Calico 隧道模式(IPIP/VXLAN)
  • kube-proxy 是否启用

1.2 规划 Cilium 配置

定义一个与 Calico 不重叠的 PodCIDR (例如 10.245.0.0/16):

NEW_POD_CIDR="10.245.0.0/16"

1.3 准备工具

# 安装 cilium CLI
curl -L --remote-name https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz
tar xzvf cilium-linux-amd64.tar.gz
sudo mv cilium /usr/local/bin/

# 验证
cilium version

🚀 阶段 2:部署 Cilium (迁移模式)

2.1 创建 Helm values 文件

cilium-migration-values.yaml

# 基础配置
kubeProxyReplacement: "disabled"
routingMode: tunnel
tunnelProtocol: geneve
ipam:
  mode: cluster-pool
  operator:
    clusterPoolIPv4PodCIDRList: ["10.245.0.0/16"]
    clusterPoolIPv4MaskSize: 24

# 兼容模式
bpf:
  hostLegacyRouting: true
cni:
  customConf: true        # 不接管 /etc/cni/net.d
  exclusive: false

# 暂时关闭策略强制
policyEnforcementMode: never

# 关闭 Hubble/UI
hubble:
  enabled: false

2.2 安装 Cilium(不替换现有 CNI)

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

helm install cilium cilium/cilium \
  --version 1.18.2 \
  --namespace kube-system \
  -f cilium-migration-values.yaml

2.3 验证部署

kubectl -n kube-system get pods -l k8s-app=cilium
cilium status --namespace kube-system

✅ 预期结果:所有 Cilium Pod Running ,但旧 Pod 仍使用 Calico 网络。


🔄 阶段 3:滚动节点迁移

3.1 选定节点

kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
kubectl cordon <node-name>

3.2 让节点切换到 Cilium CNI

在该节点:

sudo mv /etc/cni/net.d /etc/cni/net.d.bak
sudo mkdir -p /etc/cni/net.d
sudo cp /var/lib/cilium/cni/net.d/05-cilium.conf /etc/cni/net.d/

或者:

kubectl label node <node-name> cilium.io/no-schedule=false

重新允许 Pod 调度:

kubectl uncordon <node-name>

3.3 验证 Pod IP 与连通性

# 检查新建 Pod 的 IP 来源
kubectl get pods -o wide -n <namespace>

# 连通性测试
cilium connectivity test

✅ 验证:

  • 新 Pod 获得 10.245.x.x IP;
  • 能访问旧 Pod(Calico);
  • Service 解析与 DNS 正常。

3.4 重复其他节点

依次执行:

kubectl drain nodeX ...
kubectl uncordon nodeX

直到全部节点迁移完成。


🧹 阶段 4:切换为单 Cilium 模式

4.1 启用 Cilium NetworkPolicy 和 kube-proxy 替代

helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --set kubeProxyReplacement=true \
  --set policyEnforcementMode=default \
  --set cni.exclusive=true

4.2 删除 Calico 组件

kubectl delete -n kube-system daemonset calico-node
kubectl delete -n kube-system deployment calico-kube-controllers
kubectl delete crd bgppeers.crd.projectcalico.org bgpconfigurations.crd.projectcalico.org ippools.crd.projectcalico.org

4.3 清理旧网络残留

# 删除旧 CNI 文件
sudo rm -rf /etc/cni/net.d/calico*

# 清理路由与残留 veth
sudo ip link del <calico-interface> || true
sudo ip route flush table main

4.4 最终验证

cilium status
cilium connectivity test
kubectl get pods -A -o wide

✅ 所有 Pod IP 来自新 CIDR ;
✅ 跨节点访问、Service、DNS 正常;
✅ 网络策略可生效。


📊 阶段 5:可选增强

功能说明启用命令
Hubble 可视化流量观测helm upgrade cilium cilium/cilium --reuse-values --set hubble.enabled=true
kube-proxy 替代内建 service LB--set kubeProxyReplacement=true
BGP 模式替代 Calico BGP--set bgpControlPlane.enabled=true

🧠 总结

阶段目标状态
1. 准备记录 Calico 配置
2. 安装 Cilium迁移模式
3. 滚动节点迁移Calico→Cilium
4. 清理 Calico单 CNI 运行
5. 增强 & 验证Hubble、BGP 等

是否希望我帮你根据你当前集群(Calico 模式、Pod CIDR、k8s 版本)生成一份 具体命令模板文件(例如 migration-plan.yaml + shell 脚本)?
那样你可以直接照着执行。