El Horizontal Pod Autoscaler (HPA) permite ajustar automáticamente el número de Pods de una aplicación según métricas como el consumo de CPU. En esta guía vas a crear un laboratorio con un Deployment, un Service y un HPA basado en CPU; después generarás carga para comprobar el escalado ascendente y el retorno controlado al mínimo.
El laboratorio mantendrá entre 2 y 10 réplicas e intentará que el consumo medio se aproxime al 50 % de la CPU solicitada por cada Pod.
Alcance: el HPA escala Pods. No aumenta la CPU o memoria asignada a cada Pod ni crea nodos. Si el clúster no tiene capacidad suficiente, las réplicas nuevas quedarán en estado Pending.Cómo funciona el Horizontal Pod Autoscaler
El controlador HPA consulta periódicamente las métricas disponibles mediante la API de Kubernetes. Después compara el valor actual con el objetivo configurado y actualiza el subrecurso scale del Deployment.
Cuando el objetivo está expresado como porcentaje de CPU, Kubernetes calcula la utilización respecto de resources.requests.cpu. Por esta razón, los contenedores deben declarar una solicitud de CPU: si falta, la utilización no queda definida correctamente y el HPA puede no actuar.
De forma simplificada, Kubernetes calcula las réplicas deseadas así:
réplicas deseadas =
techo(réplicas actuales × métrica actual / métrica objetivo)El cambio no es instantáneo. El controlador también considera la disponibilidad de métricas, el estado Ready de los Pods, la tolerancia configurada y las ventanas de estabilización.

Requisitos previos
Antes de comenzar, necesitas:
- Un clúster Kubernetes activo y con capacidad para ejecutar hasta 10 réplicas pequeñas durante la prueba.
kubectlconfigurado con el contexto correcto.- Permisos para crear namespaces, Deployments, Services y recursos HPA.
- Permisos para consultar métricas y eventos.
- La API
metrics.k8s.iodisponible mediante Metrics Server u otro adaptador compatible. - Dos terminales: una para generar carga y otra para observar el escalado.
- Acceso de salida desde los nodos hacia los registros de imágenes utilizados.
Advertencia: ejecuta este procedimiento en un namespace de laboratorio. La prueba genera carga y consume capacidad del clúster.
Paso 1: comprobar el contexto, los permisos y las métricas
Comprueba primero que kubectl apunta al clúster correcto:
kubectl config current-context
kubectl version --clientValida los permisos necesarios:
kubectl auth can-i create namespace
kubectl auth can-i create deployment --namespace=hpa-lab
kubectl auth can-i create horizontalpodautoscaler.autoscaling \
--namespace=hpa-labLas respuestas deberían ser yes. Si recibes no, solicita los permisos necesarios antes de continuar.
Comprueba ahora que la API de métricas está disponible:
kubectl get apiservice | grep metrics.k8s.io
kubectl get --raw '/apis/metrics.k8s.io/'
kubectl top nodesEl APIService correspondiente a metrics.k8s.io debería aparecer disponible y kubectl top nodes debería mostrar valores de CPU y memoria.
Las métricas pueden tardar unos minutos en aparecer cuando Metrics Server o los nodos acaban de iniciarse.
Si Metrics Server no está disponible
Instálalo mediante el procedimiento recomendado por la distribución o el proveedor del clúster. El proyecto ofrece un manifiesto genérico:
kubectl apply -f \
https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yamlAntes de aplicarlo, revisa los requisitos oficiales de red, certificados, capa de agregación y compatibilidad.
No uses --kubelet-insecure-tls en producción para ocultar un problema de certificados. Esa opción desactiva la verificación del certificado presentado por el kubelet y debería limitarse, como máximo, a entornos de prueba controlados.
Paso 2: crear un namespace de laboratorio
Previsualiza el recurso antes de crearlo:
kubectl create namespace hpa-lab \
--dry-run=client \
-o yamlDespués crea el namespace y comprueba su estado:
kubectl create namespace hpa-lab
kubectl get namespace hpa-labSi el namespace ya existe y confirmaste que pertenece a esta prueba, no necesitas recrearlo.
Paso 3: preparar el Deployment, el Service y el HPA
Guarda el siguiente manifiesto como hpa-lab.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
namespace: hpa-lab
spec:
replicas: 2
selector:
matchLabels:
app: php-apache
template:
metadata:
labels:
app: php-apache
spec:
containers:
- name: php-apache
image: registry.k8s.io/hpa-example:latest
ports:
- name: http
containerPort: 80
resources:
requests:
cpu: 200m
memory: 64Mi
limits:
cpu: 500m
memory: 128Mi
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 3
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 10
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
namespace: hpa-lab
spec:
selector:
app: php-apache
ports:
- name: http
port: 80
targetPort: http
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: hpa-lab
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
behavior:
scaleDown:
stabilizationWindowSeconds: 300La aplicación de demostración consume CPU al responder solicitudes. El valor requests.cpu: 200m funciona como referencia para el objetivo del 50 %.
El límite de 500m restringe el consumo individual del contenedor, pero no sustituye una prueba de capacidad del clúster.
La imagen registry.k8s.io/hpa-example:latest se utiliza para reproducir el laboratorio oficial de Kubernetes. En producción, emplea una imagen mantenida por tu equipo y fija una versión o un digest revisado.
Paso 4: validar antes de aplicar
Valida primero la sintaxis de manera local:
kubectl apply --dry-run=client -f hpa-lab.yamlDespués valida el manifiesto contra el esquema, las políticas de admisión y los permisos del servidor:
kubectl apply --dry-run=server -f hpa-lab.yamlRevisa las diferencias que produciría la aplicación:
kubectl diff -f hpa-lab.yamlkubectl diff devuelve el código 1 cuando encuentra diferencias. Esto es normal. Un código superior a 1 indica un error que debes resolver.
No continúes si la validación informa:
- Un campo inválido.
- Un recurso desconocido.
- Una denegación de admisión.
- Un namespace inexistente.
- Falta de permisos.
- Un
scaleTargetRefque no coincide con elDeployment.
Paso 5: aplicar y comprobar el estado inicial
Aplica los recursos:
kubectl apply -f hpa-lab.yamlEspera a que el Deployment esté disponible:
kubectl rollout status deployment/php-apache \
-n hpa-lab \
--timeout=120sConsulta los recursos y las métricas:
kubectl get deployment,pods,service,hpa -n hpa-lab
kubectl top pods -n hpa-lab
kubectl describe hpa php-apache -n hpa-labEl resultado esperado es:
- El
Deploymenttiene 2 réplicas disponibles. - Los Pods aparecen como
RunningyReady. kubectl top podsmuestra valores de CPU.- El HPA muestra una métrica actual en
TARGETS, en lugar de<unknown>. MINPODSes2yMAXPODSes10.
Durante los primeros instantes, el HPA puede mostrar <unknown> mientras se recopilan las primeras muestras.
Paso 6: generar carga y observar el escalado
En la primera terminal, crea un Pod temporal que envíe solicitudes continuas al Service:
kubectl run load-generator \
-n hpa-lab \
--rm \
-it \
--image=busybox:1.36.1 \
--restart=Never \
-- \
/bin/sh -c \
'while sleep 0.01; do wget -q -O- http://php-apache; done'En la segunda terminal, observa el HPA y los Pods:
kubectl get hpa,pods -n hpa-lab -wPuedes registrar información adicional con:
kubectl top pods -n hpa-lab
kubectl get hpa php-apache \
-n hpa-lab \
-o 'custom-columns=NAME:.metadata.name,CURRENT:.status.currentReplicas,DESIRED:.status.desiredReplicas,CPU:.status.currentMetrics[0].resource.current.averageUtilization'
kubectl describe hpa php-apache -n hpa-labLa prueba de escalado ascendente se considera satisfactoria cuando:
- La CPU media supera el objetivo del 50 %.
DESIREDaumenta.- Aparecen más de 2 Pods.
- El número de réplicas no supera
maxReplicas: 10. - Los Pods nuevos alcanzan el estado
Ready. - La aplicación continúa respondiendo.
La velocidad exacta depende del intervalo del controlador, la llegada de métricas, el tiempo de arranque y la capacidad disponible.
Paso 7: detener la carga y comprobar la reducción
Pulsa Ctrl+C en la terminal del generador de carga. Como se utilizó --rm, Kubernetes eliminará el Pod temporal.
Mantén la observación activa:
kubectl get hpa,pods -n hpa-lab -wTambién puedes revisar las decisiones recientes del autoscaler:
kubectl describe hpa php-apache -n hpa-labLa prueba de reducción se considera satisfactoria cuando:
- El consumo de CPU desciende.
- El HPA reduce las réplicas.
- El
Deploymentvuelve a 2 Pods. - Los Pods restantes continúan disponibles.
La reducción no es inmediata. El manifiesto configura una ventana de estabilización de 300 segundos para evitar que una fluctuación breve provoque la eliminación y recreación repetida de Pods.
El retorno al mínimo puede tardar más de cinco minutos por la ventana configurada, la frecuencia de muestreo y la reconciliación del controlador.

Cómo retirar el HPA
Si quieres conservar la aplicación, pero dejar de escalar automáticamente, elimina primero el HPA:
kubectl delete hpa php-apache -n hpa-labDespués establece manualmente el número de réplicas:
kubectl scale deployment/php-apache \
-n hpa-lab \
--replicas=2Mientras el HPA esté activo, puede sobrescribir los cambios manuales realizados en spec.replicas.
kubectl rollout undo no revierte ni desactiva un HPA. Esa orden revierte una revisión del Deployment.
Cómo eliminar el laboratorio
Comprueba una vez más el contexto:
kubectl config current-contextCuando confirmes que estás en el clúster correcto, elimina el namespace:
kubectl delete namespace hpa-lab --wait=trueEsta operación elimina todos los recursos namespaced contenidos en hpa-lab.
Problemas frecuentes
El HPA muestra <unknown> en TARGETS
Ejecuta:
kubectl top pods -n hpa-lab
kubectl get apiservice | grep metrics.k8s.io
kubectl describe hpa php-apache -n hpa-labSi las métricas no aparecen después de esperar las primeras muestras, revisa:
- El estado y los logs de Metrics Server.
- La conectividad entre Metrics Server y los kubelets.
- Los certificados presentados por los kubelets.
- La capa de agregación de la API.
- Los permisos del adaptador de métricas.
El HPA recibe métricas, pero no aumenta las réplicas
Comprueba que:
- Todos los contenedores relevantes declaran
requests.cpu. - La carga llega al
Servicecorrecto. - El consumo medio supera realmente el objetivo.
- El
scaleTargetRefseñala alDeploymentadecuado. - Las condiciones y los eventos del HPA no muestran errores.
Una utilización cercana al objetivo puede quedar dentro de la tolerancia del controlador y no provocar cambios.
El HPA pide más réplicas, pero los Pods quedan Pending
El HPA ya calculó y solicitó el escalado. El problema se encuentra en la programación o en la capacidad del clúster.
Inspecciona uno de los Pods afectados:
kubectl describe pod NOMBRE_DEL_POD -n hpa-labRevisa:
- CPU y memoria disponibles.
taintsytolerations.- Afinidad y antiafinidad.
- Cuotas del namespace.
- Límites configurados.
- Restricciones de almacenamiento o red.
El HPA no crea nodos. Si no existe capacidad, necesitas ampliarla manualmente o utilizar un mecanismo de autoscaling de nodos compatible con la plataforma.
Las réplicas no bajan después de detener la carga
Revisa la utilización actual y la ventana de estabilización:
kubectl top pods -n hpa-lab
kubectl describe hpa php-apache -n hpa-labComprueba también que:
- No quede otro generador de carga activo.
- Los Pods estén
Ready. - Las métricas sean válidas.
- Hayan transcurrido los 300 segundos de estabilización.
Las réplicas oscilan o la aplicación falla al escalar
Antes de modificar las políticas del HPA:
- Ajusta los
requestscon mediciones reales. - Configura
readinessProbeystartupProbesegún el tiempo de arranque. - Comprueba que CPU represente la demanda del servicio.
- Revisa si las dependencias soportan el aumento de concurrencia.
- Conserva una ventana de estabilización suficiente.
Reducir la estabilización puede aumentar las oscilaciones si la métrica es ruidosa.
Buenas prácticas para producción
- Define
minReplicassegún las necesidades de disponibilidad. - Limita
maxReplicassegún capacidad, cuotas, presupuesto y límites de las dependencias. - Configura los
requestscon información obtenida mediante pruebas de carga. - Fija las imágenes por versión o digest.
- Diseña los Pods para que sean reemplazables y no dependan de archivos efímeros locales.
- Utiliza probes coherentes con el arranque y la disponibilidad real.
- Considera un
PodDisruptionBudgetcuando el nivel de servicio lo requiera. - Supervisa disponibilidad, latencia, errores, réplicas deseadas y capacidad.
- No uses Metrics Server como sistema histórico de monitoreo.
- Evalúa métricas personalizadas si CPU no representa correctamente la demanda.
- Combina HPA con autoscaling de nodos solo cuando la plataforma lo permita y después de validar tiempos, límites y costos.
Conclusión
Un HPA funcional depende de cuatro elementos alineados:
- Una métrica disponible.
- Solicitudes de recursos correctamente definidas.
- Un
scaleTargetRefválido. - Capacidad para programar las nuevas réplicas.
La configuración no está terminada hasta observar el aumento de Pods bajo carga y el retorno controlado al mínimo.

Como siguiente paso, repite la prueba con un perfil de tráfico representativo y registra latencia, errores y consumo de recursos. Si CPU no se correlaciona con la demanda, utiliza una métrica de negocio, solicitudes por segundo o longitud de cola mediante una canalización compatible.