Cinco niveles de madurez de la plataforma debajo del LLM: del servidor con Linux al cluster listo para vLLM

TL;DR

El post de las siete capas del stack de inferencia LLM daba por supuestas muchas piezas: un cluster Kubernetes operativo, GitOps reconciliando, identidades resueltas, GPUs visibles para el scheduler, observabilidad capaz de transportar gen_ai.*. Antes de que vLLM tenga sentido, hay que llegar a ese punto de partida, y se llega por niveles. Este post define cinco niveles de madurez de la plataforma que vive debajo del LLM, desde un servidor bare metal con Linux instalado (nivel 0) hasta un cluster listo para correr la capa de inferencia (nivel 4) y el handoff al post anterior (nivel 5). Cada nivel desbloquea una capacidad concreta —ejecutar contenedores con reproducibilidad, reconstruir el cluster desde git, autenticar humanos vía OIDC, programar GPUs con MIG y métricas DCGM, demostrar compliance sin intervención manual— y cada uno tiene un test de validación que decide si estás de verdad ahí o solo te lo cuentas. Para cada nivel: qué piezas OSS lo cubren en 2026 (Cilium, RKE2, Flux, cert-manager, Defguard, NVIDIA GPU Operator, KEDA, Trivy, Kyverno…), el orden de despliegue dentro del nivel, las decisiones que cuesta caro saltarse, y los antipatrones que te bajan de nivel cuando creías estar arriba. La tesis: subir de nivel cuesta poco esfuerzo si lo haces a tiempo, y mucho refactor si pretendes saltártelo. La inferencia LLM exige al menos nivel 4; quien intenta servir LLMs desde un nivel 1 o 2 acaba pagando con incidentes nocturnos lo que se ahorró en plataforma.

Estás aquí: los cinco niveles de un vistazo

Antes del detalle, la escalera. Cada peldaño añade una capacidad ausente en el anterior. El test del nivel es la pregunta cuya respuesta honesta dice si ya estás en él.

Cinco niveles de madurez (más el handoff al stack LLM en el nivel 5)NIVEL 0 · CAÓTICOBare metal con Linux · docker / podman ad-hoc · sin orquestador · cambios manuales con SSHNIVEL 1 · REPETIBLECluster k8s instalado (RKE2 / kubeadm) · CNI · CSI · kubectl apply / Helm desde terminal · pods rodandoNIVEL 2 · DEFINIDOGitOps (Flux) · registry interno · observabilidad infra · backups · el cluster se reconstruye desde el repoNIVEL 3 · GESTIONADOOIDC + RBAC · cert-manager · External Secrets · Kyverno · NetworkPolicy default deny · auditoríaNIVEL 4 · OPTIMIZADO PARA GPUNVIDIA GPU Operator · DCGM Exporter · MIG / time-slicing · KEDA con métricas LLM · OTel listo para gen_ai.*NIVEL 5 · HANDOFF— el cluster está preparado para que el stack LLM (las 7 capas) tenga sentido

Los niveles no son intercambiables. Un cluster en nivel 2 no puede correr LLMs en producción con garantías: técnicamente carga el pod de vLLM, pero al primer incidente nocturno se descubre que no hay TLS, ni identidades, ni alerting, ni métricas GPU, ni forma de saber quién cambió qué. Subir un nivel después de tener LLMs ya en producción cuesta órdenes de magnitud más que subirlo cuando el cluster aún está vacío.

La analogía: del puesto callejero al restaurante con estrella

Imagina la escala de un negocio de hostelería. Nivel 0 es el puesto callejero: una plancha, una bombona, un cocinero que improvisa. Puede vender comida — funciona — pero cualquier cosa que se desvíe del día normal (una inspección sanitaria, un cliente alérgico, un pedido de 200 raciones) le tira el negocio. Nivel 1 es el bar de tapas: cocina dimensionada, carta corta repetible, varios turnos. El cocinero ya no improvisa cada día; trabaja sobre un menú escrito, aunque las recetas viven en la cabeza del jefe. Nivel 2 es el restaurante con menú del día: hay procedimientos escritos, proveedores fijos, control de stock, libro de incidencias. Si el cocinero principal se cae enfermo, el segundo puede sacar el servicio sin estragos. Nivel 3 es el restaurante con carta y servicio formal: trazabilidad de cada ingrediente, alérgenos en la carta, certificación sanitaria, contrato con los proveedores, formación obligatoria del personal. Nivel 4 es la cocina especializada en un producto complejo (sushi, alta cocina, panadería artesanal): herramientas específicas que el restaurante normal no necesita (horno de leña, cuchillos especiales, cámara de fermentación), procesos calibrados, métricas de calidad. Nivel 5 es el restaurante con estrella Michelin: el sistema entero funciona, el plato es el resultado de la organización, no del talento de una persona.

La analogía aguanta hasta el final, incluido el detalle más interesante: se puede operar a cualquier nivel, pero las promesas que se pueden cumplir son distintas. El puesto callejero no puede prometer una experiencia consistente a 80 comensales con reserva. El cluster en nivel 1 no puede prometer servicio LLM productivo multi-tenant con SLA. En ambos casos el problema no es de capacidad técnica del último componente (la plancha cocina; el pod arranca); es de capacidad organizativa del sistema entero.

Vamos nivel por nivel.

Nivel 0 — Caótico: el servidor con Linux y nada más

La capacidad que da. Ejecutar contenedores con docker/podman, ejecutar binarios, conectar el servidor a la red. El operador puede entrar por SSH, hacer cosas, y ver resultados.

El test del nivel. “Si reinstalo el servidor desde cero, ¿puedo dejarlo idéntico a como estaba en una tarde, usando sólo notas guardadas?”. Si la respuesta es no (porque los pasos están en la cabeza del que lo montó, en .bash_history, en un wiki desactualizado), estás en nivel 0.

Piezas mínimas que dejar resueltas antes de subir a nivel 1.

PiezaDecisión sugerida en 2026Por qué importa al subir
Distribución LinuxDebian estable u Ubuntu LTSSoporte largo, predecible, kernel reciente disponible
KernelLTS reciente (≥ 6.6) con BPF y schedulers modernosCilium/eBPF, drivers NVIDIA recientes lo exigen
Drivers NVIDIAVersión que casa con la CUDA del motor LLM que vas a servirMismatch driver/CUDA bloquea vLLM antes de empezar
Container runtimecontainerdEstándar CNCF, integrado con RKE2/kubeadm
Filesystem raízXFS o ext4 + LVM thin poolsSnapshots, ampliación en caliente
Sincronización horariachrony con servidores propiosTLS, logs correlados, certificados cortos lo exigen
Red de gestiónVLAN dedicada, ACLs en switchAislar plano de control del tráfico de carga
Red de clusterLACP + jumbo frames + BGP (si vas a Cilium)NVLink intra-nodo no salva la red de servicio
BMC / IPMIAcceso fuera de banda con TLS y MFARecuperación cuando el sistema operativo no arranca

Antipatrones que te dejan clavado en nivel 0.

  • Servidores mascota (con nombre propio, configurados a mano, no reemplazables).
  • Cambios aplicados con vi directo sobre /etc/... sin commit a un repo.
  • Despliegue con docker-compose sin healthchecks ni reinicio automático.
  • Inventario que vive en una hoja Excel que nadie actualiza.

Orden de despliegue dentro del nivel. Imagen del sistema desde PXE/cloud-init con configuración inicial (LVM, hostname, red, SSH key, chrony) → bootstrap de bastion/jump host → inventario en Ansible (o equivalente declarativo aunque luego se reemplace) → drivers NVIDIA + container runtime → smoke test (un contenedor CUDA pasa nvidia-smi). En este punto, el servidor está listo para que entre Kubernetes.

Nivel 1 — Repetible: cluster Kubernetes operativo

La capacidad que da. Programar contenedores con scheduler, abstracción de red entre pods, volúmenes persistentes, lifecycle de cargas, escalado horizontal manual.

El test del nivel. "¿Puedo perder un nodo y que las cargas se reprogramen sin intervención humana?". Si sí, estás en nivel 1. Si no — porque los pods están pinneados a nodos, porque no hay réplicas, porque las PVCs no se reattachean — sigues en 0 con Kubernetes encima.

Piezas mínimas del nivel.

PiezaDecisión sugerida en 2026Alternativa principal
Distribución k8sRKE2 (CIS-hardened por defecto, sin sobrecosto comercial)k3s para edge muy pequeño, kubeadm puro para casos custom
CNICilium con kube-proxy replacement, BGP, Gateway APICalico (sin BGP no compite contra Cilium en 2026)
CSI block + filesystem + objectRook-Ceph (RBD + CephFS + RGW S3-compatible)OpenEBS Mayastor + Garage para deployments pequeños
IngressCilium Gateway API (mejor unificar con CNI)NGINX Ingress, Traefik
Cert básicoSelf-signed bootstrap(cert-manager entra en nivel 3)
Manejo de cargaskubectl apply + Helm desde terminalSin GitOps todavía
Container registryCualquier registry interno (o externo de confianza) con TLS(registry interno gestionado entra en nivel 2)

Antipatrones que te bajan a nivel 0.

  • Servicios desplegados con kubectl apply desde la terminal de una persona y sin guardar el YAML en ninguna parte.
  • Volúmenes persistentes sin política de backup.
  • “Cluster de un nodo” como producción permanente — un solo punto de fallo arquitectónico.
  • CNI sin NetworkPolicy disponible o sin BGP cuando la red lo requiere.

Orden de despliegue dentro del nivel. RKE2 instalado en al menos tres nodos para control plane HA → Cilium instalado en modo kube-proxy replacement + BGP control plane → Rook-Ceph en al menos tres nodos cubriendo block (RBD) + filesystem (CephFS) + object (RGW S3-compatible) con replicación 3× o Erasure Coding según pool → smoke test (un Deployment con PVC arranca, los pods se reschedulean al cordon de un nodo, los datos persisten).

Nivel 2 — Definido: el cluster se reconstruye desde git

La capacidad que da. El estado del cluster vive en un repositorio. Cualquier cambio pasa por commit. Cualquier persona puede reconstruir el cluster (o uno equivalente) desde el repo y los backups. La observabilidad básica avisa cuando algo se rompe.

El test del nivel. “Si pierdo el cluster entero, ¿puedo recrearlo en X horas desde el repo + los backups, sin intervención manual fuera del bootstrap?”. Las dos horas son negociables; lo que define el nivel es que el repo + los backups bastan, no que la persona-que-sabe esté disponible.

Piezas mínimas del nivel.

PiezaDecisión sugerida en 2026Por qué
ForgeForgejo (o Gitea, GitLab CE)OSS auto-alojado, fork comunitario de Gitea, gobernanza abierta
Reconciliador GitOpsFluxCNCF graduado, multi-tenancy nativo, lightweight
Registry de imágenesForgejo Container RegistryJunto al código, sin pieza extra
TSDB métricasVictoriaMetrics + vmagentThroughput superior a Prometheus puro, retención larga, compatible PromQL
VisualizaciónGrafanaEstándar de facto
LogsLoki o VectorOSS, integrado con Grafana
AlertingAlertmanager + Keep (orquestador OSS)Keep añade enrutamiento multi-canal sin lock-in
Backups DBBarman Cloud (Postgres)Estándar para CNPG
Backups objeto / datasetCeph RGW multisite + snapshots CephFSCross-pool y cross-site

Antipatrones que te bajan a nivel 1.

  • kubectl apply aplicado en producción fuera del repo (drift no detectado).
  • Branches main con permisos de escritura para humanos sin revisión.
  • Repo monolítico sin separación tenant/infra/apps (cambios cruzados no auditables).
  • Métricas que no se conservan más de 7 días (sin SLO observable a un mes vista).
  • Alerting que dispara para todo (fatiga) o para nada (silencio).

Orden de despliegue dentro del nivel. Forgejo desplegado primero (es prerrequisito de todo lo demás) → Flux instalado y apuntando al repo de manifests → repositorio inicial con Helm releases de Cilium y Rook-Ceph reconciliados por Flux (sustituyendo los kubectl apply del nivel 1) → VictoriaMetrics + Grafana + Loki vía Helm/Flux → backups Postgres y snapshots Ceph programados → smoke test (tira el cluster, restaura desde repo + backup, los servicios vuelven).

Nivel 3 — Gestionado: identidades, certificados, secretos y políticas

La capacidad que da. Cualquier humano que opera el cluster lo hace con identidad propia (no kubeconfig compartido), con MFA y con permisos limitados. TLS interno automático. Secretos versionados encriptados. Políticas que rechazan configuraciones inseguras antes de que entren al cluster. Auditoría completa de quién hizo qué.

El test del nivel. “Si un atacante consigue el portátil de un administrador, ¿qué puede hacer en producción?”. En nivel 3 la respuesta es “poco”: MFA bloquea el segundo factor, las políticas Kyverno bloquean cambios destructivos sin aprobación, las NetworkPolicies impiden lateral movement, los secretos están encriptados con KMS externo, el audit log queda. En nivel 2, “todo”.

Piezas mínimas del nivel.

PiezaDecisión sugerida en 2026Por qué
IdP / OIDCDefguardOSS español, WireGuard + OIDC + 2FA, multi-org
Federación con clusterOIDC en kube-apiserver, OIDC en Forgejo, OIDC en GrafanaSSO consistente
PKI internacert-manager + Trust ManagerEstándar de facto, ACME y CA interna
ACME externoLet’s Encrypt para certs de bordeSin pago, automatizado
Secretos en gitSOPS + age o KMS externoVersionable, encriptado en repo
Sync de secretosExternal Secrets OperatorPull desde KMS / Vault al cluster
Policy as codeKyverno (o OPA Gatekeeper)Kyverno tiene menos curva de aprendizaje
NetworkPolicyCilium NetworkPolicy + L7Default deny per namespace
Runtime securityTetragon (Cilium)eBPF, complementa NetworkPolicy con detección
Vulnerability scanningTrivy en pipeline CI + admissionSBOM por imagen, bloqueo de CVE críticas
Audit logkube-apiserver con --audit-policy-file enviado a LokiTrazabilidad regulatoria

Políticas Kyverno mínimas a tener vivas.

  • Deny de imágenes :latest o sin sha digest.
  • Deny de pods sin securityContext.runAsNonRoot=true.
  • Deny de pods sin resources.limits (CPU + memoria).
  • Deny de Services sin label owner=<equipo>.
  • Deny de cambios en namespaces críticos (kube-system, flux-system) sin label de aprobación.

Antipatrones que te bajan a nivel 2.

  • kubeconfig compartido entre administradores.
  • Secretos en data: plano del manifest commiteado al repo.
  • NetworkPolicy ausente en namespaces nuevos por defecto (allow-all implícito).
  • kubectl edit o kubectl patch en producción sin pasar por el repo.

Orden de despliegue dentro del nivel. Defguard desplegado y enrolado con WireGuard / OIDC → integración OIDC con kube-apiserver, Forgejo y Grafana → cert-manager instalado y emitiendo certificados internos (CA propia para mTLS, Let’s Encrypt para borde) → SOPS configurado y External Secrets Operator instalado → migración de secretos plano → encriptado → Kyverno con políticas iniciales y modo audit, después enforce → NetworkPolicy default-deny por namespace → Tetragon habilitado → smoke test (intentar saltarse cada política y comprobar que las admisiones rechazan).

Nivel 4 — Optimizado para GPU: el cluster ya sabe lo que es una H100

La capacidad que da. El scheduler de Kubernetes ve las GPUs, las distingue, las puede particionar (MIG) o multiplexar (time-slicing), exponer métricas DCGM, autoescalar con KEDA usando métricas de la propia carga LLM (vllm:num_requests_running, vllm:gpu_cache_usage_perc), transportar trazas con semantic conventions GenAI. Todo lo necesario para que el stack de inferencia LLM se apoye en una plataforma que entiende su naturaleza.

El test del nivel. “Si pongo un pod que pide nvidia.com/gpu: 1, ¿se programa en la GPU correcta, con el slice correcto, con métricas DCGM expuestas, con observabilidad GenAI lista para recibir spans?”. Si sí, estás en nivel 4. Si la respuesta requiere “depende de qué nodo y quién lo despliegue”, todavía no.

Piezas mínimas del nivel.

PiezaDecisión sugerida en 2026Por qué
GPU device pluginNVIDIA GPU OperatorDespliega drivers, container toolkit, DCGM y MIG manager con un operator
Particionamiento HWMIG (Multi-Instance GPU) en H100 cuando apliqueAislamiento hardware real, no time-slicing
Métricas GPUDCGM ExporterSM utilization, VRAM, temperatura, throttling, NVLink bandwidth
Métricas LLMvLLM Prometheus endpoint + scrapeTTFT, TPOT, KV cache, prefix hit rate
AutoscalingKEDA con ScaledObject PrometheusEscala por métricas LLM, no por CPU
Operadores LLMvLLM Production Stack / OME (Operator Model Engine)Manejo declarativo de modelos / adapters
TrazasOpenTelemetry Collector con receivers OTLP + processors + exportersSemantic conventions gen_ai.* (post)
LeaderWorkerSetAPI LeaderWorkerSet (k8s 1.30+)Topología tensor parallel coherente con NVLink
Topology Managerhabilitado con single-numa-nodePin de pods GPU a NUMA correcta

Decisión clave: MIG, time-slicing o pasthrough.

  • MIG divide una H100 en 1g.10gb, 2g.20gb, 3g.40gb, 7g.80gb (slices con aislamiento HW real). Útil para servir varios modelos pequeños o reservar capacidad por tenant con garantía. Limitación: hasta 7 instancias por GPU, perfiles predefinidos.
  • Time-slicing comparte una GPU entre varios pods sin aislamiento HW. Útil para dev/test, no para producción multi-tenant con SLA.
  • Passthrough asigna la GPU entera a un pod. Útil para tensor parallel sobre múltiples GPUs del mismo nodo (LLM grande con TP=4).

Para una plataforma LLM productiva, la regla práctica: passthrough para los modelos grandes con TP, MIG para embeddings y modelos pequeños que cohabitan, nunca time-slicing en producción.

Antipatrones que te bajan a nivel 3.

  • Instalar drivers NVIDIA a mano fuera del GPU Operator (rotura silenciosa al actualizar Kubernetes).
  • Servir un LLM con requests.gpu: 1 sin haber decidido MIG / passthrough (terminas con GPUs idle por fragmentación o pods que se pisan).
  • KEDA autoscalando por CPU (HorizontalPodAutoscaler clásico) en pods que están casi siempre al 10% de CPU pero al 95% de KV cache.
  • OpenTelemetry desplegado pero sin semantic conventions gen_ai.* (las trazas no son LLM-aware).

Orden de despliegue dentro del nivel. NVIDIA GPU Operator instalado vía Helm/Flux con la versión de driver que case con el motor LLM elegido → DCGM Exporter habilitado y métricas visibles en Grafana (dashboards NVIDIA importados) → MIG manager configurado para los nodos donde tenga sentido (mezcla typical en cluster 4×H100 SXM: dos GPUs con passthrough completo para el LLM general TP=4, dos GPUs particionadas en 2×3g.40gb cada una para LLMs pequeños + embeddings) → OpenTelemetry Collector con processors attributes para enriquecer spans con etiquetas propias (tenant_id, priority_tier) + exporters a Langfuse y a Tempo → KEDA instalado con ScaledObject de ejemplo apuntando a vllm:num_requests_running → vLLM Production Stack o OME para declarar modelos como CRD → smoke test (un Deployment de vLLM declarado vía CRD arranca, sirve un token, expone métricas, la traza llega a Langfuse, KEDA escala bajo carga sintética).

Nivel 5 — Handoff: el cluster es plataforma LLM, las siete capas entran encima

Llegado al nivel 4, el cluster cumple el contrato que el post de las siete capas asumía como punto de partida. El nivel 5 no añade infraestructura: añade el stack LLM propiamente dicho. Por completitud, los siete componentes del nivel 5 son:

  1. Gateway (Envoy AI Gateway) — entra primero, dirige tráfico a inferencia LLM y embeddings.
  2. Inferencia LLM (vLLM Production Stack o OME con vLLM) — sobre las GPUs ya descubiertas por el GPU Operator del nivel 4.
  3. Embeddings + reranker (Infinity, TEI) — pod separado del LLM, ya cubierto en el post anterior.
  4. Vector store + datos relacionales (Qdrant, PostgreSQL CNPG, Ceph RGW para pesos y adapters, CephFS para datasets) — la mayoría ya existía en nivel 2 como datos; ahora se especializa para RAG.
  5. Observabilidad LLM-aware (Langfuse) — se enchufa a la cadena OTel del nivel 4.
  6. Control plane GitOps — el del nivel 2 sigue siendo la única autoridad legítima.
  7. Dependency tracking (Hubble flows + Otterize) — sobre Cilium que ya existía en nivel 1.

El criterio para promocionar de nivel 4 a nivel 5 no es técnico: es contractual. El cluster ya soporta LLMs; la decisión es cuándo abrir tráfico real de clientes. La promoción exige: golden eval del modelo verde, runbook de incidentes firmado, SLOs negociados, plan de continuidad, mapeo a ENS / NIS2 / 42001 si aplica.

Las matemáticas que importan: cuánto cuesta saltarse un nivel

Para cuantificar la tesis del post, una estimación con orden de magnitud del coste de subir cada nivel a tiempo versus subirlo después de tener producción. Las cifras son tiempo de ingeniería con un equipo de plataforma pequeño (2-3 personas), asumiendo plantillas y experiencia previa.

NivelTiempo a montar sobre cluster vacíoTiempo a retrofit con producción rodando
0 → 11-2 semanas1-2 semanas (poco refactor downstream)
1 → 22-3 semanas4-8 semanas (migrar todo a git)
2 → 32-4 semanas8-16 semanas (rebuild de imágenes, migración de secretos, RBAC retroactivo)
3 → 41-2 semanas4-8 semanas (reconfigurar GPU, mover modelos a MIG, instrumentar gen_ai.*)
4 → 51-2 semanas2-4 semanas
Total 0 → 5~10-15 semanas~20-40 semanas si se hace en orden equivocado

Multiplicador típico observable en la práctica: 2× a 3× el coste si se hace en orden equivocado. Y eso asumiendo que se llega a hacer — muchos proyectos no superan el nivel 2 nunca porque “lo de la identidad” siempre puede esperar a otro sprint. Cuando llega el incidente, ya es tarde para empezar.

Más allá del tiempo, el coste operativo (incidentes nocturnos, escapes de seguridad, deuda invisible) crece exponencialmente con el desfase entre el nivel real y el nivel necesario. Un cluster en nivel 2 sirviendo LLMs productivos en clientes regulados es una bomba de relojería: técnicamente funciona, organizativamente no.

Diagrama final: la escalera completa con piezas

Cinco niveles de madurez · piezas OSS · handoff al stack LLMNIVEL 0 · CAÓTICO · un servidor con LinuxDebian / Ubuntu LTS · kernel ≥6.6 · containerd · drivers NVIDIA · LVM · chrony · BMC TLS+MFARed: VLAN gestión, LACP, jumbo frames, BGP en switchTest: ¿puedo reconstruir el servidor desde notas?NIVEL 1 · REPETIBLE · cluster Kubernetes operativoRKE2 (CIS-hardened) · Cilium (kube-proxy replacement + BGP) · Rook-Ceph (RBD + CephFS + RGW)Gateway API · kubectl/Helm desde terminal · pods rodando con HATest: ¿perder un nodo no requiere acción humana?NIVEL 2 · DEFINIDO · el cluster se reconstruye desde gitForgejo + Flux · Forgejo Container Registry · VictoriaMetrics + Grafana + LokiBackups Barman Cloud + Ceph snapshots/RGW multisite · Alertmanager + KeepTest: ¿puedo recrear el cluster desde repo + backups?NIVEL 3 · GESTIONADO · identidad, certs, secretos, políticasDefguard (OIDC + WireGuard) · cert-manager · SOPS + ESO · Kyverno · TrivyNetworkPolicy default deny · Tetragon · audit logTest: ¿qué puede hacer un atacante con un portátil de admin?NIVEL 4 · OPTIMIZADO PARA GPU · el scheduler entiende H100NVIDIA GPU Operator · DCGM Exporter · MIG manager · Topology Manager NUMAKEDA con métricas vLLM · OTel Collector con gen_ai.* · LeaderWorkerSet · OMEDecisión: passthrough TP=4 para LLM grande, MIG para LLMs pequeños + embeddingsTest: ¿un pod con nvidia.com/gpu:1 se programa con métricas y traza listas?NIVEL 5 · HANDOFFStack LLM (7 capas del post anterior) entra encima · gateway, vLLM, embeddings, Qdrant, Langfuse...

La escalera no es decorativa: cada nivel enable el siguiente. No se puede tener observabilidad LLM-aware (nivel 4) sin OTel desplegado vía Flux (nivel 2). No se puede tener TLS interno automático (nivel 3) sin un PKI raíz que viva en algún sitio (registro y certificados gestionados desde el nivel 2). No se puede tener KEDA escalando por métricas vLLM (nivel 4) sin Prometheus / VictoriaMetrics scrapeando (nivel 2). Los niveles no son una jerarquía conceptual: son una jerarquía de dependencias de instalación.

Decisiones de diseño típicas que rompen el progreso

Errores que se ven repetidamente y que tiran el cluster atrás de nivel:

1. Saltar de nivel 1 a nivel 4 directamente. “Tenemos prisa por servir el LLM, lo de identidad y GitOps lo hacemos después”. Después es siempre dos órdenes de magnitud más caro y siempre llega después del primer incidente.

2. Confundir Helm con GitOps. Tener Helm charts no es nivel 2. Es nivel 1 con plantillas. Nivel 2 exige que un reconciliador (Flux/ArgoCD) aplique las charts desde un repo, detecte drift y avise.

3. cert-manager sin policy de uso. Tener certificados auto-renovados pero usar TLS sólo en el ingress, sin mTLS interno entre servicios, deja la promesa de TLS coja y baja el nivel 3 a un cosplay del 3.

4. NVIDIA drivers a mano. Funciona el día uno y se rompe el día del primer upgrade de kernel. La regla: drivers siempre vía GPU Operator, nunca paquetes del sistema operativo.

5. Métricas Prometheus pero retención de 7 días. Sin retención larga (≥ 90 días) no hay SLO honesto. VictoriaMetrics con 1 año de retención cuesta poco más que Prometheus con 7 días, y desbloquea cumplimiento y postmortems serios.

6. OIDC sólo para kube-apiserver. Si Forgejo, Grafana, Defguard y vLLM cada uno tiene su propio sistema de auth, no tienes SSO, tienes islas. Un nivel 3 honesto exige federación.

7. Kyverno en modo audit permanente. Las políticas que no rechazan no son políticas, son alertas. En algún momento hay que pasar a enforce. Mientras tanto, sigues en nivel 2 con cara de 3.

8. MIG sin decisión consciente del perfil. Configurar MIG con el perfil por defecto sin haber medido el tamaño de los modelos que van a cohabitar deja GPUs fragmentadas con slices que nadie usa. La regla: MIG sólo si has medido y has decidido los perfiles por adelantado.

Todos comparten una raíz: declarar el nivel sin pasar el test del nivel. Decir “ya hicimos GitOps” cuando todavía se aplican cosas con kubectl edit en prod. Decir “ya hicimos identidad” cuando hay un kubeconfig admin compartido. Decir “estamos listos para LLM” cuando no hay DCGM Exporter ni Langfuse enchufado.

Aplicado a hardware on-premise típico: cluster 4×H100 SXM

Sobre el cluster genérico de referencia (4×H100 SXM 80 GB, NVLink, 640 GB RAM), un setup razonable después de pasar los cinco niveles distribuye así los componentes:

control plane (3 nodos sin GPU, hostnames cp-01..03)
├── kube-apiserver, etcd, controller-manager, scheduler
├── Flux, Forgejo, cert-manager, External Secrets, Kyverno
└── Tetragon (DaemonSet también aquí)

worker plane (≥ 3 nodos sin GPU, hostnames worker-cpu-01..03)
├── Cilium agent (DaemonSet)
├── Rook-Ceph OSDs + MONs + MDS (CephFS) + RGW (S3)
├── VictoriaMetrics + Grafana + Loki
├── Defguard (StatefulSet)
└── Langfuse + OTel Collector

worker plane GPU (≥ 2 nodos con 4×H100 SXM, hostnames worker-gpu-01..02)
├── NVIDIA GPU Operator (driver + container toolkit)
├── DCGM Exporter (DaemonSet)
├── MIG manager (configurando el perfil decidido)
├── vLLM (Deployment) — LLM general TP=4 ocupa 4 GPUs (passthrough)
├── vLLM (Deployment) — LLM código TP=2 ocupa 2 GPUs
├── Infinity (embeddings) — 2 réplicas cohabitan en 2 slices MIG
└── KEDA scaler escuchando métricas vLLM

La regla operativa: el plano de control y el plano CPU se separan del plano GPU. Un incidente en el plano GPU no debe llevarse por delante el plano de control (que es lo que recupera el cluster). Y el plano CPU concentra todo lo que mueve estado relevante (Forgejo, Rook-Ceph, Postgres CNPG, Langfuse): es el corazón a proteger.

El hardware GPU se especializa al máximo: pods GPU solamente corren en nodos GPU, y los nodos GPU no corren nada CPU-bound aparte del overhead operativo (Cilium, GPU Operator, DCGM). Esto se enforza con nodeSelector + taints/tolerations + Kyverno policy que rechaza pods sin requests GPU programándose en nodos GPU.

Lo que no hemos cubierto (próximos posts)

Este post recorre el camino vertical hacia arriba. Quedan piezas horizontales y otras transversales que merecen su propio artículo:

  • Multi-site activo/standby: cómo se federan dos clusters con Cilium Cluster Mesh y qué cambia en cada nivel cuando hay dos sites en lugar de uno.
  • Migración entre niveles con tráfico real: cómo se retrofitea un cluster que ya está en producción al nivel siguiente sin downtime.
  • La operación día a día: runbooks por nivel, qué dashboards mirar cada mañana, qué SLOs definir por componente.
  • El plano de coste: cuánto cuesta cada nivel en hardware, energía, horas de ingeniería, licencias OSS opcionales (soporte comercial de Rancher, Cilium Enterprise, etc.) y cuándo cada gasto se justifica.
  • Cumplimiento operacionalizado: cómo se mapean los niveles 3 y 4 a controles ENS Alto, NIS2 e ISO/IEC 42001 sin convertir el cluster en un ejercicio de paperwork.

Ver también

Referencias