Balanceo de cargas avanzado en clústeres de GKE

En esta página, se muestra cómo configurar el balanceo de cargas avanzado en clústeres de GKE para usuarios de Cloud Service Mesh (TD) administrado con la API de Kubernetes. Para obtener la guía del usuario correspondiente para configurar el balanceo de cargas avanzado con la Google Cloud API, consulta Configura el balanceo de cargas avanzado.

Puedes usar el balanceo de cargas avanzado para hacer lo siguiente:

  • Mantener el tráfico a un servicio zonal hasta que se agote la capacidad local
  • Enviar tráfico al servicio en una ubicación "principal" con conmutación por error a una ubicación secundaria cuando suficientes extremos en la ubicación principal se vuelvan en mal estado
  • Controlar cuándo se produce la conmutación por error (según el porcentaje de hosts en buen estado)

Limitaciones

  • Limitaciones generales sobre el uso del balanceo de cargas avanzado en Google Cloud
  • Esta función solo está disponible para los usuarios de Cloud Service Mesh administrado que usan Traffic Director como plano de control y requiere la versión 1.19.10-asm.22 o posterior del plano de datos.
  • No todos los campos de GCPTrafficDistributionPolicy y GCPBackendPolicy son compatibles con Cloud Service Mesh (TD) administrado. Los campos compatibles son los siguientes:
    • GCPTrafficDistributionPolicy
      • ServiceLbAlgorithm
      • AutoCapacityDrain
      • FailoverConfig
    • GCPBackendPolicy
      • MaxRatePerEndpoint
      • BackendPreference
  • El balanceo de cargas avanzado solo se puede aplicar a los servicios de Kubernetes respaldados por cargas de trabajo que se ejecutan en Google Cloud. No se admiten servicios ni cargas de trabajo externos (como ServiceEntry).
  • Las políticas de balanceo de cargas solo se pueden aplicar a servicios individuales de Kubernetes. No se admiten políticas de balanceo de cargas en todo el espacio de nombres o en toda la malla.
  • Solo se admite la capacidad de QPS.
  • Solo se admiten versiones de GKE >= 1.31.1.
  • Las políticas de balanceo de cargas avanzado de la malla de servicios solo se deben aplicar a los servicios que solo entregan tráfico de malla. No se debe aplicar a los servicios que actúan como backends de la puerta de enlace de GKE. Los comportamientos del tráfico no están definidos cuando un balanceo de cargas avanzado dirige el tráfico a un servicio de Kubernetes que entrega tráfico de malla y tráfico desde una puerta de enlace de GKE.

Configura el balanceo de cargas avanzado

Puedes usar los siguientes recursos personalizados para configurar el balanceo de cargas avanzado en GKE. Puedes encontrar la definición detallada de recursos en el repositorio gke-gateway-api.

GCPTrafficDistributionPolicy

GCPTrafficDistributionPolicy configura la política de balanceo de cargas a nivel de servicio para los servicios de Kubernetes. Te permite realizar las siguientes acciones:

  • Elegir un algoritmo de balanceo de cargas personalizado (los algoritmos compatibles se describen en la tabla de balanceo de cargas avanzado)
  • Habilitar el vaciado automático de capacidad .
  • Ajustar el umbral de estado de conmutación por error .

Si varias GCPTrafficDistributionPolicies segmentan el mismo servicio, se aplicará la política más antigua.

GCPBackendPolicy

GCPBackendPolicy configura las propiedades de los backends de servicio que afectan el comportamiento del balanceo de cargas, incluidos los siguientes:

Si varias GCPBackendPolicies segmentan el mismo servicio en un clúster, se aplicará la política más antigua.

Estado de la política

Tanto GCPTrafficDistributionPolicy como GCPBackendPolicy tienen un campo de estado que indica el estado de conexión de la política.

Por ejemplo, ejecutar kubectl describe gcpbackendpolicies example-policy -n example generaría un resultado similar al siguiente:

...
Status:
  Ancestors:
    Ancestor Ref:
      Group:
      Kind:       Service
      Name:       example-svc
      Namespace:  example
    Conditions:
      Last Transition Time:  2024-10-13T01:15:03Z
      Message:
      Observed Generation:   1
      Reason:                Attached
      Status:                True
      Type:                  Attached
    Controller Name:         gsmconfig.gke.io/controller

Configuración preliminar

Antes de completar esta guía, debes aprovisionar Cloud Service Mesh en un clúster de GKE.

  1. Verifica que las CRD estén instaladas:

    kubectl get crd
    

    El resultado es similar al siguiente:

    ...
    gcptrafficdistributionpolicies.networking.gke.io   2024-07-18T21:50:12Z
    gcpbackendpolicies.networking.gke.io               2024-07-18T21:50:12Z
    ...
    
  2. Instala la CRD de GCPBackendPolicy si aún no está instalada:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcpbackendpolicies.yaml
    
  3. Instala la CRD de GCPTrafficDistributionPolicy si aún no está instalada:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcptrafficdistributionpolicies.yaml
    

Las políticas de ejemplo de esta guía del usuario segmentan el servicio foo en el espacio de nombres foo a modo de demostración. Puedes ejecutar el siguiente comando para crear el servicio y el espacio de nombres de prueba o, si lo prefieres, puedes usar tu propio servicio y espacio de nombres:

kubectl apply -f - <<EOF
kind: Namespace
apiVersion: v1
metadata:
  name: foo
  labels:
    istio-injection: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo
  namespace: foo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-backend
  template:
    metadata:
      labels:
        app: test-backend
    spec:
      containers:
      - name: whereami
        image: gcr.io/google-samples/whereami:v1.2.23
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: foo
  namespace: foo
spec:
  selector:
    app: test-backend
  ports:
  - port: 8080
    targetPort: 8080
EOF

Configura el algoritmo de balanceo de cargas

De forma predeterminada, el tráfico a un servicio se distribuye de manera uniforme a cada backend de servicio en buen estado en una malla de servicios de Cloud Service Mesh. Puedes crear la siguiente GCPTrafficDistributionPolicy para que el tráfico se distribuya a la zona más cercana hasta la capacidad del backend:

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPTrafficDistributionPolicy
metadata:
  name: lb-policy
  namespace: foo
spec:
  targetRefs:
  - kind: Service
    group: ""
    name: foo-service
  default:
    serviceLbAlgorithm: WATERFALL_BY_ZONE
EOF

De forma predeterminada, los backends de servicio se tratan como si tuvieran capacidad infinita. Cuando hay suficientes hosts en buen estado en la zona local o más cercana, el tráfico nunca se distribuirá fuera de la zona local o más cercana para una determinada localidad del cliente. De manera opcional, puedes configurar la capacidad de tu backend de servicio con GCPBackendPolicy para que una sola zona no se sobrecargue.

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
  name: backend-policy
  namespace: foo
spec:
  targetRef:
    kind: Service
    group: ""
    name: foo-backend
  default:
    maxRatePerEndpoint: 5
EOF

Ajusta el comportamiento de la conmutación por error

De forma predeterminada, la conmutación por error no se activará mientras un porcentaje suficiente de hosts esté en buen estado en los backends principales. Para obtener más información sobre los backends principales y otra terminología, consulta la descripción general del balanceo de cargas avanzado. GCPTrafficDistributionPolicy te permite configurar el umbral de porcentaje de hosts en buen estado hasta que el tráfico se desvíe de los backends principales a los backends de conmutación por error. La conmutación por error se activa antes con un umbral más grande. Por ejemplo, si deseas que la conmutación por error se active tan pronto como el porcentaje de hosts en buen estado descienda por debajo del 90% en los backends principales, puedes configurar la siguiente GCPTrafficDistributionPolicy:

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPTrafficDistributionPolicy
metadata:
  name: lb-policy
  namespace: foo
spec:
  targetRefs:
  - kind: Service
    group: ""
    name: foo-service
  default:
   failoverConfig:
     failoverHealthThreshold: 90
EOF

Configura el balanceo de cargas avanzado en una malla de servicios de varios clústeres

GCPTrafficDistributionPolicy y GCPBackendPolicy se aplican en diferentes alcances en una malla de servicios de varios clústeres.

Cuando una GCPTrafficDistributionPolicy segmenta un servicio de varios clústeres, define el comportamiento del balanceo de cargas a nivel de servicio en todos los clústeres. Solo se debe crear una GCPTrafficDistributionPolicy para un servicio de varios clústeres en particular. Si usas la API de Istio para configurar tu malla de servicios, puedes crear GCPTrafficDistributionPolicy en cualquier clúster de la flota. Puedes verificar si una política entra en conflicto con otra inspeccionando su estado.

Cuando una GCPBackendPolicy segmenta un servicio de varios clústeres, define la configuración a nivel de backend (por ejemplo, la capacidad por pod) para los pods de backend seleccionados por su servicio de segmentación en su clúster local. Para el mismo servicio de varios clústeres, es posible definir diferentes parámetros de configuración a nivel de backend en diferentes clústeres.

En el siguiente ejemplo, se crea una GCPTrafficDistributionPolicy en el clúster A para definir el algoritmo de balanceo de cargas que se usará en toda la flota, mientras que las GCPBackendPolicies están en cada clúster. Ambas GCPBackendPolicy configuran una capacidad de 10 QPS por pod para los pods de backend en su clúster local, mientras que la GCPBackendPolicy en el clúster A configura los pods de backend en el clúster A como backend preferido.

En conjunto, estas políticas configuran los comportamientos de balanceo de cargas para el tráfico en la malla que se envía al servicio foo:

  • El tráfico desde cualquier lugar prefiere los backends en el clúster A hasta que los pods de backend en el clúster A necesiten controlar 10 QPS por pod.
    • Este comportamiento se define principalmente con la GCPBackendPolicy que estableció backendPreference en PREFERRED en el clúster A.
  • El tráfico que excede la capacidad configurada de los backends en el clúster A se enruta con el algoritmo WATERFALL_BY_ZONE al clúster B. Para obtener una explicación más detallada de los backends preferidos, consulta la descripción general del balanceo de cargas avanzado.
    • Este comportamiento se define principalmente con la GCPTrafficDistributionPolicy, que define el algoritmo, en el clúster A y GCPBackendPolicy, que define la capacidad de backend, en los clústeres A y B.

Malla de servicios de varios clústeres con balanceo de cargas avanzado

En Istio, los servicios regulares de Kubernetes se convierten de forma implícita en "varios clústeres" cuando hay varios clústeres en la malla de servicios y el servicio se crea en los límites del clúster. Si bien la siguiente GCPTrafficDistributionPolicy segmenta el servicio foo de Kubernetes regular, se aplica al servicio foo de varios clústeres que consta de cargas de trabajo correspondientes en dos clústeres.

  1. Crea la GCPTrafficDistributionPolicy para el clúster A:

    kubectl apply --context cluster-a-context -f - <<EOF
    kind: GCPTrafficDistributionPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-traffic-distribution-policy
    namespace: foo
    spec:
      targetRefs:
      - kind: Service
        group: ""
        name: foo-service
      default:
        serviceLbAlgorithm: WATERFALL_BY_ZONE
    
    EOF
    
  2. Crea la GCPBackendPolicy para el clúster A:

    kubectl apply --context cluster-a-context -f - <<EOF
    kind: GCPBackendPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-backend-policy
    namespace: foo
    spec:
      default:
        maxRatePerEndpoint: 100
        backendPreference: PREFERRED
      targetRef:
        group: ""
        kind: Service
        name: foo-service
    EOF
    
  3. Crea la GCPBackendPolicy para el clúster B:

    kubectl apply --context cluster-b-context -f - <<EOF
    kind: GCPBackendPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-backend-policy
    namespace: foo
    spec:
      default:
        maxRatePerEndpoint: 10
      targetRef:
        group: ""
        kind: Service
        name: foo-service
    EOF
    

Pasos siguientes