Cilium 替换 Calico 执行结果(深度模式)
目标机:192.168.60.128(master,单节点,Ubuntu 26.04,k8s v1.35.4,docker 29.7.2 + cri-dockerd) 环境:192.168.60.128(master,单节点,Ubuntu 26.04,k8s v1.35.4,docker 29.7.2 + cri-dockerd) 日期:2026-10-09
1. 结果概览(一句话)
就地用 Cilium 1.20.2 深度模式(kubeProxyReplacement=true + Hubble) 替换了 Calico v3.25.0, 集群全绿、Service/NodePort/DNS/出网全部实测通过,kube-proxy 已停用,iptables 规则从 406 行降到 93 行,Pod 网段切换到 10.244.0.0/24。
2. 关键指标 前后对比
| 指标 | 之前(Calico) | 之后(Cilium) |
|---|---|---|
| CNI | Calico v3.25.0 | Cilium v1.20.2 |
| 数据面 | iptables + IPIP 隧道 | eBPF + VXLAN |
| Service 转发 | kube-proxy (iptables) | Cilium eBPF (kubeProxyReplacement=True) |
| kube-proxy | systemd 服务在跑 | 已 disable --now,规则已清 |
| Pod 网段 | 172.16.0.0/16 | 10.244.0.0/24 |
| iptables 总行数 | 406 | 101(-75%) |
| 残留 cali-* | —— | 0 |
| 残留 kube-proxy 服务链(KUBE-SVC/SEP/POSTROUTING) | 81 | 0(仅剩 kubelet 自带 KUBE-FIREWALL/CANARY 共 8 行) |
| tunl0 隧道 | 有 | 已删(内核 ipip 模块会重建一个空设备,无害) |
| 可观测 | 无 | Hubble + Hubble UI |
3. 验证证据(全部实测)
集群组件:
cilium status:Cilium OK / Operator OK / Envoy OK / Hubble Relay OK / Hubble UI OK;Cluster Pods 7/7 managed by Ciliumcilium-dbg status:KubeProxyReplacement: True [ens32 192.168.60.128 (Direct Routing)]cilium-dbg bpf lb list:ClusterIP → backend 映射已在 BPF 表中(证明 Service 由 eBPF 接管)
功能(从 Pod 内实测):
- 集群 DNS:kubernetes.default.svc.cluster.local → 10.96.0.1 ✓
- API ClusterIP https://10.96.0.1/healthz → 200 ✓
- 服务名 → ClusterIP:venus-registry.venus-plugin.svc.cluster.local → 10.102.230.81,访问 → 200 ✓
- NodePort:https://192.168.60.128:30443/ → 200 ✓
- 出集群:quay.io → 200 ✓
- Pod→Pod DNS:从 netshoot Pod 查 echo Pod 内置 DNS 服务 → NOERROR ✓
- metrics-server:
kubectl top pods返回数据 ✓
4. 已知问题 / 说明(诚实记录)
cilium connectivity test未通过:失败点在其自带的 client 测试镜像quay.io/cilium/alpine-curl:v1.10.0里的 BINDdig/nslookup退出时崩溃(exit 139:isc_app_ctxshutdown(): fatal error: kill: Permission denied)。- 已用独立 netshoot Pod 复测同一路径:
dig @<echo> localhost→ NOERROR,TCP 连 echo:53 → open。 - 进一步定位:同一镜像用
docker run跑 dig 正常(rc=0);但把它当普通 K8s Pod 跑(不经 connectivity test) → dig 同样 Segmentation fault / exit 139。即:问题是「该 musl 镜像在本机 docker+cri-dockerd+kernel7.0 的 K8s Pod 上下文里」的兼容问题,与 Cilium、与数据面无关;不代表你的业务负载有问题(netshoot/glibc 镜像均正常)。 - 详见 /root/cilium-migrate/connectivity*.log
- 已用独立 netshoot Pod 复测同一路径:
- Masquerade 仍是 IPTables(
cilium-dbg status:Masquerading: IPTables)。如需纯 eBPF,可加--set bpf.masquerade=true。 - Host routing = Legacy(隧道模式下的默认),如需可切 native routing。
Host:中 docker0(172.17/16) 未被 Cilium 接管(已用 devices=ens32 指定)。
5. 后续可选优化(按需,不一定做)
bpf.masquerade=true:去掉 SNAT 的 iptables 路径,进一步纯 eBPFroutingMode=native:单节点可免封装(换性能)- 把 Cilium 镜像灌入本地 registry (registry.cluster.local:30443) 供离线/现场环境使用
- 沉淀进你的二进制安装器:加一个「CNI=Cilium」分支与离线资产
6. 回滚方式
- 首选:恢复该 VM 的基础快照。
- 若不回滚:
cilium uninstall→ 用安装器重装 Calico →systemctl enable --now kube-proxy。
7. Hubble UI 访问方式
已将 kube-system/hubble-ui 从 ClusterIP 改为 NodePort 31000(原 svc 备份在 /root/cilium-migrate/hubble-ui-svc-backup.yaml)。
- 直接访问:http://192.168.60.128:31000 (已实测 HTTP 200)
- 还原为 ClusterIP:
kubectl -n kube-system apply -f /root/cilium-migrate/hubble-ui-svc-backup.yaml - 注意:UI 无鉴权,NodePort 对所有网卡开放;仅适合内网/测试机。若你的安装器会重新 apply 清单,此改动可能被覆盖。
- 深链直达某命名空间:http://192.168.60.128:31000/?namespace=default
常见现象:「一直转圈 / No data found」≠ 坏了
Hubble UI 有一份默认黑名单,会过滤掉 reserved:host、kube-dns、reserved:remote-node、 *.cluster.local 等"基础设施噪声"。空闲的单节点集群里,流量恰好全是被过滤的那些 (metrics-server 抓 kubelet、CoreDNS 查询),所以服务图是空的,看起来像"没数据/没坏但一直转圈"。
- 实测:接入真实业务流量后,UI 立即显示
16.9 flows/s,服务图与流表正常刷新。 - 排障动作:先产生一点 Pod→Pod / Pod→Service 流量,再刷新 UI。
- 命令行对照(判断是"真没流量"还是"链路断了"):
kubectl -n kube-system exec ds/cilium -- cilium-dbg status | grep -i hubble→ 应显示Hubble: Ok ... Flows/s: >0kubectl -n kube-system logs deploy/hubble-relay --tail=20→ 应有Connected ... tls=true
8. 为跑通 cilium connectivity test 做的环境改动(已验证)
- 自建 client 镜像
cilium-test-client:v1(= nicolaka/netshoot +/usr/bin/pause),配合--curl-image cilium-test-client:v1使用。原因:默认 client 镜像quay.io/cilium/alpine-curl里的 BIND dig/nslookup 在docker exec/kubectl exec会话下退出即崩(exit 139,纯 docker 可复现), 与本集群无关。 - CoreDNS 增加节点主机名解析:
coredns-hostsConfigMap 追加一行192.168.60.128 master。 原因:cilium-cli 会在节点全部地址上验证 NodePort 就绪,节点上报了Hostname=master, 而集群内解析不了它。备份在 /root/cilium-migrate/coredns-hosts-backup.yaml。 还原:kubectl apply -f /root/cilium-migrate/coredns-hosts-backup.yaml && kubectl -n kube-system rollout restart deploy coredns
9. 相关笔记
机器上的归档:/root/cilium-migrate/(基线快照、渲染清单、连通性日志)