Configurar el balanceo de carga agrupado con MetalLB

En esta página se describe cómo configurar el balanceo de carga agrupado con MetalLB para Google Distributed Cloud. Los balanceadores de carga de MetalLB se ejecutan en un grupo de nodos de trabajador específico o en los mismos nodos que el plano de control.

Consulta la descripción general de los balanceadores de carga para ver ejemplos de topologías de balanceo de carga disponibles en Google Distributed Cloud.

Requisitos

  • Todos los nodos del balanceador de carga deben estar en la misma subred de capa 2.
  • Todas las IPs virtuales deben estar en la subred de los nodos del balanceador de carga y poder enrutarse a través de la puerta de enlace de la subred.
  • La pasarela de la subred del balanceador de carga debe escuchar los mensajes ARP gratuitos y reenviar los paquetes ARP a los nodos del balanceador de carga.

Campos de configuración

Edita la sección cluster.spec.loadBalancer del archivo de configuración del clúster para configurar el balanceo de carga agrupado. Para obtener información sobre los archivos de configuración de clústeres y ejemplos de configuraciones válidas, consulta una de las siguientes páginas:

loadBalancer.mode

Este valor debe ser bundled para habilitar el balanceo de carga agrupado.

loadBalancer.ports.controlPlaneLBPort

Este valor especifica el puerto de destino que se va a usar para el tráfico enviado al plano de control de Kubernetes (los servidores de la API de Kubernetes).

loadBalancer.vips.controlPlaneVIP

Este valor especifica la dirección IP de destino que se usará para el tráfico enviado al plano de control de Kubernetes (los servidores de la API de Kubernetes). Esta dirección IP debe estar en la misma subred de capa 2 que los nodos del clúster. No incluyas esta dirección en la sección address pools del archivo de configuración.

loadBalancer.vips.ingressVIP

Este valor especifica la dirección IP que se va a usar para los servicios que están detrás del balanceador de carga para el tráfico de entrada. Este campo no se permite en los archivos de configuración de admin cluster. Esta dirección debe figurar en la sección address pools de la configuración.

loadBalancer.addressPools

Esta sección de la configuración contiene uno o varios grupos de direcciones. Cada grupo de direcciones especifica una lista de intervalos de direcciones IP. Cuando creas un servicio de tipo LoadBalancer, las direcciones IP externas del servicio se eligen de estos intervalos.

Los grupos de direcciones se especifican con el siguiente formato:

- name: POOL_NAME
  avoidBuggyIPs: BOOLEAN
  manualAssign: BOOLEAN
  addresses:
  - IP_RANGE
  - IP_RANGE2
  • name: el nombre del grupo de direcciones, pool-name, para tu organización. Este campo no se puede modificar.
  • avoidBuggyIPs: (Opcional) true o false. Si true, el grupo omite las direcciones IP que terminan en .0 y .255. Algunos hardware de red descartan el tráfico a estas direcciones especiales. Puedes omitir este campo. Su valor predeterminado es false. Este campo se puede modificar.
  • manualAssign: (Opcional) true o false. Si true, las direcciones de este grupo no se asignan automáticamente a los servicios de Kubernetes. Si true, se usa una dirección IP de este grupo solo cuando un servicio la especifica explícitamente. Puede omitir este campo. Su valor predeterminado es false. Este campo se puede modificar.
  • addresses Una lista de uno o varios intervalos de direcciones IP que no se solapan. ip-range se puede especificar con la notación CIDR (como 198.51.100.0/24) o con la notación de intervalo (como 198.51.100.0-198.51.100.10, sin espacios alrededor del guion). Este campo no se puede modificar.

Los intervalos de direcciones IP de la lista addresses no deben solaparse y deben estar en la misma subred que los nodos que ejecutan balanceadores de carga.

loadBalancer.nodePoolSpec

En esta sección de la configuración se especifica una lista de nodos en los que se ejecutarán los balanceadores de carga. Los nodos del balanceador de carga pueden ejecutar cargas de trabajo normales de forma predeterminada. Estos nodos no tienen ningún taint especial. Aunque los nodos del grupo de nodos del balanceador de carga pueden ejecutar cargas de trabajo, están separados de los nodos de los grupos de nodos de trabajador. No puedes incluir un nodo de clúster determinado en más de un grupo de nodos. Si las direcciones IP de los nodos de los grupos de nodos se solapan, no se podrá crear el clúster ni realizar otras operaciones en él.

Si quieres evitar que las cargas de trabajo se ejecuten en un nodo del grupo de nodos del balanceador de carga, añade el siguiente taint al nodo:

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

Google Distributed Cloud añade tolerancias para este taint a los pods que se necesitan para el balanceo de carga.

En el siguiente ejemplo se muestra un pool de nodos de balanceo de carga con dos nodos. El primer nodo tiene una dirección IP estándar nodePoolSpec.nodes.address ("1.2.3.4") y una dirección IP de Kubernetes nodePoolSpec.nodes.k8sIP (10.0.0.32). Cuando especificas la dirección k8sIP opcional de un nodo, se dedica a gestionar el tráfico de datos del nodo, como las solicitudes y las respuestas de la API de Kubernetes, kubelet y las cargas de trabajo. En este caso, la dirección IP estándar nodePoolSpec.nodes.address se usa para las conexiones SSH al nodo para las operaciones administrativas del clúster. Si no especificas una dirección k8sIP, la dirección IP del nodo estándar gestiona todo el tráfico del nodo.

nodePoolSpec:
  nodes:
  - address: 1.2.3.4
    k8sIP: 10.0.0.32
  - address: 10.0.0.33

De forma predeterminada, todos los nodos del grupo de nodos del balanceador de carga deben estar en la misma subred de capa 2 que las IPs virtuales del balanceador de carga configuradas en la sección loadBalancer.addressPools del archivo de configuración. Sin embargo, si especificas una dirección IP de Kubernetes k8sIP para un nodo, solo esa dirección debe estar en la misma subred de capa 2 que las demás IPs virtuales del balanceador de carga.

Si nodePoolSpec no está definido, los balanceadores de carga agrupados se ejecutan en los nodos del plano de control. Te recomendamos que ejecutes balanceadores de carga en grupos de nodos independientes si es posible.

Balanceo de carga del plano de control

El balanceador de carga del plano de control sirve la dirección IP virtual (VIP) del plano de control. Google Distributed Cloud ejecuta Keepalived y HAProxy como pods estáticos de Kubernetes en los nodos del balanceador de carga para anunciar el VIP del plano de control. Keepalived usa el protocolo Virtual Router Redundancy Protocol (VRRP) en los nodos del balanceador de carga para ofrecer alta disponibilidad.

Balanceo de carga del plano de datos

El balanceador de carga del plano de datos se usa para todos los servicios de Kubernetes de tipo LoadBalancer. Google Distributed Cloud usa MetalLB que se ejecuta en el modo de capa 2 para el balanceo de carga del plano de datos. El balanceo de carga del plano de datos solo se puede configurar a través de Google Distributed Cloud. No modifiques directamente el ConfigMap de MetalLB. Puedes usar todas las funciones de MetalLB, incluida la compartición de direcciones IP entre servicios. Consulta la documentación de MetalLB para obtener información sobre las funciones.

MetalLB ejecuta un pod de altavoz en cada nodo mediante un daemonset, usando memberlist para ofrecer una alta disponibilidad. Hay un nodo de balanceador de carga dedicado de MetalLB para cada servicio de Kubernetes, en lugar de uno para todo el clúster. De esta forma, el tráfico se distribuye entre los nodos del balanceador de carga si hay varios servicios.

Los balanceadores de carga del plano de datos pueden ejecutarse en los nodos del plano de control o en un subconjunto de nodos de trabajador. Agrupar balanceadores de carga del plano de datos en los nodos del plano de control aumenta la utilización de los nodos del plano de control. Además, el agrupamiento en los nodos del plano de control también aumenta el riesgo de sobrecargar el plano de control y el perfil de riesgo de la información confidencial del plano de control, como las claves SSH.

Separación del balanceador de carga

Antes de la versión 1.32, cuando configurabas el balanceo de carga de capa 2 con MetalLB, los balanceadores de carga del plano de control y los del plano de datos se ejecutaban en los mismos nodos. En función de tu configuración, todos los balanceadores de carga se ejecutan en los nodos del plano de control o en el grupo de nodos del balanceador de carga.

En el siguiente diagrama se muestra la configuración predeterminada del balanceador de carga agrupado, con los balanceadores de carga del plano de control y del plano de datos ejecutándose en los nodos del plano de control o en el pool de nodos del balanceador de carga:

Configuración predeterminada del balanceador de carga

En los clústeres de la versión 1.32, puede configurar los balanceadores de carga del plano de control para que se ejecuten en los nodos del plano de control y los balanceadores de carga del plano de datos para que se ejecuten en el pool de nodos del balanceador de carga. Puedes especificar esta separación de los balanceadores de carga al crear un clúster de la versión 1.32 o actualizar un clúster de la versión 1.32 para migrar los balanceadores de carga del plano de datos de los nodos del plano de control al grupo de nodos del balanceador de carga.

La configuración del clúster para los balanceadores de carga separados debe ser similar a la del siguiente ejemplo:

apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: hybrid-ha-lb
  namespace: cluster-hybrid-ha-lb
spec:
  type: hybrid
  profile: default
  anthosBareMetalVersion: 1.33
  gkeConnect:
    projectID: project-fleet
  controlPlane:
    loadBalancer:
      mode: bundled
    nodePoolSpec:
      nodes:
      - address: 10.200.0.2
      - address: 10.200.0.3
      - address: 10.200.0.4
  clusterNetwork:
    pods:
      cidrBlocks:
      - 192.168.0.0/16
    services:
      cidrBlocks:
      - 10.96.0.0/20
  ...
  loadBalancer:
    mode: bundled
    ...
    nodePoolSpec:
      nodes:
      - address: 10.200.0.5
      - address: 10.200.0.6
      - address: 10.200.0.7
  clusterOperations:
  ...

Balanceadores de carga independientes al crear un clúster

Si vas a crear un clúster con la versión 1.32 o una posterior, puedes configurar los balanceadores de carga para que ejecuten los balanceadores de carga del plano de control en los nodos del plano de control y los balanceadores de carga del plano de datos en el grupo de nodos del balanceador de carga.

En el siguiente diagrama se muestran los balanceadores de carga del plano de control y del plano de datos separados en nodos diferentes:

Balanceadores de carga del plano de control y del plano de datos separados

Para separar los balanceadores de carga al crear un clúster, sigue estos pasos:

  1. En el archivo de configuración del clúster, especifica un grupo de nodos de balanceador de carga con loadBalancer.nodePoolSpec, tal como se describe en la sección loadBalancer.nodePoolSpec de este documento.

  2. Añade controlPlane.loadBalancer.mode al archivo de configuración del clúster y asigna el valor mode a bundled.

  3. Termina de configurar el clúster y ejecuta bmctl create cluster para crearlo.

Migrar equilibradores de carga del plano de datos fuera del plano de control

Si tienes un clúster de la versión 1.32 o posterior en el que no se ha definido controlPlane.loadBalancer.mode ni loadBalancer.nodePoolSpec, tanto el balanceador de carga del plano de control como el del plano de datos se ejecutan en el grupo de nodos del plano de control. Puedes actualizar el clúster para migrar el balanceador de carga del plano de datos a un grupo de nodos de balanceador de carga.

En el siguiente diagrama se muestran los balanceadores de carga del plano de control y del plano de datos separados después de que el balanceador de carga del plano de datos se haya migrado de los nodos del plano de control:

Balanceador de carga del plano de datos migrado al grupo de nodos del balanceador de carga

Para migrar el balanceador de carga del plano de datos a un grupo de nodos de balanceador de carga al actualizar un clúster, siga estos pasos:

  1. En el archivo de configuración del clúster, especifica un grupo de nodos de balanceador de carga con loadBalancer.nodePoolSpec, tal como se describe en la sección loadBalancer.nodePoolSpec de este documento.

  2. Añade controlPlane.loadBalancer.mode al archivo de configuración del clúster y asigna el valor mode a bundled.

  3. Para actualizar el clúster, ejecuta el siguiente comando:

    bmctl update cluster -c CLUSTER_NAME --kubeconfig=ADMIN_KUBECONFIG
    

    Haz los cambios siguientes:

    • CLUSTER_NAME: el nombre del clúster que vas a actualizar.

    • ADMIN_KUBECONFIG: la ruta del archivo kubeconfig del clúster de administrador.

Conservar la dirección IP de origen del cliente

El servicio LoadBalancer creado con la solución de balanceo de carga de capa 2 incluida usa el ajuste Cluster predeterminado para la política de tráfico externo. Este ajuste, spec.externalTrafficPolicy: Cluster, enruta el tráfico externo a los endpoints de todo el clúster, pero también oculta la dirección IP de origen del cliente.

Google Distributed Cloud admite dos métodos para conservar la dirección IP de origen del cliente:

  • Define el modo de reenvío del balanceo de carga como retorno directo del servidor (DSR). Para obtener más información sobre el modo de reenvío DSR, incluidas las instrucciones para habilitarlo, consulta Configurar el modo de reenvío del balanceo de carga.

  • Define la política de tráfico externo como local para el servicio LoadBalancer y configura los servicios y el recurso Ingress relacionados en consecuencia. En las siguientes secciones se describe cómo configurar el clúster para usar este método.

LoadBalancer servicios

Cuando uses externalTrafficPolicy: Local en tus servicios de LoadBalancer, configura los pods de tu aplicación para que se ejecuten exactamente en los nodos del balanceador de carga. Añade lo siguiente nodeSelector a los pods de tu aplicación para hacer este cambio:

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

NodePort servicios

Kubernetes realiza la traducción de direcciones de red de origen (SNAT) para los NodePort Services. Para conservar las direcciones IP de origen del cliente, asigna el valor Local a service.spec.externalTrafficPolicy. Kubernetes ya no realizará SNAT, pero debes asegurarte de que haya pods ejecutándose exactamente en la IP del nodo que hayas elegido.

Entrada

Si tus aplicaciones son servicios HTTP, puedes conseguir visibilidad de la IP del cliente configurando los componentes de entrada:

  1. Abre el istio-ingress servicio para editarlo:

    kubectl edit service -n gke-system istio-ingress
    
  2. Añade externalTrafficPolicy: Local a spec, guarda los cambios y cierra el editor.

    apiVersion: v1
    kind: Service
    ...
    spec:
    ...
      externalTrafficPolicy: Local
    
  3. Abre la istio-ingress implementación para editarla:

    kubectl edit deployment -n gke-system istio-ingress
    
  4. Añade lo siguiente nodeSelector a Deployment, guarda los cambios y cierra el editor.

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

Ahora, todos tus servicios detrás de Ingress verán un encabezado X-Forwarded-For con la IP del cliente, como en el siguiente ejemplo:

X-Forwarded-For: 21.0.104.4