Reemplaza los placeholders "TODO (fase 2+)" por narrativa completa, grounded en el codigo/manifiestos/incidentes reales del lab (no generico): - ADR 0001 (por que k3d) y ADR 0002 (por que Argo CD): pasan de template vacio a Contexto/Opciones/Decision/Consecuencias reales, apoyados en known-issues.md (blackhole MTU) y en la config real de ecommerce-app.yaml. - vision-general.md: el "por que" de cada frontera de confianza del diagrama. - gitops-flujo.md: ejemplo real con hashes de commit (Fase 3b de ADR 0006, v1.0.171 -> hotfix -> v1.0.172), selfHeal explicado con el syncPolicy real del repo. - red-y-exposicion.md: diagrama de terminacion TLS real, por que todo va "proxied", patron de diagnostico "interno sano, publico roto". - glosario.md: 9 terminos nuevos, cada uno con ejemplo real y verificado del repo (Namespace, ResourceQuota, LimitRange, NetworkPolicy, Deployment, Service, Ingress, StatefulSet, Init container). - notas-sueltas.md: MinIO/S3, limites reales del subscriber revalidate-storefront.ts, que se automatizaria desde cero. Validado con `docker build --target build` (mkdocs build --strict, mismo paso que el pipeline real) -- cero links rotos, cero warnings.
4.6 KiB
Visión general
Este lab corre sobre un NAS ZimaOS doméstico, sin IP pública ni presupuesto de nube — cada capa del diagrama de abajo existe por una razón concreta de ese contexto, no por moda arquitectónica. Esta página explica el "por qué" de cada frontera; el "cómo" vive en las páginas enlazadas al final de cada sección.
Flujo de una petición pública
flowchart LR
User(["Usuario"]) -->|HTTPS| CF["Cloudflare<br/>(DNS proxied + túnel)"]
CF -->|HTTP/2, red host| CFD["cloudflared<br/>(app ZimaOS)"]
CFD --> NPM["Nginx Proxy Manager<br/>192.168.68.61:90"]
NPM --> LB["k3d-lab-cluster-serverlb<br/>(k3d-proxy, 90→80)"]
LB --> TR["Traefik<br/>(ingress del cluster)"]
TR -->|Host: shop.cruzcloud.net| FE["frontend-svc<br/>(Next.js)"]
TR -->|Host: commerce.cruzcloud.net| MED["medusa-svc<br/>(Medusa API)"]
TR -->|Host: media.cruzcloud.net| MIN["minio-svc<br/>(imágenes de producto)"]
TR -->|Host: gitea.cruzcloud.net| GIT["Gitea"]
TR -->|Host: docs.cruzcloud.net| DOCS["docs-portal-svc<br/>(este sitio)"]
subgraph GitOps["Control plane GitOps"]
ARGO["Argo CD"] -->|sync| FE
ARGO -->|sync| MED
ARGO -->|sync| DOCS
GIT -.->|watch repos| ARGO
end
Componentes
| Capa | Qué es | Dónde vive |
|---|---|---|
| Cloudflare Tunnel | Expone *.cruzcloud.net a internet sin abrir puertos en el NAS |
Fuera del cluster, app nativa ZimaOS (cloudflared) |
| Nginx Proxy Manager | Enruta por dominio hacia el cluster | Fuera del cluster, contenedor nginxproxymanager |
| k3d | Cluster Kubernetes local (multi-nodo, Docker) | Host ZimaOS |
| Traefik | Ingress controller del cluster | Dentro de k3d |
| Argo CD | Sincroniza el estado del cluster con Git (patrón App of Apps) | Namespace argocd |
| Gitea | Origen de verdad de los manifiestos y del código de las apps | Contenedor propio, expuesto vía túnel |
Por qué cada frontera está donde está
Cloudflare Tunnel, no port-forwarding. El NAS vive detrás de NAT
residencial, sin IP pública fija. En vez de abrir puertos en el router
(superficie de ataque directa contra el hogar), cloudflared abre una
conexión saliente hacia Cloudflare y todo el tráfico público viaja
hacia adentro por esa misma conexión — el origen nunca expone un
puerto escuchando en internet. El transporte de esa conexión se fijó a
HTTP/2 en vez del QUIC por defecto tras un incidente real de
inestabilidad; ver ADR 0003.
Nginx Proxy Manager, fuera del cluster. No todo lo que sirve
*.cruzcloud.net vive dentro de k3d — Gitea, por ejemplo, corre como
contenedor Docker aparte. NPM es el único punto de enrutamiento por
dominio que necesita conocer ambos mundos (cluster y no-cluster), así
que vive fuera de Kubernetes a propósito, no por descuido.
k3d-lab-cluster-serverlb, la frontera de entrada al cluster. Es
el load balancer que el propio k3d monta automáticamente para publicar
puertos del host hacia los nodos internos — no es un componente que
este lab configuró a mano, viene con la topología multi-nodo elegida
en ADR 0001.
Traefik, enrutamiento por Host dentro del cluster. Una vez el
tráfico entra al cluster por un único puerto (90/9443), Traefik es
quien decide a qué Service mandarlo según el header Host de cada
petición — así NPM solo necesita saber "todo *.cruzcloud.net va al
puerto 90 del cluster", sin tener que aprender un forward_host nuevo
cada vez que se agrega un servicio interno. Cuando esta capa falla en
silencio (forward_host/forward_port mal apuntado en NPM), el
síntoma es siempre el mismo: "internamente sano, públicamente roto" —
ver Red y exposición.
Argo CD, el único escritor del cluster. Ningún pipeline de CI ni
ninguna persona corre kubectl apply contra producción — Argo CD es
la única pieza con permisos de escritura, y reconstruye
automáticamente cualquier diferencia entre Git y el cluster real
(selfHeal: true). El porqué completo de esa elección está en
ADR 0002; el paso a
paso de un commit real hasta quedar corriendo, en
Flujo GitOps.
Gitea, autoalojado. Además de alojar el código, Gitea corre el CI (Gitea Actions) y el registry de imágenes en el mismo lugar — un solo componente autoalojado en vez de depender de la disponibilidad y los límites de un servicio externo gratuito para un lab que ya de por sí no tiene presupuesto de nube.
Ver también: Red y exposición · Flujo GitOps · Glosario