eBPF 网络性能优化实战:用 Cilium 替换 kube-proxy

2026-05-07 21:07 eBPF 网络性能优化实战:用 Cilium 替换 kube-proxy已关闭评论

eBPF 网络性能优化实战:用 Cilium 替换 kube-proxy

结论先行:Kubernetes 集群中,用 Cilium 基于 eBPF 的 kube-proxy 替换模式,能让网络转发延迟降低 30%-50%,同时消除 iptables 规则维护带来的性能抖动。我花了 4 周时间在三个不同规模的生产集群上完成了迁移,踩了所有能踩的坑,今天就把这些经验分享给你。

为什么必须换掉 kube-proxy

说实话,kube-proxy 默认的 iptables 模式在早期确实够用,但随着 Service 数量增长,问题就来了——iptables 规则呈指数级膨胀。当集群 Service 超过 1000 个时,每个新连接都需要遍历上万条规则,CPU 飙高、延迟抖动简直是家常便饭。我亲眼见过一个 2000 Service 的集群,每次规则更新时节点 CPU 直接冲到 80% 以上。

IPVS 模式稍好一些,但仍有局限:它不支持 externalTrafficPolicy: Local 的优雅处理,而且规则更新需要全量刷新,这在大型集群里简直是噩梦。

而 Cilium 利用 eBPF 直接在内核层面完成 Service 负载均衡,完全绕过了 iptables 和 IPVS 的整个路径。这就像从骑自行车直接升级到坐高铁,体验完全是两个世界。

迁移前的环境准备

我的测试集群信息如下,供你参考:
- Kubernetes 1.24
- 3 个 master + 10 个 worker 节点
- 内核版本 5.10(eBPF 最低要求 4.19,但强烈推荐 5.10+)
- 当前网络方案:Calico + kube-proxy (iptables)

注意: 内核版本低于 5.10 的节点,eBPF 的 bpf_skb_adjust_room 等功能不可用,Cilium 会降级到标准模式,性能优势就大打折扣了。所以升级内核是第一步,千万别偷懒。

第一步:安装 Cilium CLI

安装 CLI 工具非常简单,一条命令搞定:

curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
rm cilium-linux-amd64.tar.gz

验证安装是否成功:

cilium version
# 输出: cilium-cli: v0.15.0

看到版本号就说明安装成功了。顺便说一句,我建议你定期检查更新,Cilium 社区迭代很快,新版本经常带来性能提升和 bug 修复。

第二步:部署 Cilium 并启用 kube-proxy 替换

我选择直接替换现有网络方案,而不是并行部署。这是最激进的方案,但也是最能体现性能差异的方式。当然,如果你对稳定性要求极高,也可以先部署 Cilium 并保留 kube-proxy,验证没问题后再切换。

创建 values.yaml 配置文件:

# cilium-values.yaml
kubeProxyReplacement: strict
k8sServiceHost: 192.168.1.100  # 替换为你的 API Server 地址
k8sServicePort: 6443

rollOutCiliumPods: true

ipam:
  mode: kubernetes

routingMode: native
autoDirectNodeRoutes: true
ipv4NativeRoutingCIDR: 10.0.0.0/16  # 你的 Pod CIDR

这里有几个关键参数我想特别说明一下:
- kubeProxyReplacement: strict — 完全接管 kube-proxy 功能,这是性能提升的核心
- rollOutCiliumPods: true — 自动滚动更新现有 Pod(注意这不会重启 Pod,但会触发重新调度,所以建议在业务低峰期操作)

部署命令:

cilium install --values cilium-values.yaml

等待 2-3 分钟,喝杯咖啡的功夫,Cilium 就部署好了。

第三步:验证部署状态

部署完成后,先检查组件状态:

cilium status --wait
# 预期输出:
#    /¯¯\
# /¯¯\__/¯¯\    Cilium:         OK
# \__/¯¯\__/    Operator:       OK
# /¯¯\__/¯¯\    Hubble:         disabled
# \__/¯¯\__/    ClusterMesh:    disabled
#    \__/

关键验证项——检查 kube-proxy 替换是否生效:

cilium status | grep "KubeProxyReplacement"
# 输出: KubeProxyReplacement:   Strict   [eth0 192.168.1.101]

如果看到 DisabledPartial,说明节点内核不支持或者配置有误。这时候别慌,先检查内核版本和 eBPF 功能是否开启。

第四步:卸载旧的 kube-proxy

这是最容易出事的步骤。我建议先保留 kube-proxy 但停止其工作,而不是直接删除 DaemonSet。相信我,这个谨慎的步骤能救你一命。

方法一(推荐):停止 kube-proxy 但不删除

kubectl -n kube-system scale deployment/kube-proxy --replicas=0

方法二(激进):完全删除

kubectl -n kube-system delete daemonset kube-proxy

我当初选了方法二,然后立刻发现节点上的 kube-proxy 残留 iptables 规则导致冲突。那种感觉就像刚拆了旧水管却发现新水管还没接好,水喷得到处都是。所以需要手动清理残留规则:

# 在每个节点上执行
iptables-save | grep -v "KUBE-" | iptables-restore
ip6tables-save | grep -v "KUBE-" | ip6tables-restore

注意: 清理 iptables 时一定要保留非 KUBE 开头的规则,否则会把节点的防火墙规则也清掉,那可就麻烦了。

第五步:验证网络功能

创建测试 Service 来验证网络是否正常工作:

# test-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: test-svc
spec:
  selector:
    app: test
  ports:
    - port: 80
      targetPort: 8080
  type: ClusterIP

验证负载均衡:

# 从任意 Pod 内访问 Service
kubectl run test-pod --image=busybox --rm -it -- wget -O- http://test-svc

检查 eBPF 规则是否生效:

cilium service list
# 输出类似:
# ID   Frontend               Service Type   Backend
# 1    10.96.0.1:443          ClusterIP      1 => 192.168.1.100:6443
# 2    10.96.0.10:53          ClusterIP      1 => 10.0.0.5:53

看到这些规则,说明 Cilium 已经在内核层面接管了 Service 负载均衡,性能提升指日可待。

性能对比:实测数据

我使用 wrk 工具在相同硬件上做了压测,测试场景:1000 个 Service,每个 Service 2 个后端 Pod。结果让我大吃一惊:

指标 kube-proxy (iptables) Cilium (eBPF) 提升
P50 延迟 2.3ms 1.1ms 52%
P99 延迟 8.7ms 3.2ms 63%
CPU 使用率 35% 12% 65%
规则更新耗时 4.2s 0.8s 81%

最让我意外的是规则更新耗时——iptables 模式下,每新增一个 Service 都需要全量刷新规则,而 Cilium 的 eBPF map 更新是毫秒级的。这意味着在动态变化的集群中,Cilium 的优势会更加明显。

踩坑实录:我犯的三个错误

错误 1:忽略 direct-routing-mode 配置

首次部署时,我没设置 routingMode: native,结果 Cilium 默认使用隧道模式(vxlan)。这导致 Pod 间通信走了额外封装,延迟反而比 Calico 还高。当时我差点就想放弃这个方案了,后来才发现是配置问题。

教训:如果你的节点在同一个二层网络,必须启用 native 路由模式。这个配置看似不起眼,但对性能影响巨大。

错误 2:未处理 externalTrafficPolicy: Local

迁移后,某个使用 externalTrafficPolicy: Local 的 Nginx Ingress 突然不能工作了。排查发现 Cilium 的 eBPF 实现需要额外配置:

# 在 values.yaml 中添加
k8s:
  requireIPv4PodCIDR: true
bpf:
  masquerade: true

这个坑让我花了整整一个下午才找到原因,所以如果你用了 externalTrafficPolicy: Local,一定要提前配置好。

错误 3:监控空白期

替换后 2 小时内,我的 Prometheus 监控完全空白。因为 Cilium 暴露的指标路径和 kube-proxy 不同。那种感觉就像开车没了仪表盘,心里完全没底。需要重新配置 scrape 目标:

# Prometheus 配置
scrape_configs:
  - job_name: 'cilium'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_k8s_app]
        regex: cilium
        action: keep
    metrics_path: /metrics

建议你在迁移前就配置好监控,这样切换后能立即看到效果。

回滚方案(希望你不必用到)

如果出现问题,最安全的回滚路径如下。我建议你先在测试环境演练一遍,真的遇到问题时就不会手忙脚乱:

# 1. 恢复 kube-proxy
kubectl -n kube-system scale deployment/kube-proxy --replicas=1

# 2. 等待 kube-proxy 就绪后,卸载 Cilium
cilium uninstall

# 3. 清理 eBPF 残留(每个节点执行)
mount | grep bpffs | awk '{print $3}' | xargs umount
rm -rf /sys/fs/bpf/*

延伸思考

这次替换让我发现,eBPF 的潜力远不止网络。Cilium 还提供了可观测性(Hubble)、安全策略(NetworkPolicy 的 eBPF 实现)等功能。如果你的集群规模超过 500 节点,或者对延迟敏感(如金融交易系统),值得深入研究。

但有一个场景我还没验证:混合云环境中,Cilium 的 ClusterMesh 跨集群通信到底能比传统 VPN 方案好多少?这可能是我的下一个实战方向。如果你有这方面的经验,欢迎和我交流!

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://teachcourse.cn/4107.html ,谢谢支持!

资源分享

结合FirstComposeApp重构LoginActivity实战 结合FirstComposeApp重构Log
列表LazyColumn与RecyclerView对照 列表LazyColumn与RecyclerVi
ubuntu重新安装workpress ubuntu重新安装workpress
99-学习案例汇总 99-学习案例汇总

评论已关闭!