TT Lab
开始
学习 学习路径 课程

CCA — Cilium 认证助理

BGP 控制平面与 Egress Gateway — 通往集群之外的路

在 TT Lab 中继续学习

一句话总结

BGP Control Plane 通过 BGP 向邻居路由器通告节点的 Pod CIDR 和服务 VIP,开辟从外部进入集群内部的路径;Egress Gateway 则让特定 Pod 在访问外部时经过指定的节点和 IP。不对数据路径编程的是 BGP Control Plane。Egress Gateway 会把选中的发往外部的数据包转发到网关节点,并对源地址做 SNAT,因此会改变实际的数据路径行为。必须区分通告路由和处理数据包这两件事。

为什么需要它

如果外部路由器不知道通往 Pod CIDR 的路径,仅凭 Pod IP 是无法到达的。但这并不意味着 Pod IP 本质上只能在集群内部使用,也不意味着外部访问必须经过 NAT。只要有合适的往返路径以及数据路径和策略,就可以直接路由。在使用 BGP 的环境中,Cilium 通告路由,让外部路由器学到下一跳。服务 VIP 也是如此:被分配地址和从外部能够到达该地址,是两件不同的事。

反方向也有问题。Pod IP 不断变化,节点 IP 也会变化,而旧防火墙的工作方式是“只允许来自这个 IP 的流量”。文档恰恰以这个案例来说明 Egress Gateway 的用途:让特定命名空间的 Pod 访问旧基础设施时,使用可预测的 IP 出去。CCA 的 BGP & External Networking 领域(6%)会考查这两项功能的作用和限制。

工作原理

BGP Control Plane 做什么、不做什么

文档的第一句话划定了范围。BGP Control Plane 向通过 BGP 连接的路由器通告路由,让 Pod 网络和服务能够从集群外部访问到。同时它明确说明“不会对数据路径编程,因此不要用它来保证集群内部的可达性”。开启方法是 bgpControlPlane.enabled=true,agent 只会通告已配置的地址族。只配置为使用 IPv4 的 agent 无法通告 IPv6 路由。

四种资源

资源 作用
CiliumBGPClusterConfig 应用于 nodeSelector 所选节点的 BGP 实例(localASN)和 peer(peerASN、peerAddress、peerConfigRef)
CiliumBGPPeerConfig 多个 peer 共享的会话配置——计时器、MD5 认证、eBGP multihop、graceful restart、transport、地址族和通告选择器
CiliumBGPAdvertisement 要放入路由表的前缀类型和属性(community、localPreference)
CiliumBGPNodeConfigOverride 按节点分别设置的不同取值
apiVersion: cilium.io/v2
kind: CiliumBGPClusterConfig
metadata: {name: cilium-bgp}
spec:
  nodeSelector: {matchLabels: {rack: rack0}}
  bgpInstances:
  - name: instance-65000
    localASN: 65000
    peers:
    - name: peer-65000-tor1
      peerASN: 65000
      peerAddress: fd00:10:0:0::1
      peerConfigRef: {name: cilium-peer}
---
apiVersion: cilium.io/v2
kind: CiliumBGPAdvertisement
metadata: {name: bgp-advertisements, labels: {advertise: bgp}}
spec:
  advertisements:
  - advertisementType: PodCIDR
  - advertisementType: Service
    service: {addresses: [LoadBalancerIP]}
    selector: {matchExpressions: [{key: bgp, operator: In, values: [blue]}]}

PeerConfig 的 families[].advertisements 是标签选择器。上面示例中的 advertise: bgp 标签必须匹配该选择器,通告才会真正发出。把资源都创建好了却什么都没有通告时,先检查这个标签。

默认行为中容易搞错的地方

这里把文档中的三点照录如下。第一,BGP 实例默认不带监听端口启动。这样设计是为了让同一节点上可以运行 Bird 之类的其他 BGP 路由器,所以 Cilium 只发起连接,不接收连接。需要接收时要设置 localPort,而 179 号端口需要 CAP_NET_BIND_SERVICE。第二,计时器默认值为 connectRetry 120 秒、hold 90 秒、keepalive 30 秒,文档建议在数据中心中降低到类似 hold 9 秒、keepalive 3 秒的值。第三,开启 graceful restart 后,即使 agent 重启,peer 也不会立刻撤掉路由,因此数据路径会继续转发。默认 RestartTime 为 120 秒。

通告什么

PodCIDR 通告发出的是分配给该节点的 Pod CIDR,而不是整个范围。这只在 Kubernetes 或 ClusterPool IPAM 下有效;在 MultiPool IPAM 中,则用 CiliumPodIPPool 类型,以选择器选出资源池并通告。在其他 IPAM 下,PodCIDR 类型不起任何作用。服务通告是在 service.addresses 中选择 LoadBalancerIP、ClusterIP、ExternalIP 填入,VIP 以精确的 /32 或 /128 路由发出。如果多个节点通告同一个 VIP,上游路由器会用 ECMP 分担负载,但可能超过路由器的 ECMP 路径数上限,因此文档附有警告,要求先与网络负责人确认。会话状态用 cilium bgp peers 查看。

Egress Gateway——固定出口路径

Egress Gateway 会把从 Pod 发往特定集群外部 CIDR 的 IPv4、IPv6 连接送到指定的网关节点,并用该节点可预测的 IP 做 masquerade。要启用它,除了 egressGateway.enabled=true 之外,BPF masquerade 和 kube-proxy 替代都必须已开启。策略资源是集群范围的 CiliumEgressGatewayPolicy,用 selectors[].podSelector 指定源 Pod(命名空间用 io.kubernetes.pod.namespace 标签),用 destinationCIDRs 指定目的地,用 excludedCIDRs 指定例外。内部集群 IP(Pod、节点、API 服务器)即使落在目的地范围内,也会被排除在 SNAT 对象之外。

限制同样明确。新 Pod 在策略生效之前存在延迟,期间可能以 Pod IP 或节点 IP 出去;不能与 Cluster Mesh 一起使用,也与把身份存储放在 kvstore 的模式以及 CiliumEndpointSlice 不兼容。

在现场相遇的样子

BGP 会话为 Established,并不能证明服务一定可达。先确认 peer 的地址、AS 和连接状态,再查看接收路由表(RIB)中是否有目的前缀。如果有路由,就确认选中的下一跳和内核转发路径(FIB),再用真实请求继续验证。如果没有路由,先从通告选择器和地址分配查起;如果有路由但请求失败,则调查服务后端、数据路径、策略和回程路径。不能仅凭一次 timeout 就断定是认证失败或策略阻断。

开启 Egress Gateway 之后,常会收到“部分请求仍然以节点 IP 出去”的报告,原因多半是新启动的 Pod 在策略生效之前存在延迟。如果防火墙一侧只允许网关 IP,这段短暂时间内的请求就会被拒绝。

通过实测区分出的五种状态

LabHub 于 2026-09-12 在个人 VM 上做的探测,把 Cilium 1.20.1 与 FRR 8.4.4 连接起来,比较了下面这些状态。FRR 放在充当外部路由器的网络命名空间中,没有加入默认路由。这里所说“没有路由”,指的是没有通往实验目的地的路由,并不是说路由器连直连网络的路由也全都没有。

状态 peer 目的地 RIB 目的地 FIB 实际 Pod HTTP
配置 peer 之前 Idle 无 无 连接失败
仅连接 peer Established 无 无 连接失败
通告 PodCIDR,保持 FRR 的 bgp no-rib Established 有 无 连接失败
应用 FRR 的 no bgp no-rib Established 有 有 200
撤回 PodCIDR 通告之后 Established 无 无 连接失败

bgp no-rib 是这次探测中有意把 BGP 学习与内核路由安装分开的 FRR 配置。这并不意味着开启 Cilium 的通告后,FRR 的转发配置也会自动得到解决。分配到的节点 PodCIDR 是 10.42.0.0/24,而不是整个配置池 10.42.0.0/16。失败时 curl 的退出码为 7,输出为 000。000 不是服务器给出的 HTTP 状态码,也不能把这个结果改称为 NetworkPolicy 的 timeout 阻断。必须把观测点和命令的退出码也记录下来,才能与其他失败区分开。

之后在另一组比较中,只通告所选服务 VIP 的 /32,并确认未通告的其他 VIP 以及直接访问 Pod 都会失败。与独立的外部机器不同,在同一 VM 中创建的路由器命名空间可能会受到 socket-LB 的影响。临时加入 Pod 路由后,连未通告的 VIP 也访问成功,使比较变得模糊。最终在确认 socketLB.hostNamespaceOnly=true 已应用到运行中的 agent 之后,确认在没有 Pod 路由和默认路由的情况下,只有所选 VIP 返回 200。不应把这项配置当成所有生产故障的万能解决方案,而应把它当作检查实验环境是否改变了测量对象的案例来读。

这张表是开发用探测的结果,并不是学习者已在平台上完成新的 BGP 实验的证据。后续实验会把各个对比状态分开,使得在最后一步之后也能对全部步骤重新评分。官方行为可以在FRR 8.4 BGP和Cilium socket-LB 绕过中确认。

下一项测验要确认什么

测验会考查:Gateway API 资源的作用和流量分割字段,Cilium 与其他控制器的不同之处(eBPF 拦截、ingress 身份),每个节点一个 Envoy 的结构,WireGuard 的密钥分发和端口,BGP 四种资源的作用,PodCIDR 通告范围与 VIP 路由前缀长度,监听端口的默认值,以及 Egress Gateway 的前置条件。参考:Cilium BGP Control Plane,BGP Control Plane Resources,Egress Gateway。