
Curso Kubernetes 26 — Capacidad y carga: HPA, k6 y rate limit
Capacidad no es “cuántos usuarios caben”. Es en qué punto el sistema deja de cumplir el SLO — y qué componente falla primero.
En la mayoría de los clústeres que he visto, no es la CPU. Es la base de datos, la conexión, el disco o el NAT.
Sello del curso: probado en Kubernetes 1.35 con k6 y HPA en homologación.
Qué medir
| Métrica | Por qué |
|---|---|
| p50/p95/p99 | la media esconde la cola |
| tasa de error | 200 con error de negocio no cuenta |
| throughput | req/s sostenido |
| saturación | CPU, memoria, conexiones, disco |
| tiempo de cola | dónde la solicitud espera |
La media de latencia es la métrica más inútil de capacidad. p95 con 83 ms y 0% de error es un resultado; una media de 40 ms con p99 de 4 s es un problema.
Baseline antes de la prueba
kubectl top nodes
kubectl -n portal top pods
kubectl -n portal get hpa
kubectl -n portal get pdb
kubectl -n portal get pods -o wide
Registre: réplicas, requests/limits, conexiones de Postgres, uso de memoria de los nodos. Sin baseline, la prueba se convierte en anécdota.
k6: ramp, no disparo único
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 10 },
{ duration: '5m', target: 50 },
{ duration: '3m', target: 100 },
{ duration: '2m', target: 0 },
],
thresholds: {
http_req_failed: ['rate<0.01'],
http_req_duration: ['p(95)<500'],
},
};
export default function () {
const res = http.get(`${__ENV.BASE_URL}/api/fornecedores`, {
headers: { Authorization: `Bearer ${__ENV.TOKEN}` },
});
check(res, { 'status 200': (r) => r.status === 200 });
sleep(1);
}
k6 run -e BASE_URL=https://homolog.example.com -e TOKEN=... k6.js
El ramp encuentra la rodilla de la curva: el punto en que la latencia sube y el throughput deja de crecer.
Qué ocurrió en nuestra prueba
Con 50 VUs contra el ingress:
| Métrica | Resultado |
|---|---|
| Errores | 0% |
| p95 | 83,9 ms |
| p99 | dentro de lo aceptable |
La siguiente prueba, más agresiva, derribó el Postgres: el primario se reinició y el failover llevó la base de datos a otra instancia. La aplicación estaba saludable; la base de datos no.
Conclusión práctica: escalar la aplicación sin dimensionar la base de datos transfiere el problema. 10 pods de backend con pool de 10 conexiones = 100 conexiones, y Postgres tiene un límite.
HPA: qué ve y qué ignora
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- HPA usa requests como denominador. Sin requests, no escala.
- La CPU no ve la cola de la base de datos, la latencia ni las conexiones.
- Para colas, use métricas personalizadas (KEDA) — tamaño de cola de RabbitMQ, por ejemplo.
maxReplicasdebe caber en el clúster. HPA pidiendo 8 pods con 4 nodos llenos =Pending.
kubectl -n portal describe hpa portal-backend
La salida muestra unable to fetch metrics o missing request for cpu cuando faltan requests.
Headroom de nodo
Capacidad real = suma de los allocatable menos lo que ya está reservado, con margen para:
- un nodo perdido (N+1);
- aumento de rollout (
maxSurge); - DaemonSets.
kubectl describe node <node> | sed -n '/Allocated resources/,/Events/p'
Si cada nodo está al 85%, no tienes HA: tienes un clúster esperando el próximo drain.
Rate limit y protección
La prueba de carga también revela ausencia de protección:
- Rate limit en el ingress (nginx
limit_req) o en la app. - Timeout de conexión y de lectura.
- Circuit breaker para dependencia lenta.
- Connection pool con límite y timeout corto.
Sin esto, un pico se convierte en cola infinita, y la cola se convierte en timeout en cascada.
Prueba segura
Antes de ejecutar la carga:
- Entorno aislado (homologación), nunca en producción sin ventana.
- Backup reciente de la base de datos.
- Alerta de guardia avisado.
- Criterio de parada definido (p. ej.: error > 5% durante 1 min).
- Observabilidad activada: Prometheus, Grafana, logs.
- Plan de rollback.
Y después:
kubectl -n portal get pods
kubectl -n portal logs deploy/portal-backend --tail=100
kubectl -n portal get events --sort-by=.lastTimestamp | tail -20
Laboratorio
- Ejecute una prueba corta (10 VUs, 2 min) y valide el entorno.
- Suba el ramp y siga
kubectl get hpa -wy Grafana. - Identifique el primer componente saturado.
- Reduzca
maxReplicasy repita: vea aparecer el error. - Ajuste el pool de conexiones de la app y repita.
- Documente: throughput máximo, p95 en el límite y cuello de botella.
Errores comunes
| Síntoma | Causa |
|---|---|
| p95 explota con carga baja | pool de conexiones pequeño |
| HPA no escala | sin requests o metrics-server caído |
Pods Pending en el pico |
maxReplicas por encima de la capacidad |
| La base de datos se reinicia bajo carga | conexiones/memoria de Postgres |
| 429 inesperado | rate limit del ingress |
| Prueba “pasó” y producción cayó | entorno de prueba con más recursos |
| Números irreproducibles | sin baseline ni script versionado |
Checklist
- [ ] Baseline registrado antes de la prueba.
- [ ] Script k6 versionado en el repositorio.
- [ ] Umbrales de error y p95 definidos.
- [ ] HPA con requests y
maxReplicasque cabe en el clúster. - [ ] Pool de conexiones dimensionado con la base de datos.
- [ ] Headroom de N+1 validado.
- [ ] Rate limit y timeouts configurados.
- [ ] Criterio de parada y rollback acordados.
- [ ] Resultado documentado con fecha y commit.
Glosario
- VU: usuario virtual de k6.
- ramp: aumento gradual de carga.
- rodilla: punto donde la latencia crece sin ganancia de throughput.
- headroom: margen de capacidad.
- pool: conjunto de conexiones reutilizables.
- KEDA: autoscaling por eventos/colas.
Próximo
Has medido la capacidad y sabes dónde falla. Falta combinar esto con lo que el negocio espera: SLO, SLI, on-call y postmortem sin culpa.
Próximo: Curso Kubernetes 27 — SLO/SLI, on-call y postmortem blameless
Seguir leyendo
Lea también
TutoriaisManual LSI / Broadcom MegaRAID — MegaCli y StorCLI
Con esta guía, su equipo gana autonomía para diagnosticar rebuilds, resolver foreign configurations, gestionar BBU y CacheCade — con escenarios reales de producción documentados.
20 min de leitura
Nginx Cheatsheet
Guía de bolsillo con ejemplos listos para configurar Nginx en producción: desde instalación y virtual hosts hasta ajuste de rendimiento y resolución de problemas.
12 min de leitura
KubernetesCurso Kubernetes 27 — SLO/SLI, on-call y postmortem sin culpa
Qué prometer, cómo medir y qué hacer cuando el error se dispara: SLI, SLO, presupuesto de error, alertas que despiertan a alguien y postmortem sin caza de brujas.
5 min de leitura
Comentarios
Aún sin comentarios
Sea el primero en compartir su opinión sobre este artículo.
Deje un comentario