Cilium 本地重定向策略(LRP)实战指南:从 cilium-dbg lrp 命令到 eBPF 数据面原理
2026/9/13 14:29:45 网站建设 项目流程

Cilium 本地重定向策略(LRP)实战指南:从 cilium-dbg lrp 命令到 eBPF 数据面原理

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

导读

本文以 Cilium 的cilium-dbg lrp命令族为主线,系统讲解 Local Redirect Policy(本地重定向策略,简称 LRP)的完整使用闭环:如何用命令行管理策略、如何在 Kubernetes 中通过CiliumLocalRedirectPolicyCRD 定义AddressMatcherServiceMatcher两种策略类型、如何在 eBPF 数据面验证重定向生效,并深入节点级 DNS 缓存等典型场景。读完本文,你将掌握从策略创建、查询到故障排查的完整实战技能,同时理解 LRP 在 pkg/loadbalancer/redirectpolicy 控制器与 BPF 数据面中的底层工作方式。

cilium-dbg lrp 命令概览

cilium-dbg lrp是 Cilium 命令行工具中负责管理本地重定向策略的子命令族,其定义位于 cilium-dbg/cmd/lrp.go:

var LRPCmd = &cobra.Command{ Use: "lrp", Short: "Manage local redirect policies", }

命令文档见 Documentation/cmdref/cilium-dbg_lrp.md,其顶层命令本身不执行任何操作,仅作为命名空间承载list子命令:

cilium-dbg lrp

顶层选项

选项说明
-h, --help显示lrp命令的帮助信息

继承自父命令的全局选项

所有cilium-dbg子命令都会继承以下全局选项,在通过kubectl exec进入 Cilium agent Pod 内执行时通常无需改动,但了解其含义有助于在独立运行调试时正确连接 API:

选项默认值说明
--config string$HOME/.cilium.yaml配置文件路径
-D, --debug关闭输出调试日志
-H, --host string本地 Unix socket服务端 API 的 URI
--log-driver strings-日志端点(示例:syslog
--log-opt map-日志驱动选项(示例:format=json

核心子命令:cilium-dbg lrp list

cilium-dbg lrp list用于列出当前节点上生效的本地重定向策略,完整命令文档见 Documentation/cmdref/cilium-dbg_lrp_list.md:

cilium-dbg lrp list [flags]

专属选项

选项说明
-h, --help显示list命令帮助
-o, --output string输出格式,支持jsonyamljsonpath='{}'

list同时注册了别名ls(源码见 cilium-dbg/cmd/lrp_list.go),因此cilium-dbg lrp lscilium-dbg lrp list等价。

输出字段解读

不带-o参数时,命令通过tabwriter输出人类可读的表格(printLRPList):

LRP namespace LRP name FrontendType Matching Service

每个策略条目包含四个核心列:

  • LRP namespace / LRP name:策略对象的元数据,与kubectl get ciliumlocalredirectpolicies中的命名空间与名称一一对应;
  • FrontendType:策略匹配的前端类型,常见取值为clusterIP + all svc ports(ServiceMatcher 且未限定端口)等;
  • Matching Service:命中的 Kubernetes Service(格式为namespace/serviceName)。

每个策略下方还会逐行打印前端到后端的映射明细,格式由 getPrintableMapping 生成:

<frontend-ip>:<frontend-port>/<protocol> -> <backend-ip>:<backend-port>(<pod-namespace>/<pod-name>), ...

例如在节点级 DNS 缓存场景中的典型输出:

LRP namespace LRP name FrontendType Matching Service kube-system nodelocaldns clusterIP + all svc ports kube-system/kube-dns | 10.96.0.10:53/UDP -> 10.244.1.49:53(kube-system/node-local-dns-72r7m), | 10.96.0.10:53/TCP -> 10.244.1.49:53(kube-system/node-local-dns-72r7m),

这表示发往 ClusterIP10.96.0.10的 UDP/TCP53端口流量,会被重定向到本节点node-local-dns-72r7mPod 的53端口。

底层实现:调用链

从源码调用链看,listLRPs会先通过 Cilium agent 的客户端调用client.GetLRPs()获取策略列表(cilium-dbg/cmd/lrp_list.go),该 API 返回[]*models.LRPSpec,其中FrontendMappings携带每个前端地址对应的本节点后端 Pod 列表。当指定-o参数时,命令改用结构化输出(json/yaml/jsonpath),便于脚本与自动化工具消费,此时每个条目会完整暴露LRPSpec的全部字段。

Local Redirect Policy 功能原理

理解命令输出前,需要先掌握 LRP 的定位:LRP 使发往某个 IP:端口/协议 元组或 Kubernetes Service 的 Pod 流量,在节点本地被 eBPF 重定向到本节点上的后端 Pod,且后端 Pod 的命名空间需与策略命名空间一致。LRP 通过CiliumLocalRedirectPolicyCustomResourceDefinition 进行配置,完整功能文档见 Documentation/network/kubernetes/local-redirect-policy.rst。

策略 CRD 的类型定义位于 pkg/k8s/apis/cilium.io/v2/clrp_types.go,其 Spec 由三部分组成:

字段必填说明
redirectFrontend待重定向的流量匹配条件,addressMatcherserviceMatcher二选一(不可同时为空)
redirectBackend重定向目标:localEndpointSelector选择本节点上的后端 Pod,toPorts指定目标端口
skipRedirectFromBackend否(默认false见后文“高级配置”

注意 CRD 通过 OpenAPIXValidation规则将redirectFrontendredirectBackendskipRedirectFromBackend标记为不可变(immutable),即策略一旦创建后这些字段不可修改,这也是官方文档强调“更新需删除重建”的底层原因。

策略如何处理:控制器视角

从源码结构看,LRP 的编排由 pkg/loadbalancer/redirectpolicy 包负责:控制器监听CiliumLocalRedirectPolicy资源与 Pod/Service 变更,动态维护LRPSpec与后端映射关系,最终将结果同步为LocalRedirect类型的负载均衡服务条目;同一目录下的testdata/*.txtar测试用例(如 pkg/loadbalancer/redirectpolicy/testdata/address.txtar、node-local-dns.txtar)覆盖了端口命名、地址冲突、Pod 就绪状态等边界场景,可用于深入理解控制器行为。

启用 LRP:前置条件

LRP 默认未启用,需要通过 Helm 开启并重启相关组件:

helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \ --set localRedirectPolicies.enabled=true kubectl rollout restart deploy cilium-operator -n kube-system kubectl rollout restart ds cilium -n kube-system

随后验证 agent 与 operator Pod 恢复 Running,并确认 CRD 已注册:

kubectl -n kube-system get pods -l k8s-app=cilium kubectl -n kube-system get pods -l name=cilium-operator kubectl get crds | grep ciliumlocalredirectpolicies # ciliumlocalredirectpolicies.cilium.io 2020-08-24T05:31:47Z

数据面选型:四种 Helm 组合

LRP 支持 socket 级负载均衡与 tc 负载均衡两种数据面实现,官方文档给出了四种经过验证的 Helm 组合:

  1. 完整 kube-proxy 替换(用 Cilium eBPF 实现替代 kube-proxy 并启用 LRP):

    kubeProxyReplacement: true localRedirectPolicies: enabled: true
  2. 绕过 Pod 命名空间内的 socket 级负载均衡(适用于 Pod 命名空间存在自定义重定向规则、与 socket 负载均衡冲突的场景):

    kubeProxyReplacement: true socketLB: hostNamespaceOnly: true localRedirectPolicies: enabled: true
  3. 仅启用 socket 级负载均衡(保留 kube-proxy 处理整体 Service,仍可使用 LRP):

    kubeProxyReplacement: false socketLB: enabled: true localRedirectPolicies: enabled: true
  4. 仅处理来自 Pod 的 ClusterIP 访问(其余 kube-proxy 替换全部关闭;注意此配置下宿主机命名空间的 Pod 流量不受 LRP 处理):

    kubeProxyReplacement: false localRedirectPolicies: enabled: true

部署示例:后端与客户端 Pod

以官方示例 examples/kubernetes-local-redirect/backend-pod.yaml 部署后端 Pod(其标签、容器端口/协议需与后续 LRP 的localEndpointSelectortoPorts一致):

kubectl apply -f examples/kubernetes-local-redirect/backend-pod.yaml kubectl get pods | grep lrp-pod # lrp-pod 1/1 Running 0 46s

再部署用于产生流量的客户端 Pod(examples/kubernetes-dns/dns-sw-app.yaml):

kubectl create -f examples/kubernetes-dns/dns-sw-app.yaml kubectl wait pod/mediabot --for=condition=Ready

策略类型一:AddressMatcher(按 IP:端口 匹配)

AddressMatcher 用IP 地址 + L4 端口/协议精确匹配不属于任何 Kubernetes Service 的流量。要点:

  • 前端toPorts中配置多个端口时端口必须命名,端口名用于前端端口与后端端口的映射;
  • redirectBackend.toPorts指定的端口必须真实存在于后端 Pod 的 spec 中;
  • localEndpointSelector用于在本节点选择接收重定向流量的后端 Pod。

完整示例见 examples/kubernetes-local-redirect/lrp-addrmatcher.yaml:将发往169.254.169.254:8080/TCP的流量重定向到标签为app=proxy、监听80/TCP的后端 Pod:

apiVersion: "cilium.io/v2" kind: CiliumLocalRedirectPolicy metadata: name: "lrp-addr" spec: redirectFrontend: addressMatcher: ip: "169.254.169.254" toPorts: - port: "8080" protocol: TCP redirectBackend: localEndpointSelector: matchLabels: app: proxy toPorts: - port: "80" protocol: TCP

应用并验证:

kubectl apply -f examples/kubernetes-local-redirect/lrp-addrmatcher.yaml kubectl get ciliumlocalredirectpolicies | grep lrp-addr

从类型定义看(clrp_types.go),addressMatcher.ip支持 IPv4 与 IPv6,toPorts[].protocol仅接受TCPUDPtoPorts[].port必须是合法的 uint16 端口字符串。

验证:service list 与 curl

lrp-pod同一节点的 Cilium Pod 中执行cilium-dbg service list,可以看到 eBPF kube-proxy replacement 创建了一条LocalRedirect类型的服务条目,其后端正是策略选中的lrp-pod的 IP:

kubectl describe pod lrp-pod | grep 'IP:' # IP: 10.16.70.187 kubectl exec -it -n kube-system cilium-5ngzd -- cilium-dbg service list # ID Frontend Service Type Backend # 4 172.20.0.51:80 LocalRedirect 1 => 10.16.70.187:80

从客户端 Pod 发起请求验证重定向生效:

kubectl exec mediabot -- curl -I -s http://169.254.169.254:8080/index.html # HTTP/1.1 200 OK # Server: nginx/1.19.2

最后用 tcpdump(需在lrp-pod所在节点执行)确认流量确实打到了后端 Pod 的 80 端口:

sudo tcpdump -i any -n port 80 # 01:36:24.608566 IP 10.16.215.55.60876 > 10.16.70.187.80: Flags [S], seq 2119454273, ... # 01:36:24.609007 IP 10.16.70.187.80 > 10.16.215.55.60876: Flags [P.], seq 1:239, ... HTTP/1.1 200 OK

集群级地址白名单

可通过 Helm 的localRedirectPolicies.addressMatcherCIDRs选项在全集群范围内约束允许被 AddressMatcher 重定向的地址,例如只允许169.254.169.254

localRedirectPolicies: enabled: true addressMatchCIDRs: - 169.254.169.254/32

超出白名单的地址会被 cilium-agent 拒绝并输出警告日志。

冲突保护

AddressMatcher 仅面向不属于任何 Kubernetes Service 的 IP。若redirectFrontend.addressMatcher中的 IP:端口/协议 与某个ClusterIPService 前端重合,策略不会覆盖该地址——Cilium 拒绝覆盖其他 Service 拥有的前端,并记录日志:

LocalRedirectPolicy matches an address owned by an existing service => refusing to override

此时应改用 ServiceMatcher 类型。

策略类型二:ServiceMatcher(按 Service 匹配)

ServiceMatcher 用Kubernetes Service 的名称与命名空间匹配需要重定向的流量,要求 Service 类型为clusterIP。要点:

  • redirectFrontend不指定toPorts,则该 Service 的全部端口流量都会被重定向;只重定向部分端口时需在 spec 中显式列出,且多端口时必须命名(端口名用于前后端端口映射);
  • 策略应用后,eBPF kube-proxy replacement 创建的既有 Service 条目会被替换为类型LocalRedirect的新条目,且该条目只允许包含节点本地的后端 Pod

先部署 Service(examples/kubernetes-local-redirect/k8s-svc.yaml)并确认其 ClusterIP 与 Service 条目:

kubectl apply -f examples/kubernetes-local-redirect/k8s-svc.yaml kubectl get service | grep 'my-service' # my-service ClusterIP 172.20.0.51 <none> 80/TCP 2d7h kubectl exec -it -n kube-system ds/cilium -- cilium-dbg service list # ID Frontend Service Type Backend # 4 172.20.0.51:80 ClusterIP

再创建 ServiceMatcher 类型的策略(examples/kubernetes-local-redirect/lrp-svcmatcher.yaml):

apiVersion: "cilium.io/v2" kind: CiliumLocalRedirectPolicy metadata: name: "lrp-svc" spec: redirectFrontend: serviceMatcher: serviceName: my-service namespace: default redirectBackend: localEndpointSelector: matchLabels: app: proxy toPorts: - port: "80" protocol: TCP

应用后再次查看 Service 条目,可见其类型已变为LocalRedirect,后端为本节点上被策略选中的 Pod:

kubectl apply -f examples/kubernetes-local-redirect/lrp-svcmatcher.yaml kubectl get ciliumlocalredirectpolicies | grep svc kubectl exec -it -n kube-system cilium-5ngzd -- cilium-dbg service list # ID Frontend Service Type Backend # 4 172.20.0.51:80 LocalRedirect 1 => 10.16.70.187:80

客户端请求与 tcpdump 验证方式与 AddressMatcher 一致,只是目标改为 ClusterIP:

kubectl exec mediabot -- curl -I -s http://172.20.0.51/index.html # HTTP/1.1 200 OK

高级配置:skipRedirectFromBackend

默认情况下(skipRedirectFromBackend: false),包括后端 Pod 自身在内的所有来源,只要流量匹配前端都会被重定向。某些场景下用户希望后端 Pod 发往策略前端的流量不要被重定向回自身,而是直接转发到原始前端地址,此时可在 spec 中设置:

spec: skipRedirectFromBackend: true

该能力依赖getsockopt()SO_NETNS_COOKIE选项判断来源网络命名空间:该选项自 Linux 内核 5.7 起对 BPF 程序可用,5.12 起对用户空间暴露,因此要求内核版本 >= 5.12。此外,自 Cilium 1.16.0 起,若要对已应用策略启用该配置,需要先删除并重新创建既有策略及其选中的后端 Pod(该字段同样被 CRD 标记为不可变)。

已知限制

  • 不迁移既有连接:LRP 只重定向策略生效后新建的连接;对策略匹配范围内已存在的、指向远端 Pod 的活动连接可能不会重定向。要确保全部连接都走本地重定向,应在配置策略后重启客户端 Pod
  • 不支持更新:LRP 更新目前不被支持,任何变更都需要删除旧策略后重新创建(与 CRD 的字段不可变校验一致)。

典型场景:Node-local DNS Cache(节点级 DNS 缓存)

LRP 最经典的用例是让集群内 DNS 查询优先命中节点本地的 DNS node-cache Pod,避免应用 Pod 的 DNS 请求跨节点转发到kube-dns后端,从而降低延迟并减少网络开销。

部署 node-local-dns

两种部署方式:

  • 快速部署:使用仓库提供的 examples/kubernetes-local-redirect/node-local-dns.yaml,其默认值已填充__PILLAR_LOCAL_DNS____PILLAR_DNS_DOMAIN__;若集群 DNS Service 不同,需按官方 NodeLocal DNSCache 配置说明替换__PILLAR__DNS__SERVER__等模板变量:
    kubedns=$(kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}) \ && sed -i "s/__PILLAR__DNS__SERVER__/$kubedns/g;" node-local-dns.yaml kubectl apply -f node-local-dns.yaml
  • 手动配置:需保证 node-local DNS 镜像版本 >= 1.15.16(以获得禁用 dummy 网卡创建/删除的开关);为 node-cache 追加-skipteardown=true-setupinterface=false-setupiptables=false参数;DaemonSet 设置hostNetwork: false使其运行在非宿主机命名空间;Corefile 中绑定0.0.0.0而非静态 IP,并相应调整 health-check 与 readinessProbe 的地址配置。

部署对应的 LRP

使用 examples/kubernetes-local-redirect/node-local-dns-lrp.yaml 将 DNS 流量导向本地缓存:

kubectl apply -f examples/kubernetes-local-redirect/node-local-dns-lrp.yaml

注意事项:示例默认以kube-dns作为集群 DNS Service,若实际名称不同需修改;策略命名空间需与集群 DNS Service 所在命名空间一致;示例使用dnsdns-tcp两个端口名,需与部署 yaml 中的端口名保持一致。

验证与排障

所有node-local-dnsPod 就绪后,DNS 流量即会先走本地缓存。可通过访问<node-local-dns Pod IP>:9253/metrics观察coredns_dns_requests_total指标是否随应用 Pod 发起 DNS 请求而增长来确认。

排障三步走:

  1. 确认 node-local-dns Pod 运行就绪

    kubectl --namespace kube-system get pods --selector=k8s-app=node-local-dns # node-local-dns-72r7m 1/1 Running 0 2d2h
  2. 用本文主角cilium-dbg lrp list检查策略是否在所有 agent 上正确生效

    kubectl exec -it cilium-mhnhz -n kube-system -- cilium-dbg lrp list # LRP namespace LRP name FrontendType Matching Service # kube-system nodelocaldns clusterIP + all svc ports kube-system/kube-dns # | 10.96.0.10:53/UDP -> 10.244.1.49:53(kube-system/node-local-dns-72r7m), # | 10.96.0.10:53/TCP -> 10.244.1.49:53(kube-system/node-local-dns-72r7m),
  3. 检查LocalRedirectService 条目是否创建:若条目缺失,可能是策略应用与 node-local DNS DaemonSet Pod 资源之间存在竞态,可尝试重启 node-local DNS DaemonSet Pod;问题持续时建议在官方仓库提交 issue 并附带 sysdump 数据:

    kubectl exec -it cilium-mhnhz -n kube-system -- cilium-dbg service list | grep LocalRedirect # 11 10.96.0.10:53 LocalRedirect 1 => 10.244.1.49:53 (active)

总结

Local Redirect Policy 借助 Cilium eBPF 数据面,将“匹配指定地址/Service 的流量在节点内就地重定向”变成了声明式配置:cilium-dbg lrp list负责从 agent 侧快速查看策略与前后端映射,CiliumLocalRedirectPolicyCRD 负责声明AddressMatcherServiceMatcher两种匹配语义,pkg/loadbalancer/redirectpolicy控制器与LocalRedirect服务条目则构成其数据面落地路径。无论是节点级 DNS 缓存、还是将特定 IP:端口 流量导向本机代理,掌握上述命令、配置与验证手段即可在生产集群中可靠落地,并通过cilium-dbg lrp listcilium-dbg service list的组合完成日常巡检与排障。

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询