跳转到内容

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)
CNICalico v3.25.0Cilium v1.20.2
数据面iptables + IPIP 隧道eBPF + VXLAN
Service 转发kube-proxy (iptables)Cilium eBPF (kubeProxyReplacement=True)
kube-proxysystemd 服务在跑已 disable --now,规则已清
Pod 网段172.16.0.0/1610.244.0.0/24
iptables 总行数406101(-75%)
残留 cali-*——0
残留 kube-proxy 服务链(KUBE-SVC/SEP/POSTROUTING)810(仅剩 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 Cilium
  • cilium-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. 已知问题 / 说明(诚实记录) ​

  1. cilium connectivity test 未通过:失败点在其自带的 client 测试镜像 quay.io/cilium/alpine-curl:v1.10.0 里的 BIND dig/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
  2. Masquerade 仍是 IPTables(cilium-dbg status:Masquerading: IPTables)。如需纯 eBPF,可加 --set bpf.masquerade=true。
  3. Host routing = Legacy(隧道模式下的默认),如需可切 native routing。
  4. Host: 中 docker0(172.17/16) 未被 Cilium 接管(已用 devices=ens32 指定)。

5. 后续可选优化(按需,不一定做) ​

  • bpf.masquerade=true:去掉 SNAT 的 iptables 路径,进一步纯 eBPF
  • routingMode=native:单节点可免封装(换性能)
  • 把 Cilium 镜像灌入本地 registry (registry.cluster.local:30443) 供离线/现场环境使用
  • 沉淀进你的二进制安装器:加一个「CNI=Cilium」分支与离线资产

6. 回滚方式 ​

  1. 首选:恢复该 VM 的基础快照。
  2. 若不回滚: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 做的环境改动(已验证) ​

  1. 自建 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 可复现), 与本集群无关。
  2. CoreDNS 增加节点主机名解析:coredns-hosts ConfigMap 追加一行 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/(基线快照、渲染清单、连通性日志)

基于 MIT 许可发布