本文永久链接: https://www.xtplayer.cn/cilium/after-disabling-kube-proxy-the-cilium-component-pods-cannot-run/

为什么要设置 kubeProxyReplacement=true

背景:kube-proxy 的角色与局限

在标准的 Kubernetes 集群中,kube-proxy 负责实现 Service 的 ClusterIP 和 NodePort 等负载均衡机制。传统实现基于 iptables 或 IPVS,在大量 Service 场景下存在性能瓶颈——iptables 规则链线性匹配,规则更新时需全量刷新,大规模集群中可能造成 API Server 压力激增和服务延迟。

Cilium 的 eBPF 替代方案

Cilium 的 kubeProxyReplacement=true 启用后,使用 eBPF 技术在 Linux 内核层面直接处理 Service 的负载均衡,完全替代 kube-proxy。这一机制具有以下优势:

  • 性能提升:eBPF 程序在内核中高效运行,绕过 iptables 的线性匹配开销
  • 可观测性增强:Cilium 可提供 Service 级别的细粒度监控指标
  • 释放资源:可以移除 kube-proxy DaemonSet,减少集群资源占用

为什么需要主动设置此参数

在 Rancher RKE2 发行版中,若在集群创建时通过 disable-kube-proxy: true 禁用了 kube-proxy,则必须显式设置 kubeProxyReplacement=true,否则 Cilium 无法接管 Service 的负载均衡职责,集群内 Service 访问将失效。

设置 kubeProxyReplacement=true 后 Cilium 组件无法运行

设置 kubeProxyReplacement=true 后,Cilium 会完全接管 Service 的负载均衡功能。此时,Pod 内请求 svc 地址依赖 Cilium agent 的 eBPF 程序来处理。在 Cilium pod 启动时,Cilium pod 中的 config init 容器会请求 apiserver 获取 Cilium agent 配置,获取到配置之后 Cilium agent 才可以正常运行。

┌─────────────────────────────────────────────────────────────────┐
│ Cilium Pod 启动流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. config-init 容器启动 │
│ ↓ │
│ 2. 尝试访问 API Server 获取 Agent 配置 │
│ ↓ │
│ 3. 通过默认的 kubernetes Service ClusterIP (10.43.0.1) 访问 │
│ ↓ │
│ 4. 该 ClusterIP 的负载均衡需要 Cilium Agent 的 eBPF 程序处理 │
│ ↓ │
│ 5. 但 Cilium Agent 尚未启动(配置未获取,无法启动) │
│ ↓ │
│ 6. 请求超时,config-init 容器失败 → Agent 永远无法启动 │
│ │
└─────────────────────────────────────────────────────────────────┘

查看 chart 定义 https://github.com/rancher/rke2-charts/blob/main/charts/rke2-cilium/rke2-cilium/1.19.300/templates/cilium-agent/daemonset.yaml#L227 ,可以通过 chart 参数 k8sServiceHostk8sServicePort 参数去自定义 apiserver 地址和端口。当 config init 容器启动时,如果没有通过 k8sServiceHost 参数去覆盖默认的 apiserver svc 地址,它尝试通过默认的 ClusterIP 访问 API Server。在 Rancher-rke2 发行版下,apiserver svc ip 默认为 10.43.0.1。因为 Service 的解析和负载均衡逻辑由 Cilium agent 提供,并且集群中也没有运行 kube-proxy,这就造成了一个死循环。

因此在禁用 kube-proxy 的场景下设置 kubeProxyReplacement=true,必须同时显式指定 k8sServiceHostk8sServicePort,为 config-init 容器提供 API Server 的真实访问地址。否则,config-init 容器将因无法通过 Service ClusterIP 访问 API Server 而失败,导致 Cilium Agent 无法启动,整个集群的网络功能陷入瘫痪。

解决方法

如果是在 Rancher UI 创建的 RKE2 集群,可以编辑集群 YAML,在 chartValues 中添加如下配置。

apiVersion: provisioning.cattle.io/v1
kind: Cluster
spec:
rkeConfig:
machineGlobalConfig:
cni: cilium
disable-kube-proxy: true
chartValues:
rke2-cilium: # 注意:配置直接写在 rke2-cilium 层级下
kubeProxyReplacement: true
k8sServiceHost: "10.0.0.1" # k8sServiceHost: "10.0.0.1" # 替换为 API Server 的稳定访问地址(VIP 或域名),不建议直接使用单节点 IP
k8sServicePort: "6443"
hubble:
enabled: true

或者通过导入 HelmChartConfig 配置方式自定义 cilium 配置参数。

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-cilium # 必须与对应的 HelmChart 名称一致
namespace: kube-system # 必须与对应的 HelmChart 命名空间一致
spec:
valuesContent: |-
# 开启 kube-proxy 替换
kubeProxyReplacement: true
# 使用本地代理地址,解决循环依赖问题
k8sServiceHost: "localhost"
k8sServicePort: "6443"
# 开启 Hubble 提升可观测性
hubble:
enabled: true