Módulo 8: Capstone Andes Cargo On Kubernetes
2. Repaso de arquitectura: el clúster completo
Descripción
Esta lección no aplica ningún manifiesto nuevo — reúne, en un solo diagrama, los ocho namespaces que hoy conviven dentro de andes-cargo-cluster, confirmados contra el clúster real antes de escribir esta lección, y el flujo completo que conecta tres de ellos: Gitea, ArgoCD, y el propio clúster. Es el mapa que las lecciones 3 y 4 —el cambio que pasa y el cambio que el gate detiene— dan por conocido.
Conexión con el módulo
La lección 1 enumeró, en una tabla por módulo, qué dejó corriendo cada uno. Esta lección reorganiza esa misma información por namespace, no por módulo — la vista que de verdad importa quien opera el clúster día a día, porque un namespace agrupa objetos que se administran juntos, sin importar en qué lección de esta guía se hayan construido.
Los ocho namespaces, confirmados contra el clúster real
kubectl get namespaces
Qué esperar (literal, ejecutado — AGE es tu valor variable; el resto, incluida la cuenta de namespaces, es literal en este punto de la guía):
NAME STATUS AGE
andes-cargo Active 2h58m
argocd Active 85m
default Active 2h58m
gatekeeper-system Active 48m
gitea Active 88m
ingress-nginx Active 2h57m
kube-node-lease Active 2h58m
kube-public Active 2h58m
kube-system Active 2h58m
kyverno Active 47m
local-path-storage Active 2h58m
Cuatro de estos once namespaces son infraestructura del propio kind (kube-system, kube-node-lease, kube-public, local-path-storage) — existieron desde la lección 5 del Módulo 1, antes de que Andes Cargo tuviera ningún objeto propio, y no cambian entre módulos. default tampoco tiene ningún recurso de Andes Cargo — es el namespace que Kubernetes usa cuando nadie especifica ninguno, y esta guía nunca lo usó a propósito desde el Módulo 2. Los seis namespaces que sí importan para este capstone son: andes-cargo (el único con recursos de negocio), y cinco de infraestructura del laboratorio (gitea, argocd, gatekeeper-system, kyverno, ingress-nginx) — cada uno construido en un módulo distinto, ninguno considerado nunca "de Andes Cargo" en sí mismo.
El diagrama completo: seis namespaces, un solo clúster
andes-cargo-cluster (kind v0.32.0, Kubernetes v1.36.1)
┌──────────────────────────────────────────────────────────────────────────────────┐
│ │
│ namespace: gitea (M5) namespace: argocd (M5) │
│ ┌─────────────────────┐ ┌───────────────────────────────────┐ │
│ │ gitea (Pod) │◄────────│ argocd-server │ │
│ │ repo: │ watch │ argocd-repo-server │ │
│ │ andes-cargo/ │ cada │ argocd-application-controller │ │
│ │ andes-cargo-k8s │ ~3 min │ (compara Git vs. clúster, aplica │ │
│ │ (10 manifiestos) │ │ la diferencia, sin kubectl apply) │ │
│ └─────────────────────┘ └───────────────┬───────────────────┘ │
│ │ aplica el estado deseado │
│ ▼ │
│ namespace: gatekeeper-system (M6) namespace: kyverno (M6) │
│ ┌──────────────────────┐ ┌──────────────────────────┐ │
│ │ gatekeeper- │ │ kyverno-admission- │ │
│ │ controller-manager │ │ controller │ │
│ │ (Constraint: │ │ (ClusterPolicy: │ │
│ │ require-resource-limits) │ │ require-resource-limits) │ │
│ └───────────┬──────────┘ └───────────┬──────────────┘ │
│ │ admission (ambos, en paralelo) │ │
│ └────────────────┬───────────────┘ │
│ ▼ │
│ namespace: andes-cargo (M1-M4) │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ Deployment andes-cargo-status-api (2-6 réplicas, HPA) │ │
│ │ Service status-api-service (ClusterIP) │ │
│ │ ConfigMap + Secret (endpoint LocalStack, credenciales dummy) │ │
│ │ Ingress status-api-ingress (host andes-cargo.local) │ │
│ │ NetworkPolicy × 2 (default-deny-ingress, allow-from-ingress-nginx) │ │
│ └───────────────────────────────┬────────────────────────────────┘ │
│ │ expuesto por │
│ ▼ │
│ namespace: ingress-nginx (M4) │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ ingress-nginx-controller — la única puerta HTTP del clúster │ │
│ │ (http://andes-cargo.local, vía extraPortMappings de kind-config.yaml)│ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────────┘
▲
│ kubectl (contexto kind-andes-cargo-cluster) — herramienta de
│ observación e instalación inicial; NUNCA la vía por la que
│ un cambio de andes-cargo-status-api llega al clúster (M5-M8)
tu terminal
Tres flechas de este diagrama merecen una lectura despacio, porque son la tesis completa de esta guía en forma de dibujo:
- Gitea → ArgoCD, con la etiqueta "watch cada ~3 min" — no es una flecha de una sola vez. ArgoCD compara el repositorio contra el clúster real de forma continua, en un bucle que nunca se detiene (Módulo 5, lección 2). Esa flecha es la razón por la que las lecciones 3 y 4 de este módulo nunca necesitan un
kubectl apply. - ArgoCD → Gatekeeper/Kyverno, con la etiqueta "aplica el estado deseado" — cuando ArgoCD decide que el clúster necesita cambiar, no tiene ningún privilegio especial frente a los dos motores de políticas. Cada objeto que ArgoCD intenta crear o modificar atraviesa exactamente la misma fase de admission que atravesaría si tú mismo corrieras
kubectl applya mano — el portero del Módulo 6 no distingue quién toca la puerta. - kubectl, con la flecha punteada hacia arriba, marcada "NUNCA la vía" — esta es la línea que distingue este capstone de los Módulos 1-4: ahí,
kubectl applyera el mecanismo normal para cambiar el clúster. Desde el Módulo 5 en adelante, y en las lecciones 3-4 de este módulo en particular,kubectlse usa exclusivamente para observar (get,describe,logs) — nunca para aplicar un cambio deandes-cargo-status-api.
El flujo GitOps, como secuencia
sequenceDiagram
participant Tú as Tú (git push)
participant Gitea as Gitea (andes-cargo-k8s)
participant ArgoCD as ArgoCD (application-controller)
participant Admission as Gatekeeper + Kyverno
participant Etcd as etcd (andes-cargo-cluster)
Tú->>Gitea: git push origin main
Note over Gitea: el commit ya existe en el repositorio
loop cada ~3 minutos (o al detectar el webhook)
ArgoCD->>Gitea: compara HEAD de main vs. estado del clúster
end
ArgoCD->>Admission: intenta aplicar el objeto que cambió
alt el objeto cumple las políticas
Admission->>Etcd: allowed: true — el objeto se guarda
Etcd-->>ArgoCD: Sync Status: Synced
else el objeto viola una política
Admission-->>ArgoCD: allowed: false — admission webhook denied
Note over ArgoCD: el objeto anterior sigue corriendo, sin cambios
end
Este diagrama es literalmente el guion de las lecciones 3 y 4: la rama alt de arriba ("cumple las políticas") es la lección 3; la rama else ("viola una política") es la lección 4. La diferencia entre las dos no está en ningún paso previo a Admission — Git recibe el commit igual en los dos casos, ArgoCD lo detecta igual en los dos casos. La diferencia está, exclusivamente, en la decisión que toman Gatekeeper y Kyverno en el momento exacto en que ArgoCD intenta aplicar el objeto.
Analogía: el mapa completo de la fábrica
Si la lección 1 presentó la fábrica automatizada como una sola imagen, esta lección es su plano de planta. Cada namespace es un área distinta de la fábrica, con su propio equipo y su propia función, ninguna redundante: el área de recepción de órdenes (gitea), el área de control de la línea (argocd), las dos estaciones de control de calidad que revisan cada pieza en paralelo antes de que entre a la línea de ensamblaje (gatekeeper-system y kyverno), la línea de ensamblaje misma donde vive el producto terminado (andes-cargo), y el mostrador de despacho al público (ingress-nginx). Nadie en esta fábrica reporta directo a un operario humano parado en la puerta con una llave inglesa (kubectl apply manual) — cada área reporta al plano que Git declara, y el plano solo cambia cuando alguien lo edita y lo sube, nunca cuando alguien entra a la fábrica y mueve algo con la mano.
Errores comunes
Confundir "namespace de infraestructura del laboratorio" con "namespace de Andes Cargo" (de alcance). Qué pasa: alguien, al ver gitea/argocd/gatekeeper-system/kyverno en la lista de namespaces, asume que son recursos de negocio de Andes Cargo, igual que andes-cargo. Cómo detectarlo: si tu respuesta a "¿qué hace Andes Cargo en el namespace gitea?" es cualquier cosa distinta de "nada — Gitea es la herramienta que sirve el repositorio, no un recurso del caso de negocio". Cómo corregirlo: repasa el diagrama de esta lección — solo andes-cargo contiene objetos que representan al negocio (Deployment, Service, ConfigMap, etc.); los otros cinco namespaces relevantes son, en conjunto, "la fábrica", nunca "el producto".
Asumir que kubectl apply sigue siendo el mecanismo normal de cambio, porque lo fue en los Módulos 1-4 (de hábito adquirido temprano). Qué pasa: alguien, al llegar a las lecciones 3-4 de este módulo, por costumbre abre una terminal y prepara un kubectl apply -f deployment.yaml antes de tocar Git. Cómo detectarlo: si tu primer instinto frente a "quiero cambiar algo de andes-cargo-status-api" es escribir un comando de kubectl que no empiece con get, describe o logs. Cómo corregirlo: desde el Módulo 5, la única vía legítima de cambio para cualquier recurso administrado por el Application de ArgoCD es un commit en andes-cargo-k8s, seguido de git push — la flecha punteada del diagrama de esta lección existe exactamente para marcar esta distinción con claridad.
Leer el diagrama mermaid como si Admission fuera un solo componente (de simplificación excesiva). Qué pasa: alguien lee la caja Gatekeeper + Kyverno de la secuencia y asume que los dos motores actúan como una sola unidad, con una sola decisión conjunta. Cómo detectarlo: si esperas un único mensaje de rechazo cuando un objeto viola la política, sin considerar que los dos motores evalúan de forma completamente independiente. Cómo corregirlo: la lección 4 de este módulo retoma esta distinción con evidencia real — los dos motores no son una sola caja, evalúan por separado, y (novedad frente al Módulo 6) no siempre cubren exactamente el mismo alcance de objetos.
Ejercicios
Ejercicio 1 — Clasifica los once namespaces sin mirar la lección. Sin volver a la sección "Los ocho namespaces", clasifica de memoria cada uno de los once namespaces del clúster en una de tres categorías: "infraestructura de kind" (existió desde el Módulo 1), "infraestructura del laboratorio" (Gitea/ArgoCD/Gatekeeper/Kyverno/ingress-nginx), o "recursos de Andes Cargo".
Ver solución
Infraestructura de kind: kube-system, kube-node-lease, kube-public, local-path-storage, default (este último no es infraestructura per se, pero tampoco contiene ningún recurso de esta guía). Infraestructura del laboratorio: gitea, argocd, gatekeeper-system, kyverno, ingress-nginx. Recursos de Andes Cargo: solo andes-cargo. Nueve de los once namespaces del clúster nunca contienen un objeto que represente al negocio — solo uno lo hace.
Ejercicio 2 — Traza el camino completo de un git push, sin mirar el diagrama mermaid. Enumera, en orden, cada componente que un cambio en deployment.yaml atraviesa desde que corres git push hasta que el cambio queda corriendo (o rechazado) en el clúster.
Ver solución
(1) El commit llega al repositorio en el Pod gitea, namespace gitea. (2) argocd-application-controller, namespace argocd, detecta la diferencia en su próximo ciclo de comparación (hasta unos minutos después). (3) ArgoCD intenta aplicar el objeto contra kube-apiserver. (4) kube-apiserver invoca, en paralelo, el ValidatingWebhookConfiguration de Gatekeeper (namespace gatekeeper-system) y el de Kyverno (namespace kyverno). (5) Si ambos permiten el objeto, se guarda en etcd y el clúster converge; si cualquiera lo deniega, el objeto nunca se guarda, y el estado anterior sigue corriendo en andes-cargo.
Ejercicio 3 — Explica por qué la flecha kubectl del diagrama está punteada y no sólida. En una frase, explica la diferencia visual entre las flechas sólidas del diagrama (Gitea→ArgoCD, ArgoCD→Admission, etc.) y la flecha punteada de kubectl.
Ver solución
Una explicación razonable: "Las flechas sólidas representan el flujo real por el que un cambio de andes-cargo-status-api llega al clúster desde el Módulo 5 en adelante — ninguna de ellas depende de que un humano ejecute un comando en el momento del cambio. La flecha punteada de kubectl representa una relación distinta: la herramienta que usas para observar el resultado (get, describe, logs), no para producirlo — está punteada, y marcada 'nunca la vía', precisamente para que no se confunda con las flechas del flujo de cambio real."
Resumen y siguiente paso
Esta lección confirmó, contra el clúster real, los once namespaces que existen hoy en andes-cargo-cluster — cuatro de infraestructura de kind, cinco de infraestructura del laboratorio, y uno solo con recursos de negocio (andes-cargo) — y presentó dos diagramas del mismo sistema desde ángulos distintos: el mapa espacial (qué vive en cada namespace) y la secuencia temporal (qué pasa, paso a paso, desde un git push hasta que el clúster converge o rechaza el cambio). La flecha punteada de kubectl, marcada "nunca la vía", es el detalle que las dos lecciones siguientes ponen a prueba con evidencia literal.
Antes de avanzar deberías poder: clasificar cualquiera de los once namespaces en su categoría correcta; trazar de memoria el camino completo de un git push hasta el clúster; y explicar por qué kubectl apply dejó de ser el mecanismo normal de cambio desde el Módulo 5.
Siguiente lección: un cambio que cruza el gate completo. Ahí vas a subir un cambio real a Git, y vas a confirmar, con evidencia literal, cada flecha de este diagrama funcionando en secuencia — sin un solo kubectl apply de por medio.
Recursos
- Kubernetes — Namespaces — referencia oficial del mecanismo de aislamiento lógico que organiza los once namespaces de este diagrama.
- Argo CD — How it Works — la descripción oficial del bucle de comparación continua que la secuencia mermaid de esta lección representa.
- Kubernetes — Dynamic Admission Control — el punto exacto del ciclo de vida donde
Gatekeeper + Kyvernointerceptan cada objeto en el diagrama de secuencia. kubernetes-and-eks-in-production-guide(NIEVA), Módulos 1-6 — la fuente de cada namespace y cada componente de este diagrama, construidos uno por uno.