ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Cilium L2 Announcements 与 L2 Aware LB 实战指南:让 Service 在局域网内“看得见、连得上“

Cilium L2 Announcements 与 L2 Aware LB 实战指南:让 Service 在局域网内“看得见、连得上“ Cilium L2 Announcements 与 L2 Aware LB 实战指南让 Service 在局域网内看得见、连得上【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/ciliumL2 Announcements 是 Cilium 提供的一项让 Kubernetes Service 在本地局域网L2 网络上可见且可达的功能主要面向没有 BGP 路由的本地机房 / 办公 / 园区网络场景。本文以 Documentation/network/l2-announcements.rst 为主线结合仓库中 pkg/l2announcer/l2announcer.go、pkg/datapath/l2responder/l2responder.go 等源码实现系统讲解其工作原理、启用配置、CiliumL2AnnouncementPolicy策略、基于 Kubernetes Lease 的 Leader Election、故障切换Failover机制与完整排障流程读完即可在集群中落地并独立排查问题。一、功能概述把 Service VIP 播报给局域网L2 Announcements又称 L2 Aware LB当前为 Beta 特性的核心目标是让 Service 的 IP 在本地局域网上可见、可路由。其工作方式如下当特性启用后Cilium 会响应针对ExternalIPs和/或LoadBalancer IPs的ARPIPv4与NDPIPv6查询。这些 IP 是虚拟 IPVIP并未真正安装在某个网络设备上而是分布在多个节点上。对于每个 Service任意时刻只有一个节点会响应 ARP/NDP 查询并回报自己的 MAC 地址。该节点借助 Cilium 自带的 Service 负载均衡能力将流量转发到后端 Pod从而扮演**南北向负载均衡器North/South Load Balancer**的角色。与 NodePort 方案相比L2 Announcements 有显著优势维度NodePortL2 AnnouncementsIP 唯一性所有 Service 共享节点 IP端口冲突受限每个 Service 可拥有唯一 IP多个 Service 可复用相同端口号故障转移客户端决定发往哪个节点节点宕机后 IP端口组合即不可用Service VIP 会随 Leader 选举自动迁移到另一节点流量持续可用从源码层面看这一行为由 pkg/l2announcer/l2announcer.go 中的L2Announcer组件驱动它汇总所有CiliumL2AnnouncementPolicy筛选出与本地节点标签匹配的策略再找出匹配策略的 Service对每个 Service 尝试抢占 Lease持有 Lease 的节点将「IP 网络设备」组合写入 StateDB 的L2AnnounceTable最终由数据面datapath组件消费并处理对应流量。二、启用配置Helm 与 ConfigMap 两种方式启用 L2 Announcements 及其全部前置要求可以通过 Helm 或直接修改 ConfigMap 两种方式。方式一Helmhelm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \ --set l2announcements.enabledtrue \ --set k8sClientRateLimit.qps{QPS} \ --set k8sClientRateLimit.burst{BURST} \ --set kubeProxyReplacementtrue \ --set k8sServiceHost${API_SERVER_IP} \ --set k8sServicePort${API_SERVER_PORT}方式二ConfigMapenable-l2-announcements: true kube-proxy-replacement: true k8s-client-qps: {QPS} k8s-client-burst: {BURST}⚠️ 重要提醒由于该特性会显著增加对 Kubernetes API Server 的访问量合理设置客户端速率限制k8sClientRateLimit.qps与k8sClientRateLimit.burst非常关键。默认的 5 QPS / 突发 10 QPS 很快就会被 L2 Announcements 的 Leader Election 流量耗尽具体计算方法见下文「QPS 估算」小节。在 pkg/option/config.go 中可以看到对应的选项定义EnableL2Announcementsenable-l2-announcements、L2AnnouncerLeaseDurationl2-announcements-lease-duration、L2AnnouncerRenewDeadlinel2-announcements-renew-deadline、L2AnnouncerRetryPeriodl2-announcements-retry-period它们最终被读取进DaemonConfig供 pkg/l2announcer/l2announcer.go 使用。前置条件必须启用 Kube Proxy Replacement 模式即kubeProxyReplacementtrue/kube-proxy-replacement: true。所有参与 L2 Aware LB 播报的网络设备必须被启用并纳入设备列表如果显式设置了--devices标志对应 Helm 的devices选项则相关设备必须包含在内否则不会在这些设备上播报。已知限制入口无负载均衡受 L3→L2 转换协议的工作方式所限某个 IP 的所有 ARP/NDP 请求都会到达同一个节点因此流量进入集群之前不存在负载均衡。节点负载可能不均衡当前特性没有流量均衡机制同一策略下的节点可能被不对称地加载详见下文「Leader Election」。与externalTrafficPolicy: Local不兼容可能导致 Service IP 在没有 Pod 的节点上被播报从而造成流量丢弃详见「排障」章节。三、CiliumL2AnnouncementPolicy精细控制播什么、在哪播、怎么播策略Policy用于精细控制哪些 Service 应被播报、在哪些节点上播报、以及通过哪些接口播报。下面是一个使用了全部可选字段的完整示例apiVersion: cilium.io/v2alpha1 kind: CiliumL2AnnouncementPolicy metadata: name: policy1 spec: serviceSelector: matchLabels: color: blue nodeSelector: matchExpressions: - key: node-role.kubernetes.io/control-plane operator: DoesNotExist interfaces: - ^eth[0-9] externalIPs: true loadBalancerIPs: true该 CRD 的类型定义位于 pkg/k8s/apis/cilium.io/v2alpha1/l2announcement_types.go对应的 CRD 清单位于 pkg/k8s/apis/cilium.io/client/crds/v2alpha1/ciliuml2announcementpolicies.yaml是集群级Cluster 作用域资源短名为l2announcement。3.1 Service Selector服务选择器serviceSelector是一个标准 Kubernetes 标签选择器决定哪些 Service 被此策略选中未提供时策略选中所有 Service。被选中的 Service 必须满足loadBalancerClass未设置、或显式设置为io.cilium/l2-announcer该常量在源码中定义为L2AnnounceLoadBalancerClass见 l2announcement_types.go。除标签外还支持两个特殊用途的选择器字段它们不匹配标签而是匹配.meta元数据选择器匹配字段io.kubernetes.service.namespace.meta.namespaceio.kubernetes.service.name.meta.name源码层面l2announcer.go 中的svcAndMetaLabels()会把 Service 的命名空间和名称注入标签集合从而让上述两个特殊选择器可以正常工作。3.2 Node Selector节点选择器nodeSelector是一个标签选择器决定哪些节点是候选播报节点。由于被选中的节点见 Leader Election 小节将充当特定 Service 全部流量的南北向负载均衡器通常建议挑选集群中的一小部分节点来承担该角色例如排除 control-plane 节点如示例所示。3.3 Interfaces接口选择器interfaces是一组正则表达式Go 正则语法决定选中的 Service 在哪些网络接口上被播报该字段可选未指定时使用所有接口。多个表达式之间是OR 关系即任何匹配任一表达式的网络设备都会被选中。L2 播报仅当所选设备同时属于devicesHelm 选项中指定的设备集合时才生效。⚠️注意此选择器不是安全功能——即使不在指定接口播报Service 仍可通过其他方式例如手工硬编码 ARP/NDP 表项在接口上访问。3.4 IP 类型externalIPs 与 loadBalancerIPsexternalIPs和loadBalancerIPs决定播报哪种类型的 IP两者默认均为false因此一个可用的策略应至少将其中一个设为true。externalIPs: true播报 Service.spec.externalIPs字段中的所有 IP。这些 IP 由 Service 作者自行管理。loadBalancerIPs: true播报 Service.status.loadbalancer.ingress字段中的所有 IP。这些 IP 可由 Cilium 的 LB-IPAMlb_ipam分配集群管理员可配置其分配规则以更好地控制 IP。提示如果打算使用externalIPs应同时设置externalIPs.enabletrue这个 Helm 选项以启用对 External IP 的 Service 负载均衡。3.5 Status策略错误的状态反馈如果策略因任何原因无效其Status会如实反映。例如当提供了非法的 matchExpression 时$ kubectl describe l2announcement Name: policy1 Namespace: Labels: none Annotations: none API Version: cilium.io/v2alpha1 Kind: CiliumL2AnnouncementPolicy Metadata: #[...] Spec: #[...] Service Selector: Match Expressions: Key: something Operator: NotIn Values: Status: Conditions: Last Transition Time: 2023-05-12T15:39:01Z Message: values: Invalid value: []string(nil): for in, notin operators, values set cant be empty Observed Generation: 1 Reason: error Status: True Type: io.cilium/bad-service-selector从源码看l2announcer.go 中的updatePolicyStatus()会针对三类校验分别维护条件类型io.cilium/bad-node-selector节点选择器解析失败、io.cilium/bad-service-selector服务选择器解析失败、io.cilium/bad-interface-regex接口正则编译失败。用户修正策略后对应条件的Status会自动变为False以表示错误已消除。四、Leader Election保证同一 VIP 只有一个应答者由于 ARP/NDP 的工作机制主机为每个 IP 只保存一条 MAC 记录即最近一次应答者。这意味着集群中同一时刻只允许一个节点应答某个 VIP 的请求。4.1 工作原理为了实现这一点每个 Cilium agent 都会解析自己节点上被选中的 Service并为每个 Service 参与 Leader Election。其实现基于 Kubernetes 的Lease 机制每个 Service 对应一个 LeaseLease 持有者会在被选中的接口上开始应答 ARP/NDP 请求Lease 的选取顺序是先到先得first come, first serve最先抢到 Lease 的节点成为持有者。这也是可能导致流量不对称分布的原因。源码实现位于 pkg/l2announcer/l2announcer.goaddSelectedService()会为每个被选中的 Service 创建一个resourcelock.LeaseLock并启动一个独立的 leader-election 协程serviceLeaderElection基于k8s.io/client-go/tools/leaderelection成为 Leader 后通过recalculateL2EntriesTableEntries()将「IP 接口」条目写入 StateDB 的L2AnnounceTable表结构见 pkg/datapath/tables/l2_announce.go。4.2 查看 LeasesLease 创建在 Cilium 部署所在的命名空间通常是kube-system$ kubectl -n kube-system get lease NAME HOLDER AGE cilium-l2announce-default-deathstar worker-node 2d20h cilium-operator-resource-lock worker-node2-tPDVulKoRK 2d20h kube-controller-manager control-plane-node_9bd97f6c-cd0c-4565-8486-e718deb310e4 2d21h kube-scheduler control-plane-node_2c490643-dd95-4f73-8862-139afe771ffd 2d21h以cilium-l2announce-开头的 Lease 即本特性创建名称最后部分是「命名空间.服务名」HOLDER列显示当前持有 Lease 的节点名也就是正在播报该 Service IP 的节点。Lease 名称的拼接规则在源码中有明确实现newLeaseLock()格式为cilium-l2announce-namespace.service-name。查看单个 Lease 的详细内容$ kubectl -n kube-system get lease/cilium-l2announce-default-deathstar -o yaml apiVersion: coordination.k8s.io/v1 kind: Lease metadata: creationTimestamp: 2023-05-09T15:13:32Z name: cilium-l2announce-default-deathstar namespace: kube-system resourceVersion: 449966 uid: e3c9c020-6e24-4c5c-9df9-d0c50f6c4cec spec: acquireTime: 2023-05-09T15:14:20.108431Z holderIdentity: worker-node leaseDurationSeconds: 3 leaseTransitions: 1 renewTime: 2023-05-12T12:15:26.773020Z字段含义acquireTime当前 Leader 取得 Lease 的时间holderIdentity当前持有者Leader节点名leaseDurationSeconds若 Leader 在该时长内未续租将选出新 LeaderleaseTransitionsLease 换手的次数renewTimeLeader 最后一次续租的时间。4.3 三个可调 Lease 参数Helm 选项含义默认值约束l2announcements.leaseDuration决定leaseDurationSeconds即 Leader 失联多久后触发故障转移15s必须大于 1s且大于leaseRenewDeadlinel2announcements.leaseRenewDeadlineLeader 续租的间隔5s必须比leaseRetryPeriod大至少 20%且不得低于 1nsl2announcements.leaseRetryPeriod续租失败后的重试等待时间2s必须比leaseRenewDeadline小至少 20%且大于 1ns故障转移时间窗口理论最短故障转移时间为leaseDuration - leaseRenewDeadline最长为leaseDuration leaseRenewDeadline。默认值下故障转移发生在10s 到 20s之间使用下面的示例参数则为2s 到 4s。以更激进的故障转移参数为例Helm 方式helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \ --set l2announcements.enabledtrue \ --set kubeProxyReplacementtrue \ --set k8sServiceHost${API_SERVER_IP} \ --set k8sServicePort${API_SERVER_PORT} \ --set k8sClientRateLimit.qps{QPS} \ --set k8sClientRateLimit.burst{BURST} \ --set l2announcements.leaseDuration3s \ --set l2announcements.leaseRenewDeadline1s \ --set l2announcements.leaseRetryPeriod200msConfigMap 方式enable-l2-announcements: true kube-proxy-replacement: true l2-announcements-lease-duration: 3s l2-announcements-renew-deadline: 1s l2-announcements-retry-period: 200ms k8s-client-qps: {QPS} k8s-client-burst: {BURST}权衡取舍更快的故障检测意味着更高的 CPU 与网络开销——每个 Service 都会带来一定的 CPU 和网络开销。Service 数量少的集群可以更容易承受更快的故障转移时间大规模集群若开销过高可能需要适当增大这些参数。值得一提的是l2announcer.go 中的leaseTimings()会对用户配置做健壮性校验如果leaseDuration 1s、renewDeadline 1ns、retryPeriod 1ns、leaseDuration renewDeadline或renewDeadline不满足与retryPeriod的 20% 比例约束都会以警告日志形式覆盖为安全默认值。4.4 QPS 估算如何设置客户端速率限制Leader Election 会持续产生 API 流量具体数量取决于配置的 lease duration、renew deadline 以及使用该特性的 Service 数量。默认客户端速率限制为5 QPS、突发 10 QPS在启用 L2 Announcements 时很快就会被打满因此必须按需调整。在最坏场景Service 分布不均下峰值负载可基于 renew deadline 估算QPS #services * (1 / leaseRenewDeadline) // example #services 65 leaseRenewDeadline 2s QPS 65 * (1 / 2s) 32.5 QPS在多节点场景下Lease 会分散在各节点上且未持有 Lease 的参与节点 QPS 更低因此将基础 QPS 设为计算值附近通常足够突发 QPSburst应略高于计算值以容忍其他同样访问 API Server 的特性带来的流量突发。4.5 Failover故障转移流程参与 Leader Election 的节点检测到 Lease 持有者超过leaseDurationSeconds未续租它们会向 API Server 请求让自己成为新持有者第一个被处理的请求成功其余被拒绝节点成为新 Leader 后会在所有配置的接口上发送免费 ARP 应答Gratuitous ARP接受免费 ARP 的客户端会立即更新 ARP 表将流量发送给新 Leader⚠️ 并非所有客户端都接受免费 ARP因为可能被用于 ARP 欺骗这类客户端只有在自身 ARP 表 TTL 到期重新查询时才会切换因此实际停机时间可能比 Lease 配置的更长。源码中garpOnNewEntry()见 pkg/datapath/l2responder/l2responder.go会在 BPF map 中不存在某「IP 接口」条目时即发生了故障转移主动发送 gratuitous ARPIPv6 场景则通过gneighOnNewEntry()发送 NDP Advertisement并同步加入/退出 solicited-node 组播组以保持 NDP 一致性。五、数据面实现从 StateDB 表到 BPF 应答 Map整个 L2 Announcements 的落地点是 BPF 数据面。架构上分三层L2Announcerpkg/l2announcer/l2announcer.go计算期望状态——哪些「VIP 接口」组合应该由本节点应答写入 StateDB 表l2-announce。L2 Responder Reconcilerpkg/datapath/l2responder/l2responder.go监听该表的增量变化将其调和reconcile进两个 BPF mapcilium_l2_responder_v4与cilium_l2_responder_v6除增量同步外还每 5 分钟做一次全量调和作为冗余保障。BPF 数据面bpf/lib/l2_responder.h在收到 ARP/NDP 请求时查询 map命中则用本节点 MAC 地址应答并累加responses_sent统计字段。两个 map 的最大条目数在 bpf/node_config.h 中定义为L2_RESPONDER_MAP4_SIZE 4096与L2_RESPONDER_MAP6_SIZE 4096。仓库还提供了对应的 BPF 单元测试如 bpf/tests/tc_l2_announcement.cIPv4 ARP 应答与 bpf/tests/tc_l2_announcement6.cIPv6 NDP 应答验证了向cilium_l2_responder_v4/v6map 写入条目后 ARP/NDP 应答确实生效。六、Troubleshooting从启用检查到数据面验证本节提供逐步排障指南帮助你定位问题或将其缩小到特定领域。步骤 1确认特性已启用$ kubectl -n kube-system exec ds/cilium -- cilium-dbg config --all | grep EnableL2Announcements EnableL2Announcements : true $ kubectl -n kube-system exec ds/cilium -- cilium-dbg config --all | grep KubeProxyReplacement KubeProxyReplacement : true $ kubectl -n kube-system exec ds/cilium -- cilium-dbg config --all | grep EnableExternalIPs EnableExternalIPs : true如果EnableL2Announcements或KubeProxyReplacement为false请修正配置并重新部署 Helm Chart见上文「启用配置」如果打算使用 External IPEnableExternalIPs应设为true。步骤 2确认至少有一个策略L2 Announcements没有策略就不会工作$ kubectl get CiliumL2AnnouncementPolicy NAME AGE policy1 6m16s步骤 3检查 Lease 是否创建L2 Announcements 应为每个被策略匹配的 Service 创建一个 Lease$ kubectl -n kube-system get lease | grep cilium-l2announce cilium-l2announce-default-service-red kind-worker 34s如果输出为空说明策略配置不正确或 agent 运行异常。查看 agent 日志$ kubectl -n kube-system logs ds/cilium | grep l2常见错误一agent 无法创建 Lease通常因为未使用 Helm Chart 部署导致 ClusterRole 权限缺失$ kubectl -n kube-system logs ds/cilium | grep error time2024-06-25T12:01:43Z levelerror msgerror retrieving resource lock kube-system/cilium-l2announce-default-service-red: leases.coordination.k8s.io \cilium-l2announce-default-service-red\ is forbidden: User \system:serviceaccount:kube-system:cilium\ cannot get resource \leases\ in API group \coordination.k8s.io\ in the namespace \kube-system\ subsysklog解决办法重新部署 Helm Chart或手动更新 ClusterRole$ kubectl edit clusterrole cilium在rules中加入以下权限块- apiGroups: - coordination.k8s.io resources: - leases verbs: - create - get - update - list - delete常见错误二客户端速率限制配置过低。日志中会出现客户端侧限流的提示$ kubectl -n kube-system logs ds/cilium | grep l2 2023-07-04T14:59:51.959400310Z levelinfo msgWaited for 1.395439596s due to client-side throttling, not priority and fairness, request: GET:https://127.0.0.1:6443/apis/coordination.k8s.io/v1/namespaces/kube-system/leases/cilium-l2announce-default-example subsysklog 2023-07-04T15:00:12.159409007Z levelinfo msgWaited for 1.398748976s due to client-side throttling, not priority and fairness, request: PUT:https://127.0.0.1:6443/apis/coordination.k8s.io/v1/namespaces/kube-system/leases/cilium-l2announce-default-example subsysklog这类日志与续租间歇性失败、连接问题、频繁的 Leader 变更相关请参考上文「QPS 估算」小节调整速率限制。如果遇到其他 L2 相关的错误请携带错误信息与复现步骤到 GitHub 提交 Issue。步骤 4检查 agent 内部状态假设 Lease 已创建接下来检查 agent 内部状态。选一个不工作的 Service查看其 Lease 的HOLDER找到持有者节点对应的 cilium agent Pod然后检查 l2-announce 状态$ kubectl -n kube-system get lease cilium-l2announce-default-service-red NAME HOLDER AGE cilium-l2announce-default-service-red node-name 20m $ kubectl -n kube-system get pod -l app.kubernetes.io/namecilium-agent -o wide | grep node-name agent-pod 1/1 Running 0 35m 172.19.0.3 kind-worker none none $ kubectl -n kube-system exec pod/agent-pod -- cilium-dbg shell -- db/show l2-announce # IP NetworkInterface 10.0.10.0 eth0l2-announce 状态应包含 Service 的 IP 及其播报所对应的网络接口。如果 Lease 存在但其 IP 不在 l2-announce 状态中或缺少某个网络设备的条目复查策略中的设备选择器是否匹配目标设备注意其值是正则表达式如果过滤器看起来正确或未指定检查 agent 已知的设备列表$ kubectl -n kube-system exec ds/cilium -- cilium-dbg shell -- db/show devices Name Index Selected Type MTU HWAddr Flags Addresses lxc5d23398605f6 10 false veth 1500 b6:ed:d8:d2:dd:ec up|broadcast|multicast fe80::b4ed:d8ff:fed2:ddec lxc3bf03c00d6e3 12 false veth 1500 8a:d1:0c:91:8a:d3 up|broadcast|multicast fe80::88d1:cff:fe91:8ad3 eth0 50 true veth 1500 02:42:ac:13:00:03 up|broadcast|multicast 172.19.0.3, fc00:c111::3, fe80::42:acff:fe13:3 lo 1 false device 65536 up|loopback 127.0.0.1, ::1 cilium_net 2 false veth 1500 1a:a9:2f:4d:d3:3d up|broadcast|multicast fe80::18a9:2fff:fe4d:d33d cilium_vxlan 4 false vxlan 1500 2a:05:26:8d:79:9c up|broadcast|multicast fe80::2805:26ff:fe8d:799c lxc611291f1ecbb 8 false veth 1500 7a:fb:ec:54:e2:5c up|broadcast|multicast fe80::78fb:ecff:fe54:e25c lxc_health 16 false veth 1500 0a:94:bf:49:d5:50 up|broadcast|multicast fe80::894:bfff:fe49:d550 cilium_host 3 false veth 1500 22:32:e2:80:21:34 up|broadcast|multicast 10.244.1.239, fd00:10:244:1::f58a只有Selected为true的设备才能用于 L2 Announcements通常所有分配了 IP 的物理设备都会被选中可用--devices标志或devicesHelm 选项过滤设备若目标设备在列表中但未被选中请检查该标志/选项是否将其过滤掉了若设备未出现在列表或未被选中而你确信它应该被选中请到 GitHub 提交 Issue。步骤 5测试 ARP 应答如果 l2-announce 状态中已包含 IP 与设备的组合但仍存在连接问题说明需要测试集群内的 ARP。挑选一个与 Lease 持有者处于同一 L2 网络的 cilium agent Pod非持有者向 Service IP 发送 ARP 请求$ kubectl -n kube-system exec pod/cilium-z4ef7 -- sh -c apt update apt install -y arping arping -i netdev-on-l2 service-ip [omitting apt output...] ARPING 10.0.10.0 58 bytes from 02:42:ac:13:00:03 (10.0.10.0): index0 time11.772 usec 58 bytes from 02:42:ac:13:00:03 (10.0.10.0): index1 time9.234 usec 58 bytes from 02:42:ac:13:00:03 (10.0.10.0): index2 time10.568 usec如果输出如上图所示但同一 L2 网络内的客户端仍无法访问问题可能出在客户端侧如果期望从 L2 网络外部访问却不成功请检查网关设备的 ARP 与路由表。如果 ARP 请求失败输出显示Timeout检查持有 Lease 的 cilium-agent 的 BPF map$ kubectl -n kube-system exec pod/cilium-vxz67 -- bpftool map dump pinned /sys/fs/bpf/tc/globals/cilium_l2_responder_v4 [{ key: { ip4: 655370, ifindex: 50 }, value: { responses_sent: 20 } } ]responses_sent字段在数据面每次应答 ARP 请求时递增若为0说明 ARP 请求根本没有到达该节点问题在入向路径若大于0说明问题出在回程路径两种情况都需要检查网络与客户端。步骤 6排查 ExternalTrafficPolicy 相关丢包即使 ARP 请求得到应答Service 仍可能不可达——这通常与 L2 Announcements 无关而是其他 Cilium 特性导致。但有一个常见问题与本特性直接相关Service 上使用了.spec.externalTrafficPolicy: Local。该设置通常告知负载均衡器只向「至少有一个就绪 Pod」的节点转发流量以避免二次跳转但 L2 Announcements 目前不感知此设置会在所有匹配策略的节点上播报 Service IP若流量到达一个没有 Pod 的节点该节点会直接丢弃流量。解决办法将 Service 的.spec.externalTrafficPolicy改为Cluster。若以上步骤均未解决你的问题请携带详细步骤到 GitHub 提交 Issue。七、L2 Pod Announcements直接播报 Pod IPL2 Pod Announcements 是另一个独立启用的特性它通过Gratuitous ARP 应答 / NDP Advertisement在 L2 网络上播报 Pod IP。启用后节点会为每个本地创建的 Pod在配置的网络接口上发送免费 ARP / NDP 通告。启用方式Helmhelm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \ --set l2podAnnouncements.enabledtrue \ --set l2podAnnouncements.interfacePattern^eth0$ConfigMapenable-l2-pod-announcements: true l2-pod-announcements-interface-pattern: ^eth0$interfacePattern/l2-pod-announcements-interface-pattern接受一个正则表达式用于匹配发送通告的接口。匹配多个接口可使用^(eth0|ens1)$这类模式Helmhelm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \ --set l2podAnnouncements.enabledtrue \ --set l2podAnnouncements.interfacePattern^(eth0|ens1)$ConfigMapenable-l2-pod-announcements: true l2-pod-announcements-interface-pattern: ^(eth0|ens1)$该特性的实现位于 pkg/datapath/gneigh/processor.go配置选项EnableL2PodAnnouncements与L2PodAnnouncementsInterfacePattern定义于 pkg/datapath/gneigh/cells.go处理器会按正则匹配出的设备列表发送 gratuitous ARP/NDP 消息若未设置接口正则则直接报错返回。⚠️注意该特性目前尚不支持 IPv6——只发送 ARP 消息不会发送 Unsolicited Neighbor Advertisements。八、总结L2 Announcements 为无 BGP 的局域网场景提供了一条极简的 Service 暴露路径通过CiliumL2AnnouncementPolicy精细控制播报范围借助 Kubernetes Lease 实现 VIP 的单点应答与故障自动迁移最终由 BPF 数据面完成 ARP/NDP 应答与负载均衡。上手时请务必牢记三件事开启 kube-proxy-replacement、合理估算客户端 QPS 限制、至少配置一条策略——这三点是特性正常工作的基石。若需进一步深入可继续阅读仓库中的源码与测试pkg/l2announcer/l2announcer_test.go、pkg/datapath/l2responder/l2responder_test.go 以及 BPF 测试 bpf/tests/tc_l2_announcement.c。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进