RKE2 + Cilium + kubeProxyReplacement + NodeLocalDNS + LRP 使用注意事项
在使用以下配置组合时,不同 RKE2 版本可能会遇到不同问题,本文对已知问题进行总结:
- RKE2 使用 Cilium CNI
- Cilium 启用
kubeProxyReplacement - 使用 RKE2 CoreDNS 的
nodelocal.enabled配置开启 NodeLocalDNS - 使用 RKE2 CoreDNS 的
nodelocal.use_cilium_lrp配置创建 Cilium LocalRedirectPolicy(LRP),将集群 DNS 的流量重定向至本节点的node-local-dnsPod
在 Cilium 完全替代 kube-proxy 后,ClusterIP 流量由 eBPF 在进入 Pod 网络栈前处理,传统 NodeLocalDNS 依赖的 iptables 截获方式不再适用,因此需要使用 LRP。
相关配置
RKE2 Cilium Helm Chart 配置:
1 | # https://github.com/rancher/rke2-charts/tree/main/charts/rke2-cilium/rke2-cilium |
RKE2 CoreDNS Helm Chart 配置:
1 | # https://github.com/rancher/rke2-charts/tree/main/charts/rke2-coredns/rke2-coredns |
RKE2 配置:
1 | cni: cilium |
通过 Rancher 创建的 RKE2 集群配置:
1 | spec: |
已知问题
问题一:NodeLocalDNS Pod 卡在 Init 阶段
在较旧的 RKE2 CoreDNS Helm Chart 中,Cilium LRP 模式下的 node-local-dns Pod 仍包含 wait-coredns 初始化容器。
相关 issue:
初始化容器通过集群 DNS 地址(10.43.0.10)检查 CoreDNS 是否可访问,但此时 node-local-dns 主容器尚未启动,LRP 也没有可用的本地后端,因此形成启动依赖问题,Pod 会一直停留在 Init:0/1:
1 | kube-system node-local-dns-xxx 0/1 Init:0/1 |
initContainer 日志:
1 | waiting for dns service |
PR #809 调整了 Cilium LRP 模式下的 NodeLocalDNS 渲染逻辑,避免继续依赖不适用于该启动顺序的 CoreDNS 初始化检查,并为 Cilium LRP 模式生成相应的 NodeLocalDNS 配置。
RKE2 包含该修复的版本为:
v1.31.14+rke2r2v1.32.11+rke2r1v1.33.7+rke2r1v1.34.3+rke2r1
另外,从该修复开始,RKE2 CoreDNS Helm Chart 将 LRP 的 frontend 从 serviceMatcher 改为 addressMatcher:
1 | # 旧配置 |
从 PR #809 中的描述来看,当时通过 serviceMatcher 重定向 Service 流量存在问题,因此改为直接匹配 rke2-coredns-rke2-coredns Service 的 ClusterIP。此时 Service 仍然存在,从而引发了问题三中描述的问题。
问题二:LRP 端口名称不一致,BPF 后端未正确编程
旧版 LRP 模板中,前端端口名称为 udp-53 和 tcp-53,而 LRP 后端及 node-local-dns Pod 使用 dns 和 dns-tcp。
当 LRP 包含多个端口时,Cilium 会根据端口名称建立前端与后端之间的映射。端口名称必须是符合 Kubernetes IANA 规范的名称,并且必须能够与后端 Pod 实际声明的端口对应。名称不一致时,Cilium 可能创建 LocalRedirect frontend,但不能为其正确配置本地 BPF backend。
相关 issue:
Pod 内执行 DNS 查询时可能出现:
1 | nslookup: can't connect to remote host (10.43.0.10): Operation not permitted |
Cilium Pod 可以看到 LocalRedirect frontend,但 BPF backend 不正确:
1 | root@test-2:~# kubectl -n kube-system exec ds/cilium -c cilium-agent -- cilium-dbg lrp list |
该问题有时不是在部署后立即出现,而是在运行约 10–15 分钟、Cilium 重新同步相关对象后出现。
PR #854 将 LRP 前端和后端的端口名称统一为:
- UDP/53:
dns - TCP/53:
dns-tcp
修复版本为:
v1.32.11+rke2r3v1.33.7+rke2r3v1.34.3+rke2r3v1.35.1+rke2r1
Workaround 为手动调整 LRP,使前端、后端与 node-local-dns Pod 的端口映射统一:
1 | apiVersion: cilium.io/v2 |
问题三:addressMatcher 与现有 RKE2 CoreDNS Service 竞争同一个 IP
Cilium 对 serviceMatcher 和 addressMatcher 的定义如下:
- 目标 IP / 端口属于 Kubernetes Service 时,应使用
serviceMatcher - 目标 IP / 端口不属于 Kubernetes Service 时,应使用
addressMatcher
某些旧版 RKE2 CoreDNS Helm Chart 会同时创建:
- 名为
rke2-coredns-rke2-coredns的 Kubernetes Service,ClusterIP 为10.43.0.10 - 使用
10.43.0.10的addressMatcherLRP
在这种情况下,Cilium LRP 和 Kubernetes Service 会同时尝试管理同一个 IP,从而产生竞态问题。
相关 KB 和 issue:
- https://support.scc.suse.com/s/kb/Cilium-LRP-policy-incompatibility-with-node-local-dns-due-to-addressMatcher?language=en_US
- https://github.com/rancher/rke2/issues/9726
Cilium Pod 会看到错误日志:
1 | time=2026-09-16T03:58:16.174198083Z level=warn msg="Failure processing services" module=agent.controlplane.loadbalancer-reflectors.k8s-reflector error="frontend already owned by another service: 10.43.0.10:53/TCP is owned by kube-system/lrp-nodelocal:local-redirect" |
且 Backend 为空:
1 | root@test-2:~# kubectl -n kube-system exec ds/cilium -c cilium-agent -- cilium-dbg service list |
最终修复没有将 RKE2 CoreDNS Helm Chart 自动生成的 LRP 改回 serviceMatcher,而是调整了配置的渲染:启用 nodelocal.enabled 和 nodelocal.use_cilium_lrp 时,不再创建 rke2-coredns-rke2-coredns 的 Kubernetes Service。
PR #892 引入了修复,RKE2 修复版本为:
v1.32.13+rke2r2v1.33.9+rke2r1v1.34.6+rke2r1v1.35.3+rke2r1
Workaround 为手动调整 LRP,改回 serviceMatcher 避免竞争问题:
1 | apiVersion: cilium.io/v2 |
RKE2 + Cilium + kubeProxyReplacement + NodeLocalDNS + LRP 使用注意事项
https://warnerchen.github.io/2026/09/16/RKE2-Cilium-kubeProxyReplacement-NodeLocalDNS-LRP-使用注意事项/