Balanceo de cargas en paquetes con MetalLB

En este documento, se muestra cómo configurar GKE en VMware para usar el balanceo de cargas en paquetes con el balanceador de cargas de MetalLB.

En GKE en VMware, MetalLB se ejecuta en modo de capa 2.

Ejemplo de una configuración de MetalLB

A continuación, se muestra un ejemplo de una configuración para clústeres que ejecutan el balanceador de cargas MetalLB:

Configuración del balanceador de cargas de MetalLB.
Configuración del balanceador de cargas de MetalLB

En el diagrama anterior, se muestra una implementación de MetalLB. MetalLB se ejecuta directamente en los nodos del clúster. En este ejemplo, el clúster de administrador y el clúster de usuario están en dos VLAN independientes, y cada clúster se encuentra en una subred independiente:

Clúster Subred
Clúster de administrador 172.16.20.0/24
Clúster de usuario 172.16.40.0/24

admin-cluster.yaml

En el siguiente ejemplo de un archivo de configuración del clúster de administrador, se muestra la configuración que aparece en el diagrama anterior:

  • Balanceador de cargas de MetalLB

  • VIP en MetalLB para el servidor de API de Kubernetes y complementos del clúster de administrador

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

En el siguiente ejemplo de un archivo de bloque IP, se muestra la designación de las direcciones IP para los nodos en el clúster de administrador. Esto también incluye la dirección del nodo del plano de control del clúster de usuario y una dirección IP que se usará durante la actualización del clúster.

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

En el siguiente ejemplo de un archivo de configuración de clúster de usuario, se muestra la configuración de lo siguiente:

  • Grupos de direcciones para que el controlador MetalLB elija y las asigne a los Services de tipo LoadBalancer. La VIP de entrada está en uno de estos grupos.

  • VIP designada para el servidor de la API de Kubernetes del clúster de usuario y la VIP de entrada que elegiste configurar para el proxy de entrada. La VIP del servidor de la API de Kubernetes se encuentra en la subred del clúster de administrador porque el plano de control de un clúster de usuario se ejecuta en un nodo del clúster de administrador.

  • Un grupo de nodos habilitado para usar MetalLB. Se implementará MetalLB en los nodos del clúster de usuario que pertenezcan a ese grupo de nodos.

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

La configuración del ejemplo anterior especifica un conjunto de direcciones disponibles para los Services. Cuando un desarrollador de aplicaciones crea un Service de tipo LoadBalancer en el clúster de usuario, el controlador de MetalLB elegirá una dirección IP de este grupo.

user-cluster-ipblock.yaml

En el siguiente ejemplo de un archivo de bloque IP, se muestra la designación de las direcciones IP para los nodos en el clúster de usuario. Esto incluye una dirección IP para usar durante la actualización del clúster.

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

Configura MetalLB

Abre puertos de firewall

MetalLB usa la biblioteca de listas de miembros de Go para realizar la elección de líder. La biblioteca memberlist usa el puerto TCP 7946 y el puerto UDP 7946 para intercambiar información. Asegúrate de que se pueda acceder a esos puertos para el tráfico entrante y saliente en todos los nodos del balanceador de cargas.

Habilita MetalLB para un clúster de administrador nuevo

En el archivo de configuración del clúster de administrador, configura loadBalancer.kind como "MetalLB".

loadBalancer:
  kind: "MetalLB"

Completa el resto del archivo de configuración del clúster de administrador y crea tu clúster de administrador, como se describe en Crea un clúster de administrador.

Especifica grupos de direcciones

El controlador MetalLB realiza la administración de direcciones IP para los objetos Service. Por lo tanto, cuando un desarrollador de aplicaciones crea un Service de tipo LoadBalancer en un clúster de usuario, no tiene que especificar de forma manual una dirección IP para ese objeto. En su lugar, el controlador de MeltalLB elige una dirección IP de un grupo de direcciones que especificas en el momento de la creación del clúster.

Piensa en la cantidad de servicios de tipo LoadBalancer que pueden estar activos en el clúster de usuario en un momento determinado. Luego, en la sección loadBalancer.metalLB.addressPools del archivo de configuración de tu clúster de usuario, especifica suficientes direcciones IP para alojar esos objetos Service.

La VIP de entrada del clúster de usuario debe estar entre las direcciones que especificas en un grupo de direcciones. Esto se debe a que un servicio de tipo LoadBalancer expone el proxy de entrada.

Si los desarrolladores de tu aplicación no necesitan crear servicios de tipo LoadBalancer, no es necesario que especifiques ninguna dirección que no sea la VIP de entrada.

Las direcciones deben estar en formato CIDR o en rango. Si deseas especificar una dirección individual, usa un CIDR /32. Por ejemplo:

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

Si necesitas ajustar las direcciones en un grupo después de que se crea el clúster, puedes usar gkectl update cluster. Para obtener más información, consulta Actualiza MetalLB.

Habilita MetalLB para un clúster de usuario nuevo

En el archivo de configuración del clúster de usuario, haz lo siguiente:

  • Establece loadBalancer.kind en "MetalLB".
  • Especifica uno o más grupos de direcciones para los objetos Service. La VIP de entrada debe estar en uno de estos grupos.
  • Configura enableLoadBalancer como true para al menos un grupo de nodos en el clúster.

Completa el resto del archivo de configuración del clúster de usuario y crea el clúster de usuario, como se describe en Crea un clúster de usuario.

Asignación manual de direcciones de servicio

Si no quieres que el controlador MetalLB asigne de forma automática direcciones IP de un grupo en particular a los objetos Service, establece el campo manualAssign del grupo en true. Luego, un desarrollador puede crear un objeto Service de tipo LoadBalancer y especificar de forma manual una de las direcciones del grupo. Por ejemplo:

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

Evita direcciones IP con errores

Si configuras el campo avoidBuggyIPs de un grupo de direcciones como true, el controlador de MetalLB no usará direcciones del grupo que terminan en .0 o .255. Esto evita el problema de los dispositivos consumidores con errores que descartan por error el tráfico enviado a esas direcciones IP especiales. Por ejemplo:

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

Crea un Service de tipo LoadBalancer

Estos son dos manifiestos: uno para un objeto Deployment y otro para un objeto 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

Ten en cuenta que el manifiesto del objeto Service no especifica una dirección IP externa. El controlador de MetalLB elegirá una dirección IP externa del grupo de direcciones que especificaste en el archivo de configuración del clúster de usuario.

Guarda los manifiestos en un archivo llamado my-dep-svc.yaml. Luego, crea los objetos Deployment y Service:

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

Observa el Service:

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

El resultado muestra la dirección IP externa que se asignó de forma automática al objeto Service. Por ejemplo:

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

Verifica que la dirección IP externa asignada se haya tomado del grupo de direcciones que especificaste en el archivo de configuración del clúster de usuario. Por ejemplo, 192.0.2.2 se encuentra en este grupo de direcciones:

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

Llama al objeto Service:

curl EXTERNAL_IP_ADDRESS:60000

El resultado muestra un mensaje Hello, world!:

Hello, world!
Version: 2.0.0

Actualiza MetalLB

Después de crear el clúster, puedes actualizar los grupos de direcciones de MetalLB y el campo enableLoadBalancer en los grupos de nodos. Realiza los cambios deseados en el archivo de configuración del clúster de usuario y, a continuación, llama a gkectl update cluster:

gkectl update cluster --kubeconfig ADMIN_CLUSTER_KUBECONIFG --config USER_CLUSTER_CONFIG

Pods de MetalLB y ConfigMap

El controlador de MetalLB se ejecuta como un objeto Deployment y el interlocutor de MetalLB se ejecuta como un DaemonSet en los nodos de los grupos que tienen enableLoadBalancer configurado como true. El controlador de MelB administra las direcciones IP asignadas a los objetos Service. El interlocutor de MetalLB realiza la elección de líder y anuncia las VIP del objeto Service.

Visualiza todos los Pods de MetalLB:

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

Puedes usar los registros de los Pods de MetalLB para solucionar problemas.

La configuración de MetalLB se almacena en un ConfigMap en un formato que MetalLB conoce. No cambies ConfigMap de forma directa. En su lugar, usa gkectl update cluster como se describió antes. Si deseas ver el ConfigMap para solucionar problemas, haz lo siguiente:

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

Beneficios de usar MetalLB

  • MetalLB se ejecuta directamente en los nodos de tu clúster, por lo que no requiere VM adicionales.

  • El controlador de MetalLB realiza la administración de direcciones IP para los objetos Service, por lo que no tienes que elegir de forma manual una dirección IP para cada objeto Service.

  • Las instancias activas de MetalLB para diferentes objetos Service pueden ejecutarse en diferentes nodos.

  • Puedes compartir una dirección IP entre diferentes objetos Service.

MetalLB en comparación con F5 BIG-IP y Seesaw

  • Las VIP deben estar en la misma subred que los nodos del clúster. Este también es un requisito para Seesaw, pero no para BIG-IP de F5.

  • No hay métricas para el tráfico.

  • No hay conmutación por error sin interrupciones. Las conexiones existentes se restablecen durante la conmutación por error.

  • El tráfico externo a los Pods de un objeto Service en particular pasa por un solo nodo que ejecuta la bocina de MetalLB. Esto significa que la dirección IP de cliente suele no ser visible para los contenedores que se ejecutan en el pod.