Soluciona problemas de balanceo de cargas en GKE


En esta página, se muestra cómo resolver problemas relacionados con el balanceo de cargas en clústeres de Google Kubernetes Engine (GKE) mediante recursos de puerta de enlace, Service o Ingress.

Si necesitas asistencia adicional, comunícate con Atención al cliente de Cloud.

No se encontró el BackendConfig

Este error ocurre cuando un BackendConfig de un puerto de Service se especifica en la anotación de Service, pero no se pudo encontrar el recurso BackendConfig.

Para evaluar un evento de Kubernetes, ejecuta el siguiente comando:

kubectl get event

En el siguiente resultado de ejemplo, se indica que no se encontró tu BackendConfig:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

Para resolver este problema, asegúrate de no haber creado el recurso BackendConfig en el espacio de nombres incorrecto ni escrito mal su referencia en la anotación del Service.

No se encontró la política de seguridad de Ingress

Después de crear el objeto Ingress, si la política de seguridad no está asociada de forma correcta al Service LoadBalancer, evalúa el evento de Kubernetes para ver si hay un error de configuración. Si el BackendConfig especifica una política de seguridad que no existe, se emite un evento de advertencia de forma periódica.

Para evaluar un evento de Kubernetes, ejecuta el siguiente comando:

kubectl get event

En el siguiente resultado de ejemplo, se indica que no se encontró la política de seguridad:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

Para resolver este problema, especifica el nombre de la política de seguridad correcto en tu BackendConfig.

Aborda los errores 500 de la serie con NEG durante el escalamiento de las cargas de trabajo en GKE

Síntoma:

Cuando usas NEG aprovisionados por GKE para el balanceo de cargas, es posible que experimentes errores 502 o 503 en los servicios durante la reducción vertical de escala de la carga de trabajo. Los errores 502 se producen cuando los Pods finalizan antes de que se cierren las conexiones existentes, mientras que los errores 503 se producen cuando el tráfico se dirige a Pods borrados.

Este problema puede afectar a los clústeres si usas productos de balanceo de cargas administrados por GKE que usan NEG, incluidos los NEG independientes, de puerta de enlace y de Ingress. Si escalas tus cargas de trabajo con frecuencia, tu clúster tiene un mayor riesgo de verse afectado.

Diagnóstico:

Quitar un Pod en Kubernetes sin desviar su extremo ni quitarlo del NEG primero genera errores de la serie 500. Para evitar problemas durante la finalización de los Pods, debes considerar el orden de las operaciones. En las siguientes imágenes, se muestran situaciones en las que BackendService Drain Timeout no está configurado y BackendService Drain Timeout se establece con BackendConfig.

Situación 1: BackendService Drain Timeout no está configurado.

En la siguiente imagen, se muestra una situación en la que BackendService Drain Timeout no está configurado.

Tiempo de espera del desvío de BackendService no está configurado

Situación 2: BackendService Drain Timeout está configurado.

En la siguiente imagen, se muestra una situación en la que BackendService Drain Timeout está configurado.

Tiempo de espera del desvío de BackendService está configurado

El momento exacto en el que se producen los errores de la serie 500 depende de los siguientes factores:

  • Latencia de desconexión de la API de NEG: La latencia de desconexión de la API de NEG representa el tiempo actual que tarda la operación de desconexión en finalizar en Google Cloud. Esto depende de una variedad de factores externos a Kubernetes, incluidos el tipo de balanceador de cargas y la zona específica.

  • Latencia de desvío: La latencia de desvío representa el tiempo que tarda el balanceador de cargas en comenzar a dirigir el tráfico fuera de una parte específica del sistema. Una vez que se inicia el desvío, el balanceador de cargas deja de enviar solicitudes nuevas al extremo. Sin embargo, aún hay una latencia en la activación del desvío (latencia de desvío) que puede causar errores 503 temporales si el Pod ya no existe.

  • Configuración de la verificación de estado: Los umbrales de verificación de estado más sensibles mitigan la duración de los errores 503, ya que pueden indicarle al balanceador de cargas que deje de enviar solicitudes a los extremos, incluso si la operación de desconexión no ha finalizado.

  • Período de gracia de finalización: El período de gracia de finalización determina el tiempo máximo que tiene un Pod para salir. Sin embargo, un Pod puede salir antes de que se complete el período de gracia de finalización. Si un Pod tarda más que este período, se fuerza la salida del Pod al final de este período. Este es un parámetro de configuración del Pod y debe configurarse en la definición de la carga de trabajo.

Resolución posible:

Para evitar esos errores 5XX, aplica la siguiente configuración. Los valores de tiempo de espera son sugeridos y es posible que debas ajustarlos para tu aplicación específica. En la siguiente sección, se te guiará a través del proceso de personalización.

En la siguiente imagen, se muestra cómo mantener el Pod activo con preStopHook:

Tiempo de espera del desvío de BackendService está configurado

Para evitar errores de la serie 500, sigue estos pasos:

  1. Establece el BackendService Drain Timeout del servicio en 1 minuto.

  2. Extiende terminationGracePeriod en el Pod.

    Establece terminationGracePeriodSeconds en el Pod en 3.5 minutos. Cuando se combina con la configuración recomendada, esto les da a los Pods un período de 30 a 45 segundos para un cierre ordenado después de que el extremo del Pod se quite del NEG. Si necesitas más tiempo para el cierre ordenado, puedes extender el período de gracia o seguir las instrucciones mencionadas en la sección Personaliza los tiempos de espera.

    En el siguiente manifiesto de Pod, se especifica un tiempo de espera de vaciado de conexiones de 210 segundos (3.5 minutos):

    spec:
      terminationGracePeriodSeconds: 210
      containers:
      - name: my-app
        ...
      ...
    
  3. Aplica un preStopHook a todos los contenedores.

    Aplica un preStopHook que garantizará que el Pod esté activo durante 120 segundos más mientras el extremo del Pod se vacía en el balanceador de cargas y se quita el extremo del NEG.

    spec:
      containers:
      - name: my-app
        ...
        lifecycle:
          preStopHook:
            exec:
              command: ["/bin/sh", "-c", "sleep 120s"]
      ...
    

Personaliza los tiempos de espera

Para garantizar la continuidad del Pod y evitar errores de la serie 500, el Pod debe estar activo hasta que se quite el extremo del NEG. Especialmente para evitar errores 502 y 503, considera implementar una combinación de tiempos de espera y un preStopHook.

Para mantener el Pod activo por más tiempo durante el proceso de cierre, agrega un preStopHook al Pod. Ejecuta preStopHook antes de que se le indique a un Pod que debe salir, por lo que preStopHook se puede usar para mantener al Pod activo hasta que se quite su extremo correspondiente del NEG.

Para extender el período en que un Pod permanece activo durante el proceso de cierre, inserta preStopHook en la configuración del Pod de la siguiente manera:

spec:
  containers:
  - name: my-app
    ...
    lifecycle:
      preStopHook:
        exec:
          command: ["/bin/sh", "-c", "sleep <latency time>"]

Puedes establecer tiempos de espera y parámetros de configuración relacionados para administrar el cierre ordenado de Pods durante las reducciones verticales de escala de las cargas de trabajo. Puedes ajustar los tiempos de espera según casos de uso específicos. Te recomendamos que comiences con tiempos de espera más largos y reduzcas la duración según sea necesario. Puedes personalizar los tiempos de espera configurando parámetros relacionados con el tiempo de espera y el preStopHook de las siguientes maneras:

Tiempo de espera de desvío del servicio de backend

El parámetro Backend Service Drain Timeout no está configurado de forma predeterminada y no tendrá efecto. Si configuras el parámetro Backend Service Drain Timeout y lo activas, el balanceador de cargas dejará de enrutar solicitudes nuevas al extremo y esperará el tiempo de espera antes de finalizar las conexiones existentes.

Puedes establecer el parámetro Backend Service Drain Timeout mediante BackendConfig con Ingress, GCPBackendPolicy con la puerta de enlace o de forma manual en BackendService con NEG independientes. El tiempo de espera debe ser de 1.5 a 2 veces más extenso que el tiempo que lleva procesar una solicitud. Esto garantiza que si una solicitud llega justo antes de que se inicie el desvío, se completará antes de que se complete el tiempo de espera. Establecer el parámetro Backend Service Drain Timeout en un valor mayor que 0 ayuda a mitigar los errores 503 porque no se envían solicitudes nuevas a los extremos programados para su eliminación. Para que este tiempo de espera sea eficaz, debes usarlo junto con el preStopHook a fin de asegurarte de que el Pod permanezca activo mientras se produce el desvío. Sin esta combinación, las solicitudes existentes que no se completen recibirán un error 502.

Tiempo de preStopHook

El preStopHook debe retrasar el cierre del Pod lo suficiente para que se completen la latencia de desvío y el tiempo de espera de desvío del servicio de backend, lo que garantiza que el vaciado de conexiones y la eliminación de extremos del NEG se realicen correctamente antes de que se cierre el Pod.

Para obtener resultados óptimos, asegúrate de que el tiempo de ejecución de preStopHook sea menor o igual que la suma de los valores de Backend Service Drain Timeout y latencia de desvío.

Esto se puede calcular con la siguiente fórmula:

preStopHook >= Backend Service Drain Timeout + Drain Latency

Te recomendamos establecer la latencia de desvío en 1 minuto. Si los errores 500 persisten, calcula la duración total del caso y agrega el doble de ese tiempo a la latencia. Esto garantiza que tu Pod tenga tiempo suficiente para desviarse de forma ordenada antes de quitarse del servicio. Puedes ajustar este valor si es demasiado largo para tu caso de uso específico.

Como alternativa, puedes estimar el tiempo analizando la marca de tiempo de eliminación del Pod y la marca de tiempo en la que el extremo se quitó del NEG en los Registros de auditoría de Cloud.

Parámetro de período de gracia de finalización

Debes configurar el parámetro terminationGracePeriod a fin de permitir el tiempo suficiente para que el preStopHook finalice y para que el Pod complete un cierre ordenado.

De forma predeterminada, cuando no se establece de forma explícita, el terminationGracePeriod es 30 segundos. Puedes calcular el terminationGracePeriod óptimo con la siguiente fórmula:

terminationGracePeriod >= preStopHook Time + Pod shutdown time

Puedes definir terminationGracePeriod dentro de la configuración del Pod de la siguiente manera:

  spec:
    terminationGracePeriodSeconds: <terminationGracePeriod>
    containers:
    - name: my-app
      ...
    ...

No se encontró el NEG cuando se creó un recurso Ingress interno

El siguiente error puede ocurrir cuando creas un Ingress interno en GKE:

Error syncing: error running backend syncing routine: googleapi: Error 404: The resource 'projects/PROJECT_ID/zones/ZONE/networkEndpointGroups/NEG' was not found, notFound

Este error se produce porque Ingress para los balanceadores de cargas de aplicaciones internos requiere grupos de extremos de red (NEG) como backends.

En entornos de VPC compartida o clústeres con las Políticas de red habilitadas, agrega la anotación cloud.google.com/neg: '{"ingress": true}' al manifiesto del Service.

504 Gateway Timeout: tiempo de espera de solicitud ascendente

El siguiente error puede ocurrir cuando accedes a un Service desde un Ingress interno en GKE:

HTTP/1.1 504 Gateway Timeout
content-length: 24
content-type: text/plain

upsteam request timeout

Este error se produce porque los proxies de Envoy envían el tráfico a los balanceadores de cargas de aplicaciones internos en el rango de subredes de solo proxy.

Para permitir el tráfico desde el rango de subred de solo proxy, crea una regla de firewall en el targetPort del Service.

Error 400: Valor no válido para el campo “resource.target”

El siguiente error puede ocurrir cuando accedes a un Service desde un Ingress interno en GKE:

Error syncing:LB_NAME does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION_NAME/targetHttpProxies/LB_NAME. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.

Para resolver este problema, crea una subred de solo proxy.

Error durante la sincronización: error durante la ejecución de la rutina de sincronización del balanceador de cargas: el balanceador de cargas no existe

Uno de los siguientes errores puede ocurrir cuando se actualiza el plano de control de GKE o cuando modificas un objeto Ingress:

"Error during sync: error running load balancer syncing routine: loadbalancer
INGRESS_NAME does not exist: invalid ingress frontend configuration, please
check your usage of the 'kubernetes.io/ingress.allow-http' annotation."

Como alternativa, puedes hacer lo siguiente:

Error during sync: error running load balancer syncing routine: loadbalancer LOAD_BALANCER_NAME does not exist:
googleapi: Error 400: Invalid value for field 'resource.IPAddress':'INGRESS_VIP'. Specified IP address is in-use and would result in a conflict., invalid

Para resolver estos problemas, prueba los siguientes pasos:

  • Agrega el campo hosts en la sección tls del manifiesto de Ingress y, luego, borra el Ingress. Espera cinco minutos para que GKE borre los recursos de Ingress sin usar. Luego, vuelve a crear el Ingress. Para obtener más información, consulta El campo de hosts de un objeto Ingress.
  • Revierte los cambios que realizaste al Ingress. Luego, agrega un certificado a través de una anotación o un Secret de Kubernetes.

El Ingress externo produce errores HTTP 502

Usa la siguiente guía para solucionar errores HTTP 502 con recursos externos de Ingress:

  1. Habilita los registros para cada servicio de backend asociado a cada Service de GKE al que hace referencia el Ingress.
  2. Usa los detalles del estado para identificar las causas de las respuestas HTTP 502. Los detalles de estado que indican la respuesta HTTP 502 que se originó en el backend requieren la solución de problemas dentro de los Pods de entrega, no del balanceador de cargas.

Grupos de instancias no administrados

Es posible que experimentes errores HTTP 502 con recursos de Ingress externos si el Ingress externo usa backends de grupos de instancias no administrados. Este problema se produce cuando se cumplen todas las siguientes condiciones:

  • El clúster tiene una gran cantidad total de nodos entre todos los grupos de nodos.
  • Los Pods de entrega para uno o más servicios a los que hace referencia el Ingress se encuentran en unos pocos nodos.
  • Los servicios a los que se hace referencia en el Ingress usan externalTrafficPolicy: Local.

Para determinar si tu Ingress externo usa backends de grupo de instancias no administrados, haz lo siguiente:

  1. Ve a la página de Ingress en la consola de Google Cloud.

    Ir a Ingress

  2. Haz clic en el nombre de tu Ingress externo.

  3. Haz clic en el nombre del balanceador de cargas. Aparecerá la página Detalles del balanceo de cargas.

  4. Verifica la tabla en la sección Servicios de backend para determinar si el Ingress externo usa NEG o grupos de instancias.

Para resolver este problema, usa una de las siguientes soluciones:

  • Usa un clúster nativo de la VPC.
  • Usa externalTrafficPolicy: Cluster para cada servicio al que se hace referencia en el Ingress externo. Esta solución hace que pierdas la dirección IP de cliente original en las fuentes del paquete.
  • Usa la anotación node.kubernetes.io/exclude-from-external-load-balancers=true. Agrega la anotación a los nodos o grupos de nodos que no ejecutan ningún Pod de entrega para ningún Service al que haga referencia cualquier Ingress externo o Service LoadBalancer en el clúster.

Usa los registros del balanceador de cargas para solucionar problemas

Puedes usar los registros del balanceador de cargas de red de transferencia interno y los registros del balanceador de cargas de red de transferencia externo para solucionar problemas relacionados con los balanceadores de cargas y correlacionar el tráfico de los balanceadores de cargas con los recursos de GKE.

Los registros se agregan por conexión y se exportan casi en tiempo real. Los registros se generan para cada nodo de GKE involucrado en la ruta de datos de un Service LoadBalancer, para el tráfico de entrada y salida. Las entradas de registro incluyen campos adicionales para los recursos de GKE, como los siguientes: - Nombre del clúster - Ubicación del clúster - Nombre del Service - Espacio de nombres del Service - Nombre del Pod - Espacio de nombres del Pod

Precios

No se aplican cargos adicionales por usar registros. Según cómo transfieras registros, se aplican los precios estándar para Cloud Logging, BigQuery o Pub/Sub. La habilitación de los registros no afecta el rendimiento del balanceador de cargas.

Usa herramientas de diagnóstico para solucionar problemas

La herramienta de diagnóstico check-gke-ingress inspecciona los recursos de Ingress en busca de opciones de configuración incorrectas comunes. Puedes usar la herramienta de check-gke-ingress de las siguientes maneras:

¿Qué sigue?

Si necesitas asistencia adicional, comunícate con Atención al cliente de Cloud.