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