GKE Ingress para el balanceo de cargas de HTTP(S)

En esta página, se proporciona una descripción general del funcionamiento de Ingress para el balanceo de cargas de HTTP(S). Google Kubernetes Engine (GKE) proporciona un controlador Ingress integrado y administrado llamado GKE Ingress. Este controlador implementa recursos de Ingress como balanceadores de cargas de Google Cloud para cargas de trabajo HTTP(S) en GKE.

Descripción general

En GKE, un objeto Ingress define las reglas para enrutar el tráfico HTTP(S) a las aplicaciones que se ejecutan en un clúster. Un objeto Ingress se asocia con uno o más objetos Service, y cada uno está asociado con un conjunto de pods.

Cuando creas un objeto Ingress, el controlador GKE Ingress crea un balanceador de cargas de HTTP(S) de Google Cloud y lo configura según la información en el Ingress y sus objetos Service asociados.

Ingress para tráfico interno y externo

Los recursos de GKE Ingress se dividen en dos tipos:

Características del balanceo de cargas de HTTP(S)

El balanceo de cargas de HTTP(S) configurado por Ingress incluye las características siguientes:

Configuración flexible para servicios
Un Ingress define cómo llega el tráfico a tus servicios y la forma en que se enruta a tu aplicación. Además, un Ingress puede proporcionar una sola dirección IP para varios Services en tu clúster.
Integración en los servicios de red de Google Cloud
Un Ingress puede configurar características de Google Cloud, como certificados SSL administrados por Google (Beta), Google Cloud Armor, Cloud CDN, y, también, Identity-Aware Proxy .
Asistencia para varios certificados TLS
Un Ingress puede especificar el uso de varios certificados TLS para la finalización de solicitudes.

Balanceo de cargas nativo del contenedor

El balanceo de cargas nativo del contenedor es la práctica de realizar el balanceo de cargas directamente en extremos de pod en GKE mediante grupos de extremos de red (NEG).

Antes de los NEG, los balanceadores de cargas de Compute Engine enviaban tráfico a los grupos de instancias con direcciones IP de nodo como backends. Este método tiene varias limitaciones:

  • Se generan dos saltos de balanceo de cargas.
  • Agrega latencia.
  • El balanceador de cargas de Compute Engine no tiene visibilidad directa de los pods, lo que da como resultado un balanceo de tráfico que no es óptimo.

Con los NEG, las cargas del tráfico se balancean desde el proxy de Ingress directamente hacia la IP del pod, y no se desvía la IP del nodo ni las herramientas de redes de kube-proxy. Además, las puertas de preparación del pod se implementan para determinar el estado de los pods desde la perspectiva del balanceador de cargas y no solo de las verificaciones de preparación y capacidad de respuesta de Kubernetes. Esto garantiza que el tráfico no se pierda durante los eventos del ciclo de vida, como el inicio del pod, la pérdida del pod o la pérdida de nodos.

Se recomienda aprovechar el balanceo de cargas nativo del contenedor mediante la implementación de Ingress con NEG, y se debe usar siempre que sea posible. No es el modo predeterminado de los Services y debe aplicarse de forma explícita con la anotación de cloud.google.com/neg a los Services que son backends de una regla de Ingress:

kind: Service
...
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
...

Servicios de backends múltiples

Un balanceador de cargas de HTTP(S) proporciona una dirección IP estable que puedes usar para enrutar solicitudes a una variedad de servicios de backend.

Por ejemplo, puedes configurar el balanceador de cargas para enrutar solicitudes a diferentes servicios de backend según la ruta de URL. Las solicitudes enviadas a your-store.example se pueden enrutar a un servicio de backend que muestra artículos a precio completo; las solicitudes enviadas a your-store.example/discounted se pueden enrutar a un servicio de backend que muestra artículos con descuento.

También puedes configurar el balanceador de cargas para enrutar solicitudes según el nombre de host. Las solicitudes enviadas a your-store.example pueden ir a un servicio de backend y las solicitudes enviadas a your-experimental-store.example pueden ir a otro.

En un clúster de GKE, puedes crear un objeto Ingress de Kubernetes para crear y configurar un balanceador de cargas HTTP(S). Un objeto Ingress debe estar asociado con uno o más objetos Service, cada uno de los cuales está asociado con un conjunto de pods.

A continuación, se detalla un manifiesto para un Ingress llamado my-ingress:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

Cuando creas el Ingress, el controlador GKE Ingress crea y configura un balanceador de cargas de HTTP(S) según la información en el Ingress y los Services asociados. Además, se le asigna una dirección IP estable al balanceador de cargas que puedes asociar con un nombre de dominio.

En el ejemplo anterior, supón que asociaste la dirección IP del balanceador de cargas con el nombre de dominio your-store.example. Cuando un cliente envía una solicitud a your-store.example, la solicitud se enruta a un servicio de Kubernetes llamado my-products en el puerto 60000. Cuando un cliente envía una solicitud a your-store.example/discounted, la solicitud se enruta a un servicio de Kubernetes llamado my-discounted-products en el puerto 80.

El único carácter comodín admitido para el campo path de un Ingress es el carácter *. El carácter * debe estar después de una barra diagonal (/) y debe ser el último carácter del patrón. Por ejemplo, /*, /foo/* y /foo/bar/* son patrones válidos, pero *, /foo/bar* y /foo/*/bar no lo son.

Un patrón más específico tiene prioridad sobre uno menos específico. Si tienes /foo/* y /foo/bar/*, entonces se considera que /foo/bar/bat coincide con /foo/bar/*.

Para obtener más información sobre las limitaciones de ruta y la coincidencia de patrones, consulta la documentación de mapas de URL.

El manifiesto para el servicio my-products podría verse así:

apiVersion: v1
kind: Service
metadata:
  name: my-products
spec:
  type: NodePort
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50000

En el manifiesto de servicio, observa que type es NodePort. Este es el tipo requerido de un Ingress que se usa para configurar un balanceador de cargas HTTP(S).

En el manifiesto de servicio, el campo selector indica que cualquier pod que tenga las etiquetas app: products y department: sales es miembro de este servicio.

Cuando llega una solicitud al Service en el puerto 60000, se enruta a uno de los pods miembros en el puerto TCP 50000.

Cada pod miembro debe tener un contenedor que escuche en el puerto TCP 50000.

El manifiesto para el servicio my-discounted-products podría verse así:

apiVersion: v1
kind: Service
metadata:
  name: my-discounted-products
spec:
  type: NodePort
  selector:
    app: discounted-products
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

En el manifiesto de servicio, el campo selector indica que cualquier pod que tenga las etiquetas app: discounted-products y department: sales es miembro de este servicio.

Cuando llega una solicitud al servicio del puerto 80, se enruta a uno de los pods miembros en el puerto TCP 8080.

Cada pod miembro debe tener un contenedor que escuche en el puerto TCP 8080.

Backend predeterminado

Puedes especificar un backend predeterminado si proporcionas un campo backend en el manifiesto de Ingress. Todas las solicitudes que no coincidan con las rutas del campo rules se enviarán al servicio y al puerto especificados en el campo backend. Por ejemplo, en el siguiente Ingress, toda solicitud que no coincida con / ni /discounted se enviará a un servicio llamado my-products en el puerto 60001.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: my-products
    servicePort: 60001
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

Si no especificas un backend predeterminado, GKE proporciona uno que muestra 404.

Asignaciones de recursos de Ingress a Compute Engine

El controlador GKE Ingress implementa y administra recursos del balanceador de cargas de Compute Engine según los recursos de Ingress que se implementan en el clúster. La asignación de los recursos de Compute Engine depende de la estructura del recurso de Ingress. Conocer estas asignaciones de recursos te ayuda con la planificación, el diseño y la solución de problemas.

El manifiesto my-ingress que aparece en la sección Servicios de backend múltiples especifica un recurso Ingress externo con dos coincidencias de rutas de URL que hacen referencia a dos Services de Kubernetes diferentes. Estos son algunos de los recursos de Compute Engine creados en nombre de my-ingress:

  • Una VIP pública que corresponde a una forwardingRule.
  • Reglas de firewall de Compute Engine que permiten el tráfico para las verificaciones de estado y el tráfico de las aplicaciones.
  • Un proxy HTTP de destino. Si se configuró TLS, el resultado sería un proxy HTTPS adicional.
  • Un mapa de URL que tiene una sola hostRule, pathMatchers para /* y /discounted. Esto apunta a los backendServices correspondientes.
  • NEG que contienen una lista de direcciones IP de pod de cada Service como extremos. Estos se crean como resultado de los Services my-discounted-products y my-products. En el siguiente diagrama, se proporciona una descripción general de las asignaciones de recursos de Ingress a Compute Engine.

Diagrama de asignación de recursos de Ingress a Compute Engine

Opciones para proporcionar certificados SSL

Existen tres maneras de proporcionar certificados SSL a un balanceador de cargas de HTTPS:

Certificados administrados por Google
Los certificados SSL administrados por Google se aprovisionan, implementan, renuevan y administran para tus dominios. Los certificados administrados no admiten dominios de comodín.
Certificados autoadministrados compartidos con Google Cloud
Puedes aprovisionar tu propio certificado SSL y crear un recurso de certificado en tu proyecto de Google Cloud. Luego, puedes enumerar el recurso de certificado en una anotación en un Ingress para crear un balanceador de cargas de HTTP(S) que use el certificado. Consulta las instrucciones para certificados ya compartidos a fin de obtener más información.
Certificados autoadministrados como recursos secretos
Puedes aprovisionar tu propio certificado SSL y crear un secreto para retenerlo. Luego, puedes hacer referencia al secreto en una especificación Ingress para crear un balanceador de cargas HTTP(S) que use el certificado. Para obtener más información, consulta las instrucciones para usar certificados en secretos.

Verificaciones de estado

Un Service expuesto a través de un Ingress debe responder a las verificaciones de estado del balanceador de cargas. Cualquier contenedor que sea el destino final del tráfico del balanceador de cargas debe realizar una de las acciones siguientes para indicar que está en buen estado:

  • Entrega una respuesta con un estado HTTP 200 a las solicitudes GET en la ruta /.

  • Configura una prueba de disponibilidad HTTP. Entrega una respuesta con un estado HTTP 200 a las solicitudes GET en la path especificada por el sondeo de prueba de disponibilidad. El servicio expuesto a través de un Ingress debe apuntar al mismo puerto de contenedor en el que está habilitada la prueba de disponibilidad.

    Por ejemplo, supongamos que un contenedor especifica la siguiente prueba de disponibilidad:

    ...
    readinessProbe:
      httpGet:
        path: /healthy
    

    Luego, si el controlador de la ruta /healthy del contenedor muestra un estado HTTP 200, el balanceador de cargas considera que el contenedor está activo y en buen estado.

Usa varios certificados TLS

Supongamos que quieres usar un balanceador de cargas de HTTP(S) para entregar contenido de dos nombres de host: your-store.example y your-experimental-store.example. Además, quieres que el balanceador de cargas use un certificado con your-store.example y uno diferente con your-experimental-store.example.

Puedes hacerlo mediante la especificación de varios certificados en un manifiesto de Ingress. El balanceador de cargas elige un certificado si el nombre común (CN) del certificado coincide con el nombre de host usado en la solicitud. Para obtener información detallada sobre cómo configurar varios certificados, consulta Usa varios certificados SSL en el balanceo de cargas de HTTP(S) con Ingress.

El Service de Kubernetes en comparación con el servicio de backend de Google Cloud

Un servicio de Kubernetes y un servicio de backend de Google Cloud son elementos diferentes. Existe una relación fuerte entre los dos, pero esta no tiene por qué ser de uno a uno. El controlador GKE Ingress crea un servicio de backend de Google Cloud para cada par (serviceName, servicePort) en un manifiesto de Ingress. Por lo tanto, es posible que un objeto Service de Kubernetes esté relacionado con varios servicios de backend de Google Cloud.

Limitaciones

  • La extensión total del espacio de nombres y el nombre de un Ingress no debe exceder los 40 caracteres. Si incumples esta pauta, puede que el controlador GKE Ingress actúe de forma anormal. Para obtener más información, consulta este problema en GitHub.

  • La cantidad máxima de reglas para un mapa de URL es de 50. Esto significa que puedes especificar un máximo de 50 reglas en un Ingress.

  • Si no usas NEG con el controlador GKE Ingress, los clústeres de GKE tienen un límite de 1,000 nodos. Cuando los servicios se implementan con NEG, no hay límite de nodos de GKE. Los Services ajenos a NEG expuestos a través de Ingress no funcionan de forma correcta en clústeres de más de 1,000 nodos.

  • A fin de que el controlador GKE Ingress use tus readinessProbes como verificaciones de estado, los pods para un Ingress deben existir en el momento de la creación de este. Si tus réplicas se escalan a 0, se aplicará la verificación de estado predeterminada. Para obtener más información, consulta este comentario sobre el problema.

  • Los cambios en readinessProbe de un pod no afectan el Ingress después de que se crea.

  • El balanceador de cargas de HTTPS finaliza TLS en ubicaciones distribuidas de manera global a fin de minimizar la latencia entre los clientes y el balanceador de cargas. Si necesitas control geográfico sobre la ubicación donde finaliza TLS, debes usar un controlador Ingress personalizado y el balanceo de cargas de red de GCP y finalizar TLS en backends ubicados en regiones adecuadas para tus necesidades.

Próximos pasos