配置使用 MetalLB 进行捆绑式负载均衡

本页面介绍如何使用 MetalLB for Google Distributed Cloud 配置捆绑式负载均衡。MetalLB 负载均衡器在专用的工作器节点池或与控制平面相同的节点上运行。

如需查看 Google Distributed Cloud 中提供的负载均衡拓扑示例,请参阅负载均衡器概览

要求

  • 所有负载均衡器节点都必须位于同一 L2 子网中。
  • 所有 VIP 都必须位于负载均衡器的节点子网中,并且可通过子网的网关路由。
  • 负载均衡器子网的网关必须侦听免费 ARP 消息,并将 ARP 数据包转发到负载均衡器节点。

配置字段

修改集群配置文件的 cluster.spec.loadBalancer 部分以配置捆绑式负载均衡。如需了解集群配置文件和有效配置的示例,请参阅以下某个页面:

loadBalancer.mode

此值必须为 bundled 才能启用捆绑式负载均衡。

loadBalancer.ports.controlPlaneLBPort

此值指定发送到 Kubernetes 控制平面(Kubernetes API 服务器)的流量要使用的目标端口。

loadBalancer.vips.controlPlaneVIP

此值指定发送到 Kubernetes 控制平面(Kubernetes API 服务器)的流量要使用的目标 IP 地址。此 IP 地址必须与集群中的节点位于同一个第 2 层子网中。请勿在配置文件的 address pools 部分中列出此地址。

loadBalancer.vips.ingressVIP

此值指定要用于在负载均衡器后用于入站流量的 Service 的 IP 地址。管理员集群配置文件中不允许使用此字段。此地址必须列在配置的地址池部分中。

loadBalancer.addressPools

配置的这一部分包含一个或多个地址池。每个地址池都会指定 IP 地址范围列表。创建 LoadBalancer 类型的 Service 时,系统会从这些范围中选择该 Service 的外部 IP 地址。

地址池按以下格式指定:

- name: POOL_NAME
  avoidBuggyIPs: BOOLEAN
  manualAssign: BOOLEAN
  addresses:
  - IP_RANGE
  - IP_RANGE2
  • name:地址池的名称 (pool-name),以便您进行整理。该字段不可更改。
  • avoidBuggyIPs:(可选)truefalse。如果为 true,则池会忽略以 .0.255 结尾的 IP 地址。某些网络硬件会丢弃流向这些特殊地址的流量。您可以省略此字段,其默认值为 false。 此字段可更改。
  • manualAssign:(可选)truefalse。如果为 true,则此池中的地址不会自动分配给 Kubernetes Service。如果为 true,则只有在服务明确指定时,此池中的 IP 地址才会被使用。您可以省略此字段,其默认值为 false。此字段可更改。
  • addresses:包含一个或多个不重叠的 IP 地址范围的列表。可以用 CIDR 表示法(如 198.51.100.0/24)或范围表示法(如 198.51.100.0-198.51.100.10,短划线前后没有空格)指定 ip-range。该字段不可更改。

addresses 列表中的 IP 地址范围不得重叠,并且必须与运行负载均衡器的节点位于同一子网中。

loadBalancer.nodePoolSpec

配置的这一部分指定要运行负载均衡器的节点列表。默认情况下,负载均衡器节点可以运行常规工作负载;这些节点上没有特殊的污点。虽然负载均衡器节点池中的节点可以运行工作负载,但它们与工作器节点池中的节点是分开的。一个给定的集群节点不能添加到多个节点池中。节点池之间的节点 IP 地址重叠会阻止集群创建和其他集群操作。

如果要阻止工作负载在负载均衡器节点池中的节点上运行,请将以下污点添加到该节点:

node-role.kubernetes.io/load-balancer:NoSchedule

Google Distributed Cloud 会将此污点的容忍设置添加到负载均衡所需的 Pod。

nodePoolSpec:
  nodes:
  - address: 10.0.0.32
  - address: 10.0.0.33

负载均衡器节点池中的所有节点必须与在配置文件的 loadBalancer.addressPools 部分中配置的负载均衡器 VIP 位于同一 L2 子网中。

如果未设置 nodePoolSpec,捆绑式负载均衡器会在控制平面节点上运行。如果可能,建议您在不同的节点池中运行负载均衡器。

控制平面负载均衡

控制平面负载均衡器提供控制平面虚拟 IP 地址 (VIP)。Google Distributed Cloud 将 Keepalived 和 HAProxy 作为负载均衡器节点上的 Kubernetes 静态 pod 运行,以通告控制平面 VIP。keepalived 在负载均衡器节点上使用虚拟路由器冗余协议 (VRRP) 以实现高可用性。

数据平面负载均衡

数据平面负载均衡器用于类型为 LoadBalancer 的所有 Kubernetes Service。Google Distributed Cloud 使用在第 2 层模式下运行的 MetalLB 进行数据平面负载均衡。数据平面负载均衡只能通过 Google Distributed Cloud 进行配置,请勿直接修改 MetalLB ConfigMap。您可以使用所有 MetalBL 功能,包括跨 Service 共享 IP 地址。如需了解功能信息,请参阅 MetalLB 文档。

MetalBL 使用 daemonset 在每个节点上运行一个 speaker pod,通过 memberlist 实现高可用性。每个 Kubernetes Service 都有一个 MetalLB 专用负载均衡器节点,而不是整个集群一个。这样一来,如果存在多个 Service,流量会在负载均衡器节点之间分配。

数据平面负载均衡器可以在控制平面节点或一组工作器节点上运行。将数据平面负载均衡器捆绑到控制平面节点可提高控制平面节点的利用率。但捆绑到控制平面节点也会增加控制平面的过载风险并增加控制平面上的机密信息(如 SSH 密钥)的风险。

保留客户端来源 IP 地址

使用捆绑式第 2 层负载均衡解决方案创建的 LoadBalancer Service 使用外部流量政策的默认 Cluster 设置。spec.externalTrafficPolicy: Cluster 设置会将外部流量路由到集群范围的端点,但也会遮掩客户端来源 IP 地址。

以下部分介绍了如何配置集群以保留客户端来源 IP 地址

NodePort 服务

Kubernetes 会为 NodePort Service 执行来源网络地址转换 (NAT)。如需保留客户端来源 IP 地址,请将 service.spec.externalTrafficPolicy 设置为 Local。Kubernetes 不会再执行来源 NAT,但您必须确保有 Pod 正在您选择的节点 IP 地址上运行。

LoadBalancer 服务

LoadBalancer Service 中使用 externalTrafficPolicy: Local 时,请将应用 pod 设置为在负载均衡器节点上运行。将以下 nodeSelector 添加到您的应用 Pod 以进行此更改:

apiVersion: v1
kind: Pod
...
spec:
  nodeSelector:
      baremetal.cluster.gke.io/lbnode: "true"
...

入站流量

如果您的应用是 HTTP 服务,您可以通过配置入站流量组件来实现客户端 IP 地址可见性:

  1. 打开 istio-ingress Service 进行修改:

    kubectl edit service -n gke-system istio-ingress
    
  2. externalTrafficPolicy: Local 添加到 spec,然后保存并退出编辑器。

    apiVersion: v1
    kind: Service
    ...
    spec:
    ...
      externalTrafficPolicy: Local
    
  3. 打开 istio-ingress Deployment 进行修改:

    kubectl edit deployment -n gke-system istio-ingress
    
  4. 将以下 nodeSelector 添加到 Deployment,然后保存并退出编辑器。

    apiVersion: apps/v1
    kind: Deployment
    ...
    spec:
      ...
      template:
        ...
        spec:
          ...
          nodeSelector:
              baremetal.cluster.gke.io/lbnode: "true"
    ...
    

现在,Ingress 后面的所有服务都会看到具有客户端 IP 地址的 X-Forwarded-For 标头,如以下示例所示:

X-Forwarded-For: 21.0.104.4