Implementa Ingress en clústeres


En esta página, se muestra cómo implementar un Ingress que entrega una aplicación en varios clústeres de GKE. Para obtener más información sobre Ingress de varios clústeres, consulta Ingress de varios clústeres.

Para obtener una comparación detallada entre Ingress de varios clústeres (MCI), la puerta de enlace de varios clústeres (MCG) y el balanceador de cargas con grupos de extremos de red independientes (LB y NEG independientes), consulta Elige tu clúster múltiple API de balanceo de cargas para GKE.

Instructivo para la implementación

En las siguientes tareas, implementarás una app ficticia llamada whereami y MultiClusterIngress en dos clústeres. El Ingress proporciona una dirección IP virtual (VIP) compartida para las implementaciones de la aplicación.

Esta página se basa en el trabajo realizado en Configura Ingress de varios clústeres, en el que creaste y registraste dos clústeres. Confirma que tienes dos clústeres que también estén registrados en una flota:

gcloud container clusters list

El resultado es similar a este:

NAME    LOCATION        MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION     NUM_NODES  STATUS
gke-eu  europe-west1-b  1.16.8-gke.9    ***             e2-medium      1.16.8-gke.9     2          RUNNING
gke-us  us-central1-b   1.16.8-gke.9    ***             e2-medium      1.16.6-gke.13 *  2          RUNNING

Crea el espacio de nombres

Debido a que las flotas tienen la propiedad de similitud de espacio de nombres, recomendamos que coordines la creación y administración de los espacios de nombres entre los clústeres para que el mismo grupo sea propietario y administrador de los espacios de nombres idénticos. Puedes crear espacios de nombres por equipo, por entorno, por aplicación o por componente de la aplicación. Los espacios de nombres pueden ser tan detallados como sea necesario, siempre que un espacio de nombres ns1 en un clúster tenga el mismo significado y uso que ns1 en otro clúster.

En este ejemplo, crearás un espacio de nombres whereami para cada aplicación en cada clúster.

  1. Crea un archivo llamado namespace.yaml que tenga el siguiente contenido:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: whereami
    
  2. Cambia al contexto de gke-us:

    kubectl config use-context gke-us
    
  3. Crea el espacio de nombres:

    kubectl apply -f namespace.yaml
    
  4. Cambia al contexto de gke-eu:

    kubectl config use-context gke-eu
    
  5. Crea el espacio de nombres:

    kubectl apply -f namespace.yaml
    

    El resultado es similar a este:

    namespace/whereami created
    

Implementa la app.

  1. Crea un archivo llamado deploy.yaml que tenga el siguiente contenido:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-deployment
      namespace: whereami
      labels:
        app: whereami
    spec:
      selector:
        matchLabels:
          app: whereami
      template:
        metadata:
          labels:
            app: whereami
        spec:
          containers:
          - name: frontend
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
            - containerPort: 8080
    
  2. Cambia al contexto de gke-us:

    kubectl config use-context gke-us
    
  3. Implementa la aplicación whereami:

    kubectl apply -f deploy.yaml
    
  4. Cambia al contexto de gke-eu:

    kubectl config use-context gke-eu
    
  5. Implementa la aplicación whereami:

    kubectl apply -f deploy.yaml
    
  6. Verifica que la aplicación whereami se haya implementado correctamente en cada clúster:

    kubectl get deployment --namespace whereami
    

    El resultado debería ser similar al siguiente en ambos clústeres:

    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    whereami-deployment   1/1     1            1           12m
    

Implementa a través del clúster de configuración

Ahora que la aplicación está implementada en gke-us y gke-eu, implementarás un balanceador de cargas mediante la implementación de los recursos MultiClusterIngress y MultiClusterService en el clúster de configuración. Estos son los equivalentes de varios clústeres de los recursos Ingress y Service.

En los pasos de la guía de configuración, configuraste el clúster gke-us como el clúster de configuración. El clúster de configuración se usa para implementar y configurar Ingress en todos los clústeres.

  1. Configura el contexto en el clúster de configuración.

    kubectl config use-context gke-us
    

MultiClusterService

  1. Crea un archivo llamado mcs.yaml que tenga el siguiente contenido:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    
  2. Implementa el recurso MultiClusterService que coincida con la aplicación whereami:

    kubectl apply -f mcs.yaml
    
  3. Verifica que el recurso whereami-mcs se haya implementado correctamente en el clúster de configuración:

    kubectl get mcs -n whereami
    

    El resultado es similar a este:

    NAME       AGE
    whereami-mcs   9m26s
    

    Este MultiClusterService crea un Service sin interfaz gráfica derivado en cada clúster que coincida con pods con app: whereami. Puedes ver que existe uno en el clúster kubectl get service -n whereami de gke-us.

    El resultado es similar a este:

    NAME                                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
    mci-whereami-mcs-svc-lgq966x5mxwwvvum   ClusterIP   None          <none>        8080/TCP         4m59s
    

También habrá un Service sin interfaz gráfica similar en gke-eu. Estos Services locales se usan para seleccionar de forma dinámica los extremos del pod a fin de programar el balanceador de cargas del Ingress global con backends.

MultiClusterIngress

  1. Crea un archivo llamado mci.yaml que tenga el siguiente contenido:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
    

    Ten en cuenta que esta configuración enruta todo el tráfico al MultiClusterService llamado whereami-mcs que existe en el espacio de nombres whereami.

  2. Implementa el recurso MultiClusterIngress que hace referencia a whereami-mcs como un backend:

    kubectl apply -f mci.yaml
    

    El resultado es similar a este:

    multiclusteringress.networking.gke.io/whereami-ingress created
    

    Ten en cuenta que MultiClusterIngress tiene el mismo esquema que el Ingress de Kubernetes. La semántica del recurso Ingress también es la misma, salvo el campo backend.serviceName.

El campo backend.serviceName en un MultiClusterIngress hace referencia a un MultiClusterService en la API de Fleet en lugar de un servicio en un clúster de Kubernetes. Esto significa que cualquiera de las opciones de configuración para Ingress, como la finalización de TLS, se puede establecer de la misma manera.

Valida un estado de implementación exitosa

La implementación del balanceador de cargas de Google Cloud puede tardar varios minutos en implementarse para los balanceadores de cargas nuevos. La actualización de los balanceadores de cargas existentes se completa más rápido porque no es necesario implementar los recursos nuevos. El recurso MultiClusterIngress detalla los recursos subyacentes de Compute Engine que se crearon en su nombre de MultiClusterIngress.

  1. Verifica que la implementación se haya realizado correctamente:

    kubectl describe mci whereami-ingress -n whereami
    

    El resultado es similar a este:

    Name:         whereami-ingress
    Namespace:    whereami
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                    {"apiVersion":"networking.gke.io/v1","kind":"MultiClusterIngress","metadata":{"annotations":{},"name":"whereami-ingress","namespace":"whe...
    API Version:  networking.gke.io/v1
    Kind:         MultiClusterIngress
    Metadata:
      Creation Timestamp:  2020-04-10T23:35:10Z
      Finalizers:
        mci.finalizer.networking.gke.io
      Generation:        2
      Resource Version:  26458887
      Self Link:         /apis/networking.gke.io/v1/namespaces/whereami/multiclusteringresses/whereami-ingress
      UID:               62bec0a4-8a08-4cd8-86b2-d60bc2bda63d
    Spec:
      Template:
        Spec:
          Backend:
            Service Name:  whereami-mcs
            Service Port:  8080
    Status:
      Cloud Resources:
        Backend Services:
          mci-8se3df-8080-whereami-whereami-mcs
        Firewalls:
          mci-8se3df-default-l7
        Forwarding Rules:
          mci-8se3df-fw-whereami-whereami-ingress
        Health Checks:
          mci-8se3df-8080-whereami-whereami-mcs
        Network Endpoint Groups:
          zones/europe-west1-b/networkEndpointGroups/k8s1-e4adffe6-whereami-mci-whereami-mcs-svc-lgq966x5m-808-88670678
          zones/us-central1-b/networkEndpointGroups/k8s1-a6b112b6-whereami-mci-whereami-mcs-svc-lgq966x5m-808-609ab6c6
        Target Proxies:
          mci-8se3df-whereami-whereami-ingress
        URL Map:  mci-8se3df-whereami-whereami-ingress
      VIP:        34.98.102.37
    Events:
      Type    Reason  Age                    From                              Message
      ----    ------  ----                   ----                              -------
      Normal  ADD     3m35s                  multi-cluster-ingress-controller  whereami/whereami-ingress
      Normal  UPDATE  3m10s (x2 over 3m34s)  multi-cluster-ingress-controller  whereami/whereami-ingress
    

    Hay varios campos que indican el estado de la implementación de este Ingress:

    • Events es el primer lugar para buscar. Si se produjo un error, aparecerá aquí.

    • Cloud Resource enumera los recursos de Compute Engine, como las reglas de reenvío, los servicios de backend y las reglas de firewall que creó el controlador de Ingress de Anthos. Si no aparecen en la lista, significa que aún no se crearon. Puedes inspeccionar recursos individuales de Compute Engine mediante Console o el comando gcloud para obtener el estado.

    • VIP muestra una dirección IP una vez que se asignó una. Ten en cuenta que es posible que el balanceador de cargas aún no procese tráfico, aunque exista la VIP. Si no ves una VIP después de un par de minutos o si el balanceador de cargas no entrega 200 respuestas en 10 minutos, consulta la página sobre solución de problemas y operaciones.

    Si los eventos de salida son Normal, es probable que la implementación del MultiClusterIngress sea correcta, pero la única manera de determinar si toda la ruta del tráfico es funcional es probándola.

  2. Valida que la aplicación realiza las entregas en la VIP con el extremo /ping:

    curl INGRESS_VIP/ping
    

    Reemplaza INGRESS_VIP por la dirección IP virtual (VIP).

    El resultado es similar a este:

    {
    "cluster_name": "gke-us",
    "host_header": "34.120.175.141",
    "pod_name": "whereami-deployment-954cbf78-mtlpf",
    "pod_name_emoji": "😎",
    "project_id": "my-project",
    "timestamp": "2021-11-29T17:01:59",
    "zone": "us-central1-b"
    }
    

    El resultado debe indicar la región y el backend de la aplicación.

  3. También puedes ir a la URL http://INGRESS_VIP en tu navegador para ver una versión gráfica de la aplicación que muestra la región desde la que se entrega.

    El clúster al que se reenvía el tráfico depende de tu ubicación. El GCLB está diseñado para reenviar el tráfico del cliente al backend disponible con capacidad más cercano.

Especificaciones de los recursos

Especificaciones de MultiClusterService

La definición de MultiClusterService consta de dos partes:

  1. Una sección template, que define el servicio que se creará en los clústeres de Kubernetes. Ten en cuenta que, si bien la sección template contiene campos compatibles con un servicio típico, solo hay dos campos compatibles con MultiClusterService: selector y ports. Los otros campos se ignoran.

  2. Una sección clusters opcional, que define qué clústeres recibirán el tráfico y las propiedades del balanceo de cargas para cada clúster. Si no se especifica una sección clusters o si no se enumera ningún clúster, se usarán todos los clústeres de forma predeterminada.

En el siguiente manifiesto, se describe un MultiClusterService estándar:

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: NAME
  namespace: NAMESPACE
spec:
  template:
    spec:
      selector:
        app: POD_LABEL
      ports:
      - name: web
        protocol: TCP
        port: PORT
        targetPort: TARGET_PORT

Reemplaza lo siguiente:

  • NAME: el nombre de MultiClusterService. El campo serviceName hace referencia a este nombre en los recursos MultiClusterIngress.
  • NAMESPACE: es el espacio de nombres de Kubernetes en el que se implementa el MultiClusterService. Debe estar en el mismo espacio de nombres que el MultiClusterIngress y los pods en todos los clústeres del entorno.
  • POD_LABEL: es la etiqueta que determina qué pods se seleccionan como backends para este MultiClusterService en todos los clústeres de la flota.
  • PORT: Debe coincidir con el puerto al que hace referencia MultiClusterIngress que hace referencia a este MultiClusterService.
  • TARGET_PORT es el puerto que se usa para enviar tráfico al pod desde el GCLB. Se crea un NEG en cada clúster con este puerto como su puerto de entrega.

Especificaciones de MultiClusterIngress

En el siguiente mci.yaml, se describe el frontend del balanceador de cargas:

apiVersion: networking.gke.io/v1
kind: MultiClusterIngress
metadata:
  name: NAME
  namespace: NAMESPACE
spec:
  template:
    spec:
      backend:
       serviceName: DEFAULT_SERVICE
       servicePort: PORT
      rules:
        - host: HOST_HEADER
          http:
            paths:
            - path: PATH
              backend:
                serviceName: SERVICE
                servicePort: PORT

Reemplaza lo siguiente:

  • NAME: El nombre del recurso MultiClusterIngress.
  • NAMESPACE: es el espacio de nombres de Kubernetes en el que se implementa el MultiClusterIngress. Debe estar en el mismo espacio de nombres que el MultiClusterService y los pods en todos los clústeres del entorno.
  • DEFAULT_SERVICE actúa como el backend predeterminado para todo el tráfico que no coincide con ninguna regla de host ni de ruta de acceso. Este es un campo obligatorio y se debe especificar un backend predeterminado en el MultiClusterIngress, incluso si hay otras coincidencias de host o de ruta de acceso configuradas.
  • PORT: cualquier número de puerto válido. Este debe coincidir con el campo port de los recursos MultiClusterService.
  • HOST_HEADER coincide con el tráfico según el campo del encabezado del host HTTP. El campo host es opcional.
  • PATH coincide con el tráfico según la ruta de acceso de la URL HTTP. El campo path es opcional.
  • SERVICE: es el nombre de un MultiClusterService que se implementa en el mismo espacio de nombres y clúster de configuración que este MultiClusterIngress.

Características de Ingress de varios clústeres

En esta sección, se muestra cómo configurar características adicionales de Ingress de varios clústeres.

Selección de clústeres

De forma predeterminada, los servicios derivados de Multi Cluster Ingress se programan en cada clúster miembro. Sin embargo, es posible que desees aplicar reglas de entrada a clústeres específicos. Estos son algunos casos prácticos:

  • Aplica Ingress de varios clústeres a todos los clústeres, excepto al clúster de configuración para aislarlo.
  • Migra cargas de trabajo entre clústeres de manera azul-verde.
  • Enrutamiento a los backends de aplicaciones que solo existen en un subconjunto de clústeres
  • Uso de una sola VIP L7 para el enrutamiento del host o de la ruta a backends que se alojan en clústeres diferentes

La selección de clústeres te permite seleccionarlos por región o nombre en el objeto MultiClusterService. Esto controla a qué clústeres apunta tu MultiClusterIngress y dónde están programados los Services derivados. Los clústeres dentro de la misma flota y la misma región no deben tener el mismo nombre para que se pueda hacer referencia a los clústeres de manera única.

  1. Abrir mcs.yaml

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    

    Actualmente, con esta especificación se crean servicios derivados en todos los clústeres, que es el comportamiento predeterminado.

  2. Agrega las siguientes líneas en la sección de clústeres:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
      clusters:
      - link: "us-central1-b/gke-us"
      - link: "europe-west1-b/gke-eu"
    

    En este ejemplo, se crean recursos Service derivados solo en clústeres de gke-us y gke-eu. Debes seleccionar clústeres para aplicar reglas de entrada de manera selectiva. Si no se especifica la sección “clústeres” del MultiClusterService, o si no se enumera ningún clúster, se interpretará como “todos” los clústeres de forma predeterminada.

Compatibilidad con HTTPS

El Secret de Kubernetes admite HTTPS. Antes de habilitar la compatibilidad con HTTPS, debes crear una dirección IP estática. Esta IP estática permite que HTTP y HTTPS compartan la misma dirección IP. Para obtener más información, consulta cómo crear una IP estática.

Una vez que creaste una dirección IP estática, puedes crear un secreto.

  1. Crea un secreto:

    kubectl -n whereami create secret tls SECRET_NAME --key PATH_TO_KEYFILE --cert PATH_TO_CERTFILE
    

    Reemplaza lo siguiente:

    • SECRET_NAME por el nombre del Secret.
    • PATH_TO_KEYFILE por la ruta de acceso al archivo de claves TLS.
    • PATH_TO_CERTFILE por la ruta de acceso al archivo del certificado TLS.
  2. Actualiza el archivo mci.yaml con el nombre del Secret:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
      annotations:
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
          tls:
          - secretName: SECRET_NAME
    

    Reemplaza SECRET_NAME por el nombre del Secret. STATIC_IP_ADDRESS es la dirección IP o la URL completa de la dirección que asignaste en la sección Crea una IP estática.

  3. Vuelve a implementar el recurso MultiClusterIngress:

    kubectl apply -f mci.yaml
    

    El resultado es similar a este:

    multiclusteringress.networking.gke.io/whereami-ingress configured
    

Compatibilidad con BackendConfig

Con la siguiente CRD de BackendConfig puedes personalizar la configuración en el recurso de BackendService de Compute Engine:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: whereami-health-check-cfg
  namespace: whereami
spec:
  healthCheck:
    checkIntervalSec: [int]
    timeoutSec: [int]
    healthyThreshold: [int]
    unhealthyThreshold: [int]
    type: [HTTP | HTTPS | HTTP2 | TCP]
    port: [int]
    requestPath: [string]
  timeoutSec: [int]
  connectionDraining:
    drainingTimeoutSec: [int]
  sessionAffinity:
    affinityType: [CLIENT_IP | CLIENT_IP_PORT_PROTO | CLIENT_IP_PROTO | GENERATED_COOKIE | HEADER_FIELD | HTTP_COOKIE | NONE]
    affinityCookieTtlSec: [int]
  cdn:
    enabled: [bool]
    cachePolicy:
      includeHost: [bool]
      includeQueryString: [bool]
      includeProtocol: [bool]
      queryStringBlacklist: [string list]
      queryStringWhitelist: [string list]
  securityPolicy:
    name: ca-how-to-security-policy
  logging:
    enable: [bool]
    sampleRate: [float]
  iap:
    enabled: [bool]
    oauthclientCredentials:
      secretName: [string]

Para usar BackendConfig, conéctalo a tu recurso MultiClusterService mediante una anotación:

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: whereami-mcs
  namespace: whereami
  annotations:
    cloud.google.com/backend-config: '{"ports": {"8080":"whereami-health-check-cfg"}}'
spec:
 template:
   spec:
     selector:
       app: whereami
     ports:
     - name: web
       protocol: TCP
       port: 8080
       targetPort: 8080

Para obtener más información sobre la semántica de BackendConfig, consulta la sección Asocia un puerto de servicio a un BackendConfig.

Compatibilidad con gRPC

La configuración de aplicaciones de gRPC en Ingress de varios clústeres requiere una configuración muy específica. A continuación, te mostramos algunas sugerencias para asegurarte de que el balanceador de cargas esté configurado de forma correcta:

  1. Asegúrate de que el tráfico del balanceador de cargas que va a tu aplicación sea HTTP/2. Usa los protocolos de aplicación para configurarlo.
  2. Asegúrate de que tu aplicación esté configurada correctamente para SSL, ya que este es un requisito de HTTP/2. Ten en cuenta que se acepta el uso de certificados autofirmados.
  3. Debes desactivar mTLS en tu aplicación porque este no es compatible con balanceadores de cargas externos de L7.

Ciclo de vida de los recursos

Cambios de configuración

Los recursos MultiClusterIngress y MultiClusterService se comportan como objetos estándar de Kubernetes, por lo que los cambios en los objetos se reflejan de forma asíncrona en el sistema. Cualquier cambio que dé como resultado una configuración no válida hace que los objetos de Google Cloud asociados permanezcan sin cambios y se genere un error en la transmisión de eventos del objeto. Los errores asociados con la configuración se informarán como eventos.

Administra recursos de Kubernetes

Si borras el objeto Ingress se elimina el balanceador de cargas HTTP(S), por lo que el tráfico ya no se reenviará a ningún MultiClusterService definido.

Si borras MultiClusterService, se quitarán los servicios derivados asociados de cada clúster.

Administra clústeres

Puedes cambiar el conjunto de clústeres al que apunta el balanceador de cargas si agregas o quitas clústeres de la flota.

Por ejemplo, para quitar el clúster gke-eu como backend de un Ingress, ejecuta lo siguiente:

gcloud container fleet memberships unregister CLUSTER_NAME \
  --gke-uri=URI

Reemplaza lo siguiente:

  • CLUSTER_NAME: El nombre de tu clúster.
  • URI es el URI del clúster de GKE.

Para agregar un clúster en Europa, ejecuta lo siguiente:

gcloud container fleet memberships register europe-cluster \
  --context=europe-cluster --enable-workload-identity

Puedes obtener más información sobre las opciones de registro de clústeres en Registra un clúster de GKE.

Ten en cuenta que registrar o cancelar el registro de un clúster cambia su estado como backend para todos los Ingress. Si cancelas el registro del clúster gke-eu, se quita como backend disponible para todos los Ingress que crees. Si se registra un clúster nuevo, sucede lo contrario.

Inhabilita Ingress de varios clústeres

Antes de inhabilitar Ingress de varios clústeres, debes asegurarte de borrar tus recursos MultiClusterIngress y MultiClusterService y verificar que se borren todos los recursos de red asociados.

Luego, para inhabilitar el Ingress de clústeres múltiples, usa el siguiente comando:

gcloud container fleet ingress disable

Si no borras los recursos MultiClusterIngress y MultiClusterService antes de inhabilitar el Ingress de varios clústeres, es posible que veas un error similar al siguiente:

Feature has associated resources that should be cleaned up before deletion.

Si deseas forzar la inhabilitación de Ingress de varios clústeres, usa el siguiente comando:

gcloud container fleet ingress disable --force

Anotaciones

Las siguientes anotaciones son compatibles con los recursos MultiClusterIngress y MultiClusterService.

Anotaciones de MultiClusterIngress

Anotación Description
networking.gke.io/frontend-config Hace referencia a un recurso FrontendConfig en el mismo espacio de nombres que el recurso MultiClusterIngress.
networking.gke.io/static-ip Se refiere a la dirección IP literal de una IP estática global.
networking.gke.io/pre-shared-certs Se refiere a un recurso SSLCertificate.

Anotaciones de MultiClusterService

Anotación Description
networking.gke.io/app-protocols Usa esta anotación a fin de configurar el protocolo para la comunicación entre el balanceador de cargas y la aplicación. Los protocolos posibles son HTTP, HTTPS y HTTP/2. Consulta HTTPS entre el balanceador de cargas y la aplicación y HTTP/2 para el balanceo de cargas con Ingress.
cloud.google.com/backend-config Usa esta anotación para configurar el servicio de backend asociado con un servicePort. Para obtener más información, consulta Configuración de Ingress.

Políticas de SSL y redireccionamientos HTTPS

Puedes usar el recurso FrontendConfig para configurar las políticas de SSL y los redireccionamientos HTTPS. Con las políticas de SSL puedes especificar qué conjuntos de cifrado y versiones de TLS acepta el balanceador de cargas. Los redireccionamientos HTTPS te permiten aplicar el redireccionamiento de HTTP o puerto 80 a HTTPS o puerto 443. En los siguientes pasos, se configura una política de SSL y un redireccionamiento HTTPS juntos. Ten en cuenta que también se pueden configurar de forma independiente.

  1. Crea una política de SSL que rechace las solicitudes con una versión anterior a TLS v1.2.

    gcloud compute ssl-policies create tls-12-policy \
     --profile MODERN \
     --min-tls-version 1.2 \
     --project=PROJECT_ID
    

    Reemplaza PROJECT_ID por el ID del proyecto en el que se ejecutan los clústeres de GKE.

  2. Consulta tu política para asegurarte de que se haya creado.

    gcloud compute ssl-policies list --project=PROJECT_ID
    

    El resultado es similar al siguiente:

    NAME           PROFILE  MIN_TLS_VERSION
    tls-12-policy  MODERN   TLS_1_2
    
  3. Crea un certificado para foo.example.com como en este ejemplo. Una vez que tengas los key.pem y cert.pem, almacena estas credenciales como un secreto al que hará referencia el recurso MultiClusterIngress.

    kubectl -n whereami create secret tls SECRET_NAME --key key.pem --cert cert.pem
    
  4. Guarda el siguiente recurso FrontendConfig como frontendconfig.yaml. Consulta Configura recursos FrontendConfig para obtener más información sobre los campos compatibles dentro de FrontendConfig.

    apiVersion: networking.gke.io/v1beta1
    kind: FrontendConfig
    metadata:
      name: frontend-redirect-tls-policy
      namespace: whereami
    spec:
      sslPolicy: tls-12-policy
      redirectToHttps:
        enabled: true
    

    Este FrontendConfig habilitará los redireccionamientos HTTPS y una política de SSL que aplique una versión mínima de TLS de 1.2.

  5. Implementa frontendconfig.yaml en el clúster de configuración.

    kubectl apply -f frontendconfig.yaml --context MCI_CONFIG_CLUSTER
    

    Reemplaza MCI_CONFIG_CLUSTER por el nombre de tu clúster de configuración.

  6. Guarda el siguiente MultiClusterIngress como mci-frontendconfig.yaml.

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: foo-ingress
      namespace: whereami
      annotations:
        networking.gke.io/frontend-config: frontend-redirect-tls-policy
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: default-backend
            servicePort: 8080
          rules:
          - host: foo.example.com
            http:
              paths:
                - backend:
                    serviceName: whereami-mcs
                    servicePort: 8080
          tls:
          - secretName: SECRET_NAME
    
    • Reemplaza STATIC_IP_ADDRESS por una dirección IP global estática que ya hayas aprovisionado.
    • Reemplaza SECRET_NAME por el Secret en el que se almacena el certificado foo.example.com.

    Cuando se habilitan los redireccionamientos a HTTPS, existen dos requisitos:

    • Se debe habilitar TLS, ya sea a través del campo spec.tls o a través de la anotación del certificado ya compartido networking.gke.io/pre-shared-certs. MultiClusterIngress no se implementará si los redireccionamientos HTTPS están habilitados, pero HTTPS no.
    • Se debe hacer referencia a una IP estática a través de la anotación networking.gke.io/static-ip. Las IP estáticas son necesarias cuando se habilita HTTPS en un Ingress de varios clústeres.
  7. Implementa un Ingress de varios clústeres en tu clúster de configuración.

    kubectl apply -f mci-frontendconfig.yaml --context MCI_CONFIG_CLUSTER
    
  8. Espera uno o dos minutos y, luego, inspecciona foo-ingress.

    kubectl describe mci foo-ingress --context MCI_CONFIG_CLUSTER
    

    Un resultado correcto se parece al siguiente:

    • El estado Cloud Resources se propaga con nombres de recursos
    • El campo VIP se propaga con la dirección IP del balanceador de cargas
    Name:         foobar-ingress
    Namespace:    whereami
    
    ...
    
    Status:
      Cloud Resources:
        Backend Services:
          mci-otn9zt-8080-whereami-bar
          mci-otn9zt-8080-whereami-default-backend
          mci-otn9zt-8080-whereami-foo
        Firewalls:
          mci-otn9zt-default-l7
        Forwarding Rules:
          mci-otn9zt-fw-whereami-foobar-ingress
          mci-otn9zt-fws-whereami-foobar-ingress
        Health Checks:
          mci-otn9zt-8080-whereami-bar
          mci-otn9zt-8080-whereami-default-backend
          mci-otn9zt-8080-whereami-foo
        Network Endpoint Groups:
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluste-mci-default-backend-svc--80-9e362e3d
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluster--mci-bar-svc-067a3lzs8-808-89846515
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluster--mci-foo-svc-820zw3izx-808-8bbcb1de
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluste-mci-default-backend-svc--80-a528cc75
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluster--mci-bar-svc-067a3lzs8-808-36281739
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluster--mci-foo-svc-820zw3izx-808-ac733579
        Target Proxies:
          mci-otn9zt-whereami-foobar-ingress
          mci-otn9zt-whereami-foobar-ingress
        URL Map:  mci-otn9zt-rm-whereami-foobar-ingress
      VIP:        34.149.29.76
    Events:
      Type     Reason  Age                From                              Message
      ----     ------  ----               ----                              -------
      Normal   UPDATE  38m (x5 over 62m)  multi-cluster-ingress-controller  whereami/foobar-ingress
    
  9. Envía una solicitud HTTP a través de curl para verificar que los redireccionamientos HTTPS funcionen de forma correcta.

    curl VIP
    

    Reemplaza VIP por la dirección IP de Ingress de varios clústeres.

    El resultado debería mostrar que la solicitud se redireccionó al puerto HTTPS, lo que indica que los redireccionamientos funcionan de forma correcta.

  10. Envía una solicitud HTTPS con la versión 1.1 de TLS para verificar que la política de TLS funcione de forma correcta. Debido a que el DNS no está configurado para este dominio, usa la opción --resolve para indicarle a curl que resuelva la dirección IP directamente.

    curl https://foo.example.com --resolve foo.example.com:443:VIP --cacert CERT_FILE -v
    

    En este paso, se requiere el archivo PEM del certificado que se usa para proteger el MultiClusterIngress. Un resultado correcto será similar al siguiente:

    ...
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=foo.example.com
    *  start date: Sep  1 10:32:03 2021 GMT
    *  expire date: Aug 27 10:32:03 2022 GMT
    *  common name: foo.example.com (matched)
    *  issuer: O=example; CN=foo.example.com
    *  SSL certificate verify ok.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x7fa10f00e400)
    > GET / HTTP/2
    > Host: foo.example.com
    > User-Agent: curl/7.64.1
    > Accept: */*
    >
    * Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
    < HTTP/2 200
    < content-type: application/json
    < content-length: 308
    < access-control-allow-origin: *
    < server: Werkzeug/1.0.1 Python/3.8.6
    < date: Wed, 01 Sep 2021 11:39:06 GMT
    < via: 1.1 google
    < alt-svc: clear
    <
    {"cluster_name":"gke-us","host_header":"foo.example.com","metadata":"foo","node_name":"gke-gke-us-default-pool-22cb07b1-r5r0.c.mark-church-project.internal","pod_name":"foo-75ccd9c96d-dkg8t","pod_name_emoji":"👞","project_id":"mark-church-project","timestamp":"2021-09-01T11:39:06","zone":"us-central1-b"}
    * Connection #0 to host foo.example.com left intact
    * Closing connection 0
    

    El código de respuesta es 200 y se usa TLSv1.2, lo que indica que todo funciona correctamente.

    A continuación, puedes verificar que la política de SSL aplique la versión correcta de TLS si intentas conectarte con TLS 1.1. Tu política de SSL debe estar configurada para una versión mínima de 1.2 a fin de que este paso funcione.

  11. Envía la misma solicitud del paso anterior, pero aplica una versión de TLS 1.1.

    curl https://foo.example.com --resolve foo.example.com:443:VIP -v \
      --cacert CERT_FILE \
      --tls-max 1.1
    

    Un resultado correcto será similar al siguiente:

    * Added foo.example.com:443:34.149.29.76 to DNS cache
    * Hostname foo.example.com was found in DNS cache
    *   Trying 34.149.29.76...
    * TCP_NODELAY set
    * Connected to foo.example.com (34.149.29.76) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: cert.pem
      CApath: none
    * TLSv1.1 (OUT), TLS handshake, Client hello (1):
    * TLSv1.1 (IN), TLS alert, protocol version (582):
    * error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
    * Closing connection 0
    curl: (35) error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
    

    Si no se completa el protocolo de enlace TLS, se indica que la política de SSL bloqueó correctamente TLS 1.1.

Crea una IP estática

  1. Asigna una IP estática:

    gcloud compute addresses create ADDRESS_NAME --global
    

    Reemplaza ADDRESS_NAME por el nombre de la IP estática que se asignará.

    El resultado contiene la URL completa de la dirección que creaste, similar a la siguiente:

    Created [https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses/ADDRESS_NAME].
    
  2. Visualiza la dirección IP que acabas de crear:

    gcloud compute addresses list
    

    El resultado es similar a este:

    NAME          ADDRESS/RANGE  TYPE      STATUS
    ADDRESS_NAME  STATIC_IP_ADDRESS  EXTERNAL  RESERVED
    

    En esta salida, se incluye lo siguiente:

    • El ADDRESS_NAME que definiste.
    • El STATIC_IP_ADDRESS asignado.
  3. Actualiza el archivo mci.yaml con la IP estática:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
      annotations:
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
    

    Reemplaza STATIC_IP_ADDRESS por uno de los siguientes:

    • La dirección IP asignada, similar a: 34.102.201.47
    • La URL completa de la dirección que creaste, similar a: "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses/ADDRESS_NAME"

    STATIC_IP_ADDRESS no es el nombre del recurso (ADDRESS_NAME).

  4. Vuelve a implementar el recurso MultiClusterIngress:

    kubectl apply -f mci.yaml
    

    El resultado es similar a este:

    multiclusteringress.networking.gke.io/whereami-ingress configured
    
  5. Sigue los pasos en Valida un estado de implementación exitoso para verificar que la implementación se entregue en STATIC_IP_ADDRESS.

Certificados ya compartidos

Los certificados compartidos previamente son certificados subidos a Google Cloud que el balanceador de cargas puede usar para la finalización de TLS en lugar de los certificados almacenados en secretos de Kubernetes. Estos certificados se suben fuera de banda de GKE a Google Cloud y se hace referencia a ellos mediante un recurso MultiClusterIngress. También se admiten varios certificados, ya sea mediante certificados compartidos previamente o secretos de Kubernetes.

Para usar los certificados en Ingress de varios clústeres, se requiere la anotación networking.gke.io/pre-shared-certs y los nombres de los certificados. Cuando se especifican varios certificados para un MultiClusterIngress determinado, rige un orden predeterminado sobre qué certificado se presenta al cliente.

Puedes generar una lista de los certificados SSL disponibles si ejecutas lo siguiente:

gcloud compute ssl-certificates list

En el siguiente ejemplo, se describe el tráfico del cliente a uno de los hosts especificados que coincide con el nombre común de los certificados compartidos previamente, por lo que se presentará el certificado respectivo que coincida con el nombre de dominio.

kind: MultiClusterIngress
metadata:
  name: shopping-service
  namespace: whereami
  annotations:
    networking.gke.io/pre-shared-certs: "domain1-cert, domain2-cert"
spec:
  template:
    spec:
      rules:
      - host: my-domain1.gcp.com
        http:
          paths:
          - backend:
              serviceName: domain1-svc
              servicePort: 443
      - host: my-domain2.gcp.com
        http:
          paths:
          - backend:
              serviceName: domain2-svc
              servicePort: 443

Certificados administrados por Google.

Los certificados administrados por Google son compatibles con los recursos MultiClusterIngress a través de la anotación networking.gke.io/pre-shared-certs. Ingress de varios clústeres admite la conexión de certificados administrados por Google a un recurso MultiClusterIngress. Sin embargo, a diferencia de Ingress de un solo clúster, la generación declarativa de un recurso ManagedCertificate de Kubernetes no es compatible con recursos MultiClusterIngress. La creación original del certificado administrado por Google debe realizarse directamente a través de la API de compute ssl-certificates create para poder adjuntarla a un MultiClusterIngress. Para ello, sigue estos pasos:

  1. Crea un certificado administrado por Google como en el paso 1 aquí. No pases al paso 2, ya que Ingress de clústeres múltiples adjuntará este certificado.

    gcloud compute ssl-certificates create my-google-managed-cert \
        --domains=my-domain.gcp.com \
        --global
    
  2. Haz referencia al nombre del certificado en tu MultiClusterIngress con la anotación networking.gke.io/pre-shared-certs.

    kind: MultiClusterIngress
    metadata:
    name: shopping-service
    namespace: whereami
    annotations:
      networking.gke.io/pre-shared-certs: "my-google-managed-cert"
    spec:
    template:
      spec:
        rules:
        - host: my-domain.gcp.com
          http:
            paths:
            - backend:
                serviceName: my-domain-svc
                servicePort: 8080
    

El manifiesto anterior adjunta el certificado a tu MultiClusterIngress a fin de que pueda finalizar el tráfico para tus clústeres de GKE de backend. Google Cloud renovará automáticamente tu certificado antes de que se venza. Las renovaciones se realizan con transparencia y no requieren ninguna actualización del Ingress de varios clústeres.

Protocolos de las aplicaciones

Para la conexión del proxy del balanceador de cargas con tu aplicación, se usa HTTP de forma predeterminada. Con la anotación networking.gke.io/app-protocols, puedes configurar el balanceador de cargas para que use HTTPS o HTTP/2 cuando reenvíe solicitudes a tu aplicación. En el campo annotation del siguiente ejemplo, http2 se refiere al nombre del puerto MultiClusterService y HTTP2 se refiere al protocolo que usa el balanceador de cargas.

kind: MultiClusterService
metadata:
  name: shopping-service
  namespace: whereami
  annotations:
    networking.gke.io/app-protocols: '{"http2":"HTTP2"}'
spec:
  template:
    spec:
      ports:
      - port: 443
        name: http2

BackendConfig

Consulta la sección anterior sobre cómo configurar la anotación.

¿Qué sigue?