Configura Cloud CDN con Ingress

En esta guía, se muestra cómo usar una definición de recurso personalizado (CRD) BackendConfig para configurar Cloud CDN en Google Kubernetes Engine (GKE).

Descripción general

En un clúster de GKE, el balanceo de cargas HTTP(S) (un componente de Cloud Load Balancing) controla el tráfico entrante. Por lo general, el balanceador de cargas de HTTP(S) se configura mediante un controlador de entrada de GKE, que obtiene la información de configuración de un objeto Ingress de Kubernetes. El objeto Ingress se asocia a uno o más objetos de servicio. Cada objeto de servicio tiene información de enrutamiento que se usa para direccionar una solicitud entrante a un pod y un puerto específicos.

A partir de la versión 1.10.5-gke.3 de Kubernetes, puedes asociar un puerto de servicio con un recurso personalizado llamado BackendConfig con la configuración adicional del balanceador de cargas externo.

El controlador del Ingress de GKE lee la información de configuración de BackendConfig y configura el balanceador de cargas según corresponda. Un BackendConfig tiene información de configuración específica de Cloud Load Balancing. Los recursos Ingress y de servicio de Kubernetes no ofrecen una manera de configurar las funciones específicas de los proveedores como Cloud CDN, BackendConfig te permite hacer esa configuración.

A continuación, se detalla el panorama general de cómo configurar un BackendConfig en este ejercicio:

  1. Crea un BackendConfig.
  2. Crea un servicio y asocia uno de sus puertos al BackendConfig.
  3. Crea un Ingress y asócialo con el par (servicio, puerto).

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

Establece la configuración de gcloud predeterminada mediante uno de los siguientes métodos:

  • Usa gcloud init si deseas ver una explicación sobre cómo configurar parámetros predeterminados.
  • Usa gcloud config para establecer el ID, la zona y la región del proyecto de manera individual.

Usa gcloud init

Si recibes el error One of [--zone, --region] must be supplied: Please specify location, completa esta sección.

  1. Ejecuta gcloud init y sigue las instrucciones:

    gcloud init

    Si usas SSH en un servidor remoto, usa la marca --console-only para evitar que el comando abra un navegador:

    gcloud init --console-only
  2. Sigue las instrucciones a fin de autorizar a gcloud para que use tu cuenta de Google Cloud.
  3. Crea una configuración nueva o selecciona una existente.
  4. Elige un proyecto de Google Cloud.
  5. Elige una zona predeterminada de Compute Engine.

Usa gcloud config

  • Establece tu ID del proyecto predeterminado:
    gcloud config set project project-id
  • Si trabajas con clústeres zonales, establece tu zona de procesamiento predeterminada:
    gcloud config set compute/zone compute-zone
  • Si trabajas con clústeres regionales, establece tu región de procesamiento predeterminada:
    gcloud config set compute/region compute-region
  • Actualiza gcloud a la versión más reciente:
    gcloud components update

Crea un espacio de nombres

Crea un espacio de nombres de Kubernetes para los objetos que se usan en esta guía:

kubectl create namespace cdn-how-to

Crea una implementación

  1. Crea un archivo llamado my-deployment.yaml basado en el siguiente manifiesto de implementación. Este manifiesto declara que deseas ejecutar dos réplicas de la aplicación web ingress-gce-echo-amd64:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      namespace: cdn-how-to
      name: my-deployment
    spec:
      selector:
        matchLabels:
          purpose: demonstrate-cdn
      replicas: 2
      template:
        metadata:
          labels:
            purpose: demonstrate-cdn
        spec:
          containers:
          - name: echo-amd64
            image: gcr.io/google-samples/hello-app-cdn:1.0
    
  2. Crea el recurso de implementación:

    kubectl apply -f my-deployment.yaml
    

Crea una BackendConfig

  1. Crea un archivo llamado my-backend-config.yaml basado en el siguiente manifiesto de BackendConfig. En el manifiesto, se especifica una política de caché Cloud CDN y se declara que Cloud CDN debe estar habilitada:

      apiVersion: cloud.google.com/v1
      kind: BackendConfig
      metadata:
        namespace: cdn-how-to
        name: my-backend-config
      spec:
        cdn:
          enabled: true
          cachePolicy:
            includeHost: true
            includeProtocol: true
            includeQueryString: false
    
  2. Crea el recurso BackendConfig:

    kubectl apply -f my-backend-config.yaml
    
  3. Observa el BackendConfig:

    kubectl get backendconfig my-backend-config --output yaml --namespace cdn-how-to
    

    Puedes ver la política de caché de Cloud CDN en el resultado:

      apiVersion: cloud.google.com/v1
      kind: BackendConfig
      metadata:
        name: my-backend-config
        namespace: cdn-how-to
        ...
      spec:
        cdn:
          cachePolicy:
            includeHost: true
            includeProtocol: true
            includeQueryString: false
          enabled: true
    

Crea un servicio

  1. Crea un archivo llamado my-service.yaml basado en el siguiente manifiesto de servicio:

    apiVersion: v1
    kind: Service
    metadata:
      namespace: cdn-how-to
      name: my-service
      labels:
        purpose: demonstrate-cdn
      annotations:
        cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
    spec:
      type: NodePort
      selector:
        purpose: demonstrate-cdn
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
    
  2. Crea el recurso de servicio:

    kubectl apply -f my-service.yaml
    
  3. Observa el servicio:

    kubectl get service my-service --namespace cdn-how-to --output yaml
    

    El resultado es similar al siguiente ejemplo:

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
        ...
      labels:
        purpose: demonstrate-cdn
      name: my-service
      namespace: cdn-how-to
      ...
    spec:
      clusterIP: 10.51.255.39
      externalTrafficPolicy: Cluster
      ports:
      - nodePort: 31484
        port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        purpose: demonstrate-cdn
      sessionAffinity: None
      type: NodePort
    status:
      loadBalancer: {}
    

    A los fines de este ejercicio, estas son las cuestiones importantes para tener en cuenta sobre tu servicio:

    • El puerto 80 del servicio está asociado a un BackendConfig con el nombre my-backend-config. Esto se especifica en la anotación cloud.google.com/backend-config.

    • El servicio tiene el tipo NodePort. Este es el tipo requerido para los servicios que se van a asociar a un Ingress.

    • Cualquier pod que tenga la etiqueta purpose: demonstrate-cdn es miembro del servicio. Esto se especifica en el campo selector.

    • El tráfico dirigido al servicio en el puerto TCP 80 se enruta al puerto TCP 8080 en uno de los pods miembro. Esto se especifica en los campos port y targetPort.

Cómo reservar una dirección IP externa estática

  1. Reserva una dirección IP externa estática:

    gcloud compute addresses create cdn-how-to-address --global
    
  2. Observa la dirección IP externa estática:

    gcloud compute addresses list --filter "name=cdn-how-to-address"
    

    En el resultado, se muestra el nombre y el valor de la dirección:

    NAME                ...     ADDRESS        STATUS
    cdn-how-to-address          203.0.113.1    RESERVED
    

Crea un Ingress

  1. Crea un archivo llamado my-ingress.yaml basado en el siguiente manifiesto de Ingress:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      namespace: cdn-how-to
      name: my-ingress
      annotations:
        kubernetes.io/ingress.global-static-ip-name: "cdn-how-to-address"
    spec:
      rules:
      - http:
          paths:
          - path: /*
            backend:
              serviceName: my-service
              servicePort: 80
    
  2. Crea el recurso Ingress:

    kubectl apply -f my-ingress.yaml
    
  3. Espera diez minutos a que el controlador de Ingress de Kubernetes configure un balanceador de cargas de Cloud y, luego, observa el Ingress:

    kubectl get ingress my-ingress --output yaml --namespace cdn-how-to
    

    El resultado es similar al siguiente ejemplo:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      ...
      name: my-ingress
      namespace: cdn-how-to
      ...
    spec:
      rules:
      - http:
          paths:
          - backend:
              serviceName: my-service
              servicePort: 80
            path: /*
    status:
      loadBalancer:
        ingress:
        - ip: 201.0.113.1
    

    A los fines de este ejercicio, estas son las cuestiones importantes que debes tener en cuenta sobre tu Ingress:

    • La dirección IP para el tráfico entrante aparece en loadBalancer:ingress:.

    • El Ingress tiene una regla que se aplica a las solicitudes HTTP entrantes desde cualquier host. Esto se debe a que no existe un campo host en la regla. Por eso, de manera predeterminada, se aplica la regla a todos los hosts.

    • Todas las solicitudes entrantes se tratan de la misma manera, independientemente de la ruta de URL. Esto se especifica mediante el valor path /*.

    • Las solicitudes entrantes se enrutan a un pod miembro de my-service. En este ejercicio, los pods miembros tienen la etiqueta purpose: demonstrate-cdn.

    • Las solicitudes se enrutan al pod en el puerto de destino especificado en my-service. En este ejercicio, el puerto de destino del pod es 8080.

Visualiza la app web

Ingresa este comando curl dos veces, de la siguiente manera:

curl -v static-address/?cache=true

en el ejemplo anterior, static-address es tu dirección IP externa estática.

El resultado muestra los encabezados y el cuerpo de la respuesta. En los encabezados de respuesta, puedes ver que el contenido se almacenó en caché. El encabezado Age te indica cuántos segundos se almacenó en caché el contenido:

...
< HTTP/1.1 200 OK
< Date: Fri, 25 Jan 2019 02:34:08 GMT
< Content-Length: 70
< Content-Type: text/plain; charset=utf-8
< Via: 1.1 google
< Cache-Control: max-age=86400,public
< Age: 2716
<
Hello, world!
Version: 1.0.0
Hostname: my-deployment-7f589cc5bc-l8kr8

Cómo visualizar registros de balanceo de cargas

Puedes verificar que el contenido se haya almacenado en caché con los registros de Stackdriver para el balanceo de cargas HTTP. Antes de verificar los registros, asegúrate de haber solicitado una respuesta de la aplicación al menos dos veces.

Console

  1. En Cloud Console, ve a la página Registros en el menú Registro.

    Ir a la página Registros

  2. En el primer menú desplegable, selecciona Balanceador de cargas de HTTP de Cloud.

  3. Expande la entrada de registro más reciente y el campo httpRequest de la entrada.

  4. En el campo httpRequest, puedes ver que cacheHit es true.

    httpRequest: {
    cacheHit:  true
    cacheLookup:  true
    ...
    

gcloud

Ejecuta el siguiente comando, en el que project-id es el ID del proyecto:

gcloud logging read \
    'logName="projects/project-id/logs/requests"' \
    --limit 2

El resultado muestra que hubo un acierto de caché:

httpRequest:
cacheHit: true
cacheLookup: true

Limpieza

Después de completar los ejercicios de esta guía, completa los siguientes pasos para quitar los recursos a fin de evitar cargos no deseados en tu cuenta:

  1. Borra los objetos Kubernetes que creaste para este ejercicio:

    kubectl delete ingress my-ingress --namespace cdn-how-to
    kubectl delete service my-service --namespace cdn-how-to
    kubectl delete backendconfig my-backend-config --namespace cdn-how-to
    kubectl delete deployment my-deployment --namespace cdn-how-to
    kubectl delete namespace cdn-how-to
    
  2. Borra tu dirección IP externa estática:

    gcloud compute addresses delete cdn-how-to-address --global
    

Limitaciones

Identity-Aware Proxy y Cloud CDN no se pueden habilitar para el mismo servicio de backend de balanceo de cargas de HTTP(S).

Solución de problemas

No se encontró el BackendConfig

Este error se muestra cuando un BackendConfig para un puerto de servicio se especifica en la anotación del servicio, pero no se pudo encontrar ese recurso BackendConfig. Esto puede ocurrir si no creaste el recurso BackendConfig en absoluto, lo creaste en el espacio de nombres equivocado o escribiste mal la referencia en la anotación del servicio.

kubectl get event
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

Cloud CDN e IAP están habilitados

Este error se produce cuando habilitaste IAP y Cloud CDN en una BackendConfig.

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: BackendConfig default/config-default is not valid:
iap and cdn cannot be enabled at the same time.

Contenido no almacenado en caché

Si notas que tu contenido no se está almacenando en caché, asegúrate de que tu aplicación esté configurada de manera adecuada para habilitar el almacenamiento en caché del contenido. Para obtener más información, consulta la capacidad de almacenamiento en caché.

Próximos pasos