Lab práctico · Semana 2: Cómputo: Compute Engine, MIG, GKE, Cloud Run y cuándo usar cada uno

Cluster GKE Autopilot con despliegue, Service y autoescalado de pods

⏱ 75-100 minDificultad: mediaApartados: 2.31.3

Qué vas a construir

Un cluster GKE Autopilot regional en Madrid, un Deployment con una aplicación de ejemplo, un Service de tipo LoadBalancer para exponerla, un Horizontal Pod Autoscaler y una prueba de carga para verlo escalar, observando cómo Autopilot añade capacidad sin que toques ningún nodo.

flowchart LR
  U["Internet"] --> LB["Passthrough Network Load Balancer"]
  LB --> SVC["Service hola-svc tipo LoadBalancer"]
  SVC --> P1["Pod hola"]
  SVC --> P2["Pod hola"]
  HPA["HPA: CPU 50 %, de 2 a 10 pods"] --> D["Deployment hola"]
  D --> P1
  D --> P2
  GKE["Autopilot: Google gestiona los nodos"] -.-> P1

Antes de empezar

  • Labs 01 y 02 hechos.
  • Proyecto nuevo y API de GKE:
export PROJECT_ID="pca-lab-05-$RANDOM"
export REGION="europe-southwest1"
export BILLING_ID="$(gcloud billing accounts list --format='value(ACCOUNT_ID)' --limit=1)"
gcloud projects create "$PROJECT_ID" --name="pca-lab-05"
gcloud billing projects link "$PROJECT_ID" --billing-account="$BILLING_ID"
gcloud config set project "$PROJECT_ID"
gcloud services enable container.googleapis.com

Paso 1: Crea el cluster Autopilot

Qué y por qué: Autopilot es regional por diseño (plano de control replicado en varias zonas) y Google gestiona los nodos. Tarda varios minutos en crearse.

gcloud container clusters create-auto pca-autopilot \
  --location="$REGION" \
  --release-channel=regular

gcloud container clusters list

Por consola: Kubernetes Engine → Clusters → Crear → Autopilot.

Obtén las credenciales para kubectl (ya instalado en Cloud Shell):

gcloud container clusters get-credentials pca-autopilot --location="$REGION"
kubectl get nodes

Puede que veas pocos nodos o ninguno: Autopilot solo crea nodos cuando hay pods que los necesitan.

Paso 2: Despliega la aplicación

Qué y por qué: un Deployment mantiene N réplicas de un pod y gestiona sus actualizaciones. En Autopilot es obligatorio pensar en las peticiones de recursos (requests), porque son lo que pagas y lo que usa Google para dimensionar los nodos.

cat > hola.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hola
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hola
  template:
    metadata:
      labels:
        app: hola
    spec:
      containers:
      - name: hola
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
  name: hola-svc
spec:
  type: LoadBalancer
  selector:
    app: hola
  ports:
  - port: 80
    targetPort: 8080
EOF

kubectl apply -f hola.yaml
kubectl get pods -o wide -w

Los pods pasarán por Pending mientras Autopilot aprovisiona capacidad, y después a Running. Sal con Ctrl+C. Fíjate en la columna NODE: no has creado ningún nodo, pero existen.

Paso 3: Accede a través del Service

Qué y por qué: un Service LoadBalancer en GKE crea un passthrough Network Load Balancer regional con IP externa. (Para HTTPS, rutas y Cloud Armor usarías Ingress o Gateway, que crean un Application Load Balancer; lo verás en redes.)

kubectl get service hola-svc -w

Cuando EXTERNAL-IP deje de estar en <pending> (uno o dos minutos), sal con Ctrl+C y prueba:

export IP="$(kubectl get service hola-svc -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
for i in $(seq 1 6); do curl -s "http://$IP"; done

Verás respuestas de los dos pods (el Hostname cambia).

Paso 4: Autoescala los pods con HPA

Qué y por qué: el Horizontal Pod Autoscaler añade réplicas cuando sube la CPU. En Autopilot no configuras el escalado de nodos: si los pods nuevos no caben, Google añade nodos.

kubectl autoscale deployment hola --cpu-percent=50 --min=2 --max=10
kubectl get hpa

Genera carga desde un pod dentro del cluster:

kubectl run carga --image=busybox:1.36 --restart=Never -- \
  /bin/sh -c "while true; do wget -q -O- http://hola-svc > /dev/null; done"

Observa (en dos o tres minutos debería crecer el número de réplicas):

kubectl get hpa hola -w

En otra pestaña de Cloud Shell, mira los pods y los nodos:

kubectl get pods
kubectl get nodes

Cuando hayas visto el escalado, para la carga:

kubectl delete pod carga

El HPA reducirá las réplicas pasados unos minutos. Si la carga no basta para superar el 50 % de CPU, lanza un segundo pod de carga con otro nombre.

Paso 5: Una actualización progresiva

Qué y por qué: el Deployment sustituye pods poco a poco, sin cortar el servicio.

kubectl set image deployment/hola hola=us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
kubectl rollout status deployment/hola
curl -s "http://$IP"
kubectl rollout history deployment/hola

La respuesta mostrará Version: 2.0.0. Para volver atrás: kubectl rollout undo deployment/hola.

Comprueba que funciona

  • gcloud container clusters list muestra el cluster con modo Autopilot en europe-southwest1.
  • curl http://$IP responde desde varios pods.
  • kubectl get hpa muestra más de 2 réplicas durante la carga.
  • Tras el set image, la respuesta indica la versión 2.0.0.

Limpieza

Borra primero el Service (libera el balanceador y la IP) y después el cluster. O borra el proyecto entero.

kubectl delete -f hola.yaml
kubectl delete hpa hola
gcloud container clusters delete pca-autopilot --location="$REGION" --quiet
gcloud projects delete "$PROJECT_ID"

Comprueba en Kubernetes Engine → Clusters y en Red → Balanceo de carga que no queda nada.

Preguntas para pensar como arquitecto

1. ¿Qué habría cambiado si hubieras usado GKE Standard?

Tendrías que crear y dimensionar node pools, decidir tipos de máquina, activar el cluster autoscaler y gestionar actualizaciones de nodos. Pagarías por los nodos aunque estuvieran medio vacíos. A cambio, tendrías control total de los nodos (kernel, DaemonSets privilegiados, tipos de máquina concretos).

2. ¿Por qué son tan importantes las requests de CPU y memoria en Autopilot?

Porque en Autopilot pagas principalmente por los recursos que solicitan los pods y porque el HPA calcula el porcentaje de uso respecto a esas requests. Requests infladas cuestan dinero; requests muy bajas provocan escalados erráticos o falta de recursos.

3. El pod necesita leer objetos de un bucket de Cloud Storage. ¿Cómo le das acceso?

Con Workload Identity Federation for GKE (activado por defecto en Autopilot): concedes el rol necesario (por ejemplo, roles/storage.objectViewer sobre el bucket) a la identidad de la cuenta de servicio de Kubernetes del pod, o a una cuenta de servicio de IAM vinculada. Nunca montando una clave JSON en un Secret.

4. Si la aplicación fuera una API HTTP sin estado, sin dependencias de Kubernetes, ¿la pondrías en GKE?

Probablemente no: Cloud Run ofrece lo mismo con menos operación, escala a cero y sin tarifa de cluster. GKE compensa cuando hay muchos servicios, necesitas el ecosistema de Kubernetes, portabilidad, cargas con estado o control de red y planificación que Cloud Run no da.


Volver al módulo