Lesson  in  Kubernetes 101

Horizontal Pod Autoscaler

Deja que el clúster escale por ti: configura un HPA sobre un Deployment, genera carga real y observa cómo las réplicas crecen para absorberla. Lección opcional.

En la lección de Deployments escalaste a mano con kubectl scale. Funciona, pero exige que alguien esté mirando. El Horizontal Pod Autoscaler (HPA) cierra el bucle: compara el consumo real de los Pods con un objetivo que tú declaras y ajusta las réplicas solo.

El capítulo de escalado del libro presenta los tres autoescaladores de Kubernetes (HPA, VPA y el de nodos) y por qué resuelven problemas distintos. Este módulo pone en marcha los dos primeros.

Important

⚠️ Esta lección es opcional y algo más caprichosa que el resto: depende del ciclo de métricas de metrics-server (unos 15 segundos) y de la ventana de decisión del HPA, así que entre generar carga y ver réplicas nuevas pueden pasar de 1 a 3 minutos. Es el comportamiento real del autoscaling, no un fallo del laboratorio.

El HPA necesita saber cuánto consume cada Pod, y esa información la sirve metrics-server, que k3s trae instalado. Compruébalo desde la pestaña dev-machine:

kubectl top nodes
kubectl top pods -A

Ese kubectl top que acabas de usar es, además, la herramienta básica de observabilidad de recursos del día a día.

Paso 1: Un Deployment con requests (obligatorio) y su Service

El HPA de CPU calcula porcentajes sobre los requests del Pod. Sin requests no hay porcentaje posible, y el HPA queda inservible: es la razón práctica definitiva para declararlos siempre. Crea api.yaml con las dos piezas:

cat << 'EOF' > api.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: nginx
        image: ghcr.io/iximiuz/labs/nginx:alpine
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 20m
            memory: 64Mi
---
apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
  ports:
  - port: 80
    targetPort: 80
EOF

Todo en este archivo lo has escrito ya en lecciones anteriores; el único detalle nuevo es la intención: ese cpu: 20m deliberadamente bajo hará que un poco de carga se convierta en un porcentaje alto, para que el laboratorio escale rápido.

kubectl apply -f api.yaml

Paso 2: El HPA

Crea hpa.yaml:

cat << 'EOF' > hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 1
  maxReplicas: 4
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
EOF

El YAML, explicado con preguntas y respuestas

¿Qué señala scaleTargetRef?

El objeto al que el HPA moverá las réplicas. No gestiona Pods directamente: modifica el campo replicas del Deployment y deja que la maquinaria que ya conoces (Deployment, ReplicaSet) haga el resto.

¿Qué significa averageUtilization: 50?

El objetivo: que la media de CPU de los Pods ronde el 50 por ciento de sus requests. Con requests de 20m, eso son 10m de consumo medio. Si la media sube, el HPA añade réplicas para repartir; si baja, retira.

¿Para qué sirven minReplicas y maxReplicas?

Son las barandillas. El mínimo garantiza servicio aun sin carga; el máximo protege al clúster (y a tu factura) de un pico o de una métrica enloquecida.

¿Por qué autoscaling/v2 y no v1?

La v2 es la API actual y admite varias métricas a la vez, incluidas memoria y métricas personalizadas. La v1 solo entendía CPU.

Aplícalo y observa su primer cálculo (tarda unos segundos en dejar de decir unknown):

kubectl apply -f hpa.yaml
kubectl get hpa api-hpa

Paso 3: Carga y despegue

Genera tráfico continuo con un Pod que no deja de pedir la página:

kubectl run generador --image=ghcr.io/iximiuz/labs/nginx:alpine --command -- \
  sh -c 'for i in 1 2 3 4 5; do (while true; do wget -qO- http://api >/dev/null 2>&1; done) & done; wait'

Y ponte cómodo a mirar el instrumento clave:

kubectl get hpa api-hpa --watch

Verás la columna TARGETS pasar de un porcentaje bajo a superar el 50 por ciento, y poco después la columna REPLICAS subir. Paciencia: el ciclo completo (metrics-server mide, HPA decide, Deployment despliega) tarda entre 1 y 3 minutos.

Cuando pase la verificación, ejecuta el experimento inverso: borra el generador (kubectl delete pod generador) y deja el watch abierto. La vuelta a 1 réplica tardará bastante más, unos 5 minutos: el HPA reduce con una ventana de estabilización deliberadamente conservadora, porque quedarse corto de réplicas duele más que ir sobrado.

Resumen

  • El HPA ajusta las réplicas de un Deployment comparando consumo real contra un objetivo declarado.
  • Sin requests no hay HPA de CPU: el porcentaje se calcula sobre ellos.
  • metrics-server es el proveedor de la señal, y kubectl top tu ventana a ella.
  • Escalar hacia arriba es rápido; hacia abajo, prudente. Es diseño, no lentitud.

Y con esto termina el curso. Has recorrido el camino completo: del primer Pod a un clúster que se repara, se configura, se protege y ahora también se dimensiona solo.

Previous lesson
Jobs y CronJobs