Hasta ahora, en todo el curso, ha habido un clúster. Los namespaces rutas-norte-dev, rutas-norte-pre y rutas-norte-pro convivían en él, separados por cuotas, políticas de red y RBAC. Es una arquitectura perfectamente defendible y es donde empieza casi todo el mundo.
Pero llega un momento en que deja de serlo. Puede ser una actualización del plano de control que afecta a los tres entornos a la vez; puede ser el auditor preguntando por qué el clúster que ejecuta rutas-norte-dev tiene acceso a la red donde viven los datos personales de producción; puede ser que la empresa abra operaciones en otra región y la latencia desde Portugal a eu-west-1 empiece a notarse en la conversión. En Rutas Norte fue lo primero: una actualización de EKS que salió mal en pre dejó también pro inaccesible durante diecinueve minutos.
Esta lección trata de qué cambia cuando la plataforma deja de caber en un clúster: por qué se llega ahí, qué topologías existen, cómo se trabaja a diario sin aplicar en el clúster equivocado, cómo Argo CD gobierna una flota, cómo se conectan clústeres entre sí, y el problema que no tiene solución fácil cuando hay que recuperarse de un desastre, que es el dato.
Advertencia de cumplimiento normativo. La distribución de clústeres entre regiones afecta directamente a la residencia de los datos personales de los clientes de Rutas Norte. Replicar
postgres-reservasa otra región, almacenar copias de seguridad fuera de la región principal, o permitir que un clúster de una región consulte datos alojados en otra, son decisiones con implicaciones legales que deben ser revisadas y aprobadas por el responsable de cumplimiento normativo antes de implantarse. Los ejemplos de esta lección son ilustrativos.
Contenido
- Por qué una empresa acaba con varios clústeres
- Topologías habituales y cuál elegir
- El trabajo diario con varios contextos
- Despliegue multi-clúster con Argo CD
- Configuración y políticas comunes: el clúster como producto
- Conectividad entre clústeres
- Recuperación ante desastres
- El plan de Rutas Norte
- El coste, la complejidad y cuándo no hacerlo
- Por qué una empresa acaba con varios clústeres
No es una decisión que se tome una mañana. Se llega por acumulación de razones, y conviene reconocerlas para saber cuál te está empujando.
1.1. Aislamiento entre producción y el resto
Los namespaces separan cargas, pero no separan el plano de control. Comparten servidor de API, etcd, planificador, CNI, controlador de Ingress y complementos. Todo lo que sea "de clúster" es compartido: CRDs, ClusterRole, webhooks de admisión, versiones de operadores.
En la práctica, esto significa que un desarrollador que despliega un CRD mal formado en dev, o un operador que consume memoria sin control, puede degradar producción. En Rutas Norte fue un webhook de validación mal configurado en dev el que, al no responder, bloqueó la creación de pods en todo el clúster durante ocho minutos, producción incluida.
1.2. Radio de impacto
Con un clúster, la pregunta "¿qué pasa si el clúster falla?" tiene una respuesta única y muy mala: todo cae. El plano de control gestionado de EKS es muy fiable, pero no es el único punto de fallo: un NetworkPolicy demasiado amplia, un agotamiento de IPs de la VPC, una versión de CNI defectuosa o un error humano con kubectl delete afectan a todo lo que hay dentro.
1.3. Regiones y latencia
Rutas Norte opera principalmente en el norte peninsular, pero está estudiando expandirse al sur de Francia. Una petición desde Toulouse a eu-west-1 (Irlanda) suma unos 35-45 ms de ida y vuelta solo por la red. Sobre una compra de billete con seis llamadas encadenadas, eso son casi 300 ms de latencia añadida que el usuario percibe.
1.4. Requisitos normativos de residencia del dato
Este es el motivo que no admite discusión técnica: si la normativa aplicable, un contrato con un cliente corporativo o una decisión del responsable de cumplimiento exige que los datos personales de determinados clientes no salgan de un territorio, hace falta infraestructura en ese territorio. No hay configuración de namespace que resuelva eso.
1.5. Versiones distintas
Kubernetes publica una versión menor cada cuatro meses aproximadamente, y el soporte de cada una dura alrededor de catorce. Actualizar es obligatorio, y probar la actualización en el mismo clúster que produce es imposible por definición. Con varios clústeres se puede llevar dev a la versión nueva, dejar que rompa lo que tenga que romper, y actualizar producción semanas después con la lección aprendida.
1.6. El clúster también se actualiza
Relacionado, pero distinto: hasta las actualizaciones que salen bien tienen ventanas de riesgo. Los nodos se reemplazan, los complementos se reinician, el CNI se actualiza. Con un solo clúster, cada actualización es un evento de producción. Con dos, es un evento de producción una vez cada dos actualizaciones, porque la primera se ha ensayado.
1.7. Y lo que cuesta
| Coste | Detalle |
|---|---|
| Plano de control | En EKS, unos 73 €/mes por clúster; multiplicado por la flota |
| Complementos duplicados | Prometheus, Grafana, ingress-nginx, cert-manager, Kyverno, Argo CD en cada clúster |
| Capacidad ociosa | Cada clúster necesita margen propio; no se comparte |
| Complejidad operativa | Cada procedimiento se ejecuta N veces, o hay que automatizarlo para N |
| Deriva entre clústeres | El riesgo real: dos clústeres que deberían ser iguales dejan de serlo |
| Carga cognitiva | "¿En qué clúster estoy?" es una pregunta con consecuencias |
La deriva merece énfasis: el problema de tener varios clústeres no es tenerlos, es mantenerlos iguales. Un parche aplicado a mano en uno y no en otro genera una diferencia que nadie recuerda hasta que causa un incidente meses después. Todo lo del apartado 5 existe para combatir eso.
- Topologías habituales y cuál elegir
| Topología | Descripción | Ventajas | Inconvenientes | Cuándo |
|---|---|---|---|---|
| Por entorno | Un clúster para dev+pre, otro para pro |
Aísla el plano de control de producción; permite ensayar actualizaciones | Duplica complementos; no resuelve regiones | Casi siempre el primer paso. Es lo más rentable |
| Por región | Un clúster por región geográfica | Latencia baja; residencia del dato; tolerancia a fallo regional | Replicación de datos entre regiones (el problema difícil) | Presencia en varias geografías o requisito normativo |
| Por unidad de negocio | Un clúster por equipo o producto | Autonomía total; costes claramente atribuidos | Proliferación; complementos multiplicados; mucha deriva | Organizaciones grandes con equipos de plataforma por unidad |
| Por criticidad | Uno para lo crítico, otro para lo demás | Protege lo importante sin duplicar todo | Frontera difusa: ¿dónde va lo intermedio? | Cuando hay una diferencia clara entre lo crítico y lo accesorio |
| Clúster de gestión | Uno que solo aloja las herramientas (Argo CD, observabilidad central) y gobierna los demás | Punto único de despliegue y visibilidad; no compite con las cargas | Punto único de fallo del gobierno; sobredimensionado para flotas pequeñas | A partir de tres o cuatro clústeres |
2.1. Recomendación
Empieza por uno. Un solo clúster con namespaces bien separados, cuotas, políticas de red y RBAC resuelve el 80 % de los casos y cuesta una fracción.
El primer desdoblamiento debe ser producción frente al resto. Es el que aporta más por unidad de complejidad: aísla el plano de control de lo crítico, permite ensayar actualizaciones y satisface a cualquier auditoría razonable.
El segundo, si llega, viene impuesto por la geografía o la normativa, no por preferencias de arquitectura.
El clúster de gestión, a partir del tercero. Con dos clústeres, Argo CD puede vivir en el de producción gestionando ambos. Con cuatro, hace falta un sitio neutral.
graph TB
subgraph fase1["Fase 1 · hoy"]
C1[Clúster único<br/>ns dev / pre / pro]
end
subgraph fase2["Fase 2 · Rutas Norte ahora"]
C2A[rutasnorte-pro<br/>eu-west-1]
C2B[rutasnorte-nopro<br/>dev + pre · eu-west-1]
ACD2[Argo CD en pro] -.gestiona.-> C2A
ACD2 -.gestiona.-> C2B
end
subgraph fase3["Fase 3 · si llega la expansión"]
MGT[Clúster de gestión<br/>Argo CD + observabilidad]
C3A[pro eu-west-1]
C3B[pro eu-west-3]
C3C[nopro]
MGT --> C3A
MGT --> C3B
MGT --> C3C
end
fase1 --> fase2 --> fase3
- El trabajo diario con varios contextos
Aquí es donde se producen los accidentes. Un kubectl delete deploy ejecutado creyendo estar en dev cuando se está en pro es un incidente real y frecuente.
3.1. El kubeconfig con varios clústeres
# ~/.kube/config (fragmento)
apiVersion: v1
kind: Config
current-context: rutasnorte-nopro
clusters:
- name: rutasnorte-pro
cluster:
server: https://ABC123.gr7.eu-west-1.eks.amazonaws.com
certificate-authority-data: LS0tLS1CRUdJTiBDRVJU...
- name: rutasnorte-nopro
cluster:
server: https://DEF456.gr7.eu-west-1.eks.amazonaws.com
certificate-authority-data: LS0tLS1CRUdJTiBDRVJU...
users:
- name: joan-pro
exec:
apiVersion: client.authentication.k8s.io/v1
command: aws
args: [eks, get-token, --cluster-name, rutasnorte-pro, --role-arn,
"arn:aws:iam::111122223333:role/rutasnorte-pro-lectura"]
- name: joan-nopro
exec:
apiVersion: client.authentication.k8s.io/v1
command: aws
args: [eks, get-token, --cluster-name, rutasnorte-nopro]
contexts:
# El nombre del contexto es la primera línea de defensa: que dé miedo.
- name: PRODUCCION-rutasnorte
context: { cluster: rutasnorte-pro, user: joan-pro, namespace: rutas-norte-pro }
- name: rutasnorte-nopro
context: { cluster: rutasnorte-nopro, user: joan-nopro, namespace: rutas-norte-dev }kubectl config get-contexts
kubectl config use-context rutasnorte-nopro
kubectl config current-contextCURRENT NAME CLUSTER NAMESPACE
PRODUCCION-rutasnorte rutasnorte-pro rutas-norte-pro
* rutasnorte-nopro rutasnorte-nopro rutas-norte-dev3.2. kubectx y kubens
kubectx # lista contextos
kubectx rutasnorte-nopro # cambia de contexto
kubectx - # vuelve al anterior
kubens rutas-norte-pre # cambia de namespace sin tocar el contextoSon dos utilidades pequeñas que ahorran mucho tiempo. Instalarlas es lo primero que hace cualquiera que trabaje con más de un clúster.
3.3. Las medidas para no equivocarse de clúster
Cinco capas, de la más blanda a la más dura. Las tres primeras son avisos; las dos últimas son barreras reales.
Capa 1: el prompt muestra el contexto. Es imprescindible. Sin esto, todo lo demás es opcional.
# ~/.bashrc — contexto y namespace en el prompt, en rojo si es producción
contexto_k8s() {
local ctx ns
ctx=$(kubectl config current-context 2>/dev/null) || return
ns=$(kubectl config view --minify -o jsonpath='{..namespace}' 2>/dev/null)
if [[ "$ctx" == *PRODUCCION* ]]; then
printf '\001\e[41;97m\002 ⚠ %s:%s \001\e[0m\002' "$ctx" "${ns:-default}"
else
printf '\001\e[36m\002(%s:%s)\001\e[0m\002' "$ctx" "${ns:-default}"
fi
}
PS1='$(contexto_k8s) \w \$ 'Fondo rojo cuando estás en producción. Parece trivial y es la medida que más accidentes evita.
Capa 2: contexto por sesión, no global. El problema de use-context es que cambia el estado de todas las terminales abiertas. Una solución mejor es aislar el kubeconfig por terminal:
# Alias que abre una sesión con su propio kubeconfig
alias k-pro='export KUBECONFIG=~/.kube/pro.yaml && echo "⚠ SESIÓN DE PRODUCCIÓN"'
alias k-dev='export KUBECONFIG=~/.kube/nopro.yaml'Así, la terminal de producción es la de producción y punto: no hay forma de que un use-context de otra ventana la cambie.
Capa 3: confirmación explícita para verbos destructivos.
# Envoltorio de kubectl: pide confirmación en producción para lo peligroso
kubectl() {
local ctx; ctx=$(command kubectl config current-context 2>/dev/null)
if [[ "$ctx" == *PRODUCCION* && "$1" =~ ^(delete|drain|cordon|scale|patch|replace|edit)$ ]]; then
echo "⚠ Vas a ejecutar '$1' en $ctx"
read -r -p "Escribe el nombre del clúster para confirmar: " r
[[ "$r" == "$ctx" ]] || { echo "Cancelado."; return 1; }
fi
command kubectl "$@"
}Capa 4: contextos de solo lectura por defecto. Esta es la primera barrera real, porque no depende de la disciplina de nadie. El usuario joan-pro del kubeconfig asume el rol rutasnorte-pro-lectura, mapeado a un ClusterRole de solo lectura:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: plataforma-lectura-pro
subjects:
- kind: Group
name: rutasnorte:plataforma
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: view # ClusterRole integrado: get, list, watch. Nada más.
apiGroup: rbac.authorization.k8s.ioEscribir en producción exige asumir explícitamente otro rol, con una sesión temporal y un motivo registrado. Es una fricción deliberada de treinta segundos que convierte cada escritura en un acto consciente.
Capa 5: no escribir nunca a mano en producción. El objetivo último. Con GitOps (10-05), el único que aplica cambios en pro es Argo CD. Las personas leen, diagnostican y proponen cambios en Git. La escritura manual queda reservada para incidentes, con el procedimiento de asunción de rol y su registro de auditoría.
| Medida | Coste de implantación | Accidentes que evita |
|---|---|---|
| Prompt con contexto | 5 minutos | La mayoría de los despistes |
| Kubeconfig por sesión | 10 minutos | Cambios de contexto cruzados entre terminales |
| Confirmación en verbos destructivos | 15 minutos | Los delete por inercia |
| Contextos de solo lectura | 1 hora + RBAC | Todos los accidentes de escritura casual |
Solo GitOps escribe en pro |
El proyecto entero | Todo, y además da trazabilidad |
- Despliegue multi-clúster con Argo CD
Argo CD gestiona clústeres remotos desde una única instalación. Cada clúster se registra como un destino y las Application apuntan al que corresponda.
4.1. Registrar clústeres
# Desde el clúster donde vive Argo CD
argocd cluster add rutasnorte-nopro --name nopro \
--label entorno=nopro --label region=eu-west-1
argocd cluster add PRODUCCION-rutasnorte --name pro \
--label entorno=pro --label region=eu-west-1 --label critico=true
argocd cluster listSERVER NAME VERSION STATUS LABELS
https://DEF456.gr7.eu-west-1.eks.amazonaws.com nopro 1.30 Successful entorno=nopro,region=eu-west-1
https://ABC123.gr7.eu-west-1.eks.amazonaws.com pro 1.30 Successful entorno=pro,region=eu-west-1,critico=true
https://kubernetes.default.svc in-cluster 1.30 SuccessfulLas etiquetas son la parte importante: son lo que permite escribir "despliega esto en todos los clústeres de producción" sin enumerarlos.
argocd cluster add crea una ServiceAccount en el clúster destino con los permisos necesarios y guarda sus credenciales como un Secret en el clúster de Argo CD. Ese Secret es una credencial de alto valor: quien lo lea puede desplegar en producción. Debe estar protegido por RBAC estricto y, preferiblemente, cifrado en reposo con una clave gestionada externamente.
4.2. El generador de clústeres de ApplicationSet
Un ApplicationSet genera Application automáticamente a partir de una plantilla y un generador. El generador de clústeres crea una por cada clúster que cumpla un selector.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: plataforma-base
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- clusters:
# Todos los clústeres registrados con esta etiqueta.
selector:
matchLabels:
rutasnorte.example/gestionado: "true"
template:
metadata:
# El nombre incluye el clúster: una Application por clúster.
name: 'base-{{.name}}'
spec:
project: plataforma
source:
repoURL: https://github.com/rutasnorte/manifiestos
targetRevision: main
path: 'plataforma/base'
kustomize:
# Cada clúster tiene su parche con sus particularidades.
components:
- '../componentes/{{index .metadata.labels "entorno"}}'
destination:
server: '{{.server}}'
namespace: plataforma
syncPolicy:
automated: { prune: true, selfHeal: true }
syncOptions: [CreateNamespace=true]Esto despliega los complementos comunes (Kyverno, cert-manager, ingress-nginx, node-exporter) en todos los clústeres etiquetados, con las diferencias por entorno resueltas por Kustomize.
Para las aplicaciones de negocio, el generador de matriz combina clústeres con aplicaciones:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: rutas-norte-aplicaciones
namespace: argocd
spec:
goTemplate: true
generators:
- matrix:
generators:
# Eje 1: clústeres de producción
- clusters:
selector:
matchLabels: { entorno: pro }
# Eje 2: los componentes, leídos de los directorios del repositorio
- git:
repoURL: https://github.com/rutasnorte/manifiestos
revision: main
directories:
- path: 'overlays/pro/*'
template:
metadata:
name: '{{.path.basename}}-{{.name}}'
annotations:
# Ordena el despliegue: la base de datos antes que la API.
argocd.argoproj.io/sync-wave: '{{if eq .path.basename "postgres-reservas"}}-1{{else}}0{{end}}'
spec:
project: rutas-norte
source:
repoURL: https://github.com/rutasnorte/manifiestos
targetRevision: main
path: '{{.path.path}}'
destination:
server: '{{.server}}'
namespace: 'rutas-norte-pro'
syncPolicy:
automated: { prune: true, selfHeal: true }Con dos clústeres de producción y seis componentes, esto genera doce Application sin escribir doce ficheros. Añadir una región es registrar un clúster con la etiqueta correcta; añadir un componente es crear un directorio.
4.3. Cómo se combina con Kustomize
La estructura del repositorio soporta dos dimensiones: entorno y clúster.
manifiestos/
├── base/
│ ├── api-reservas/
│ ├── tienda-web/
│ └── postgres-reservas/
├── componentes/ # variaciones reutilizables
│ ├── alta-disponibilidad/ # más réplicas, PDB estricto
│ ├── recursos-reducidos/ # para dev
│ └── replica-lectura/ # solo para clústeres secundarios
└── overlays/
├── dev/
├── pre/
├── pro-eu-west-1/ # región principal
│ ├── kustomization.yaml
│ └── parche-region.yaml
└── pro-eu-west-3/ # región secundaria
├── kustomization.yaml
└── parche-region.yaml# overlays/pro-eu-west-3/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: rutas-norte-pro
resources:
- ../../base/api-reservas
- ../../base/tienda-web
components:
- ../../componentes/alta-disponibilidad
- ../../componentes/replica-lectura # aquí PostgreSQL es réplica, no primario
patches:
- path: parche-region.yaml
target: { kind: Deployment }
images:
# El MISMO digest que en eu-west-1: la promoción actualiza ambos overlays.
- name: api-reservas
newName: registry.rutasnorte.example/rutasnorte/api-reservas
digest: sha256:9a8b7c6d5e4f30291a8b7c6d5e4f30291a8b7c6d5e4f30291a8b7c6d5e4f3029Regla importante: lo que es igual entre clústeres vive en base; lo que difiere, y solo eso, en el overlay. Cada línea de un overlay es una diferencia que alguien tendrá que entender dentro de seis meses. Si un overlay crece mucho, casi siempre significa que la base está mal factorizada.
- Configuración y políticas comunes: el clúster como producto
Con varios clústeres, la pregunta deja de ser "¿cómo despliego mi aplicación?" y pasa a ser "¿cómo garantizo que los N clústeres cumplen las mismas reglas?".
La idea de clúster como producto consiste en que el equipo de plataforma no entrega "acceso a un clúster", sino un producto con contrato: un clúster recién creado ya viene con observabilidad, políticas de seguridad, RBAC, cuotas, controlador de Ingress, gestión de certificados y copias configuradas. Nadie tiene que montar nada, y por tanto nadie lo monta distinto.
5.1. Qué forma parte del producto
| Categoría | Componentes | Desplegado por |
|---|---|---|
| Seguridad | Kyverno con las políticas corporativas, Pod Security Standards, Falco | ApplicationSet plataforma-base |
| Identidad y acceso | ClusterRole y bindings por grupo del proveedor de identidad |
ApplicationSet plataforma-rbac |
| Redes | ingress-nginx, cert-manager con los emisores, NetworkPolicy deny-all por defecto |
ApplicationSet plataforma-base |
| Observabilidad | kube-prometheus-stack, Fluent Bit hacia el destino central, reglas de alerta | ApplicationSet plataforma-observabilidad |
| Costes | OpenCost, etiquetado obligatorio de cargas | ApplicationSet plataforma-base |
| Copias | Velero con su destino y su calendario | ApplicationSet plataforma-base |
| Autoescalado | Karpenter con las clases de nodo aprobadas | Terraform (es infraestructura, no carga) |
5.2. Las políticas que garantizan la homogeneidad
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: exigir-etiquetas-corporativas
annotations:
policies.kyverno.io/description: >-
Toda carga debe declarar equipo y componente. Sin esto, el reparto
de costes de 11-06 y la respuesta a incidentes son imposibles.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: etiquetas-obligatorias
match:
any:
- resources:
kinds: [Deployment, StatefulSet, DaemonSet, CronJob, Rollout]
exclude:
any:
- resources:
namespaces: [kube-system, plataforma, argocd, monitorizacion]
validate:
message: "Faltan las etiquetas rutasnorte.example/equipo y app.kubernetes.io/part-of"
pattern:
metadata:
labels:
rutasnorte.example/equipo: "?*"
app.kubernetes.io/part-of: "?*"5.3. Detectar la deriva
Aunque todo se despliegue por GitOps, la deriva aparece: versiones de complementos instalados por Terraform, parches de emergencia, diferencias en la versión del propio Kubernetes. Conviene un informe periódico.
#!/usr/bin/env bash
# comparar-flota.sh — ejecutado semanalmente por un CronJob
for CTX in rutasnorte-nopro PRODUCCION-rutasnorte; do
echo "=== $CTX ==="
kubectl --context "$CTX" version -o json | jq -r '.serverVersion.gitVersion'
kubectl --context "$CTX" get clusterpolicies -o name | sort
helm --kube-context "$CTX" list -A -o json | jq -r '.[] | "\(.name)\t\(.chart)"' | sort
doneY la comprobación que importa de verdad, hecha desde Argo CD:
# Ninguna Application debe estar OutOfSync sin motivo declarado
argocd app list -o json | jq -r '.[] | select(.status.sync.status != "Synced")
| "\(.metadata.name)\t\(.spec.destination.name)\t\(.status.sync.status)"'
- Conectividad entre clústeres
Dos clústeres son dos redes de pods distintas. Un pod de eu-west-3 no puede resolver api-reservas.rutas-norte-pro.svc.cluster.local del clúster de eu-west-1, ni alcanzar sus IPs. Hay tres niveles de solución, con complejidad muy distinta.
6.1. Nivel 1: DNS global y balanceo entre regiones
Lo más simple y lo que resuelve la mayoría de los casos. El tráfico de usuarios se dirige a la región adecuada mediante DNS, y cada región es autosuficiente.
www.rutasnorte.example
├── política de latencia
├── eu-west-1 → balanceador del clúster pro-1 [comprobación de salud: /salud]
└── eu-west-3 → balanceador del clúster pro-3 [comprobación de salud: /salud]- Política de latencia: cada usuario va a la región más rápida para él.
- Política de conmutación: si la comprobación de salud de una región falla, el DNS deja de resolverla.
- Límite importante: el DNS tiene TTL. Con TTL de 60 segundos, la conmutación tarda entre uno y varios minutos, porque hay resolutores que ignoran los TTL cortos. No hay conmutación instantánea por DNS.
6.2. Nivel 2: conectividad de red entre clústeres
Cuando un servicio de un clúster necesita llamar a otro de otro clúster (por ejemplo, la réplica de PostgreSQL siguiendo al primario), hace falta conectividad de red real: emparejamiento de VPC o pasarela de tránsito, rangos CIDR que no se solapen, y reglas de cortafuegos explícitas.
El requisito de los rangos merece atención: si los dos clústeres usan 10.244.0.0/16 para pods, el enrutamiento entre ellos es imposible. Hay que planificar el direccionamiento antes de crear el segundo clúster, y es un error que se paga con una reconstrucción.
6.3. Nivel 3: malla de servicio multi-clúster
Istio, Linkerd o Cilium Cluster Mesh permiten que un Service de un clúster sea alcanzable desde otro de forma transparente, con mTLS, reparto de carga entre regiones, conmutación por localidad y observabilidad unificada.
Qué resuelven de verdad:
- Descubrimiento transparente:
api-reservas.rutas-norte-pro.svcfunciona desde cualquier clúster de la malla. - Conmutación por localidad: se prefiere la instancia local y se desborda a la remota solo si la local no está sana.
- mTLS entre clústeres sin tocar la aplicación.
- Una sola vista de la topología del tráfico.
Qué cuestan:
- Un sidecar por pod (o eBPF, según la implementación), con su consumo de CPU y memoria.
- Un plano de control más que operar y actualizar.
- Una capa entera de nuevos modos de fallo, con una curva de aprendizaje considerable.
- Depuración notablemente más difícil: el tráfico ya no va donde parece.
El criterio honesto: una malla multi-clúster se justifica cuando hay muchos servicios llamándose entre regiones. Si la comunicación entre clústeres se reduce a la replicación de la base de datos y a un par de llamadas, el emparejamiento de VPC y unos Services de tipo ExternalName resuelven lo mismo por una fracción del coste.
Rutas Norte no usa malla de servicio. Con dos clústeres, seis componentes y una única conversación entre regiones (la replicación de PostgreSQL), no está justificada. Se revisará si aparece una tercera región.
- Recuperación ante desastres
Aquí es donde el multi-clúster deja de ser una cuestión de arquitectura y pasa a ser una cuestión de supervivencia del negocio.
7.1. Activo-pasivo frente a activo-activo
| Aspecto | Activo-pasivo | Activo-activo |
|---|---|---|
| Tráfico normal | Todo a la región principal | Repartido entre regiones |
| Región secundaria | Infraestructura mínima, datos replicándose | Capacidad completa sirviendo |
| Coste adicional | 20-40 % | 100 % o más |
| Tiempo de recuperación | Minutos a horas | Segundos (el DNS deja de enviar a la caída) |
| Complejidad del dato | Replicación en una dirección | Escrituras en dos sitios: el problema difícil |
| Se prueba | Con simulacros programados | Continuamente, por construcción |
| Riesgo de sorpresa | Alto: el camino frío puede no funcionar | Bajo: el camino está siempre caliente |
El argumento a favor del activo-activo no es el tiempo de recuperación, es que el camino de recuperación se ejerce todos los días. Un secundario pasivo que nunca ha servido tráfico real es una hipótesis, igual que la copia que nunca se restauró de 11-02.
El argumento en contra es doble: cuesta el doble, y sobre todo obliga a resolver las escrituras concurrentes en dos regiones, que es un problema de diseño de aplicación, no de infraestructura.
7.2. RTO y RPO
Los mismos conceptos de 11-02, ahora a escala de región:
| Escenario | RTO objetivo | RPO objetivo | Cómo se consigue |
|---|---|---|---|
| Caída de un pod | segundos | 0 | Réplicas y sondas |
| Caída de un nodo | 1-2 min | 0 | Reprogramación y topologySpread |
| Caída de una zona | 2-5 min | 0 | Reparto multi-zona dentro del clúster |
| Caída del clúster | 30 min | < 5 min | Segundo clúster + replicación |
| Caída de la región | 2 h | < 15 min | Clúster en otra región + copias replicadas |
7.3. El problema que no tiene solución fácil: el dato
Los manifiestos se replican con git push. La aplicación arranca en cualquier sitio en minutos. El dato es otra cosa.
Replicación asíncrona de PostgreSQL entre regiones. Es lo que hace Rutas Norte: una réplica en eu-west-3 que sigue al primario de eu-west-1 por replicación en flujo. El retraso típico entre Irlanda y París es de 25-40 ms de red, lo que en la práctica significa un retraso de replicación de menos de un segundo con carga normal, y de unos segundos durante el puente de mayo.
La consecuencia: si la región principal desaparece de golpe, se pierden las transacciones confirmadas que aún no habían llegado a la réplica. Con RPO de 15 minutos hay margen de sobra, pero conviene decirlo con claridad: activo-pasivo con replicación asíncrona no es RPO cero. Puede haber reservas confirmadas al cliente que no existan tras la conmutación, y el negocio tiene que saber qué hacer con eso.
Replicación síncrona daría RPO cero, pero cada confirmación de transacción esperaría la ida y vuelta a la otra región: 35 ms añadidos a cada escritura. En el puente de mayo, eso es inasumible.
graph LR
subgraph W1["eu-west-1 · principal"]
P[(postgres-reservas<br/>PRIMARIO)]
API1[api-reservas<br/>8-40 réplicas]
API1 --> P
end
subgraph W3["eu-west-3 · secundaria"]
R[(postgres-reservas<br/>RÉPLICA en pie)]
API3[api-reservas<br/>2 réplicas mínimas]
API3 -.solo lectura.-> R
end
S3[(Copias + WAL<br/>replicadas a ambas regiones)]
P ==>|replicación asíncrona<br/>retraso menor de 1 s| R
P --> S3
DNS[DNS global<br/>latencia + salud] --> API1
DNS -.si eu-west-1 falla.-> API3
Y el problema aún peor: la vuelta. Cuando la región principal se recupera, su base de datos tiene un estado divergente del de la que ha estado sirviendo. No se puede simplemente volver: hay que reconstruir la antigua principal como réplica de la nueva y luego conmutar ordenadamente. Ese procedimiento tiene que estar escrito antes de necesitarlo.
- El plan de Rutas Norte
8.1. Estado actual: dos clústeres, misma región
| Clúster | Región | Contiene | Nodos |
|---|---|---|---|
rutasnorte-nopro |
eu-west-1 | rutas-norte-dev, rutas-norte-pre, entornos efímeros de 11-03 |
3-8 (Karpenter, mayoría interrumpibles) |
rutasnorte-pro |
eu-west-1 | rutas-norte-pro, Argo CD, observabilidad |
6-30 (Karpenter, base bajo demanda + interrumpibles para lo tolerante) |
La separación resolvió el problema que la motivó: las actualizaciones de EKS se ensayan en nopro, y un webhook mal configurado por desarrollo ya no puede afectar a la venta de billetes.
8.2. El plan aprobado: segunda región
Tras el análisis de riesgo, la dirección aprobó una región secundaria en eu-west-3 (París) en modo activo-pasivo, con estas decisiones:
| Decisión | Valor | Razón |
|---|---|---|
| Modo | Activo-pasivo | El activo-activo exigiría resolver escrituras multi-región en api-reservas, un proyecto de meses |
| Capacidad en reposo | 2 réplicas de api-reservas y tienda-web, siempre encendidas |
Un secundario a cero es un secundario que no se sabe si funciona |
| Base de datos | Réplica de CloudNativePG siguiendo al primario | RPO real de segundos |
| Copias | Replicadas a ambas regiones, con inmutabilidad | Un desastre no puede llevarse región y copias a la vez |
| Manifiestos | Mismo repositorio, overlay pro-eu-west-3 |
Una sola fuente de verdad |
| Argo CD | Instancia en pro de eu-west-1 y una segunda instancia inactiva en eu-west-3 |
Si cae la región principal, cae también el Argo CD que la gobierna |
| DNS | Registros con comprobación de salud, TTL 60 s | Conmutación en 1-3 minutos |
| Coste adicional estimado | ~34 % sobre la factura actual | Aprobado por dirección |
El punto de Argo CD merece atención. Es un error clásico: poner la herramienta que despliega dentro del clúster que puede desaparecer. Rutas Norte lo resuelve con una segunda instancia en eu-west-3 apuntando al mismo repositorio, con syncPolicy.automated desactivada en condiciones normales; se activa como parte del procedimiento de conmutación.
8.3. Procedimiento de conmutación
# ===== PROCEDIMIENTO DE CONMUTACIÓN A eu-west-3 =====
# Ejecutar SOLO con la decisión del mando de incidencia (11-06).
# Tiempo objetivo total: 30 minutos.
# --- Paso 1 (2 min). Confirmar que es un desastre regional, no una avería local.
# Comprobar el estado de la región en el panel del proveedor y desde una red externa.
# --- Paso 2 (3 min). Congelar escrituras a la región caída si aún es alcanzable,
# para evitar el escenario de doble primario.
kubectl --context PRODUCCION-rutasnorte scale deploy/api-reservas --replicas=0 || true
# --- Paso 3 (5 min). Promocionar la réplica de PostgreSQL en eu-west-3.
kubectl --context rutasnorte-pro-w3 -n rutas-norte-pro \
cnpg promote postgres-reservas postgres-reservas-1
kubectl --context rutasnorte-pro-w3 -n rutas-norte-pro get cluster postgres-reservas
# Anotar el último LSN aplicado: define la pérdida real de datos.
# --- Paso 4 (5 min). Activar Argo CD secundario y escalar la aplicación.
kubectl --context rutasnorte-pro-w3 -n argocd patch application api-reservas-w3 \
--type merge -p '{"spec":{"syncPolicy":{"automated":{"selfHeal":true,"prune":true}}}}'
kubectl --context rutasnorte-pro-w3 -n rutas-norte-pro scale deploy/api-reservas --replicas=12
kubectl --context rutasnorte-pro-w3 -n rutas-norte-pro rollout status deploy/api-reservas
# --- Paso 5 (3 min). Verificación por capas de 11-01 contra la URL interna.
curl -sf https://api-w3.rutasnorte.example/preparado
npm run pruebas:humo -- --base-url https://api-w3.rutasnorte.example
# --- Paso 6 (2 min). Conmutar el DNS.
aws route53 change-resource-record-sets --hosted-zone-id Z123 \
--change-batch file://conmutar-a-w3.json
# --- Paso 7 (10 min). Vigilar y comunicar.
# Panel de Grafana de la región secundaria. Comunicación al negocio: qué
# reservas pueden haberse perdido (según el LSN del paso 3).8.4. El simulacro anual
Un procedimiento escrito y nunca ejecutado es una redacción, no un plan. Rutas Norte hace un simulacro anual completo en octubre, fuera de temporada alta:
| Fase | Contenido |
|---|---|
| Preparación (2 semanas antes) | Revisar el procedimiento, avisar al negocio, definir criterios de éxito y de abortado |
| Ejecución | Conmutación real a eu-west-3 con tráfico de producción, en horario de baja demanda |
| Permanencia | 4 horas sirviendo desde la región secundaria |
| Retorno | Reconstruir eu-west-1 como réplica y conmutar de vuelta ordenadamente |
| Análisis posterior | Tiempos reales de cada paso, qué falló, acciones de mejora con responsable y fecha |
Resultados del simulacro de octubre de 2025, el primero: RTO real de 71 minutos frente al objetivo de 30. Los hallazgos fueron reveladores y ninguno se habría descubierto sin ejecutarlo:
- El certificado TLS de
eu-west-3había caducado: cert-manager no podía completar el reto ACME porque el DNS no apuntaba a esa región. Se corrigió usando el reto DNS-01 en lugar de HTTP-01. - Los ExternalSecrets de
eu-west-3apuntaban a un almacén que no estaba replicado a esa región. - Nadie recordaba dónde estaba escrito el procedimiento de conmutación del DNS.
- La réplica de PostgreSQL llevaba once días sin replicar por una regla de cortafuegos añadida en un cambio no relacionado. Nadie lo sabía porque no había alerta sobre el retraso de replicación entre regiones.
Ese último hallazgo, por sí solo, justificó el simulacro entero: en un desastre real se habrían perdido once días de reservas.
- El coste, la complejidad y cuándo no hacerlo
9.1. Lo que realmente cuesta
| Concepto | Coste anual estimado en Rutas Norte |
|---|---|
| Plano de control del segundo clúster | ~880 € |
Plano de control del tercero (eu-west-3) |
~880 € |
| Capacidad mínima en la región secundaria | ~9.400 € |
| Réplica de PostgreSQL entre regiones | ~4.200 € |
| Tráfico entre regiones (replicación) | ~1.800 € |
| Complementos duplicados (cómputo) | ~3.100 € |
| Total infraestructura | ~20.260 € |
| Tiempo de plataforma (implantación, ~6 semanas-persona) | ~24.000 € |
| Mantenimiento continuo (~15 % de una persona) | ~9.000 €/año |
Es una inversión seria. La pregunta que la justifica no es técnica: ¿cuánto cuesta a Rutas Norte una hora caída durante el puente de mayo? Si son 40.000 € de ventas perdidas más el daño reputacional, la inversión se paga con evitar un solo incidente regional. Si el negocio puede absorber medio día caído sin consecuencias graves, no.
9.2. Cuándo NO hacerlo
- Cuando un solo clúster todavía funciona. Si los namespaces, cuotas y políticas de red cubren tus necesidades de aislamiento, añadir clústeres solo añade deriva.
- Cuando no hay GitOps. Con despliegues manuales, N clústeres significan N oportunidades de divergir. GitOps es requisito previo, no complemento.
- Cuando no hay observabilidad centralizada. Diagnosticar un incidente saltando entre paneles de tres clústeres es inviable. Los logs y las métricas de toda la flota deben verse en un sitio.
- Cuando el equipo no da abasto con uno. Multiplicar la infraestructura no multiplica la capacidad del equipo, la divide.
- Cuando la razón es "por si acaso". Sin un escenario concreto que resolver, la complejidad se paga sin recibir nada.
- Cuando el dato no se puede replicar. Si la aplicación no tolera coherencia eventual y no hay presupuesto para rediseñarla, un segundo clúster da una falsa sensación de seguridad.
9.3. El orden correcto de las inversiones
Antes de plantearse el segundo clúster, conviene tener resuelto lo anterior, porque casi todo mejora la fiabilidad más por menos dinero:
- Copias probadas y restauración cronometrada (11-02).
- GitOps con todo en Git (10-05).
- Observabilidad y alertas con runbooks (07-04, 11-06).
- Alta disponibilidad dentro del clúster: multi-zona, PDB,
topologySpread(09-05). - Despliegues seguros con canario (11-04).
- Y entonces sí, el segundo clúster.
Un equipo que salta al paso 6 sin los cinco anteriores acaba con dos clústeres frágiles en lugar de uno.
Errores Comunes y Consejos
- Crear el segundo clúster con el mismo rango CIDR que el primero. Impide el enrutamiento entre ellos y obliga a reconstruir. Planifica el direccionamiento de toda la flota antes de crear el segundo.
- Poner Argo CD solo dentro del clúster de producción. Cuando ese clúster desaparece, desaparece la capacidad de desplegar en cualquier sitio. Instancia secundaria o clúster de gestión aparte.
- Suponer que el DNS conmuta al instante. Los TTL cortos no siempre se respetan; cuenta con uno a tres minutos como mínimo.
- Un secundario a cero réplicas. Un camino frío no se sabe si funciona. Capacidad mínima permanente y tráfico real, aunque sea poco.
- No alertar sobre el retraso de replicación entre regiones. Es exactamente el fallo que Rutas Norte descubrió en el simulacro: once días sin replicar y nadie lo sabía.
- Duplicar el overlay entero al añadir una región. Solo lo que difiere va en el overlay; si crece mucho, la base está mal factorizada.
- Instalar una malla de servicio multi-clúster por defecto. Es una de las piezas más complejas del ecosistema. Solo se justifica con mucha comunicación entre regiones.
- Consejo: pon el contexto en el prompt hoy mismo, con fondo rojo para producción. Es la medida de mayor retorno por minuto invertido de toda la lección.
- Consejo: haz que los contextos de producción sean de solo lectura por defecto. Escribir debe exigir un acto deliberado y registrado.
- Consejo: escribe el procedimiento de conmutación y el de vuelta. La vuelta es más difícil que la ida y casi nadie la documenta.
Ejercicios
Ejercicio 1: decidir si desdoblar
Una empresa tiene un clúster con dev, pre y pro en namespaces separados, GitOps con Argo CD, copias probadas mensualmente y observabilidad centralizada. Ha sufrido dos incidentes en seis meses: uno por un operador instalado por desarrollo que consumió toda la memoria de un nodo compartido, y otro por una actualización de la versión del clúster que dejó pro degradado durante 25 minutos. El equipo de plataforma son dos personas. Recomienda una topología, justifícala y di explícitamente qué NO recomiendas y por qué.
Ejercicio 2: escribir el ApplicationSet
Rutas Norte añade el clúster rutasnorte-pro-w3 con las etiquetas entorno=pro, region=eu-west-3 y rol=secundario. Escribe un ApplicationSet que despliegue api-reservas en todos los clústeres con entorno=pro, usando el overlay overlays/pro-{{region}}, y que en los clústeres con rol=secundario arranque con menos réplicas. Indica además qué debe cumplirse en el repositorio para que funcione.
Ejercicio 3: analizar el simulacro
En el simulacro anual, un equipo obtiene: paso 3 (promoción de PostgreSQL) 4 min, paso 4 (Argo CD y escalado) 22 min, paso 5 (verificación) 6 min, paso 6 (DNS) 14 min. RTO total 46 min frente a un objetivo de 30. Identifica los dos pasos problemáticos, propón una causa probable para cada uno y una acción correctora concreta.
Soluciones
Solución 1. Recomendación: topología por entorno, dos clústeres — uno para pro y otro para dev+pre. Justificación: los dos incidentes sufridos son exactamente los que esta topología resuelve; el primero es contención de recursos y del plano de control entre entornos, el segundo es la imposibilidad de ensayar la actualización antes de aplicarla a producción. Además, los requisitos previos están cubiertos: hay GitOps, copias probadas y observabilidad centralizada, así que la deriva es manejable. El coste incremental para dos personas es asumible porque la mayor parte de la operación ya está automatizada.
Lo que no se recomienda: (a) un clúster por unidad de negocio, porque con dos personas de plataforma la proliferación es inasumible y no hay ningún problema que lo motive; (b) una segunda región, porque ninguno de los incidentes fue regional y el coste (infraestructura más replicación del dato) no está justificado por la evidencia disponible; (c) un clúster de gestión dedicado, innecesario con solo dos clústeres, donde Argo CD puede vivir en el de producción gestionando ambos.
Solución 2.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: api-reservas-flota
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- clusters:
selector:
matchLabels: { entorno: pro }
template:
metadata:
name: 'api-reservas-{{index .metadata.labels "region"}}'
spec:
project: rutas-norte
source:
repoURL: https://github.com/rutasnorte/manifiestos
targetRevision: main
path: 'overlays/pro-{{index .metadata.labels "region"}}'
kustomize:
components:
# Componente adicional solo en los secundarios.
- '{{if eq (index .metadata.labels "rol") "secundario"}}../../componentes/capacidad-reducida{{else}}../../componentes/capacidad-completa{{end}}'
destination:
server: '{{.server}}'
namespace: rutas-norte-pro
syncPolicy:
automated: { prune: true, selfHeal: true }Requisitos en el repositorio: (a) deben existir los directorios overlays/pro-eu-west-1 y overlays/pro-eu-west-3; (b) deben existir los componentes capacidad-reducida y capacidad-completa; (c) todos los clústeres destino deben estar registrados en Argo CD con las etiquetas entorno, region y rol; (d) el AppProject rutas-norte debe tener ambos servidores en su lista de destinos permitidos, o Argo CD rechazará las Application generadas. Nota adicional: como el HPA gobierna las réplicas, el componente debería ajustar minReplicas/maxReplicas del HPA, no el campo replicas del Deployment.
Solución 3. Pasos problemáticos: el 4 (22 min sobre unos 5 esperados) y el 6 (14 min sobre 2).
Paso 4: causa probable, la región secundaria no tenía capacidad de nodos disponible y hubo que esperar a que el autoescalador aprovisionara nodos nuevos, incluyendo la descarga de imágenes que no estaban en caché en esos nodos. Acción correctora: mantener capacidad mínima permanente y precalentar las imágenes (por ejemplo, con un DaemonSet que las descargue, o reservando nodos con las imágenes ya presentes). Alternativa complementaria: sobreaprovisionar con pods de baja prioridad que Karpenter desaloje al escalar (09-03).
Paso 6: catorce minutos para un cambio de DNS indica que no estaba automatizado; probablemente alguien editó registros a mano en una consola web bajo presión, o hubo que buscar las credenciales. Acción correctora: guionizar el cambio con el fichero de cambio ya escrito y versionado en el repositorio, ejecutable con un solo comando, y probarlo fuera del simulacro. Comprobar además que el TTL de los registros es de 60 segundos y no el valor por defecto, que suele ser mucho mayor.
Conclusión
Hemos visto por qué una empresa acaba con varios clústeres —aislamiento del plano de control, radio de impacto, latencia por regiones, residencia del dato, versiones distintas y el simple hecho de que un clúster también se actualiza— y qué cuesta eso realmente. Recorrimos las topologías habituales con la recomendación de empezar por uno y desdoblar primero producción frente al resto; las cinco capas de defensa para no aplicar nunca en el clúster equivocado, de las que la más rentable es poner el contexto en el prompt y la más efectiva es que producción sea de solo lectura por defecto; el gobierno de la flota con el generador de clústeres de ApplicationSet combinado con las superposiciones de Kustomize; la idea de clúster como producto para combatir la deriva; los tres niveles de conectividad entre clústeres y el criterio honesto sobre cuándo una malla de servicio se justifica; y la recuperación ante desastres, donde lo difícil nunca son los manifiestos sino el dato, con su replicación asíncrona, su RPO no nulo y el procedimiento de vuelta que casi nadie escribe.
El plan de Rutas Norte, con dos clústeres hoy y una región secundaria aprobada, ilustra lo esencial: la decisión no se toma por elegancia arquitectónica, sino comparando el coste de la redundancia con el coste de una hora caída en el puente de mayo. Y el simulacro de octubre, con su RTO real de 71 minutos y sus once días de replicación rota que nadie había detectado, deja la lección más importante: un procedimiento no ejecutado no es un plan.
Ya tenemos la plataforma desplegada, con estado, con canalización, con despliegues seguros y con una flota gobernada. Falta lo que ningún tutorial cuenta y lo que ocupa realmente el día a día: mantenerla viva. En la última lección del módulo, Operación en Producción: Incidencias, Runbooks y Costes, veremos cómo se gestiona una incidencia, cómo se escribe un runbook útil, cómo el presupuesto de error decide qué hace el equipo el mes que viene, cómo se planifica la capacidad del puente de mayo y por qué la factura de Kubernetes se dispara y qué hacer al respecto.
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
