Saltar a contenido

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