TL;DR: Kubernetes (K8s) es un orquestador de contenedores que automatiza el despliegue, escalado y gestión de aplicaciones en contenedores. Esta guía ofrece visión general, arquitectura, YAMLs listos para usar, comandos de uso diario y un mini-proyecto para levantar un servicio web con Ingress en minutos.
¿Qué es Kubernetes?#
Kubernetes es una plataforma de código abierto (“open source”) para orquestar contenedores (generalmente Docker) en clústeres. Se encarga de:
- Escalado automático (HPA, VPA, Cluster Autoscaler)
- Alta disponibilidad y autorrecuperación (ReplicaSet, probes)
- Despliegues predecibles (rolling update, canary / blue-green)
- Red, DNS interno y balanceo de carga (Services / Ingress)
- Configuración y secretos (ConfigMaps / Secrets)
- Almacenamiento persistente (PV / PVC / StorageClass)
Arquitectura (Visión Rápida)#
Plano de Control (Control Plane):
- kube-apiserver: puerta de entrada para toda interacción con el clúster.
- etcd: base de datos clave-valor que mantiene el estado del clúster.
- scheduler: decide en qué nodo debe ejecutarse un Pod.
- controller-manager / cloud-controller-manager: reconcilia el estado deseado vs. el estado actual; integra con proveedores de nube.
Nodos de Trabajo (Workers):
- kubelet: agente en el nodo; garantiza que los Pods estén en ejecución.
- kube-proxy: aplica las reglas de red y el balanceo de carga por Service.
- Container runtime: p.ej.
containerd.
Objetos Fundamentales#
- Pod: unidad mínima desplegable (uno o varios contenedores).
- ReplicaSet / Deployment: réplicas + estrategia de actualización.
- StatefulSet: estado estable / identidad fija (bases de datos, colas, etc.).
- DaemonSet: un Pod por nodo (por ej.: agentes de logs / monitorización).
- Job / CronJob: tareas puntuales o programadas.
- Service: expone un conjunto de Pods (ClusterIP / NodePort / LoadBalancer).
- Ingress: enrutamiento HTTP/HTTPS externo hacia Services.
- ConfigMap / Secret: configuración y credenciales.
- Namespace / RBAC: aislamiento lógico y permisos.
- PV / PVC / StorageClass: almacenamiento persistente y aprovisionamiento dinámico.
Manos a la obra: desplegando una aplicación web#
A continuación, una aplicación NGINX con Deployment, Service e Ingress.
Pre-requisitos locales:
kubectl+ un clúster (p.ej.: minikube o kind) y un Ingress Controller (en minikube:minikube addons enable ingress).
1) Deployment + Service (archivo deploy.yaml)#
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "250m"
memory: "128Mi"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: web-svc
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
protocol: TCP
type: ClusterIP
### **2) Ingress (archivo ingress.yaml)**
> Para clústeres locales, usa el addon de minikube o instala un Ingress Controller NGINX.
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: web.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-svc
port:
number: 80
3) Aplicando y probando#
kubectl apply -f deploy.yaml
kubectl apply -f ingress.yaml
kubectl get pods -w
kubectl get svc,ingress
Minikube:
minikube addons enable ingress
# Mapear host local
echo "$(minikube ip) web.local" | sudo tee -a /etc/hosts
# Prueba
curl -I http://web.local
kind:
- Crea el clúster con puertos mapeados (ej.: 80/443) e instala un ingress controller (NGINX). Consulta el manifiesto del proyecto ingress-nginx.
Configuración y Secretos#
ConfigMap + Secret (ejemplo)#
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_MESSAGE: "Hello from ConfigMap"
---
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
stringData:
DB_PASSWORD: supersecreta
Uso en el Pod (fragmento de Deployment):
spec:
containers:
- name: app
image: nginx:1.27-alpine
env:
- name: APP_MESSAGE
valueFrom:
configMapKeyRef:
name: app-config
key: APP_MESSAGE
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: DB_PASSWORD
Almacenamiento Persistente#
PVC genérico (StorageClass por defecto)#
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
Uso en el Pod:
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc
containers:
- name: app
volumeMounts:
- name: data
mountPath: /var/lib/data
Consejo: en la nube, usa StorageClass del proveedor (EBS/GCE PD/Azure Disk). En local, minikube ya ofrece una clase por defecto.
Autoscaling#
Horizontal Pod Autoscaler (HPA)#
Requiere
metrics-serverinstalado.
kubectl autoscale deployment web-deploy --cpu-percent=70 --min=3 --max=10
kubectl get hpa
VPA (Vertical) y Cluster Autoscaler (nodos) complementan el HPA.
Estrategias de Despliegue#
RollingUpdate (por defecto): actualiza gradualmente, con
maxSurge/maxUnavailable.Recreate: elimina todo y despliega la nueva versión (downtime).
Blue/Green / Canary: enrutamiento gradual mediante Ingress/Service + etiquetas/selectores.
Ejemplo: Ajuste de estrategia en el Deployment (ya incluido arriba):
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
Observabilidad & Debug (Hoja-resumen)#
# Explorar recursos
kubectl get nodes
kubectl get ns
kubectl get all -n default
# Descrever e inspecionar
kubectl describe pod <pod>
kubectl logs <pod> # logs do contêiner principal
kubectl logs -f <pod> -c <container>
# Acesso a um Pod
kubectl exec -it <pod> -- sh
kubectl port-forward svc/web-svc 8080:80
# Deploys e rollouts
kubectl rollout status deploy/web-deploy
kubectl rollout history deploy/web-deploy
kubectl rollout undo deploy/web-deploy
# Aplicar/Validar YAML
kubectl apply -f arquivo.yaml
kubectl diff -f arquivo.yaml
kubectl delete -f arquivo.yaml
Seguridad (Buenas Prácticas)#
RBAC mínimo necesario; usa
ServiceAccountespecífica por aplicación.Namespaces por equipo/producto para aislamiento + ResourceQuota / LimitRange.
Requests/Limits siempre definidos para cada contenedor.
Secrets para credenciales; evita secretos en ConfigMap / variables de entorno en claro.
NetworkPolicies para restringir tráfico L3/L4 entre Pods.
PSA/PSS (Pod Security Standards) para políticas de ejecución más estrictas.
Imágenes confiables y escaneo (Trivy/Grype) + pull siempre con digest cuando sea posible.
Checklist de Producción
- Ingress** con TLS (Let’s Encrypt/ACME) + redirección HTTP→HTTPS
- metrics-server + HPA
- Logs centralizados (Loki/ELK) y métricas (Prometheus/Grafana)
- Backups de etcd y volúmenes
- Alertas (Alertmanager) y dashboards
- Políticas: NetworkPolicy, RBAC, PSS
- Cotas por namespace; revisión de
requests/limits - CI/CD con manifiestos versionados (Kustomize/Helm/GitOps)
Errores Comunes y Soluciones#
- Pods en CrashLoopBackOff: verifica
kubectl logsy probes (tal vezinitialDelaySecondssea muy corto). ImagePullBackOff: revisa nombre/tag/registry/credenciales (imagePullSecret).- Servicio no responde: revisa
selectory etiquetas del Pod; puertos correctos. - Ingress 404: regla/host incorrectos o Ingress Controller no instalado.
- Sin métricas en el HPA: instala/configura
metrics-server.
Próximos Pasos#
- Convierte los YAMLs en Helm charts o Kustomize.
- Añade canary vía Ingress + peso de tráfico.
- Crea pipelines CI/CD con validación (lint),
kubectl diffy despliegue automático.
Referencias útiles: Documentación oficial de Kubernetes; proyectos ingress-nginx, metrics-server, Prometheus, Grafana, Loki, Kustomize y Helm.
Apéndice — Creando un clúster local rápidamente#
minikube:
minikube start --driver=docker
minikube addons enable ingress
kind: (ejemplo de configuración mínima kind-config.yaml)
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
apiServer:
extraArgs:
enable-admission-plugins: NodeRestriction
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
kind create cluster --name k8s-lab --config kind-config.yaml
# instala el Ingress Controller NGINX según la documentación del proyecto
Nota final: Este post fue escrito para el tema Hugo Relearn. Las secciones, TOC y navegación lateral se generan automáticamente por el tema. Si tu versión de Hugo está desactualizada, actualiza a una versión ≥ 0.126.3 para evitar advertencias de compatibilidad.


