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

本文档介绍了如何配置 GKE on VMware,以将捆绑式负载均衡与 MetalLB 负载均衡器结合使用。

在 GKE on VMware 中,MetalLB 以第 2 层模式运行。

MetalLB 配置示例

以下是运行 MetalLB 负载均衡器的集群的配置示例:

MetalLB 负载均衡器配置。
MetalLB 负载均衡器配置

上图显示了 MetalLB 部署。MetalLB 直接在集群节点上运行。在此示例中,管理员集群和用户集群位于两个不同的 VLAN 中,每个集群位于单独的子网中:

集群 子网
管理员集群 172.16.20.0/24
用户集群 172.16.40.0/24

admin-cluster.yaml

管理员集群配置文件的以下示例显示了上图中显示的以下配置:

  • MetalLB 负载均衡器

  • MetalLB 上用于Kubernetes API 服务器和管理员集群插件的 VIP 地址

network:
  hostConfig:
  ...

  ipMode:
    type: "static"
    ipBlockFilePath: "config-folder/admin-cluster-ipblock.yaml"
...

loadBalancer:
  kind: "MetalLB"
  ...

  vips:
    controlPlaneVIP: "172.16.20.100"
    addonsVIP: "172.16.20.101"

admin-cluster-ipblock.yaml

以下示例 IP 地址块文件显示管理员集群中节点的 IP 地址指定。这也包括用户集群的控制平面节点的地址以及要在集群升级期间使用的 IP 地址。

blocks:
- netmask: "255.255.255.0"
  gateway: "17.16.20.1"
  ips:
  - ip: 172.16.20.50
    hostname: admin-vm-1
  - ip: 172.16.20.51
    hostname: admin-vm-2
  - ip: 172.16.20.52
    hostname: admin-vm-3
  - ip: 172.16.20.53
    hostname: admin-vm-4
  - ip: 172.16.20.54
    hostname: admin-vm-5

user-cluster.yaml

以下示例用户集群配置文件显示了以下配置:

  • 供 MetalLB 控制器从中选择并分配给 LoadBalancer 类型的 Service 的地址池。入站流量 VIP 地址在其中一个池内。

  • 为用户集群的 Kubernetes API 服务器指定的 VIP 地址,以及您选择为入站流量代理配置的入站流量 VIP 地址。由于用户集群的控制平面在管理员集群的节点上运行,因此 Kubernetes API 服务器 VIP 地址在管理员集群子网上。

  • 已启用 MetalLB 的节点池。MetalLB 将部署在用户集群中属于该节点池的节点上。

network:
  hostConfig:
  ...

  ipMode:
    type: "static"
    ipBlockFilePath: "config-folder/user-cluster-ipblock.yaml"
...

loadBalancer:
  kind: MetalLB
  metalLB:
    addressPools:
    - name: "address-pool-1"
      addresses:
      - "172.16.40.100/32"
      - "172.16.40.101-172.16.40.112
      avoidBuggyIPs: true
  ...

  vips:
    controlPlaneVIP: "172.16.20.102"
    ingressVIP: "172.16.40.102"
...

nodePools:
- name: "node-pool-1"
  cpus: 4
  memoryMB: 8192
  replicas: 3
  enableLoadBalancer: true

上例中的配置指定了可用于 Service 的一组地址。当应用开发者在用户集群中创建 LoadBalancer 类型的 Service 时,MetalLB 控制器会从该池中选择一个 IP 地址。

user-cluster-ipblock.yaml

以下示例 IP 地址块文件显示用户集群中节点的 IP 地址指定。这包括要在集群升级期间使用的 IP 地址。

blocks:
- netmask: "255.255.255.0"
  gateway: "17.16.40.1"
  ips:
  - ip: 172.16.40.21
    hostname: user-vm-1
  - ip: 172.16.40.22
    hostname: user-vm-2
  - ip: 172.16.40.23
    hostname: user-vm-3
  - ip: 172.16.40.24
    hostname: user-vm-4
  - ip: 172.16.40.25
    hostname: user-vm-5

设置 MetalLB

打开防火墙端口

MetalLB 使用 Go 成员列表库进行领导者选举。memberlist 库使用 TCP 端口 7946 和 UDP 端口 7946 来交换信息。确保所有负载均衡器节点上的传入和传出流量都可以访问这些端口。

为新的管理员集群启用 MetalLB

管理员集群配置文件中,将 loadBalancer.kind 设置为 "MetalLB"

loadBalancer:
  kind: "MetalLB"

填写管理员集群配置文件的其余部分,并按照创建管理员集群中所述创建管理员集群。

指定地址池

MetalLB 控制器可为 Service 执行 IP 地址管理。因此,当应用开发者在用户集群中创建 LoadBalancer 类型的 Service 时,他们无需手动为该 Service 指定 IP 地址。相反,MetalLB controller 会从您在创建集群时指定的地址池中选择 IP 地址。

考虑在任何给定时间用户集群中可能处于活跃状态的 LoadBalancer 类型的 Service 的数量。然后,在用户集群配置文件的 loadBalancer.metalLB.addressPools 部分中,指定足够的 IP 地址来容纳这些 Service。

用户集群的入站流量 VIP 必须是您在地址池中指定的地址之一。这是因为入站流量代理由 LoadBalancer 类型的 Service 公开。

如果应用开发者无需创建 LoadBalancer 类型的 Service,则您无需指定入站流量 VIP 以外的任何地址。

地址必须采用 CIDR 格式或范围格式。如果要指定单个地址,请使用 /32 CIDR。例如:

addresses:
  - "192.0.2.0/26"
  - "192.0.2.64-192.0.2.72"
  - "192.0.2.75/32

如果您需要在创建集群后调整池中的地址,则可以使用 gkectl update cluster。如需了解详情,请参阅更新 MetalLB

为新用户集群启用 MetalLB

用户集群配置文件中,执行以下操作:

  • loadBalancer.kind 设置为 "MetalLB"
  • 为 Service 指定一个或多个地址池。入站流量 VIP 地址必须在其中一个池内。
  • 针对集群中的至少一个节点池,将 enableLoadBalancer 设置为 true

填写用户集群配置文件的其余部分,并按照创建用户集群中所述创建用户集群。

手动分配 Service 地址

如果您不希望 MetalLB 控制器自动将特定池中的 IP 地址分配给 Service,请将池的 manualAssign 字段设置为 true。之后,开发者便可以创建 LoadBalancer 类型的 Service 并手动指定池中的一个地址。例如:

loadBalancer:
  metalLB:
    addressPools:
    - name: "my-address-pool-2"
      addresses:
      - "192.0.2.73-192.0.2.80"
      manualAssign: true

避免存在错误的 IP 地址

如果您将地址池的 avoidBuggyIPs 字段设置为 true,则 MetalLB 控制器将不会使用以 .0 或 .255 结尾的池中的地址。这样可以避免有问题的用户设备错误地丢弃发送到这些特殊 IP 地址的流量。例如:

loadBalancer:
  metalLB:
    addressPools:
    - name: "my-address-pool-1"
      addresses:
      - "192.0.2.0/24"
      avoidBuggyIPs: true

创建 LoadBalancer 类型的 Service

以下是两份清单:一份用于 Deployment,另一份用于 Service:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  selector:
    matchLabels:
      greeting: hello
  replicas: 3
  template:
    metadata:
      labels:
        greeting: hello
    spec:
      containers:
      - name: hello
        image: gcr.io/google-samples/hello-app:2.0
---
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: LoadBalancer
  selector:
    greeting: hello
  ports:
  - name: metal-lb-example-port
    protocol: TCP
    port: 60000
    targetPort: 8080

请注意,Service 清单未指定外部 IP 地址。MetalLB controller 将会从您在用户集群配置文件中指定的地址池中选择外部 IP 地址。

将清单保存到名为 my-dep-svc.yaml 的文件中。然后,创建 Deployment 和 Service 对象:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG apply -f my-dep-svc.yaml

查看 Service:

kubectl --kubeconfig USER_CLUSTER_KUBECONIFG get service my-service --output wide

输出会显示自动分配给 Service 的外部 IP 地址。例如:

NAME         TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)           AGE   SELECTOR
my-service   LoadBalancer   10.96.2.166   192.0.2.2   60000:31914/TCP   28s

验证分配的外部 IP 地址是否取自您在用户集群配置文件中指定的地址池。例如,192.0.2.2 便取自此地址池:

metalLB:
  addressPools:
  - name: "address-pool-1"
    addresses:
     - "192.0.2.0/24"
     - "198.51.100.1-198.51.100.3"

调用 Service:

curl EXTERNAL_IP_ADDRESS:60000

输出会显示 Hello, world! 消息:

Hello, world!
Version: 2.0.0

更新 MetalLB

创建集群后,您可以更新节点池中的 MetalLB 地址池和 enableLoadBalancer 字段。在用户集群配置文件中进行所需的更改,然后调用 gkectl update cluster

gkectl update cluster --kubeconfig ADMIN_CLUSTER_KUBECONIFG --config USER_CLUSTER_CONFIG

MetalLB Pod 和 ConfigMap

MetalLB controller 作为 Deployment 运行,MetalLB speaker 在 enableLoadBalancer 设置为 true 的池中的节点上作为 DaemonSet 运行。MetalLB controller 负责管理分配给 Service 的 IP 地址。MetalLB speaker 负责选举 leader 并公布 Service VIP。

查看所有 MetalLB Pod:

kubectl --kubeconfig USER_CLUSTER_KUBECONIFG get pods --namespace kube-system --selector app=metallb

您可以使用 MetalLB Pod 中的日志进行问题排查。

MetalLB 配置以 MetalLB 已知的格式存储在 ConfigMap 中。请勿直接更改 ConfigMap,而是改用前面所述的 gkectl update cluster。如需查看 ConfigMap 以进行问题排查,请运行以下命令:

kubectl --kubeconfig USER_CLUSTER_KUBECONIFG get configmap metallb-config --namespace kube-system

使用 MetalLB 的优势

  • MetalLB 直接在您的集群节点上运行,因此不需要额外的虚拟机。

  • MetalLB 控制器为 Service 进行 IP 地址管理,因此您无需为每个 Service 手动选择 IP 地址。

  • 不同 Service 的 MetalLB 的活跃实例可以在不同的节点上运行。

  • 您可以在不同 Service 之间共享 IP 地址

MetalLB 与 F5 BIG-IP 和 Seesaw 进行比较

  • VIP 地址必须与集群节点位于同一子网中。这也是 Seesaw 的要求,但 F5 BIG-IP 对此则不做要求。

  • 没有流量指标。

  • 不存在无中断故障切换;现有连接在故障切换期间会重置。

  • 发送到特定 Service 的各个 Pod 的外部流量会通过运行 MetalLB speaker 的单个节点传递。这意味着客户端 IP 地址通常对 Pod 中运行的容器不可见。