Cloud CDN

En esta página, se muestra cómo utilizar un recurso personalizado BackendConfig para configurar Cloud CDN (Cloud CDN) en Google Kubernetes Engine.

Descripción general

En un clúster de GKE, el balanceo de cargas de HTTP(S), que es un componente de Cloud Load Balancing, controla el tráfico entrante. Por lo general, el balanceador de cargas de HTTP(S) se configura con un controlador de Ingress 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 utiliza para direccionar una solicitud entrante a un pod y un puerto específicos.

A partir de la versión de Kubernetes 1.10.5-gke.3, tienes la posibilidad de agregar configuraciones al balanceador de cargas si vinculas un puerto de servicio a un recurso personalizado llamado BackendConfig.

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

Sigue estos pasos a fin de prepararte para esta tarea:

  • Asegúrate de que habilitaste la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Asegúrate de que instalaste el SDK de Cloud.
  • 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

Cómo crear un espacio de nombres

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

kubectl create namespace cdn-how-to

Crea una implementación

En el manifiesto de esta implementación, se declara que quieres 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

Copia el manifiesto a un archivo llamado my-deployment.yaml y crea la implementación:

kubectl apply -f my-deployment.yaml

Cómo crear un BackendConfig

A continuación, se detalla un manifiesto para un BackendConfig. Se especifica una política de caché Cloud CDN y se declara que Cloud CDN debe estar habilitado:

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

Copia el manifiesto en un archivo con el nombre my-backend-config.yaml y crea el BackendConfig:

kubectl apply -f my-backend-config.yaml

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/v1beta1
kind: BackendConfig
metadata:
  name: my-backend-config
  namespace: cdn-how-to
  ...
spec:
  cdn:
    cachePolicy:
      includeHost: true
      includeProtocol: true
      includeQueryString: false
    enabled: true

Cómo crear un servicio

A continuación, se detalla un manifiesto para un servicio:

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

Guarda el manifiesto en un archivo con el nombre my-service.yaml y crea el servicio:

kubectl apply -f my-service.yaml

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:
    beta.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 beta.cloud.google.com/backend-config.

  • El servicio es de 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 será 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 miembros. Esto se especifica en los campos port y targetPort.

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

Reserva una dirección IP externa estática:

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

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

Cómo crear un Ingress

A continuación, se detalla un manifiesto para un Ingress:

apiVersion: extensions/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

Copia el manifiesto a un archivo llamado my-ingress.yaml y crea el Ingress:

kubectl apply -f my-ingress.yaml

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: extensions/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, estos son los aspectos importantes que se deben tener en cuenta sobre tu Ingress:

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

  • El Ingress tiene una regla para las solicitudes HTTP entrantes desde cualquier host. Esto se debe a que no hay 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 lo especifica el valor path en /*.

  • Las solicitudes entrantes se enrutan a un pod que es un 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 aplicación web

Ingresa el comando curl dos veces:

curl -v [STATIC_ADDRESS]/?cache=true

donde [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

Visualiza 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

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

Ir a la página Registros

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

Expande la entrada del registro más reciente y, luego, el campo httpRequest de la entrada.

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

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

gcloud

gcloud logging read \
    'logName="projects/[PROJECT_ID]/logs/requests"' \
    --limit 2

donde [PROJECT_ID] es el ID del proyecto.

El resultado muestra que hubo un acierto de caché:

httpRequest:
cacheHit: true
cacheLookup: true

Limitaciones

Cloud CDN y Cloud Identity-Aware Proxy 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 y Cloud IAP habilitados

Este error se muestra cuando habilitas Cloud IAP y Cloud CDN en un 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é.

Limpieza

Luego de completar los ejercicios de esta página, sigue estos pasos para quitar los recursos y evitar cargos no deseados en tu cuenta:

Borra los objetos de 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

Borra tu dirección IP externa estática:

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

Qué sigue

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Documentación de Kubernetes Engine