From 7a83ed61b95962b7ca056280edeb6853f2f6f582 Mon Sep 17 00:00:00 2001 From: Cristian Felipe Cruz Buitron Date: Sun, 9 Aug 2026 02:34:15 -0500 Subject: [PATCH] fix(medusa): forzar podAffinity con commerce-postgres para evitar blackhole MTU cross-node Diagnostico: pg_isready y el cliente pg de Medusa fallan de forma consistente (100%, 186/186 intentos) cuando el pod queda agendado en un nodo distinto al de commerce-postgres-0. TCP handshake (nc/ping) funciona cruzando nodos, pero el primer paquete de datos real de la sesion nunca llega - blackhole de PMTU Discovery entre los nodos del cluster k3d (flannel VXLAN / MTU del bridge Docker subyacente). Se agrega podAffinity requiredDuringSchedulingIgnoredDuringExecution (no nodeSelector fijo, mantiene portabilidad) para que medusa-deploy siempre comparta nodo con commerce-postgres-0 y evite cruzar el blackhole. Es un workaround, no el fix de raiz: documentado en docs/known-issues.md junto con el TODO de ajustar el MTU del cluster a 1400. --- docs/known-issues.md | 44 ++++++++++++++++++++++++ workloads/ecommerce/commerce/medusa.yaml | 8 +++++ 2 files changed, 52 insertions(+) create mode 100644 docs/known-issues.md diff --git a/docs/known-issues.md b/docs/known-issues.md new file mode 100644 index 0000000..d0f87eb --- /dev/null +++ b/docs/known-issues.md @@ -0,0 +1,44 @@ +# 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). diff --git a/workloads/ecommerce/commerce/medusa.yaml b/workloads/ecommerce/commerce/medusa.yaml index 36e462f..e8b1abf 100644 --- a/workloads/ecommerce/commerce/medusa.yaml +++ b/workloads/ecommerce/commerce/medusa.yaml @@ -20,6 +20,14 @@ spec: imagePullSecrets: - name: gitea-registry-secret + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app: commerce-postgres + topologyKey: kubernetes.io/hostname + initContainers: - name: wait-for-postgres image: postgres:17-alpine