Tres incidentes resueltos en la sesión del 2026-08-12/13: 504 intermitente por QUIC inestable en cloudflared, precios null por falta de region_id en el Store API de Medusa v2 (se descarta la hipótesis inicial de regiones COP duplicadas con evidencia directa en Postgres), e imágenes en blanco por un proxy host mal configurado en Nginx Proxy Manager para media.cruzcloud.net. Se agregan también dos notas de referencia en known-issues.md: la topología Cloudflare Tunnel -> NPM -> k3d, y el requisito de region_id explícito en StoreGetProductsParams.
98 lines
4.9 KiB
Markdown
98 lines
4.9 KiB
Markdown
# Known issues
|
|
|
|
## Blackhole de red cross-node en el cluster k3d (MTU/PMTUD, flannel VXLAN)
|
|
|
|
**Estado:** workaround aplicado, fix definitivo pendiente.
|
|
|
|
**Síntoma:** cualquier pod que necesite hablar con `commerce-postgres-0`
|
|
(StatefulSet, sin réplicas, fijo a un nodo) falla de forma consistente y
|
|
reproducible al 100% cuando queda agendado en un nodo **distinto** al de
|
|
Postgres. El handshake TCP (SYN/ACK, `nc`, `ping`) funciona perfecto entre
|
|
nodos, pero el primer paquete de datos real de la sesión (protocolo Postgres,
|
|
`pg_isready` incluido) nunca llega — se cuelga hasta hacer timeout.
|
|
|
|
**Diagnóstico:**
|
|
|
|
- Confirmado aislando el nodo con `nodeName` en pods de prueba: 100% de
|
|
fallos (186/186 intentos) agendando cross-node (`agent-0` → Postgres en
|
|
`server-0`); 100% de éxito agendando en el mismo nodo.
|
|
- MTU dentro de los pods (interfaz `flannel.1`/VXLAN) es 1450 en ambos nodos
|
|
— consistente, no es un mismatch obvio a nivel flannel.
|
|
- `ping` sin `-M do` (permite fragmentación) no muestra pérdida de paquetes
|
|
hasta payloads de 2000 bytes entre los contenedores Docker de los nodos.
|
|
- Encaja con un blackhole de PMTU Discovery: el bridge Docker externo que
|
|
conecta los contenedores de los nodos k3d probablemente tiene un MTU real
|
|
menor a 1500, y los paquetes TCP con el bit DF puesto (como los de la
|
|
sesión de Postgres) se pierden en vez de fragmentarse o generar el ICMP
|
|
"fragmentation needed" que permitiría el ajuste automático.
|
|
|
|
**Workaround temporal (aplicado en `workloads/ecommerce/commerce/medusa.yaml`):**
|
|
|
|
`podAffinity` con `requiredDuringSchedulingIgnoredDuringExecution` sobre
|
|
`medusa-deploy`, forzando que sus pods se agenden siempre en el mismo nodo
|
|
que `commerce-postgres-0` (`matchLabels: app: commerce-postgres`,
|
|
`topologyKey: kubernetes.io/hostname`). Esto evita el tráfico cross-node
|
|
entre Medusa y Postgres, pero no resuelve el problema de fondo — cualquier
|
|
otro workload que necesite cruzar nodos para hablar con Postgres (u otro
|
|
servicio) puede pisar el mismo blackhole.
|
|
|
|
**TODO — fix definitivo pendiente:**
|
|
|
|
Ajustar el MTU del cluster k3d a un valor seguro (`1400`) de forma
|
|
consistente en la red Docker del cluster y en flannel, para eliminar el
|
|
blackhole de raíz y poder quitar el `podAffinity` (o dejarlo como
|
|
optimización, no como requisito de disponibilidad).
|
|
|
|
## Topología de red: Cloudflare Tunnel → Nginx Proxy Manager → k3d
|
|
|
|
**Estado:** referencia de arquitectura — no es un issue abierto, pero el
|
|
patrón de falla que describe ya se repitió una vez (ver
|
|
`docs/playbooks/incidente-medusa-imagenes-proxy-npm-2026-08.md`) y puede
|
|
volver a aparecer con otro subdominio.
|
|
|
|
**Ruta real de una petición pública a `*.cruzcloud.net`:**
|
|
|
|
```
|
|
Internet → Cloudflare (DNS proxied, túnel) → contenedor `cloudflared`
|
|
(app nativa de ZimaOS, red Host) → Nginx Proxy Manager
|
|
(contenedor `nginxproxymanager`, config en
|
|
/DATA/AppData/nginxproxymanager/data/) → 192.168.68.61:90
|
|
→ `k3d-lab-cluster-serverlb` (k3d-proxy, publica 90→80 y 9443→443)
|
|
→ Traefik (ingress del cluster) → Service correspondiente,
|
|
enrutado por el header `Host`.
|
|
```
|
|
|
|
Los proxy hosts de NPM viven en
|
|
`/DATA/AppData/nginxproxymanager/data/database.sqlite` (tabla
|
|
`proxy_host`) y NPM regenera solo el `.conf` correspondiente en
|
|
`data/nginx/proxy_host/<id>.conf` cuando cambia la fila en la base —
|
|
no hace falta editar el `.conf` a mano, y si se edita a mano puede
|
|
sobreescribirse en cualquier cambio posterior desde la UI/DB.
|
|
|
|
**Patrón de diagnóstico:** si un subdominio `*.cruzcloud.net` responde
|
|
`500 Internal Server Error` con header `Server: openresty` cuando se
|
|
accede públicamente, pero el mismo path funciona bien contra el
|
|
ingress interno del cluster (`curl -H "Host: <subdominio>"
|
|
http://<IP-del-nodo>/...`), el problema **no está en el cluster ni en
|
|
la app** — está en el proxy host de NPM para ese subdominio. Revisar
|
|
`forward_host`/`forward_port` en la tabla `proxy_host` y compararlos
|
|
contra un host que sí funcione (ej. `shop.cruzcloud.net`,
|
|
`commerce.cruzcloud.net`, ambos con `forward_host='192.168.68.61'`,
|
|
`forward_port=90`).
|
|
|
|
## Nota de arquitectura: Medusa v2 Store API requiere `region_id` explícito
|
|
|
|
**Estado:** no es un issue, es un requisito de la API que causó un
|
|
incidente real por no ser conocido — ver
|
|
`docs/playbooks/incidente-medusa-precios-region-id-2026-08.md`.
|
|
|
|
El endpoint `/store/products` de Medusa v2 (validado por
|
|
`StoreGetProductsParams`, `.strict()`) **no acepta `currency_code` ni
|
|
`country_code`** como parámetros para resolver el contexto de precio
|
|
(`calculated_price`). El único parámetro válido para ese fin es
|
|
`region_id`, apuntando a una región existente y configurada vía Admin
|
|
API. Cualquier integración nueva contra el Store API de Medusa v2 que
|
|
necesite precios calculados debe pasar `region_id` explícito — no
|
|
asumir que `currency_code` o `country_code` son suficientes, aunque lo
|
|
sean en Medusa v1 o en otras APIs de e-commerce.
|