Cerramos el módulo 9 con un diagnóstico incómodo: la plataforma Rutas Norte ya sabe escalar sola, resistir el puente de mayo y protegerse durante los mantenimientos, pero el directorio k8s/ se ha convertido en más de 120 ficheros YAML duplicados entre dev, pre y pro que alguien aplica a mano desde su portátil. El módulo 10 va precisamente de eso: de las herramientas que rodean a Kubernetes y que convierten un montón de manifiestos sueltos en un sistema operable.
Empezamos por el eslabón más cercano al equipo de desarrollo: el clúster local. Antes de plantillar nada con Helm (10-03), superponer nada con Kustomize (10-04) o reconciliar nada con Argo CD (10-05), hace falta un sitio barato y desechable donde probar los cambios. En el módulo 1 levantamos el clúster de prácticas con minikube start --profile=rutas-norte casi como un trámite, y dijimos que volveríamos a ello. Ha llegado el momento: en esta lección vamos a fondo con minikube, conocemos kind (la herramienta preferida en integración continua), comparamos las cinco alternativas más habituales y, sobre todo, aprendemos qué se puede validar en un clúster local y qué no, que es la raíz del clásico «en mi máquina funciona».
Contenido
- Por qué todo equipo necesita un clúster desechable
- Minikube a fondo: perfiles y controladores
- Dimensionado, versión de Kubernetes y clústeres multinodo
- El catálogo de addons
- Trabajar con imágenes locales sin registro
- Acceso al clúster: tunnel, service, dashboard, mount y ssh
- El ciclo de vida: stop, start, delete y logs
- kind a fondo: nodos como contenedores
- Tabla comparativa: minikube, kind, k3d, Docker Desktop y Rancher Desktop
- Las diferencias con producción que provocan «en mi máquina funciona»
- Receta reproducible: el entorno completo de Rutas Norte en local
- Errores comunes y consejos
- Ejercicios
- Conclusión
- Por qué todo equipo necesita un clúster desechable
En Rutas Norte S.L. hay tres entornos reales: rutas-norte-dev, rutas-norte-pre y rutas-norte-pro. Los tres viven en clústeres compartidos. Eso significa que cuando una desarrolladora quiere probar si su nuevo NetworkPolicy rompe la conexión entre api-reservas y postgres-reservas, tiene dos opciones malas:
- Aplicarlo en
rutas-norte-devy arriesgarse a bloquear el trabajo de los otros seis compañeros que comparten ese namespace. - No probarlo y descubrirlo en
pre, con el ciclo de espera que eso implica.
Un clúster local resuelve el dilema. Es suyo, gratis, rápido de recrear y, si lo rompe, minikube delete y vuelta a empezar en tres minutos.
Qué SÍ se puede validar en local
| Aspecto | ¿Validable en local? | Comentario |
|---|---|---|
| Sintaxis y validez de los manifiestos | Sí, perfectamente | kubectl apply --dry-run=server ya valida contra el esquema real |
| Comportamiento de un Deployment, rollout y rollback | Sí | El controlador es el mismo que en producción |
| Sondas de liveness/readiness/startup | Sí | Misma lógica del kubelet |
| ConfigMaps, Secrets y variables de entorno | Sí | Idéntico |
| RBAC: Roles, RoleBindings, ServiceAccounts | Sí | La API es la misma |
| Ingress y enrutado por host/ruta | Sí, con el addon o extraPortMappings |
Otro controlador, pero mismas reglas |
| CRDs y operadores | Sí | Se instalan igual |
| HPA con métricas de CPU | Sí, con metrics-server |
El comportamiento es realista |
| Jobs, CronJobs, StatefulSets | Sí | Idéntico |
Qué NO se puede validar en local
| Aspecto | Por qué falla | Dónde se estudió |
|---|---|---|
Balanceador de nube real (Service LoadBalancer) |
No hay proveedor de nube que asigne IP | 04-02 |
| Rendimiento y latencia reales del almacenamiento | La StorageClass local es un directorio del nodo | 05-04 |
| NetworkPolicies con el CNI por defecto | Muchos CNI locales las ignoran silenciosamente | 04-06 |
| Distribución topológica entre zonas | Hay una sola "zona" ficticia | 09-05 |
| Cluster Autoscaler y adición de nodos | No hay grupo de nodos elástico | 09-03 |
| Cuotas y presión real de recursos | Tu portátil no es un nodo de 64 GB | 03-04 |
| Federación de identidad con la nube (IRSA, Workload Identity) | No hay proveedor de identidad | 10-06 |
| Latencia entre nodos y particiones de red | Todo corre en la misma máquina | — |
La regla práctica: el clúster local valida la corrección de tus manifiestos y la lógica de tu aplicación; no valida el rendimiento, la topología ni la integración con la nube.
flowchart LR
A[Portátil<br/>minikube / kind] -->|valida sintaxis,<br/>lógica, RBAC| B[rutas-norte-dev]
B -->|valida integración,<br/>datos parecidos| C[rutas-norte-pre]
C -->|valida carga,<br/>topología, coste| D[rutas-norte-pro]
style A fill:#e8f4ff
style D fill:#ffe8e8
- Minikube a fondo: perfiles y controladores
minikube es una herramienta que levanta un clúster de Kubernetes de un solo nodo (o de varios) dentro de una máquina virtual o un contenedor de tu equipo. Lo hemos usado desde el módulo 1; ahora vamos a entender qué hace por dentro.
Perfiles: varios clústeres a la vez
Un perfil es un clúster independiente con su propio nombre, su propia configuración y su propio contexto de kubectl. Es la razón por la que en el módulo 1 escribimos --profile=rutas-norte y no simplemente minikube start.
# Crear (o arrancar) el clúster del curso
minikube start --profile=rutas-norte
# Crear un segundo clúster para probar una versión antigua de Kubernetes
minikube start --profile=rutas-norte-viejo --kubernetes-version=v1.28.15
# Ver todos los perfiles y su estado
minikube profile listSalida típica:
|--------------------|-----------|---------|--------------|------|---------|---------|-------|--------|
| Profile | VM Driver | Runtime | IP | Port | Version | Status | Nodes | Active |
|--------------------|-----------|---------|--------------|------|---------|---------|-------|--------|
| rutas-norte | docker | docker | 192.168.49.2 | 8443 | v1.30.4 | Running | 3 | * |
| rutas-norte-viejo | docker | docker | 192.168.58.2 | 8443 | v1.28.15| Stopped | 1 | |
|--------------------|-----------|---------|--------------|------|---------|---------|-------|--------|Sin --profile, minikube usa el perfil minikube. Puedes fijar el perfil activo para no repetirlo en cada orden:
minikube profile rutas-norte # a partir de aquí, todas las órdenes van a este perfil
minikube status # ya no hace falta --profileConsejo: fijar el perfil es cómodo pero peligroso, porque es un estado invisible. En los scripts del equipo Rutas Norte usamos siempre --profile=rutas-norte explícito.
Cada perfil crea también su contexto de kubectl con el mismo nombre:
Controladores: dónde vive el nodo
El controlador (driver) decide dónde se ejecuta el nodo de minikube. Es la decisión más importante al empezar.
| Controlador | Plataforma | Aislamiento | Velocidad de arranque | Notas |
|---|---|---|---|---|
docker |
Linux, macOS, Windows | Contenedor | Muy rápida (~40 s) | El más usado; el nodo es un contenedor |
podman |
Linux principalmente | Contenedor | Rápida | Alternativa sin demonio; algo menos probado |
kvm2 |
Linux | Máquina virtual | Media (~90 s) | Aislamiento real de kernel; ideal si pruebas cosas de kernel |
hyperkit |
macOS Intel | Máquina virtual | Media | Sustituido en la práctica por docker o qemu en Apple Silicon |
qemu |
macOS Apple Silicon, Linux | Máquina virtual | Lenta | Útil cuando no hay Docker |
virtualbox |
Multiplataforma | Máquina virtual | Lenta | Compatible en todas partes, pero el más lento |
none |
Linux | Ninguno | Instantánea | Instala Kubernetes directamente en tu máquina; no lo uses en un portátil |
Cómo elegir, en tres preguntas:
- ¿Tienes Docker o Podman funcionando? Usa
--driver=docker(opodman). Es lo más rápido y lo que menos memoria consume, porque no hay una VM completa por medio. - ¿Necesitas probar módulos del kernel, un CNI exigente o
iptablesde verdad? Usakvm2en Linux. Un contenedor comparte kernel con el anfitrión y algunas cosas no se pueden aislar. - ¿Estás en Windows sin WSL2 o en un entorno corporativo restringido?
hypervovirtualboxson la salida.
# Elección explícita del controlador
minikube start --profile=rutas-norte --driver=docker
# Fijar el controlador por defecto para todos los perfiles futuros
minikube config set driver dockerCon el controlador docker, el nodo es literalmente un contenedor. Puedes verlo:
CONTAINER ID IMAGE NAMES
a3f19c2b7d41 gcr.io/k8s-minikube/kicbase:v0.0.45 rutas-norte
8b7e2211ff05 gcr.io/k8s-minikube/kicbase:v0.0.45 rutas-norte-m02Ese kicbase es la imagen que contiene systemd, containerd, el kubelet y las herramientas necesarias para que un contenedor se comporte como un nodo.
- Dimensionado, versión de Kubernetes y clústeres multinodo
Dimensionado
Por defecto minikube pide 2 CPU y 2 GB de memoria. Para Rutas Norte eso se queda corto en cuanto instalamos Prometheus (07-03) y cert-manager (04-05):
minikube start \
--profile=rutas-norte \
--driver=docker \
--cpus=4 \
--memory=8192 \
--disk-size=40gExplicación de cada opción:
--cpus=4: número de CPU virtuales asignadas al nodo. Con menos de 4, elkube-apiservery Prometheus compiten y el clúster se siente lento.--memory=8192: memoria en MiB (8 GB). Puedes escribir también8g. Ojo: esta memoria se reserva frente a tu sistema; si tu portátil tiene 16 GB, no le des 12.--disk-size=40g: tamaño del disco del nodo. Las imágenes de contenedor se acumulan rápido; 20 GB se agotan en un par de semanas de trabajo real.
Estos valores se recuerdan por perfil. Si mañana ejecutas minikube start --profile=rutas-norte sin flags, respeta lo que ya configuraste. Para cambiarlos hay que borrar y recrear el perfil (o usar minikube config set antes).
Una advertencia importante: --cpus y --memory no se pueden cambiar en caliente con el controlador de VM. Si te quedas corto, minikube delete --profile=rutas-norte y vuelve a crearlo con los valores nuevos. Por eso conviene tener el script de creación versionado (apartado 11).
Fijar la versión de Kubernetes
Esta es una de las prácticas más rentables y más olvidadas. Si rutas-norte-pro corre Kubernetes 1.30 y tu minikube corre 1.32, puedes escribir manifiestos que funcionan en tu portátil y son rechazados en producción, o al revés: puedes no detectar una API obsoleta.
# Comprobar qué versiones concretas conoce tu minikube
minikube start --help | grep -A2 kubernetes-version
kubectl versionSalida:
Regla del equipo de plataforma de Rutas Norte: el fichero del script de arranque local declara la misma versión menor que producción. Cuando pro sube de versión, el script se actualiza en el mismo cambio.
Clústeres multinodo
Un solo nodo no permite probar nada relacionado con la planificación: afinidades (06-05), topologySpreadConstraints (09-05), DaemonSets con varios objetivos (06-02) o el drenaje de un nodo. minikube sabe crear varios:
minikube start \
--profile=rutas-norte \
--nodes=3 \
--cpus=2 \
--memory=4096 \
--kubernetes-version=v1.30.4NAME STATUS ROLES AGE VERSION
rutas-norte Ready control-plane 3m v1.30.4
rutas-norte-m02 Ready <none> 2m v1.30.4
rutas-norte-m03 Ready <none> 2m v1.30.4Fíjate en que --cpus y --memory se aplican por nodo: tres nodos de 2 CPU y 4 GB consumen 6 CPU y 12 GB del anfitrión. Es fácil ahogar el portátil sin darse cuenta.
Puedes añadir o quitar nodos después:
Y etiquetar los nodos para simular zonas y probar la distribución topológica de 09-05:
kubectl label node rutas-norte-m02 topology.kubernetes.io/zone=zona-a
kubectl label node rutas-norte-m03 topology.kubernetes.io/zone=zona-bEsto es una simulación útil para verificar que el selector funciona, pero recuerda: siguen estando en la misma máquina física, así que no prueba la tolerancia real a la caída de una zona.
- El catálogo de addons
Los addons son componentes preempaquetados que minikube sabe instalar y mantener por ti. Es lo que evita tener que aplicar a mano los manifiestos del controlador de Ingress o del metrics-server.
|-----------------------------|--------------|--------------|
| ADDON NAME | PROFILE | STATUS |
|-----------------------------|--------------|--------------|
| csi-hostpath-driver | rutas-norte | disabled |
| dashboard | rutas-norte | disabled |
| default-storageclass | rutas-norte | enabled ✅ |
| ingress | rutas-norte | enabled ✅ |
| metrics-server | rutas-norte | enabled ✅ |
| registry | rutas-norte | disabled |
| storage-provisioner | rutas-norte | enabled ✅ |
| volumesnapshots | rutas-norte | disabled |
|-----------------------------|--------------|--------------|Los que usa este curso y por qué:
| Addon | Para qué lo usamos | Lección |
|---|---|---|
ingress |
Despliega ingress-nginx para las reglas de www.rutasnorte.example |
04-04 |
metrics-server |
Da datos a kubectl top y al HPA |
07-02, 09-01 |
storage-provisioner |
Aprovisiona PVs dinámicamente para postgres-reservas |
05-05 |
default-storageclass |
Marca standard como StorageClass por defecto |
05-04 |
csi-hostpath-driver + volumesnapshots |
Necesarios para practicar los snapshots CSI | 05-05 |
dashboard |
Interfaz web de exploración | esta lección |
registry |
Registro de imágenes dentro del clúster | esta lección |
# Activar los del curso
minikube addons enable ingress --profile=rutas-norte
minikube addons enable metrics-server --profile=rutas-norte
minikube addons enable csi-hostpath-driver --profile=rutas-norte
minikube addons enable volumesnapshots --profile=rutas-norte
# Desactivar uno que consume recursos y no estás usando
minikube addons disable dashboard --profile=rutas-norteCada addon es, por dentro, un conjunto de manifiestos que minikube aplica en el namespace kube-system (o uno propio). Puedes verlos:
Aviso importante: el addon ingress de minikube instala ingress-nginx con una configuración pensada para un solo nodo. En producción, tu equipo de plataforma probablemente lo instala con Helm y con valores muy distintos (réplicas, PDB, recursos). El comportamiento de las reglas es el mismo; el de la disponibilidad, no.
- Trabajar con imágenes locales sin registro
Este es, en la práctica diaria, el punto donde más tiempo se pierde. Has construido api-reservas:dev-local en tu portátil y el pod se queda en ImagePullBackOff, porque el nodo de minikube tiene su propio almacén de imágenes, separado del Docker de tu máquina.
Hay tres formas de resolverlo.
Opción A: minikube image load (la más simple y recomendable)
# 1. Construyes la imagen en tu máquina, como siempre
docker build -t registry.rutasnorte.example/api-reservas:dev-local ./api-reservas
# 2. La copias al almacén del nodo de minikube
minikube image load registry.rutasnorte.example/api-reservas:dev-local --profile=rutas-norte
# 3. Compruebas que está
minikube image ls --profile=rutas-norte | grep api-reservasEn el manifiesto, la clave es evitar que Kubernetes intente descargarla del registro:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-reservas
namespace: rutas-norte-dev
spec:
replicas: 1
selector:
matchLabels:
app: api-reservas
template:
metadata:
labels:
app: api-reservas
app.kubernetes.io/part-of: rutas-norte
spec:
containers:
- name: api
image: registry.rutasnorte.example/api-reservas:dev-local
# CLAVE: con IfNotPresent, el kubelet usa la imagen local
# y no intenta contactar con el registro.
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080Trampa clásica: si la etiqueta de la imagen es latest, Kubernetes aplica por defecto imagePullPolicy: Always y siempre intentará descargarla, ignorando la copia local. Nunca uses latest (ya lo vimos en 08-05); aquí además te rompe el flujo local.
Si en varios nodos, image load la copia a todos automáticamente.
Opción B: minikube docker-env (construir dentro del nodo)
Esta opción reapunta tu cliente Docker al demonio que corre dentro del nodo de minikube. Lo que construyas queda directamente disponible para el kubelet, sin paso de copia.
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.49.2:2376"
export DOCKER_CERT_PATH="/home/usuario/.minikube/certs"
export MINIKUBE_ACTIVE_DOCKERD="rutas-norte"# Aplicarlo a la sesión actual del terminal
eval $(minikube docker-env --profile=rutas-norte)
# A partir de aquí, docker build construye DENTRO del nodo
docker build -t registry.rutasnorte.example/api-reservas:dev-local ./api-reservas
# Deshacerlo cuando termines
eval $(minikube docker-env --unset --profile=rutas-norte)Ventaja: es más rápido en el bucle editar-construir-probar, porque no hay copia. Desventaja: solo funciona con el runtime docker; si el perfil usa containerd, no aplica. Y es un estado del terminal fácil de olvidar (has construido dentro del nodo y luego no encuentras la imagen en tu máquina).
Opción C: el addon registry
Levanta un registro dentro del clúster. Es la opción más parecida a producción, pero también la que más pasos exige (hay que empujar la imagen, resolver el nombre desde el nodo). Para el trabajo diario, la opción A gana casi siempre.
| Opción | Velocidad del bucle | Complejidad | Cuándo usarla |
|---|---|---|---|
image load |
Media (copia cada vez) | Muy baja | Uso general, multinodo |
docker-env |
Alta | Baja, pero con estado oculto | Iteración intensiva en un solo nodo con runtime docker |
Addon registry |
Baja | Alta | Cuando quieres reproducir el flujo real de registro |
- Acceso al clúster: tunnel, service, dashboard, mount y ssh
minikube tunnel: Services de tipo LoadBalancer
Cuando declaras un Service de tipo LoadBalancer (04-02), Kubernetes le pide a un controlador del proveedor de nube que aprovisione un balanceador. En tu portátil no hay proveedor de nube, así que el Service se queda para siempre en <pending>:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tienda-web LoadBalancer 10.104.12.201 <pending> 80:31820/TCP 2mminikube tunnel simula ese balanceador: crea rutas en tu máquina y asigna una IP externa.
# Ejecutar en un terminal APARTE y dejarlo abierto.
# Pide contraseña de administrador porque crea rutas de red.
minikube tunnel --profile=rutas-norteStatus:
machine: rutas-norte
pid: 48211
route: 10.96.0.0/12 -> 192.168.49.2
minikube: Running
services: [tienda-web]Ahora, en otro terminal:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tienda-web LoadBalancer 10.104.12.201 10.104.12.201 80:31820/TCP 5mPuntos que confunden a todo el mundo la primera vez:
- El proceso debe seguir vivo. Si cierras el terminal, la IP vuelve a
<pending>. - No es un balanceador real: no hay comprobaciones de salud del proveedor, ni distribución entre zonas, ni reglas de cortafuegos de nube. Solo enruta.
- En macOS y Windows con el controlador
docker,tunneltambién es necesario para llegar al Ingress.
minikube service: abrir un Service en el navegador
Para Services de tipo NodePort (o incluso ClusterIP con --url), esta es la vía rápida:
# Abre el navegador apuntando al servicio
minikube service tienda-web -n rutas-norte-dev --profile=rutas-norte
# Solo imprimir la URL, sin abrir navegador (útil en scripts)
minikube service tienda-web -n rutas-norte-dev --url --profile=rutas-norteminikube dashboard: la interfaz web
minikube dashboard --profile=rutas-norte
minikube dashboard --url --profile=rutas-norte # solo la URLActiva el addon dashboard si no lo estaba, levanta un proxy y abre el navegador. Útil para explorar visualmente el clúster mientras aprendes; en el día a día profesional kubectl y k9s son más rápidos.
minikube mount: compartir un directorio del anfitrión
A veces quieres que el pod vea un directorio de tu portátil: un volcado SQL de datos de prueba para postgres-reservas, o los ficheros estáticos de tienda-web.
# Terminal aparte, se queda en primer plano
minikube mount ~/rutas-norte/datos-prueba:/datos-prueba --profile=rutas-norteEn el pod se usa un hostPath (05-01) apuntando a /datos-prueba, que ahora existe dentro del nodo:
Advertencia: hostPath está prohibido por las Pod Security Standards del nivel restricted (08-03). En local es aceptable para datos de prueba; en rutas-norte-pro sería rechazado, y con razón.
minikube ssh: entrar en el nodo
Te deja dentro del nodo. Útil para:
# Ver el espacio en disco del nodo cuando hay problemas de eviction
df -h /var
# Ver las imágenes que tiene el runtime
sudo crictl images
# Ver los pods estáticos del plano de control (volveremos a esto en 10-02)
ls /etc/kubernetes/manifests
# Salir
exitEn un clúster multinodo, elige el nodo:
- El ciclo de vida: stop, start, delete y logs
# Apagar el clúster conservando todo (objetos, imágenes, datos de los PV)
minikube stop --profile=rutas-norte
# Volver a arrancarlo tal y como estaba
minikube start --profile=rutas-norte
# Estado actual
minikube status --profile=rutas-norterutas-norte
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured# Borrar el clúster (irreversible: se pierden objetos, PVs e imágenes)
minikube delete --profile=rutas-norte
# Borrar TODOS los perfiles de golpe (limpieza total)
minikube delete --all --purge--purge borra además el directorio ~/.minikube con la configuración y la caché de imágenes de Kubernetes. Úsalo cuando minikube esté en un estado raro que no consigues explicar; es el equivalente a apagar y encender.
Diagnóstico con logs
Cuando minikube start falla o el clúster arranca a medias:
minikube logs --profile=rutas-norte
# Solo los problemas detectados, mucho más legible
minikube logs --problems --profile=rutas-norte
# Seguir en directo
minikube logs -f --profile=rutas-norte==> Audit <==
==> kubelet <==
Sep 12 09:14:02 rutas-norte kubelet[2311]: E0912 09:14:02.118 Failed to
create pod sandbox: rpc error: code = Unknown desc = failed to set up
sandbox network: plugin type="bridge" failedEse tipo de mensaje casi siempre significa que el nodo se quedó sin recursos o que el estado de red del contenedor quedó corrupto tras un apagón brusco. minikube delete && minikube start lo resuelve, y es exactamente por eso que un clúster local debe ser desechable.
- kind a fondo: nodos como contenedores
kind (Kubernetes IN Docker) tiene un enfoque distinto y una filosofía más estrecha: cada nodo del clúster es un contenedor de Docker que ejecuta containerd y el kubelet. No hay addons, no hay tunnel, no hay dashboard. Solo Kubernetes, muy rápido y muy reproducible.
Precisamente por esa austeridad, es la herramienta que el propio proyecto Kubernetes usa para sus pruebas y la elección habitual en integración continua.
Un clúster mínimo
Creating cluster "rutas-norte" ...
✓ Ensuring node image (kindest/node:v1.30.4) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-rutas-norte"Tarda unos 25 segundos. El contexto se llama kind-rutas-norte (con el prefijo kind-).
Fichero de configuración: varios nodos, puertos y montajes
Aquí está la verdadera potencia de kind: el clúster se declara en un fichero versionable.
# k8s/local/kind-rutas-norte.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: rutas-norte
# Igualamos la red de pods a la de producción para que las
# NetworkPolicies con bloques CIDR se comporten igual.
networking:
podSubnet: "10.244.0.0/16"
serviceSubnet: "10.96.0.0/16"
# Desactivamos el CNI por defecto para instalar Calico y así
# PODER probar de verdad las NetworkPolicies de 04-06.
disableDefaultCNI: false
nodes:
# --- Plano de control ---
- role: control-plane
image: kindest/node:v1.30.4
# Publicamos los puertos 80 y 443 del contenedor en el portátil,
# para que el Ingress sea accesible en http://localhost sin tunnel.
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
# Etiqueta que exige el controlador de ingress-nginx para kind.
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
# --- Nodos de trabajo, etiquetados como zonas distintas ---
- role: worker
image: kindest/node:v1.30.4
labels:
topology.kubernetes.io/zone: zona-a
# Montamos un directorio del portátil dentro del nodo.
extraMounts:
- hostPath: /home/usuario/rutas-norte/datos-prueba
containerPath: /datos-prueba
readOnly: true
- role: worker
image: kindest/node:v1.30.4
labels:
topology.kubernetes.io/zone: zona-bNAME STATUS ROLES AGE VERSION
rutas-norte-control-plane Ready control-plane 47s v1.30.4
rutas-norte-worker Ready <none> 32s v1.30.4
rutas-norte-worker2 Ready <none> 32s v1.30.4Repasemos los campos clave:
extraPortMappings: publica un puerto del contenedor-nodo en tu máquina. Es la solución de kind al problema del acceso externo. ConhostPort: 80, una vez instalado ingress-nginx,curl -H "Host: www.rutasnorte.example" http://localhostllega atienda-web. Solo se puede definir al crear el clúster: si lo olvidas, hay que recrearlo.extraMounts: el equivalente aminikube mount, pero declarativo y sin proceso en primer plano. Mucho más cómodo.kubeadmConfigPatches: kind usa kubeadm por dentro (lo veremos en 10-02). Este campo te deja modificar su configuración; aquí lo usamos para poner la etiquetaingress-ready=trueque el manifiesto de ingress-nginx para kind espera en sunodeSelector.image: fija la versión de Kubernetes. Igual que con minikube, iguálala a producción.labels: etiquetas de nodo aplicadas desde el principio, sinkubectl labelposterior.
Instalar el Ingress en kind
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=120sAhora sí:
Cargar imágenes locales
docker build -t registry.rutasnorte.example/api-reservas:dev-local ./api-reservas
kind load docker-image registry.rutasnorte.example/api-reservas:dev-local --name rutas-norteIgual que en minikube, la imagen se copia a todos los nodos. Y también aquí hace falta imagePullPolicy: IfNotPresent y evitar la etiqueta latest.
También puedes cargar un fichero de imagen exportado, práctico en canalizaciones donde la construcción y la carga están en pasos distintos:
docker save registry.rutasnorte.example/api-reservas:dev-local -o api.tar
kind load image-archive api.tar --name rutas-nortePor qué kind manda en integración continua
| Motivo | Explicación |
|---|---|
| Velocidad | 25-40 s frente a 60-120 s de minikube; en una canalización que corre 40 veces al día, eso son horas |
| Sin virtualización anidada | Al ser contenedores, funciona en corredores de CI que no permiten KVM |
| Configuración en un fichero | El clúster es reproducible bit a bit desde el repositorio |
| Multinodo barato | Añadir un nodo es añadir un contenedor |
| Limpieza total | kind delete cluster no deja rastro |
| Sin estado oculto | No hay perfiles persistentes ni configuración recordada entre ejecuciones |
Un paso típico en la canalización ci-rutasnorte se reduce a: kind create cluster --config kind-ci.yaml --wait 120s, construir y cargar la imagen, kubectl apply -k k8s/entornos/dev (eso es Kustomize, lo veremos en 10-04), esperar el rollout, ejecutar las pruebas de humo y kind delete cluster al final pase lo que pase.
- Tabla comparativa: minikube, kind, k3d, Docker Desktop y Rancher Desktop
| Criterio | minikube | kind | k3d | Docker Desktop | Rancher Desktop |
|---|---|---|---|---|---|
| Qué es | Clúster local con addons | Nodos como contenedores | k3s en contenedores | Kubernetes integrado en la app | App de escritorio con k3s |
| Arranque (1 nodo) | 60-120 s | 25-40 s | 15-25 s | ~90 s (al activarlo) | ~60 s |
| Multinodo | Sí (--nodes) |
Sí (fichero) | Sí (--agents) |
No | No |
| Consumo en reposo | Medio-alto | Medio | Bajo | Alto | Medio |
| Addons integrados | Muchos (ingress, metrics, CSI, registro) | Ninguno | Traefik y servidor local incluidos | Ninguno | Traefik incluido |
| Configuración en fichero | Parcial (flags + config set) |
Completa y versionable | Completa y versionable | No | Parcial |
| Idoneidad para CI | Regular (lento, requiere driver) | Excelente | Excelente | Nula | Baja |
| Fidelidad con Kubernetes estándar | Alta | Muy alta (kubeadm real) | Media (k3s recorta componentes) | Alta | Media (k3s) |
| Registro local integrado | Addon registry |
No (se monta aparte) | Sí (k3d registry) |
Comparte el de Docker | Comparte el suyo |
| Licencia comercial | Libre | Libre | Libre | De pago en empresas grandes | Libre |
| Mejor para | Aprender y trabajo diario con extras | CI y pruebas reproducibles | Bucles ultrarrápidos, equipos pequeños | Quien ya lo tiene y no quiere más herramientas | Sustituto libre de Docker Desktop |
Notas para elegir:
- k3s (el motor de k3d y Rancher Desktop) es una distribución ligera y conforme, pero sustituye algunas piezas: usa Traefik como Ingress, SQLite en vez de etcd por defecto y desactiva componentes de nube. Es perfecto para desarrollar; es engañoso si quieres comprobar un comportamiento fino del plano de control.
- Docker Desktop con Kubernetes activado es lo más cómodo si ya lo tienes, pero es un solo nodo, no configurable, y su licencia es de pago para empresas por encima de cierto tamaño. Rutas Norte S.L. es pequeña, así que no le afecta, pero es un factor real en decisiones de equipo.
- La recomendación de este curso: minikube para el trabajo diario (por los addons, que ahorran mucha instalación manual) y kind en la canalización
ci-rutasnorte(por velocidad y reproducibilidad). Que sean dos herramientas distintas no es un problema si el manifiesto que despliegas es el mismo.
- Las diferencias con producción que provocan «en mi máquina funciona»
Este apartado es el más importante de la lección. Cada punto es un incidente real esperando a ocurrir.
10.1 No hay balanceador de nube
En local, type: LoadBalancer no hace nada sin minikube tunnel. En rutas-norte-pro, ese mismo Service aprovisiona un balanceador de verdad, con su IP pública, su coste mensual y su tiempo de aprovisionamiento de varios minutos.
Consecuencias que solo ves en la nube: anotaciones específicas del proveedor (tipo de balanceador, certificados, listas de acceso), comprobaciones de salud propias, y el hecho de que borrar el Service borra el balanceador. Lo veremos en 10-06.
Mitigación: en local, usa Ingress (04-04) y no LoadBalancer en los manifiestos de la aplicación. Deja el LoadBalancer solo para el controlador de Ingress, que en local se publica por NodePort o extraPortMappings.
10.2 La clase de almacenamiento es otra
En minikube, la StorageClass standard es un directorio del nodo servido por storage-provisioner. En rutas-norte-pro, postgres-reservas usa una StorageClass de disco de red con IOPS provisionadas (05-04).
| Diferencia | Local | Producción |
|---|---|---|
| Modo de acceso | ReadWriteOnce, pero con un nodo todo "funciona" |
ReadWriteOnce de verdad: dos pods en nodos distintos fallan |
| Rendimiento | El SSD de tu portátil | Disco de red, con latencia y límites |
| Expansión y snapshots | Puede no estar soportada | Sí, nativos del proveedor |
| Vinculación | Inmediata | Frecuentemente WaitForFirstConsumer |
Ese último punto es traicionero: en producción el PV no se crea hasta que el pod se planifica, y eso cambia el orden de los eventos. Un StatefulSet que arranca bien en local puede quedarse en Pending en la nube por una afinidad de zona incompatible.
10.3 El CNI por defecto puede ignorar las NetworkPolicies
Este es el más peligroso porque falla en silencio. Escribes una NetworkPolicy que aísla postgres-reservas para que solo api-reservas pueda hablar con él (04-06), la aplicas en tu minikube, el objeto se crea sin error... y no hace absolutamente nada, porque el CNI por defecto no la implementa.
Parece que funciona. Pero:
# Desde un pod que NO debería poder conectar
kubectl run curiosa --rm -it --image=busybox:1.36 -n rutas-norte-dev -- \
nc -zv postgres-reservas 5432Conecta. La política se ignoró.
Cómo detectarlo: kubectl get pods -n kube-system -o wide | grep -Ei 'calico|cilium|flannel|kindnet'. kindnet (el de kind por defecto) y el bridge básico no implementan NetworkPolicies; calico y cilium sí.
Mitigación: en minikube, --cni=calico. En kind, disableDefaultCNI: true con podSubnet: "192.168.0.0/16" y aplicar después el manifiesto de Calico.
Y la regla de oro: una NetworkPolicy no está probada hasta que has verificado que algo que antes conectaba, ahora no conecta. Probar solo que lo permitido sigue funcionando no demuestra nada.
10.4 No hay varias zonas ni escalado de nodos
topologySpreadConstraints (09-05) con topologyKey: topology.kubernetes.io/zone en un clúster de un nodo se satisface trivialmente. Etiquetar los nodos de un clúster multinodo simula zonas y verifica que el selector y las etiquetas son correctos, pero no prueba la tolerancia a fallos.
Igual con el Cluster Autoscaler (09-03): en local no hay grupo de nodos elástico, así que un pod Pending por falta de recursos se queda Pending para siempre. En producción aparecería un nodo nuevo en dos minutos. El síntoma en local es idéntico a un fallo grave en producción, lo que despista.
10.5 Resumen de mitigaciones
| Riesgo | Mitigación en local | Prueba definitiva |
|---|---|---|
| Balanceador ausente | Usa Ingress; minikube tunnel si hace falta |
rutas-norte-pre |
| StorageClass distinta | Nombra la clase en el manifiesto, no confíes en la de por defecto | rutas-norte-pre |
| NetworkPolicies ignoradas | Instala Calico o Cilium en local | rutas-norte-pre con prueba negativa |
| Topología y zonas | Etiqueta nodos para validar selectores | rutas-norte-pro |
| Escalado de nodos | No simulable | rutas-norte-pre |
| Recursos y límites | Ajusta límites bajos a propósito para ver qué se estrangula | Pruebas de carga con k6 (09-06) |
- Receta reproducible: el entorno completo de Rutas Norte en local
Lo peor de un entorno local es que cada persona del equipo lo tenga distinto. La solución es un script versionado en el repositorio, junto a los manifiestos.
#!/usr/bin/env bash
# k8s/local/levantar-local.sh
# Levanta el entorno local completo de Rutas Norte sobre minikube.
# Uso: ./levantar-local.sh (crea y configura)
# ./levantar-local.sh borrar (destruye el perfil)
set -euo pipefail
PERFIL="rutas-norte"
# Debe coincidir con la versión menor de rutas-norte-pro.
VERSION_K8S="v1.30.4"
NODOS=3
CPUS=2
MEMORIA=4096
DISCO="30g"
if [[ "${1:-}" == "borrar" ]]; then
echo "==> Borrando el perfil ${PERFIL}"
minikube delete --profile="${PERFIL}"
exit 0
fi
echo "==> 1/6 Creando el clúster ${PERFIL} (Kubernetes ${VERSION_K8S})"
minikube start \
--profile="${PERFIL}" \
--driver=docker \
--kubernetes-version="${VERSION_K8S}" \
--nodes="${NODOS}" \
--cpus="${CPUS}" \
--memory="${MEMORIA}" \
--disk-size="${DISCO}" \
--cni=calico # imprescindible para que las NetworkPolicies se apliquen
echo "==> 2/6 Activando addons"
for addon in ingress metrics-server csi-hostpath-driver volumesnapshots; do
minikube addons enable "${addon}" --profile="${PERFIL}"
done
echo "==> 3/6 Etiquetando nodos como zonas simuladas"
kubectl label node "${PERFIL}-m02" topology.kubernetes.io/zone=zona-a --overwrite
kubectl label node "${PERFIL}-m03" topology.kubernetes.io/zone=zona-b --overwrite
echo "==> 4/6 Creando el namespace de desarrollo"
kubectl create namespace rutas-norte-dev --dry-run=client -o yaml | kubectl apply -f -
kubectl label namespace rutas-norte-dev \
app.kubernetes.io/part-of=rutas-norte entorno=dev --overwrite
echo "==> 5/6 Construyendo y cargando las imágenes locales"
for comp in tienda-web api-reservas worker-notificaciones; do
docker build -t "registry.rutasnorte.example/${comp}:dev-local" "./${comp}"
minikube image load "registry.rutasnorte.example/${comp}:dev-local" --profile="${PERFIL}"
done
echo "==> 6/6 Esperando a que el controlador de Ingress esté listo"
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=180s
echo
echo "Clúster listo. Para llegar al Ingress:"
echo " echo \"\$(minikube ip --profile=${PERFIL}) www.rutasnorte.example api.rutasnorte.example\" | sudo tee -a /etc/hosts"
echo "Despliega la aplicación con: kubectl apply -k k8s/entornos/dev"Explicación de las decisiones del script:
set -euo pipefail: aborta a la primera orden que falle, en vez de seguir dejando un clúster a medias.- Versión de Kubernetes en una variable arriba: cuando
prosube de versión, se cambia una línea. --cni=calico: la diferencia entre probar de verdad las NetworkPolicies y engañarse.--dry-run=client -o yaml | kubectl apply -f -: el patrón idempotente de 01-06; crea el namespace si no existe y no falla si ya existe.kubectl wait: el script no termina hasta que el clúster es realmente usable. Sin esto, quien lo ejecuta prueba a desplegar y falla porque el Ingress aún no está.- El aviso final sobre
/etc/hosts: los dominioswww.rutasnorte.exampleyapi.rutasnorte.exampleno existen en ningún DNS; hay que resolverlos a mano contra la IP del nodo.
El equivalente con kind es aún más corto, porque toda la configuración del clúster ya está en kind-rutas-norte.yaml: basta kind create cluster --config ... --wait 180s, aplicar Calico e ingress-nginx, esperar al controlador y cargar las imágenes con kind load docker-image. Y no hace falta tocar /etc/hosts: gracias a extraPortMappings, el Ingress responde en http://localhost con la cabecera Host adecuada.
Errores Comunes y Consejos
1. Dar a minikube casi toda la memoria del portátil. Con 16 GB físicos, --memory=12288 deja al sistema operativo sin margen y todo va a tirones. Regla: no más de la mitad de la RAM física, y recuerda que en multinodo el valor se multiplica por el número de nodos.
2. Olvidar que --cpus y --memory se quedan grabados en el perfil. Ejecutas minikube start --profile=rutas-norte --memory=8192 un día, y al día siguiente minikube start --profile=rutas-norte sin flags: sigue usando 8192. Si crees que cambiaste el valor y no cambió nada, es esto. Para cambiarlo hay que recrear el perfil.
3. ImagePullBackOff con una imagen que "sí has construido". Casi siempre son dos causas: no hiciste minikube image load / kind load docker-image, o la etiqueta es latest y el imagePullPolicy implícito es Always. Usa etiquetas explícitas (dev-local) e imagePullPolicy: IfNotPresent.
4. Creer que una NetworkPolicy aplicada está funcionando. Comprueba siempre el CNI y haz la prueba negativa: intenta la conexión que debe estar bloqueada y verifica que da timeout. Sin esa prueba, no has probado nada.
5. Cerrar el terminal de minikube tunnel o minikube mount. Ambos son procesos en primer plano. Si desaparece la IP externa o el directorio montado, mira si el proceso sigue vivo antes de buscar causas exóticas.
6. Descubrir tarde que faltaba un extraPortMapping en kind. No se pueden añadir a un clúster ya creado. Ten el fichero de configuración con los puertos 80, 443 y quizá alguno más desde el principio.
7. Usar latest de la imagen del nodo. Tanto kindest/node como la versión de minikube deben estar fijadas. Un compañero con v1.31 y tú con v1.29 producís resultados distintos sobre los mismos manifiestos.
8. Acumular perfiles olvidados. Cada perfil detenido sigue ocupando disco. minikube profile list de vez en cuando y minikube delete --profile=X de lo que no uses.
9. Tratar el clúster local como si fuera valioso. Si dudas si algo está en un estado raro, bórralo y recréalo. El script del apartado 11 hace que eso cueste tres minutos; investigar un estado corrupto cuesta una tarde.
10. Probar el rendimiento en local. Un benchmark de postgres-reservas en tu SSD no dice nada del disco de red de producción. Para eso están rutas-norte-pre y k6 (09-06).
Ejercicios
Ejercicio 1: clúster multinodo con zonas simuladas
Crea un perfil de minikube llamado rutas-norte-topologia con 3 nodos, Kubernetes v1.30.4 y Calico como CNI. Etiqueta los dos nodos de trabajo como zona-a y zona-b. Despliega api-reservas con 4 réplicas y un topologySpreadConstraint que reparta entre zonas con maxSkew: 1, y comprueba con kubectl get pods -o wide que el reparto es 2 y 2.
Ejercicio 2: demostrar que el CNI importa
Crea dos clústeres de kind: uno con el CNI por defecto (kindnet) y otro con disableDefaultCNI: true y Calico instalado. En ambos, aplica una NetworkPolicy de denegación total de entrada en el namespace rutas-norte-dev y comprueba, con un pod busybox intentando conectar a un Service, cuál de los dos la respeta de verdad.
Ejercicio 3: bucle de desarrollo con imagen local
Con el perfil rutas-norte en marcha, construye una imagen registry.rutasnorte.example/tienda-web:dev-local, cárgala en minikube y despliégala con un Ingress para www.rutasnorte.example. Después, cambia el contenido de la página, reconstruye con la misma etiqueta, recarga la imagen y consigue que el pod sirva el contenido nuevo. Explica por qué un simple kubectl apply no basta.
Soluciones
Solución 1
minikube start --profile=rutas-norte-topologia \
--driver=docker --kubernetes-version=v1.30.4 \
--nodes=3 --cpus=2 --memory=3072 --cni=calico
kubectl label node rutas-norte-topologia-m02 topology.kubernetes.io/zone=zona-a
kubectl label node rutas-norte-topologia-m03 topology.kubernetes.io/zone=zona-b
kubectl create namespace rutas-norte-dev# api-reservas-topologia.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-reservas
namespace: rutas-norte-dev
spec:
replicas: 4
selector:
matchLabels: { app: api-reservas }
template:
metadata:
labels:
app: api-reservas
app.kubernetes.io/part-of: rutas-norte
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels: { app: api-reservas }
containers:
- name: api
image: nginx:1.27-alpine
resources:
requests: { cpu: 50m, memory: 64Mi }Deben salir 2 pods en -m02 y 2 en -m03. El nodo del plano de control no recibe pods porque tiene el taint correspondiente (06-05).
Solución 2
# kind-sin-netpol.yaml -> nodes: [{role: control-plane}], sin networking
# kind-con-netpol.yaml:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: con-netpol
networking:
disableDefaultCNI: true
podSubnet: "192.168.0.0/16"
nodes: [{role: control-plane}]
---
# denegar-todo.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: denegar-entrada, namespace: rutas-norte-dev }
spec:
podSelector: {}
policyTypes: [Ingress]for c in sin-netpol con-netpol; do
kind create cluster --config kind-${c}.yaml
[ "$c" = "con-netpol" ] && kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.1/manifests/calico.yaml && sleep 60
kubectl create ns rutas-norte-dev
kubectl -n rutas-norte-dev create deploy web --image=nginx:1.27-alpine
kubectl -n rutas-norte-dev expose deploy web --port=80
kubectl apply -f denegar-todo.yaml
echo "--- $c ---"
kubectl -n rutas-norte-dev run p --rm -i --restart=Never --image=busybox:1.36 -- \
timeout 5 wget -qO- http://web || echo "BLOQUEADO (correcto)"
doneEn sin-netpol devuelve el HTML de nginx: la política se ignoró. En con-netpol da timeout: Calico la aplica.
Solución 3
docker build -t registry.rutasnorte.example/tienda-web:dev-local ./tienda-web
minikube image load registry.rutasnorte.example/tienda-web:dev-local --profile=rutas-norte
kubectl apply -f k8s/base/tienda-web.yaml # con imagePullPolicy: IfNotPresent
# --- tras editar el contenido ---
docker build -t registry.rutasnorte.example/tienda-web:dev-local ./tienda-web
minikube image load registry.rutasnorte.example/tienda-web:dev-local --profile=rutas-norte
kubectl rollout restart deploy/tienda-web -n rutas-norte-devPor qué kubectl apply no basta: el manifiesto no ha cambiado (misma etiqueta de imagen), así que el objeto en la API es idéntico y el Deployment no genera un nuevo ReplicaSet. rollout restart añade una anotación con la marca de tiempo a la plantilla del pod, lo que sí provoca el despliegue. Esta es exactamente la razón por la que en producción se usan etiquetas inmutables con digest (08-05): la imagen nueva tiene un identificador nuevo y el cambio se propaga solo.
Conclusión
Ya sabes montar y destruir clústeres locales con criterio. Los puntos que conviene llevarse:
- minikube brilla por sus addons:
ingress,metrics-server,storage-provisionerycsi-hostpath-driverte ahorran instalar a mano media plataforma. Los perfiles permiten tener varios clústeres a la vez,--kubernetes-versioniguala tu entorno a producción, y--nodesabre la puerta a probar planificación y topología. - kind gana en velocidad y reproducibilidad: los nodos son contenedores, todo el clúster se declara en un fichero versionado con
extraPortMappingsyextraMounts, y por eso es la elección natural de la canalizaciónci-rutasnorte. - El bucle de trabajo con imágenes locales se resuelve con
minikube image loadokind load docker-image, siempre conimagePullPolicy: IfNotPresenty etiquetas que no seanlatest. - Y lo más importante: un clúster local valida corrección, no realismo. No hay balanceador de nube, la StorageClass es otra, el CNI por defecto puede ignorar tus NetworkPolicies en silencio, y no hay zonas ni escalado de nodos. Saber exactamente qué no estás probando es lo que evita el «en mi máquina funciona».
Nos queda una pregunta pendiente: los clústeres locales son juguetes controlados, pero ¿cómo se monta un clúster de verdad, en máquinas propias, sin que lo haga un proveedor de nube por ti? En la siguiente lección, Kubeadm, veremos la herramienta oficial para arrancar un clúster conforme: preparar las máquinas, instalar containerd, ejecutar kubeadm init con un fichero de configuración, unir nodos, montar un plano de control en alta disponibilidad, renovar certificados y actualizar de versión. Y descubriremos por qué kind, por dentro, no es más que kubeadm dentro de un contenedor.
Curso de Kubernetes
Módulo 1: Introducción a Kubernetes
- ¿Qué es Kubernetes?
- Arquitectura de Kubernetes
- Conceptos y Terminología Clave
- Configuración de un Clúster de Kubernetes
- La CLI de Kubernetes: kubectl
- Objetos, Manifiestos YAML y el Modelo Declarativo
- El Proyecto del Curso: la Plataforma Rutas Norte
Módulo 2: Componentes Principales de Kubernetes
- Pods
- ReplicaSets
- Deployments
- Actualizaciones, Rollbacks y Estrategias de Despliegue
- Servicios
- Namespaces
- Etiquetas, Selectores y Anotaciones
Módulo 3: Gestión de Configuración y Secretos
- ConfigMaps
- Secrets
- Variables de Entorno
- Cuotas y Límites de Recursos
- LimitRanges y Clases de Calidad de Servicio (QoS)
- ServiceAccounts y Acceso a la API desde los Pods
Módulo 4: Redes en Kubernetes
- Redes de Clúster
- Tipos de Servicios
- DNS Interno y Descubrimiento de Servicios
- Controladores de Ingress
- TLS y Gestión de Certificados con cert-manager
- Políticas de Red
Módulo 5: Almacenamiento en Kubernetes
- Volúmenes
- Volúmenes Persistentes
- Reclamaciones de Volúmenes Persistentes
- Clases de Almacenamiento
- Aprovisionamiento Dinámico, Expansión y Snapshots
- Copias de Seguridad y Restauración de Datos
Módulo 6: Conceptos Avanzados de Kubernetes
- StatefulSets
- DaemonSets
- Trabajos y CronJobs
- Init Containers, Sidecars y Patrones Multi-Contenedor
- Planificación: Afinidad, Taints y Tolerations
- Definiciones de Recursos Personalizados (CRDs)
- Operadores y el Patrón Controlador
Módulo 7: Monitoreo y Registro
- Verificaciones de Salud y Sondas
- Servidor de Métricas y kubectl top
- Monitoreo con Prometheus
- Visualización y Alertas con Grafana y Alertmanager
- Registro Centralizado con Elasticsearch, Fluentd y Kibana (EFK)
- Depuración de Aplicaciones y Eventos del Clúster
Módulo 8: Seguridad en Kubernetes
- Control de Acceso Basado en Roles (RBAC)
- Contextos de Seguridad y Endurecimiento del Contenedor
- Políticas de Seguridad de Pods y Pod Security Standards
- Seguridad de Red
- Seguridad de Imágenes
- Auditoría, Escaneo y Gestión de Vulnerabilidades
Módulo 9: Escalado y Rendimiento
- Autoescalado Horizontal de Pods
- Autoescalado Vertical de Pods
- Autoescalado de Clúster
- Escalado por Eventos y Métricas Personalizadas con KEDA
- Alta Disponibilidad: PodDisruptionBudgets y Topología
- Ajuste de Rendimiento
Módulo 10: Ecosistema y Herramientas de Kubernetes
- Minikube y Entornos Locales con kind
- Kubeadm
- Helm
- Kustomize
- GitOps con Argo CD y Flux
- Kubernetes Gestionado: EKS, AKS y GKE
Módulo 11: Estudios de Caso y Aplicaciones del Mundo Real
- Despliegue de una Aplicación Web
- Ejecución de Aplicaciones con Estado
- CI/CD con Kubernetes
- Estrategias de Despliegue: Blue-Green y Canary
- Gestión Multi-Clúster
- Operación en Producción: Incidencias, Runbooks y Costes
