Balanceo de cargas HTTP(s) con Ingress

En Google Kubernetes Engine, un objeto Ingress define las reglas del enrutamiento de tráfico HTTP(S) externo a aplicaciones que se ejecutan en un clúster. Un objeto Ingress se asocia con uno o más objetos Service, cada uno de los cuales está asociado con un conjunto de pods.

Cuando creas un objeto Ingress, el controlador de Ingress de GKE crea un balanceador de cargas HTTP(S) de Google Cloud Platform y lo configura de acuerdo con la información del Ingress y sus Services asociados.

Características del balanceo de cargas HTTP(S)

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

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

Para aprender más sobre estas características, consulta los Conceptos de balanceo de cargas HTTP(S).

Limitaciones

El largo total del espacio de nombres y el nombre de un Ingress no deben exceder 55 caracteres. Si incumples esta pauta, puede que el controlador de Ingress de GKE actúe de forma anormal. Para obtener más información, consulta este problema.

Servicios de backend 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 que se envían a your-store.example pueden enrutarse a un servicio de backend que muestra artículos de precio completo y las solicitudes enviadas a your-store.example/discount pueden enrutarse 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:

apiVersion: extensions/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 de Ingress de GKE crea y configura un balanceador de cargas 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 Service de Kubernetes llamado my-products en el puerto 60000. Cuando un cliente envía una solicitud a your-store.example/discount, la solicitud se enruta a un Service 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.

Un patrón más específico tiene prioridad sobre uno menos específico. Si tienes /foo/* y /foo/bar/*, entonces /foo/bar/bat se saca para que coincida 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 del Service my-products podría ser similar al siguiente fragmento de código:

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 del Service, ten en cuenta que el 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 del Service, el campo selector indica que cualquier pod que tenga las etiquetas app: products y department: sales es un miembro de este Service.

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

Ten en cuenta que cada pod miembro debe tener un contenedor que escuche en el puerto TCP 50000.

El manifiesto del Service my-discounted-products podría ser similar al siguiente fragmento de código:

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 del Service, el campo selector indica que cualquier pod que tenga las etiquetas app: discounted-products y department: sales es un miembro de este Service.

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

Ten en cuenta que cada pod miembro debe tener un contenedor que escuche en el puerto TCP 8080.

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 siguientes acciones para indicar que está en buen estado:

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

  • Configurar una prueba de disponibilidad HTTP. Entregar una respuesta con un estado HTTP 200 a las solicitudes GET en la path especificada por la prueba de disponibilidad

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

    ...
    readinessProbe:
      httpGet:
        path: /healthy
    

    Entonces, 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.

El Service de Kubernetes comparado con el servicio de backend de GCP

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

Compatibilidad con características de GCP

Puedes usar un BackendConfig a fin de configurar un balanceador de cargas HTTP(S) para usar características como Cloud Armor, Cloud CDN y Cloud IAP.

BackendConfig es un recurso personalizado que contiene información de configuración de las características de GCP.

El manifiesto de un Ingress refiere a un Service y el manifiesto de un Service refiere a un BackendConfig con una anotación beta.cloud.google.com/backend-config.

...
kind: Ingress
...
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-service
          servicePort: 80
...

kind: Service
metadata:
  name: my-service
  ...
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
spec:
  type: NodePort
  ...
 

Compatibilidad con WebSocket

Con el balanceo de cargas HTTP(S), el protocolo WebSocket funciona a la perfección. No se requiere configuración.

Si pretendes usar el protocolo WebSocket, es posible que quieras usar un valor de tiempo de espera mayor que los 30 segundos predeterminados. Para establecer el valor de tiempo de espera de un servicio de backend configurado con del Ingress, crea un objeto BackendConfig y usa la anotación beta.cloud.google.com/backend-config en tu manifiesto de Service.

Para obtener más información, consulta Configura un servicio de backend con un Ingress.

Direcciones IP estáticas para el balanceador de cargas HTTP(S)

Cuando creas un objeto Ingress, obtienes una dirección IP externa estable que los clientes pueden usar para acceder a tus Services y, a su vez, a tus contenedores en ejecución. La dirección IP es estable en el sentido de que dura toda la vida útil del objeto Ingress. Si borras tu Ingress y creas uno nuevo a partir del mismo archivo de manifiesto, no se garantiza que obtengas la misma dirección IP externa.

Si quieres una dirección IP permanente que se mantendrá igual si borras tu Ingress y creas uno nuevo, debes reservar una dirección IP externa estática global. Luego, en el manifiesto del Ingress, incluye una anotación que indique el nombre de tu dirección IP estática reservada.

Por ejemplo, supongamos que reservaste una dirección IP externa estática global llamada my-static-address. En tu manifiesto del Ingress, incluye una anotación kubernetes.io/ingress.global-static-ip-name tal como se muestra a continuación:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: my-static-address

Si quieres obtener más información sobre cómo crear una dirección IP externa estática para un Ingress, consulta Configura una dirección IP estática y Configura nombres de dominio con direcciones IP estáticas.

Configura HTTPS (TLS) entre el cliente y el balanceador de cargas

Un balanceador de cargas HTTP(S) actúa como un proxy entre tus clientes y tu aplicación. Si deseas aceptar solicitudes HTTPS de tus clientes, el balanceador de cargas debe contar con un certificado para que pueda demostrar su identidad a los clientes. También debe tener una clave privada para completar el protocolo de enlace HTTPS.

Cuando el balanceador de cargas acepta una solicitud HTTPS de un cliente, el tráfico entre el cliente y el balanceador de cargas se encripta con TLS. Sin embargo, el balanceador de cargas finaliza la encriptación TLS y reenvía la solicitud sin encriptar a la aplicación. Para obtener más información sobre cómo encriptar tráfico entre el balanceador de cargas y tu aplicación, consulta HTTPS entre el balanceador de cargas y tu aplicación.

Para proporcionar un balanceador de cargas HTTP(S) con un certificado y clave, puedes especificar el nombre de un Secreto de Kubernetes en el campo tls de tu manifiesto del Ingress. El secreto, que creaste antes, contiene el certificado y la clave.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-2
spec:
  tls:
  - secretName: my-secret
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-metrics
          servicePort: 60000

Los cambios en los secretos se captan de manera periódica, así que, si modificas los datos dentro del secreto, esos cambios se aplicarán en el balanceador de cargas en un máximo de 10 minutos.

Si quieres obtener más información sobre el uso de secretos para proporcionar certificados al balanceador de cargas, consulta Usa varios certificados SSL en el balanceo de cargas HTTP(S) con Ingress.

Inhabilita HTTP

Si quieres que todo el tráfico entre el cliente y el balanceador de cargas HTTP(S) use HTTPS, puedes inhabilitar HTTP usando la anotación kubernetes.io/ingress.allow-http en tu manifiesto del Ingress. Establece el valor de la anotación como "false".

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-2
  annotations:
    kubernetes.io/ingress.allow-http: "false"
spec:
  tls:
  - secretName: my-secret
  ...

Certificados compartidos previamente para balanceadores de cargas

Una alternativa al uso de secretos de Kubernetes a fin de proporcionar certificados al balanceador de cargas para la finalización de HTTP(S) es usar certificados ya cargados a tu proyecto de GCP. Para obtener más información, consulta Usa certificados compartidos previamente y Usa varios certificados SSL en el balanceo de cargas HTTP(S) con Ingress.

HTTPS (TLS) entre el balanceador de cargas y tu aplicación

Un balanceador de cargas HTTP(S) actúa como un proxy entre tus clientes y tu aplicación. Los clientes pueden usar HTTP o HTTPS para comunicarse con el proxy del balanceador de cargas. Sin embargo, la conexión del proxy del balanceador de cargas a tu aplicación usa HTTP de forma predeterminada. Si tu aplicación, que se ejecuta en un pod de GKE, es capaz de recibir solicitudes HTTPS, puedes configurar el balanceador de cargas para usar HTTPS cuando reenvía solicitudes a tu aplicación.

Para configurar el protocolo usado entre el balanceador de cargas y tu aplicación, usa la anotación cloud.google.com/app-protocols en tu manifiesto del Service.

El siguiente manifiesto del Service especifica dos puertos. La anotación establece que, cuando un balanceador de cargas HTTP(S) apunta al puerto 80 del Service, debería usar HTTP; y, cuando el balanceador de cargas apunta al puerto 443 del Service, debería usar HTTPS.

apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-https-port
    port: 443
    targetPort: 8443
  - name: my-http-port
    port: 80
    targetPort: 50001

La anotación cloud.google.com/app-protocols tiene el mismo propósito que la anotación service.alpha.kubernetes.io/app-protocols anterior. Los nombres de anotación anteriores y nuevos pueden coexistir, como se muestra en el siguiente manifiesto del Service. Cuando ambas anotaciones aparecen en el mismo manifiesto, service.alpha.kubernetes.io/app-protocols tiene prioridad.

apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
    service.alpha.kubernetes.io/app-protocols: '{"my-first-port":"HTTPS","my-second-port":"HTTP"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-first-port
    port: 443
    targetPort: 8443
  - name: my-second-port
    port: 80
    targetPort: 50001

Usa varios certificados TLS

Supongamos que quieres usar un balanceador de cargas 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 especificar varios certificados en un manifiesto de Ingress y el balanceador de cargas elegirá un certificado si el nombre común en el certificado coincide con el nombre de host usado en la solicitud. Para obtener más información sobre cómo configurar varios certificados, consulta Usa varios certificados SSL en el balanceo de cargas HTTP(S) con Ingress.

Pasos siguientes

¿Te sirvió esta página? Envíanos tu opinión:

Enviar comentarios sobre…