非常好的问题——这是在 CNI 迁移或多网络(Multus)部署 场景下经常被问到的。
我们来深入分析一下:
🧩 问题核心
“Calico 可以使用 Cilium 作为 secondary CNI 吗?”
理论上可以通过 Multus 或自定义 CNI chaining 实现,但在 实际生产环境中极不推荐,除非你非常清楚 CNI 插件链路的原理与约束。
原因在于 Calico 与 Cilium 都是 完整的 L3 网络堆栈 + Policy Engine + BPF dataplane,而不是简单的 “插件式 CNI” —— 它们都期望对 Pod 的主网络命名空间拥有完全控制权。
🚧 一般架构对比
| 项目 | Calico | Cilium |
|---|---|---|
| 网络模式 | IPIP / VXLAN / BGP | Geneve / VXLAN / Direct-Routing / BGP |
| 控制层 | Felix + Typha | Cilium Agent + BPF Maps |
| 数据平面 | iptables / eBPF | 全 eBPF |
| Policy 实现 | iptables / eBPF | eBPF |
| 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)
官方推荐的方式:
- 安装 Cilium(但不接管现有 Pod);
- 使用
cilium-cli提供的 “CNI migration tool”; - 滚动替换节点;
- 删除 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 工作负载、是否是裸金属/云环境等)做适当调整。
🧰 准备阶段
在迁移开始之前,需要做好扎实的准备工作,以降低风险。主要包括以下几个方面:
-
确认当前环境状态
- 检查当前 Calico 所使用的 Pod CIDR 范围、Overlay/Underlay 模式、是否开启 BGP、是否使用 IPIP/VXLAN 等。参见官方文档:迁移指南第一步即“检查现有集群”。(isovalent.com)
- 检查网络策略 (NetworkPolicy) 使用情况:是否大量依赖 Calico 自定义 CRD(如 GlobalNetworkPolicy)或 Calico 特有功能。因为迁移后可能需要将这些策略转为 Cilium 可识别形式。(Reddit)
- 确认节点、Pod、Service 运行状态稳定,且业务有可回滚方案。
-
规划新的 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)。
-
-
部署 Cilium(但暂时为辅助状态)
- 首先在集群安装 cilium-cli 工具,用于后续状态检查、迁移辅助操作。(Samsung Ads)
- 使用 Helm 或 manifest 安装 Cilium,使用上文中准备的 “迁移模式” 配置。此时 Calico 仍在正常运行,Pod 仍由 Calico 管理。Cilium 处于被动状态。(Cilium 文档)
- 验证 Cilium 是否部署成功(如
cilium status、节点上 Cilium DaemonSet 是否 Ready);同时验证与现有 Calico 网络兼容性(例如新 Pod 是否能正常部署,但因为仍使用 Calico,所以要确认 Cilium 不干扰现有流量)。
-
验证新的 Pod 网络可达性/路由
- 在这一阶段,你需要验证 Cilium 所负责的新 Pod CIDR 网络与旧 Calico 网络之间的互通。也就是:旧 Pod (Calico 管理)能否访问新 Pod (Cilium 网络)/新 Pod 能否访问旧 Pod。若不能,需要检查路由、主机路由表、节点配置。迁移文档中提到这一步非常关键。(Samsung Ads)
- 使用像
kubectl exec, ping,cilium connectivity test(或类似工具)来确认网络连通性。
🔄 节点逐一迁移阶段
在准备阶段完成后,就进入真正的 “逐节点切换” 阶段。核心思路是:节点滚动迁移,保持集群整体可用,每次切换少量节点/少量 Pod,从而降低风险。
-
选择一个节点迁移
- 标记一个节点为切换目标。例如将该节点 cordon(禁止新 Pod 调度)并 drain(迁出 Pod)。
- 在这个节点上,将其配置从 Calico 迁移为 Cilium 管理。具体操作包括:移除 Calico DaemonSet 或在该节点上停止 Calico 网络组件;并让 Cilium 成为该节点的 primary CNI。
- 在迁移过程中,该节点上运行的 Pod 可能要重新调度或重建,使其获得新的 Pod IP(新 CIDR)由 Cilium 分配。
-
更新该节点的 CNI 配置
- 更改
/etc/cni/net.d/配置,将默认 CNI 指向 Cilium(或更改 node-selector 让 Cilium 接管)。 - 确保该节点上 Pod 分配的 IP now 来自 Cilium 的新 CIDR。
- 验证该节点上所有新部署的 Pod 是通过 Cilium 网络,并且依然能与尚未迁移节点的 Pod(仍由 Calico 管理)通信。
- 更改
-
重复迁移其他节点
- 每次迁移完成一个节点就移开一个节点,验证网络和服务状态正常后,再迁移下一个节点。
- 在大量节点/Pod 的集群中,建议分批次迁移(例如每次 10–20% 节点)以降低风险。
-
确认所有节点迁移完成
- 全部节点都迁移到 Cilium 管理后,节点上旧 Calico 组件基本空闲,只剩下旧 Pod 网络(如果还没被重新调度)可能还在旧 CIDR。
- 此时可以关闭 Calico 的 IPAM、路由、Policy enforcement 等功能。
🧹 清理与切换为完全 Cilium 模式
当所有节点都迁移并验证无误后,就进入清理旧 CNI 并让 Cilium 成为唯一的 CNI 管理网络阶段。
-
切换为 Cilium 为 primary CNI
-
删除 / 收回 Calico 相关资源
- 删除 Calico DaemonSets、Deployments、CRDs(如 GlobalNetworkPolicy、NetworkPolicy 等旧格式)以及旧的 routing 和 IPAM 组件。 (Samsung Ads)
- 移除旧 Pod 网络池(旧 CIDR)从安全/网络文档中,并清理主机上的旧路由、ip tables 规则等。文中提到在迁移过程后期需清理 iptables 的 Calico 规则。(Samsung Ads)
- 如果原有 Calico 网络策略需要迁移至 Cilium,确认所有已有策略在 Cilium 中生效。
-
验证与监控
- 执行全量连通性测试:Pod ↔ Pod 跨节点、Pod ↔ Service ↔ 外部。使用像
cilium connectivity test或 Goldpinger 等工具。(Samsung Ads) - 验证网络策略生效、业务日志正常、无异常延迟或错误。
- 监控节点负载、网络带宽/延迟是否出现异常。Cilium 的 Hubble 可用于可视化网络流量。(cilium.io)
- 执行全量连通性测试:Pod ↔ Pod 跨节点、Pod ↔ Service ↔ 外部。使用像
-
关闭迁移模式标记
- 如果之前为迁移设定了标签、特定配置(例如
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 文档)
📋 总结流程一览
- 确认当前 Calico 网络配置、Pod CIDR、网络策略、环境状态。
- 规划 Cilium 的 Pod CIDR、隧道协议、迁移模式参数。
- 安装 cilium-cli 与 Cilium (迁移模式,暂不接管 Pod )。
- 验证网络互通(旧 Pod ↔新 Pod )。
- 节点逐一滚动迁移:cordon → drain →切换节点到 Cilium→恢复。
- 所有节点迁移完成后,切换 Cilium 为唯一 CNI,开启 NetworkPolicy 等功能。
- 删除 Calico 相关资源,清理旧网络配置。
- 全面验证连通性、策略、性能;监控业务指标。
- 关闭迁移标识/配置,完成最终清理。
如果你愿意,我可以帮你 生成一个可执行的迁移清单(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 脚本)?
那样你可以直接照着执行。