feat(docs-portal): pipeline GitOps y manifiestos K8s para el portal MkDocs

Agrega lo que faltaba para desplegar workloads/docs-portal/ (ya existente
sin commitear): deployment/service/ingress + kustomization siguiendo el
patrón de workloads/nginx, Applications de workload y gobernanza
separadas, y el workflow de Gitea Actions (build+push a Gitea Registry,
bump de versión en el manifiesto) siguiendo el mismo patrón que
build.yaml/build-medusa.yaml.
This commit is contained in:
2026-08-13 21:08:04 -05:00
parent 11737ba109
commit fb5cf8bc98
27 changed files with 1328 additions and 0 deletions
@@ -0,0 +1,88 @@
# Incidente: 504 Gateway Timeout intermitente (túnel QUIC inestable) (2026-08)
!!! info "Origen"
Migrado desde `apps-registry/docs/playbooks/incidente-cloudflared-504-quic-2026-08.md`.
Contenido técnico preservado sin cambios de fondo — solo formato adaptado a MkDocs Material.
| | |
|---|---|
| **Ventana del incidente** | Intermitente durante varias horas, 2026-08 |
| **Servicio afectado** | `cloudflared` (túnel de Cloudflare, app nativa de ZimaOS, red Host) — afecta a **todos** los subdominios detrás del mismo túnel (`gitea.cruzcloud.net`, `commerce.cruzcloud.net`, `shop.cruzcloud.net`, `media.cruzcloud.net`, Immich, Argo CD, Memos, etc.) |
| **Impacto** | `504 Gateway Timeout` intermitente en peticiones HTTP a cualquier host detrás del túnel, sin patrón evidente de horario ni de carga |
## Síntoma
`gitea.cruzcloud.net` devolvía `504 Gateway Timeout` de forma
intermitente. El mismo síntoma se observaba en otros hosts servidos por
el mismo túnel, lo que apuntaba a una causa **compartida a nivel de
túnel**, no de una app individual.
## Diagnóstico
```bash
docker logs -f cloudflared 2>&1 | grep -i -E "connIndex|protocol|retry"
```
Reveló un patrón sostenido durante horas: la conexión `connIndex=2`
(de las 4 conexiones que `cloudflared` mantiene hacia el edge de
Cloudflare) sufría fallos recurrentes de "control stream" cada 2-6
minutos, reconectándose en loop:
```text
control stream encountered a failure while serving
Retrying connection in up to 1m4s
```
Cuando una petición HTTP coincidía con el instante exacto de una de
esas caídas de `connIndex=2`, el cliente recibía el 504.
## Causa raíz
El contenedor `cloudflared` (imagen oficial `cloudflare/cloudflared:latest`)
usaba **QUIC (UDP)** como protocolo de transporte por defecto para sus
4 conexiones hacia el edge de Cloudflare. Una de esas conexiones
presentaba fallos de control stream recurrentes durante horas.
!!! warning "Causa de fondo probable"
Inestabilidad de UDP/QUIC en la red local (NAT/firewall doméstico).
QUIC es más sensible que TCP/HTTP2 a NATs agresivos o middleboxes
que no manejan bien tráfico UDP de larga vida — un patrón común en
redes domésticas, a diferencia de datacenters con NAT dedicado para
este tipo de tráfico.
## Fix aplicado
Se agregó la variable de entorno `TUNNEL_TRANSPORT_PROTOCOL=http2` en
la configuración del contenedor `cloudflared` (app ZimaOS → Ambiente →
variables), forzando HTTP/2 sobre TCP en vez de QUIC/UDP.
Tras reiniciar el contenedor, el precheck de `cloudflared` confirmó:
```text
Environment is healthy. cloudflared will use 'http2' as primary protocol.
```
y las 4 conexiones pasaron a `protocol=http2`.
Ver también el ADR correspondiente:
[0003 — Por qué HTTP/2 sobre QUIC](../decisiones/0003-por-que-http2-sobre-quic-tunnel.md).
## Validación
Curl en loop contra `gitea.cruzcloud.net` tras el cambio: latencia
estable ~0.370.4s sostenida por 24+ minutos sin un solo 504.
!!! note "Degradación puntual no relacionada, pendiente de vigilar"
Durante la ventana de validación se observó una ventana breve de
latencia alta (hasta 39s) y algunos `502`/`530`, coincidiendo con
una ejecución pesada de Gitea Actions (build/deploy de Medusa) en
el mismo host. Esto es contención de recursos local (CPU/IO del
host compitiendo entre el runner de Actions y el resto de los
servicios), **no relacionado al fix de protocolo del túnel** — no
se reabrió como parte de este incidente.
**Pendiente:** vigilar si estas ventanas de degradación coinciden
sistemáticamente con builds/deploys de Gitea Actions. Si es
recurrente, considerar mover el runner (`gitea-runner`) a otro host
o limitarle recursos para evitar que compita con el resto de las
apps del NAS.