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.
76 lines
3.7 KiB
Markdown
76 lines
3.7 KiB
Markdown
# Red y exposición
|
|
|
|
Los 5 dominios de abajo son reales y comparten exactamente el mismo
|
|
camino de red — ninguno tiene un caso especial.
|
|
|
|
## Dominios activos
|
|
|
|
| Dominio | Servicio | Namespace | TLS |
|
|
|---|---|---|---|
|
|
| `shop.cruzcloud.net` | Frontend Next.js (storefront) | `ecommerce` | Cloudflare (edge) |
|
|
| `commerce.cruzcloud.net` | Medusa Store/Admin API | `ecommerce` | Cloudflare (edge) |
|
|
| `media.cruzcloud.net` | MinIO (imágenes de producto) | `ecommerce` | Cloudflare (edge) |
|
|
| `gitea.cruzcloud.net` | Gitea | — | Cloudflare (edge) |
|
|
| `docs.cruzcloud.net` | Este portal | `docs` | Cloudflare (edge) |
|
|
|
|
## Por qué todos van "proxied" (naranja), ninguno "DNS-only"
|
|
|
|
Un registro DNS-only en Cloudflare expondría directamente la IP real
|
|
del túnel — pero acá no hay IP pública fija que exponer: el NAS está
|
|
detrás de NAT residencial. El modo proxied es lo que hace que
|
|
Cloudflare Tunnel tenga sentido en primer lugar (el tráfico entra por
|
|
el edge de Cloudflare, nunca directo al origen), así que no hay ningún
|
|
dominio de este lab para el que DNS-only sea una opción real.
|
|
|
|
## Dónde termina TLS de verdad
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
User(["Usuario"]) -->|HTTPS| CF["Cloudflare edge<br/>🔒 TLS termina acá"]
|
|
CF -->|túnel cifrado, HTTP/2| CFD["cloudflared"]
|
|
CFD -->|HTTP plano| NPM["Nginx Proxy Manager"]
|
|
NPM -->|HTTP plano| LB["k3d-proxy :90"]
|
|
LB -->|HTTP plano| TR["Traefik"]
|
|
TR -->|HTTP plano| SVC["Service interno"]
|
|
```
|
|
|
|
TLS termina en el **edge de Cloudflare**, no en Traefik ni en NPM. De
|
|
ahí hacia adentro (`cloudflared` → NPM → `k3d-proxy` → Traefik →
|
|
Service) todo el tráfico va en HTTP plano — seguro en este contexto
|
|
porque ese tramo entero vive dentro de la red local del NAS, nunca
|
|
sale a internet. Ningún componente interno necesita certificado propio
|
|
ni gestionar renovación de TLS.
|
|
|
|
## Por qué HTTP/2 y no QUIC en el túnel
|
|
|
|
`cloudflared` puede usar QUIC (UDP) o HTTP/2 (TCP) para sus conexiones
|
|
salientes hacia el edge. Este lab fuerza HTTP/2 explícitamente — no es
|
|
el default. Un incidente real de `504 Gateway Timeout` intermitente en
|
|
**todos** los subdominios (no solo uno) se rastreó hasta fallos
|
|
recurrentes del "control stream" de QUIC sobre la red doméstica del
|
|
NAS. Ver [ADR 0003](../decisiones/0003-por-que-http2-sobre-quic-tunnel.md)
|
|
para la decisión completa y el [playbook del 504](../playbooks/incidente-504-gitea-tunnel.md)
|
|
para el diagnóstico paso a paso.
|
|
|
|
## Patrón de diagnóstico: "interno sano, público roto"
|
|
|
|
Cuando un dominio público falla pero todo dentro del cluster responde
|
|
bien (pods `Running`, probes verdes, `kubectl exec` con `curl` al
|
|
Service funciona), la causa casi nunca está en Kubernetes — está en la
|
|
capa NPM. La forma rápida de confirmarlo es saltarse NPM a propósito:
|
|
`curl -H "Host: <dominio>" http://192.168.68.61:90/` habla directo con
|
|
`k3d-proxy`/Traefik sin pasar por NPM. Si eso funciona pero el dominio
|
|
público no, el problema está específicamente en el `forward_host`/
|
|
`forward_port` del proxy host en NPM (ej.: un scheme o un path colado
|
|
en `forward_host`, que rompe todo el enrutamiento).
|
|
|
|
Este patrón se repitió dos veces en este lab con la misma causa raíz
|
|
exacta: el [incidente de imágenes en `media.cruzcloud.net`](../playbooks/incidente-imagenes-npm.md)
|
|
(playbook completo) y un incidente posterior de `commerce.cruzcloud.net`
|
|
devolviendo 400 por el mismo tipo de `forward_host` roto (sin playbook
|
|
propio todavía). Una lección adicional de ese segundo incidente:
|
|
editar el `proxy_host` a mano en el sqlite de NPM **no** regenera el
|
|
`.conf` de nginx automáticamente — el cambio tiene que pasar por la
|
|
propia UI/API de NPM, o el `.conf` hay que parchearlo a mano y
|
|
recargar nginx.
|