Kubernetes
Qué es Kubernetes y cómo ayuda a que una app aguante picos de visitas.
Definición
Kubernetes (abreviado K8s: la K, ocho letras y la s) es una plataforma de código abierto para orquestar contenedores: automatiza su despliegue, su escalado y su recuperación ante fallos en un conjunto de máquinas. El nombre viene del griego kubernḗtēs, «timonel». Nació en Google, que lo liberó en 2014, y hoy lo mantiene la CNCF (Cloud Native Computing Foundation).
Su idea central es el estado deseado (desired state). No le das órdenes paso a paso («arranca este contenedor aquí»); le declaras el resultado que quieres («quiero 3 copias de esta aplicación siempre en marcha») en archivos YAML llamados manifiestos. Kubernetes compara continuamente lo que declaraste con lo que existe y actúa para igualarlos. Ese ciclo de observar, comparar y corregir se llama bucle de reconciliación y lo ejecutan programas llamados controladores.
Este artículo continúa el del día 5: allí se vio cómo empaquetar una aplicación en una imagen y ejecutarla como contenedor; aquí se ve quién se encarga de ejecutar muchos contenedores en muchas máquinas.
Arquitectura
Un clúster (cluster) es el conjunto de máquinas, llamadas nodos (nodes), que Kubernetes administra. Se divide en dos partes.
| Componente | Dónde | Función |
|---|---|---|
| kube-apiserver | Plano de control | Única puerta de entrada: expone la API REST; kubectl y todos los demás componentes hablan con él |
| etcd | Plano de control | Base de datos clave-valor con el estado del clúster |
| kube-scheduler | Plano de control | Decide en qué nodo se ejecuta cada Pod nuevo según recursos y restricciones |
| kube-controller-manager | Plano de control | Ejecuta los controladores (Deployment, nodos, etc.) que reconcilian el estado |
| kubelet | Cada nodo | Agente que arranca y vigila los contenedores asignados a su nodo |
| kube-proxy | Cada nodo | Mantiene las reglas de red que hacen funcionar los Services |
| Motor de contenedores (container runtime) | Cada nodo | Ejecuta los contenedores (containerd, CRI-O) |
El plano de control (control plane) toma las decisiones; los nodos trabajadores (worker nodes) ejecutan la carga. El usuario interactúa con kubectl, la herramienta de línea de comandos que traduce comandos y archivos en llamadas a la API.
Objetos fundamentales
Todo en Kubernetes es un objeto descrito por un manifiesto con cuatro campos de primer nivel: apiVersion, kind (tipo), metadata (nombre, etiquetas) y spec (el estado deseado).
| Objeto | Qué es | Idea clave |
|---|---|---|
| Pod | La unidad mínima desplegable: uno o varios contenedores que comparten red y almacenamiento | Es efímero: nace, muere y no se «repara», se reemplaza |
| ReplicaSet | Mantiene un número fijo de Pods idénticos | Rara vez se usa directamente |
| Deployment | Gestiona ReplicaSets: réplicas, actualizaciones y reversiones | Es el objeto que se usa para aplicaciones sin estado |
| Service | Nombre y dirección estables que reparten tráfico entre Pods | Los Pods cambian de IP; el Service no |
| Ingress | Reglas de entrada HTTP/HTTPS desde fuera del clúster hacia Services | Requiere un controlador de Ingress instalado |
| ConfigMap / Secret | Configuración y datos sensibles separados de la imagen | Un Secret está codificado, no cifrado, salvo que se configure el cifrado en reposo |
| HorizontalPodAutoscaler | Ajusta el número de réplicas según métricas | Es el autoescalado de esta guía |
| Namespace | Partición lógica del clúster | Aísla equipos o entornos |
| StatefulSet | Como Deployment, pero con identidad y almacenamiento estables | Para bases de datos y servicios con estado |
Dos mecanismos conectan los objetos entre sí: las etiquetas (labels, pares clave-valor como app: tienda-api) y los selectores (selectors), que eligen objetos por sus etiquetas. El Deployment elige sus Pods por etiqueta; el Service también.
Deployment: réplicas, actualizaciones y reversión
Un Deployment declara cuántas réplicas de un Pod deben existir y cómo cambiar de versión.
Manifiesto deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: tienda-api
labels:
app: tienda-api
spec:
replicas: 3
selector:
matchLabels:
app: tienda-api
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
template:
metadata:
labels:
app: tienda-api
spec:
containers:
- name: api
image: ghcr.io/ejemplo/tienda-api:1.0.0
ports:
- containerPort: 8000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
readinessProbe:
httpGet:
path: /salud
port: 8000
initialDelaySeconds: 3
periodSeconds: 5
livenessProbe:
httpGet:
path: /salud
port: 8000
initialDelaySeconds: 10
periodSeconds: 10
Cómo leerlo:
replicas: 3: estado deseado, tres Pods. Si uno falla o su nodo desaparece, el controlador crea otro.selector.matchLabelsdebe coincidir contemplate.metadata.labels: así el Deployment reconoce sus Pods.strategy.RollingUpdate: al cambiar la imagen, reemplaza los Pods gradualmente. ConmaxUnavailable: 0nunca baja de las 3 réplicas disponibles;maxSurge: 1permite un Pod extra durante la transición. Resultado: actualización sin interrupción.image: se fija a una etiqueta de versión concreta (1.0.0), no alatest, para que el despliegue sea reproducible. La imagen es un ejemplo; no existe un repositorio real con ese nombre.resources.requestses lo que el planificador reserva al elegir nodo;limitses el techo.100msignifica 100 milicores (0,1 de un núcleo de CPU). Superar el límite de memoria termina el contenedor (OOMKilled); superar el de CPU solo lo ralentiza.readinessProbe(sonda de disponibilidad): mientras falla, el Pod no recibe tráfico.livenessProbe(sonda de vida): si falla repetidamente, el kubelet reinicia el contenedor. Ambas suponen que la aplicación expone un endpoint/salud.
Los comandos para actualizar y revertir:
kubectl set image deployment/tienda-api api=ghcr.io/ejemplo/tienda-api:1.1.0
kubectl rollout status deployment/tienda-api
kubectl rollout undo deployment/tienda-api
Service: una dirección estable
Los Pods son efímeros y cada uno tiene su propia IP, que cambia al reemplazarse. Un Service ofrece un punto de acceso estable y balancea la carga entre los Pods que coinciden con su selector.
Manifiesto service.yaml:
apiVersion: v1
kind: Service
metadata:
name: tienda-api
spec:
type: ClusterIP
selector:
app: tienda-api
ports:
- name: http
port: 80
targetPort: 8000
port es el puerto del Service y targetPort el del contenedor. Dentro del clúster, otras aplicaciones lo alcanzan por el nombre DNS tienda-api. Solo reciben tráfico los Pods que están listos según la readinessProbe.
| Tipo de Service | Alcance | Uso típico |
|---|---|---|
| ClusterIP (por defecto) | Solo dentro del clúster | Comunicación entre servicios |
| NodePort | Un puerto en cada nodo | Pruebas, o base de otros tipos |
| LoadBalancer | Balanceador del proveedor de nube | Exponer un servicio a Internet |
| ExternalName | Alias DNS a un nombre externo | Referenciar un servicio fuera del clúster |
Para HTTP/HTTPS con varias rutas o dominios sobre una sola IP pública se usa un Ingress (o su sucesor, la Gateway API).
Autoescalado: HorizontalPodAutoscaler
El HorizontalPodAutoscaler (HPA) cambia el número de réplicas de un Deployment según una métrica observada. Escalar horizontalmente es agregar más copias; escalar verticalmente sería dar más CPU o memoria a cada copia.
Manifiesto hpa.yaml:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: tienda-api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: tienda-api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
El HPA calcula periódicamente:
réplicas deseadas = ceil( réplicas actuales × métrica actual / métrica objetivo )
Ejemplo: con 3 réplicas al 140 % del CPU solicitado y objetivo de 70 %, resulta ceil(3 × 140 / 70) = 6 réplicas. Notas importantes:
Utilizationse mide respecto arequests.cpu; por eso el Deployment debe declararrequests. Sin ellos, el HPA no puede calcular el porcentaje.- Requiere el Metrics Server instalado en el clúster para obtener las métricas.
stabilizationWindowSeconds: 300evita «aleteo» (flapping): al bajar la demanda, espera 5 minutos antes de reducir réplicas.minReplicasymaxReplicasacotan el comportamiento. Escalar réplicas solo sirve si hay nodos con espacio; el Cluster Autoscaler (o servicios equivalentes de la nube) agrega nodos, y es un componente distinto.- No escala a cero ni sirve para aplicaciones que no toleran varias copias en paralelo.
Autorreparación
Kubernetes aplica el bucle de reconciliación a varias situaciones sin intervención humana:
| Situación | Qué hace |
|---|---|
| Un Pod se elimina o su nodo cae | El ReplicaSet crea un Pod de reemplazo en otro nodo |
Un contenedor falla la livenessProbe | El kubelet lo reinicia |
| Un Pod no está listo | El Service deja de enviarle tráfico |
Una versión nueva no pasa la readinessProbe | La actualización progresiva se detiene y las réplicas antiguas siguen sirviendo |
| Sube la demanda | El HPA aumenta las réplicas |
Cuándo usar Kubernetes y cuándo no
| Situación | Recomendación |
|---|---|
| Una aplicación pequeña, un servidor | No: un contenedor con Docker Compose o un servicio gestionado basta |
| Pocos servicios, tráfico estable | Probablemente no: el costo operativo supera el beneficio |
| Muchos servicios, varios equipos, tráfico variable | Sí: es el caso para el que se diseñó |
| Necesitas actualizaciones sin interrupción y recuperación automática a escala | Sí |
| Quieres portabilidad entre proveedores de nube | Sí, con la salvedad de que las partes específicas (balanceadores, almacenamiento) cambian |
Kubernetes tiene una curva de aprendizaje alta y su operación (actualizaciones, seguridad, redes, costos) es un trabajo en sí misma. Existen servicios gestionados que operan el plano de control por ti (por ejemplo GKE, EKS, AKS); simplifican, pero no eliminan la necesidad de entender los objetos.
Buenas prácticas
- Declara siempre
requestsylimits; sin ellos, el planificador y el HPA trabajan a ciegas. - Define
readinessProbeylivenessProbedistintas en propósito: una decide si recibe tráfico, la otra si se reinicia. - Fija las imágenes a una versión concreta (o a su digest), nunca a
latest. - Guarda los manifiestos en Git y aplícalos desde un pipeline (ver el artículo del día 7): es la base de GitOps.
- Usa Namespaces y permisos mínimos (RBAC, control de acceso basado en roles).
- No guardes datos importantes en el sistema de archivos de un Pod: se pierde al reemplazarse. Usa volúmenes persistentes o servicios externos.
- Ejecuta los contenedores sin privilegios de administrador y con un sistema de archivos de solo lectura cuando sea posible.
Práctica: de los manifiestos a un clúster local
Importante sobre este artículo. Los tres manifiestos anteriores se validaron únicamente como YAML: un analizador confirmó que cada archivo es sintácticamente correcto y que declara Deployment (apps/v1), Service (v1) y HorizontalPodAutoscaler (autoscaling/v2). No se aplicaron a ningún clúster: en el entorno de redacción no había Kubernetes ni Docker instalados, así que su comportamiento real (arranque de Pods, escalado) no se ha observado. Los pasos siguientes siguen la documentación oficial; compruébalos tú en un clúster local de práctica.
Requisitos. Docker (o similar) y un clúster local. minikube o kind crean uno en tu equipo. Instalar Docker o minikube cambia tu sistema; hazlo siguiendo su documentación oficial.
1. Crea el clúster local.
minikube start
minikube addons enable metrics-server
El segundo comando instala el Metrics Server que necesita el HPA.
2. Sustituye la imagen de ejemplo por una real. Para probar solo el mecanismo, sirve cualquier imagen web (por ejemplo nginx) y ajusta containerPort, targetPort y las sondas (path: /, port: 80). Si usas la API del día 5, empaquétala y cárgala con minikube image load.
3. Aplica los manifiestos.
kubectl apply -f deployment.yaml -f service.yaml -f hpa.yaml
4. Observa el estado.
kubectl get deployments,pods,services,hpa
kubectl describe hpa tienda-api
Resultado esperado: 3 Pods en estado Running y READY 1/1.
5. Prueba la autorreparación. Elimina un Pod y observa cómo se crea otro:
kubectl delete pod <nombre-de-un-pod>
kubectl get pods --watch
6. Prueba el escalado. Genera carga contra el Service y observa cómo sube REPLICAS:
kubectl run carga --image=busybox:1.36 --restart=Never -- /bin/sh -c "while true; do wget -q -O- http://tienda-api; done"
kubectl get hpa --watch
Elimina el generador de carga al terminar: kubectl delete pod carga.
7. Actualiza y revierte con los comandos kubectl set image y kubectl rollout undo vistos arriba.
8. Limpia. kubectl delete -f deployment.yaml -f service.yaml -f hpa.yaml y minikube delete.
Preguntas frecuentes
¿Qué es Kubernetes en palabras simples?
Es un sistema que administra contenedores en un grupo de servidores (clúster): decide dónde corre cada uno, mantiene el número de copias que pediste y reemplaza las que fallan.
¿Qué diferencia hay entre Docker y Kubernetes?
Docker empaqueta y ejecuta contenedores. Kubernetes los orquesta a escala: reparte la carga entre servidores, escala el número de copias y hace actualizaciones sin cortar el servicio.
¿Qué es un pod en Kubernetes?
Es la unidad mínima que Kubernetes ejecuta: uno o varios contenedores que comparten red y almacenamiento. Normalmente se crean a través de un Deployment, no a mano.
¿Cuándo no conviene usar Kubernetes?
Cuando la aplicación es pequeña, el tráfico es estable o el equipo no puede dedicar tiempo a operarlo. En esos casos, un servicio administrado o un solo servidor con Docker suele bastar.
En el reel lo explicamos así
Piensa en el gerente de un restaurante. Tú le dices cuántos meseros quieres como mínimo; él se encarga del resto. Si el lugar se llena, llama a más meseros. Si uno falta, lo reemplaza sin que nadie se lo pida. Y cuando baja la clientela, deja ir a los que sobran. Kubernetes es ese gerente para tus contenedores: arranca los que faltan, reemplaza los que fallan y agrega más cuando sube la demanda.
Referencias
- Kubernetes: descripción general: qué es y para qué sirve.
- Componentes de Kubernetes: plano de control y nodos.
- Deployments: réplicas, actualizaciones progresivas y reversión.
- Services: tipos y selectores.
- Horizontal Pod Autoscaling: algoritmo y
autoscaling/v2. - Sondas de vida, disponibilidad y arranque.
- Gestión de recursos de contenedores:
requestsylimits. - Herramientas de instalación y minikube.
- Nota de verificación: las URLs anteriores respondieron HTTP 200 el 9-oct-2026 al comprobarse con una petición directa; no se comprobó que su contenido coincida palabra por palabra con lo descrito aquí.
El gerente de un restaurante que llama a más meseros si se llena el lugar y reemplaza a quien falta, sin que nadie se lo pida.
Glosario: del inglés al español
| Kubernetes | del griego «timonel»: dirige los contenedores |
|---|---|
| Cluster | grupo de computadoras que trabajan juntas |
| Pod | la unidad mínima donde vive un contenedor |
| Autoscaling | autoescalado |