Balanceo de carga avanzado en clústeres de GKE

En esta página se explica cómo configurar el balanceo de carga avanzado en clústeres de GKE para usuarios de Cloud Service Mesh gestionado (TD) mediante la API de Kubernetes. Para consultar la guía de usuario correspondiente sobre cómo configurar el balanceo de carga avanzado con la APIGoogle Cloud , consulta el artículo Configurar el balanceo de carga avanzado.

Puedes usar el balanceo de carga avanzado para lo siguiente:

  • Mantener el tráfico de un servicio zonal hasta que se agote la capacidad local.
  • Envía tráfico al servicio en una ubicación "principal" con conmutación por error a una ubicación secundaria cuando haya suficientes endpoints en la ubicación principal que no funcionen correctamente.
  • Controla cuándo se produce la conmutación por error (en función del porcentaje de hosts en buen estado).

Limitaciones

  • Se aplican las limitaciones generales sobre el uso del balanceo de carga avanzado en Google Cloud .
  • Esta función solo está disponible para los usuarios de Cloud Service Mesh gestionado que utilicen 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 se admiten en managedCloud Service Mesh (TD). Los campos admitidos son los siguientes:

    • GCPTrafficDistributionPolicy
      • ServiceLbAlgorithm
      • AutoCapacityDrain
      • FailoverConfig
    • GCPBackendPolicy
      • MaxRatePerEndpoint
      • BackendPreference

    Todos los campos que no se incluyen en la lista no se admiten y las políticas que tengan configurado al menos un campo no admitido no se aplican en Cloud Service Mesh .

  • El balanceo de carga 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 carga solo se pueden aplicar a servicios de Kubernetes concretos. No se admiten las políticas de balanceo de carga de todo el espacio de nombres o de toda la malla.

  • Solo se admite la capacidad de QPS.

  • Solo se admiten versiones de GKE iguales o superiores a 1.31.1.

  • Las políticas de balanceo de carga avanzadas de la malla de servicios solo se deben aplicar a los servicios que solo sirven tráfico de la malla. No se debe aplicar a los servicios que actúan como back-ends de GKE Gateway. Los comportamientos del tráfico no están definidos cuando un destino de tráfico de balanceo de carga avanzado es un servicio de Kubernetes que sirve tanto tráfico de malla como tráfico de una puerta de enlace de GKE.

Configurar el balanceo de carga avanzado

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

GCPTrafficDistributionPolicy

GCPTrafficDistributionPolicy configura la política de balanceo de carga a nivel de servicio para los servicios de Kubernetes. Con ella, puedes hacer lo siguiente:

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

GCPBackendPolicy

GCPBackendPolicy configura las propiedades de los backends de servicio que influyen en el comportamiento del balanceo de carga, como las siguientes:

Si varias GCPBackendPolicies se dirigen al mismo servicio de 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 la asociación de la política.

Por ejemplo, al ejecutar kubectl describe gcpbackendpolicies example-policy -n example, se obtendrí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. Comprueba que los CRDs estén instalados:

    kubectl get crd
    

    La salida es similar a la siguiente:

    ...
    gcptrafficdistributionpolicies.networking.gke.io   2024-07-18T21:50:12Z
    gcpbackendpolicies.networking.gke.io               2024-07-18T21:50:12Z
    ...
    
  2. Instala el CRD de GCPBackendPolicy si aún no lo has hecho:

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

    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 de usuario se dirigen al servicio foo en el espacio de nombres foo con fines de demostración. Puedes ejecutar el siguiente comando para crear el servicio y el espacio de nombres de prueba. 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

Configurar el algoritmo de balanceo de carga

De forma predeterminada, el tráfico a un servicio se distribuye de forma equitativa entre todos los backends de servicio en buen estado de una malla de servicios de Cloud Service Mesh. Puede crear el siguiente GCPTrafficDistributionPolicy para que el tráfico se distribuya a la zona más cercana hasta alcanzar 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 una capacidad infinita. Si hay suficientes hosts en buen estado en la zona local o más cercana, el tráfico nunca se distribuirá fuera de esa zona para una determinada localidad de cliente. También puedes configurar la capacidad de tu backend de servicio mediante GCPBackendPolicy para que no se sobrecargue una sola zona.

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

Ajustar el comportamiento de conmutación por error

De forma predeterminada, la conmutación por error no se activará mientras haya un porcentaje suficiente de hosts en buen estado en los backends principales. Para obtener más información sobre los back-ends principales y otros términos, consulta el artículo Introducción al balanceo de carga avanzado. GCPTrafficDistributionPolicy te permite configurar el umbral del 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 quiere que se active la conmutación por error en cuanto el porcentaje de hosts en buen estado sea inferior al 90% en los backends principales, puede 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

Configurar el balanceo de carga avanzado en una malla de servicios de varios clústeres

GCPTrafficDistributionPolicy y GCPBackendPolicy se aplican en ámbitos diferentes en una malla de servicios multiclúster.

Cuando un objeto GCPTrafficDistributionPolicy se dirige a un servicio multiclúster, define el comportamiento del balanceo de carga a nivel de servicio en todos los clústeres. Solo se debe crear un objeto GCPTrafficDistributionPolicy para un servicio multiclúster concreto. Si usas la API de Istio para configurar tu malla de servicios, puedes crear GCPTrafficDistributionPolicy en cualquier clúster de la flota. Para comprobar si una política entra en conflicto con otra, consulta su estado.

Cuando un objeto GCPBackendPolicy se dirige a un servicio multiclúster, define la configuración a nivel de backend (por ejemplo, la capacidad por pod) de los pods de backend seleccionados por su servicio de destino en su clúster local. En el mismo servicio multiclúster, se pueden definir ajustes de nivel de backend diferentes en distintos clústeres.

En el siguiente ejemplo, se crea un objeto GCPTrafficDistributionPolicy en el clúster A para definir el algoritmo de balanceo de carga que se va a usar en toda la flota, mientras que los objetos GCPBackendPolicy se encuentran en cada clúster. GCPBackendPolicy configura una capacidad de 10 qps por pod para los pods de backend de su clúster local, mientras que GCPBackendPolicy del clúster A configura los pods de backend del clúster A como backend preferido.

Juntas, estas políticas configuran los comportamientos de balanceo de carga del tráfico de la malla que se envía al servicio foo:

  • El tráfico de cualquier lugar prefiere los backends del clúster A hasta que los pods de backend del clúster A necesiten gestionar 10 qps por pod.
    • Este comportamiento se define principalmente en la política GCPBackendPolicy, que asigna el valor backendPreference a PREFERRED en el clúster A.
  • El tráfico que supera la capacidad configurada de los backends del clúster A se enruta al clúster B mediante el algoritmo WATERFALL_BY_ZONE. Para obtener una explicación más detallada de los back-ends preferidos, consulta el artículo Información general sobre el balanceo de carga avanzado.
    • Este comportamiento se define principalmente en GCPTrafficDistributionPolicy, que define el algoritmo, en el clúster A y en GCPBackendPolicy, que define la capacidad del backend, en los clústeres A y B.

Balanceo de carga avanzado de malla de servicios multiclúster

En Istio, los servicios de Kubernetes normales se convierten implícitamente en "multiclúster" cuando hay varios clústeres en la malla de servicios y el servicio se crea en los límites de los clústeres. Aunque el siguiente objeto de destino GCPTrafficDistributionPolicy se dirige al servicio de Kubernetes normal foo, se aplica al servicio multiclúster foo, que consta de cargas de trabajo correspondientes en dos clústeres.

  1. Crea el objeto 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 el objeto 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 el 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
    

Siguientes pasos