Files
apps-registry/workloads/docs-portal/docs/decisiones/0001-por-que-k3d.md
devops 056a7fb76a docs(docs-portal): Fase 2 - contenido narrativo real de arquitectura/decisiones/aprendizajes
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.
2026-08-26 23:51:18 -05:00

4.3 KiB

ADR 0001 — Por qué k3d (y no k3s directo, minikube, o un cluster cloud)

Estado: aceptada Fecha: 2026-08 (retroactiva — decisión tomada al arrancar el lab, documentada en Fase 2 del portal)

Contexto

El lab corre sobre un NAS ZimaOS doméstico, sin presupuesto para un cluster gestionado y con recursos modestos y compartidos con otras apps del NAS (Gitea, Nginx Proxy Manager, este mismo portal). El propósito del lab es doble: servir de portafolio técnico real y de material de estudio para el hijo del usuario (7mo semestre de Ingeniería de Sistemas) — ver guía del estudiante. Para que ambos objetivos tengan sentido, el cluster necesitaba comportarse como un Kubernetes real y multi-nodo, no como una caja de arena de un solo proceso: patrones como afinidad de pods, StatefulSets con almacenamiento persistente por nodo, y tráfico cross-node debían poder reproducirse y depurarse de verdad, no simularse.

También pesó la restricción del propio sistema operativo: / en ZimaOS es un squashfs de solo lectura y /usr es un overlay igualmente inmutable — instalar un binario nativo como k3s que espera escribir en /usr/local/bin, /etc/rancher, etc. de forma persistente no encaja bien con ese filesystem sin trabajo extra de por medio.

Opciones consideradas

Opción A favor En contra
k3d Multi-nodo real corriendo como contenedores Docker (server + agent), se crea/destruye en segundos, no toca el filesystem inmutable de ZimaOS más allá de /DATA Al ser Docker-in-Docker, hereda las capas de red de Docker — un blackhole de MTU/PMTUD real apareció por esto (ver Consecuencias)
k3s directo (sin Docker) Sin la capa extra de red de Docker-in-Docker, más cercano a un nodo "real" Necesita instalar servicios systemd y escribir en rutas de sistema (/usr/local/bin, /etc/rancher) que en ZimaOS son de solo lectura o requieren workarounds — solo /DATA y /etc quedan escribibles
minikube Instalación simple, muy documentado, ideal para aprender lo básico Single-node por defecto — no permite reproducir tráfico cross-node, afinidad de pods, ni el tipo de incidentes de infraestructura real que este lab busca documentar como aprendizaje
Cluster gestionado (cloud) Cero mantenimiento de infraestructura, SLA real Costo recurrente que este lab no tiene presupuestado; además reduce el valor de aprendizaje — gran parte de lo documentado en playbooks/ (MTU, DNS, límites de recursos) es justamente lo que un proveedor gestionado abstrae

Decisión

k3d, multi-nodo (hoy: 1 server + 1 agent, k3d-lab-cluster-server-0 / k3d-lab-cluster-agent-0), corriendo como contenedores Docker sobre el propio NAS.

Consecuencias

  • Se ganó un cluster real y gratuito, reproducible con un solo script (scripts/deploy-lab.sh), y suficientemente parecido a un Kubernetes de producción como para que los incidentes documentados en playbooks/ sean transferibles a un entorno cloud real.
  • Se pagó con un blackhole de red cross-node real: cualquier pod agendado en un nodo distinto al de commerce-postgres-0 (StatefulSet, fijo a un nodo) fallaba de forma consistente al hablar con Postgres — diagnosticado hasta el bit exacto (payload interno 1420 bytes OK, 1450 bytes blackhole total, sin ICMP "frag needed") y resuelto ajustando el MTU real de la interfaz flannel.1 a 1400 en cada nodo. Ver known-issues.md y el playbook del crashloop de Medusa para el diagnóstico completo. El fix no persiste solo — está automatizado en scripts/deploy-lab.sh (función fix_flannel_mtu), se reaplica cada vez que el cluster arranca o se recrea.
  • Deuda aceptada a propósito: el podAffinity que fuerza a medusa-deploy a compartir nodo con Postgres se dejó como red de contención extra después del fix de fondo — no es estrictamente necesario, pero es barato mantenerlo.
  • Para revertir esta decisión haría falta migrar a un cluster gestionado o a k3s nativo, lo que implicaría asumir el costo recurrente (cloud) o resolver las restricciones de filesystem inmutable de ZimaOS (k3s nativo) — ninguna de las dos se justifica hoy con el tamaño real del lab.