Operators de inferencia LLM en Kubernetes: OME, vLLM Production Stack, NVIDIA Dynamo y llm-d

TL;DR

Servir un LLM en producción no es ejecutar un binario: es coordinar un modelo (decenas de gigabytes que tardan minutos en cargar), un runtime (vLLM, SGLang, TensorRT-LLM con cien flags), GPUs heterogéneas (NVLink, MIG, PCIe), prefill y decode que viven mejor separados, un cache de KV que quiere offloading a tiers más fríos, routing inteligente que aproveche prefix caching, y autoscaling que reaccione a métricas que no son CPU%. Un Deployment plano de Kubernetes solo cubre el primer 20% de esto. El otro 80% lo cubren los operators de inferencia LLM, que en 2026 son cuatro relevantes: OME (LMSYS, julio 2025, multi-engine con foco en SGLang), vLLM Production Stack (Helm chart curado del propio vLLM con LMCache para tiered KV), NVIDIA Dynamo (sucesor oficial de Triton, multi-engine, scheduler propio Grove) y llm-d (donación CNCF de marzo 2026 por Red Hat + Google + IBM + CoreWeave + NVIDIA, sobre vLLM, foco en escala distribuida). Detrás de los cuatro está KServe, el operator madre del CNCF que normalizó el concepto de InferenceService y sobre el que varios se apoyan. Este artículo recorre la jerarquía completa, da un mapa de decisión y enseña a no perderse cuando alguien suelte siete siglas en la primera reunión.

Este artículo cierra la serie de inferencia LLM. Los anteriores fueron KV cache: la memoria de trabajo que sostiene la inferencia LLM, vLLM en Kubernetes: la pieza de inferencia LLM que sí escala y PagedAttention por dentro y el estado del arte del KV cache en 2026. Allí explicamos qué pasa dentro de un proceso de inferencia. Aquí explicamos cómo se coordinan muchos procesos de inferencia a través de Kubernetes.

La analogía: de init.d a systemd a operators

El que lleva 20 años en sysadmin reconocerá el patrón. Hace décadas, arrancar un servicio en Linux era un script shell en /etc/init.d/: start, stop, status, recargado a mano. Cuando los servicios se hicieron más complejos —dependencias entre ellos, monitorización, restart on failure, slots por usuario— se hizo evidente que un script no bastaba. Llegó systemd, que convirtió “un servicio” en una unidad declarativa con dependencias, recursos, restart policy, sockets, timers. El script no desapareció; se subió un nivel de abstracción.

Kubernetes hizo el mismo movimiento para servicios distribuidos. Un Deployment declara “quiero N réplicas de este contenedor”; un Service declara “estas réplicas se exponen así”; un Ingress declara “este tráfico HTTP entra aquí”. El controller traduce la declaración en estado real y mantiene el sistema convergente.

Servir LLMs en 2024 era el equivalente al /etc/init.d/: cada equipo escribía sus Deployment/Service/HPA con scripts customizados de carga de modelo, drenaje de sesiones, manejo de GPU. Lo cubrimos en el artículo de vLLM en Kubernetes: se puede hacer, y de hecho funciona, pero es repetitivo, frágil y nadie está extrayendo las abstracciones correctas. Servir LLMs en 2026 ha vivido la misma transición que los servicios: ha aparecido el equivalente a systemd —los operators de inferencia— que normalizan las abstracciones y dejan al ingeniero declarar lo importante: “este modelo, con este runtime, así de escalable, con esta política de routing”.

Hay cuatro operators relevantes en 2026 y un quinto antecesor común. Vamos por orden.

Por qué un operator, y no solo un Deployment

Listar lo que un operator de inferencia aporta sobre un Deployment plano es la mejor manera de entender qué problema resuelve:

Modelo como ciudadano de primera clase. En un Deployment, el modelo es “lo que descargas en un initContainer y montas como volumen”. En un operator, el modelo es una CustomResource con metadatos (origen, fingerprint, licencia, GPU requirements). Pueden compartirse entre InferenceServices, versionarse, replicarse a múltiples nodos. Es la diferencia entre “un fichero” y “un artifact gestionado”.

Runtime como ciudadano de primera clase. Idem para el runtime (vLLM/SGLang/TRT-LLM): no es “una imagen Docker con flags”; es una ServingRuntime que declara qué args acepta, qué métricas exporta, qué tipos de despliegue soporta (single-node, multi-node TP, PD-disag). Cambiar de runtime es cambiar una referencia, no reescribir todos los manifests.

Composición declarativa. Una InferenceService (CRD nuclear de KServe y descendientes) referencia un modelo y un runtime, declara la política de escalado, enlaza observabilidad, configura routing. El controller compone todas las piezas: Deployment(s), Service, HPA, eventualmente LeaderWorkerSet, ScaledObject de KEDA, HTTPRoute de Gateway API. Tú declaras intención; el operator emite los 8 recursos derivados.

Prefill–decode disaggregation operacional. Como vimos en el artículo de PagedAttention, separar prefill y decode en pools distintos puede dar 7× goodput. Modelar eso con Deployments planos es viable, pero requiere coordinar dos sets de pods, un transport para mover KV cache, routing condicional. Un operator lo modela como una sola InferenceService con dos sub-pools.

Autoscaling con métricas LLM. El HPA estándar no entiende vllm:num_requests_waiting. Un operator integra KEDA o Prometheus Adapter automáticamente y expone las métricas correctas como knobs del CRD.

Multi-tenancy. Múltiples modelos en el mismo cluster, con cuotas, prioridades y fairness. Un Deployment por modelo escalando independientemente está bien hasta el quinto modelo; a partir de ahí, la coordinación de GPUs entre tenants se vuelve operationally hostil.

Lifecycle del modelo. Pesos en PVC compartido, calentamiento del primer pod, rolling updates con maxUnavailable: 0, drenaje de sesiones activas, observabilidad integrada. Cosas que en Deployment plano hay que reinventar en cada equipo.

Si tu carga es un modelo, un nodo, hasta tres réplicas, un Deployment plano basta y un operator es overkill. Si tu carga es dos o más modelos, escalado serio, disaggregation o multi-tenancy, un operator deja de ser opcional.

KServe: el antecesor común

Antes de los cuatro nuevos, hay que mencionar a KServe, que es el operator madre del que descienden conceptualmente todos los demás. Nació como KFServing dentro del proyecto Kubeflow en 2019, pasó a llamarse KServe al independizarse en 2021, y en 2025 fue aceptado en la CNCF como proyecto incubando hacia graduado.

La contribución conceptual de KServe es el CRD InferenceService, que se ha convertido en el vocabulario común del campo: un objeto K8s declarativo que une un model (origen + metadata) con un predictor (runtime + recursos) y produce un servicio HTTP listo. Bajo el capó, el controller emite Deployments, Services, HorizontalPodAutoscalers, Knative Services si haces serverless, Istio VirtualServices si haces traffic splitting.

KServe fue diseñado en una era pre-LLM: sus primeros casos de uso eran modelos scikit-learn, TensorFlow y PyTorch tradicionales servidos como REST APIs simples. Eso le da fortalezas (es maduro, lleva 6 años en producción en Bloomberg, JPMorgan y otros) y debilidades (no fue diseñado para gestionar tensor parallel multi-nodo, prefill–decode disaggregation, ni los patrones específicos de LLMs).

La forma en la que el ecosistema ha reaccionado es elegante: los nuevos operators de LLM heredan o se inspiran en InferenceService pero extienden la API con primitivos específicos de LLM. OME es el ejemplo más claro: usa el nombre InferenceService y la idea de “modelo + runtime → servicio”, pero añade BaseModel, ServingRuntime con flags LLM-aware, y modos de despliegue (PD-disag, multi-node) que KServe no contempla nativamente.

OME (Open Model Engine)

OME lo publicó el equipo de LMSYS en julio 2025 (anunciado en su blog). Es un operator que entiende SGLang en profundidad (es su runtime de primera clase) pero también soporta vLLM, TensorRT-LLM y Triton.

La jerarquía de CRDs

OME modela el dominio con cuatro CRDs principales:

  • BaseModel y ClusterBaseModel: el modelo en sí. Define origen (Hugging Face, S3, URL), fingerprint, metadatos. La versión Cluster* es global; la BaseModel es namespaced. Permite que múltiples InferenceService referencien el mismo modelo sin duplicar la descarga.
  • FineTunedWeight: adapters LoRA o pesos finetuneados que se sirven encima de un BaseModel. Crítico para multi-tenant donde cada cliente tiene su finetune.
  • ServingRuntime y ClusterServingRuntime: el runtime (vLLM, SGLang, etc.) con su configuración. Declara qué args acepta, qué métricas exporta, qué modos de despliegue soporta.
  • InferenceService: la pieza central, declarativa, que une BaseModel + ServingRuntime + infraestructura.
apiVersion: ome.io/v1beta1
kind: InferenceService
metadata:
  name: llama3-70b-prod
  namespace: inference
spec:
  model:
    name: meta-llama-3-70b-instruct           # referencia a un BaseModel
  runtime:
    name: sglang-h100                          # referencia a un ServingRuntime
  deploymentMode: PrefillDecodeDisaggregated   # standard | PD | MultiNode | Serverless
  prefill:
    minReplicas: 2
    maxReplicas: 8
    resources:
      requests:
        nvidia.com/gpu: 4
  decode:
    minReplicas: 4
    maxReplicas: 16
    resources:
      requests:
        nvidia.com/gpu: 1
  router:
    type: cache-aware                          # SGLang router con cache awareness
  autoscaling:
    metricSource: keda
    metrics:
    - type: prometheus
      metricName: vllm_requests_waiting
      threshold: "10"

Esto es lo que el operador toma como entrada. La salida son aproximadamente 8 recursos derivados que serían un horror declarar a mano: dos LeaderWorkerSets (uno por pool prefill/decode), dos Services, un Deployment para el router, ScaledObjects de KEDA por cada pool, HTTPRoute de Gateway API, y un PriorityClass que conecta con Kueue para gang scheduling.

Los cuatro modos de despliegue

OME materializa la InferenceService de forma distinta según deploymentMode:

  • Standard: un Deployment con N réplicas; clásico. Para modelos pequeños o single-GPU.
  • PrefillDecodeDisaggregated: dos pools coordinados; el router de SGLang los enruta.
  • MultiNode: tensor parallel sobre múltiples nodos vía LeaderWorkerSet, con NCCL/InfiniBand. Para modelos >70B donde un solo nodo no llega.
  • Serverless: Knative-style scale-to-zero. Para cargas esporádicas donde el coste de mantener GPUs encendidas no compensa. Trade-off: el primer request paga el coste de cold start del modelo (minutos).

Integración con el ecosistema K8s

OME no inventa primitivos donde ya existen. Se apoya en:

  • Kueue para gang scheduling: todos los pods de un tensor parallel deben arrancar a la vez o ninguno; Kueue lo garantiza.
  • LeaderWorkerSet (LWS) para multi-nodo: workers se unen al cluster Ray del leader, ciclo de vida atómico (caída de uno reinicia el grupo).
  • KEDA para autoscaling por métricas Prometheus específicas de LLM (queue depth, GPU cache usage, TTFT p95).
  • Gateway API y su Inference Extension para routing avanzado (model-aware, prefix-aware, weighted canary).

La consecuencia: OME se siente “idiomáticamente Kubernetes”. No introduce conceptos nuevos donde no hace falta; usa primitivos estándar y se concentra en lo específico del dominio LLM.

Cuándo elegirlo

OME es la opción natural si SGLang es tu runtime principal y/o si vienes del ecosistema KServe y quieres una evolución idiomática. Es maduro pero relativamente joven (un año en el momento de este artículo); espera bordes ásperos en features avanzadas.

vLLM Production Stack

vLLM Production Stack es el proyecto oficial del propio vLLM para producción en Kubernetes. Su filosofía es opuesta a la de OME: en lugar de un operator con CRDs nuevos, es un Helm chart curado que despliega un conjunto coherente de piezas.

Las tres piezas

El stack tiene tres componentes:

  1. Serving engines: pods de vLLM, configurados con los flags que llevamos viendo en toda la serie (--enable-prefix-caching, --kv-cache-dtype fp8, etc.). El Helm chart te deja declararlos como una lista; despliega los Deployments y Services subyacentes.
  2. Request router: un proxy delante de los engines que decide a cuál enviar cada petición. Soporta varias políticas:
    • Round-robin: trivial, para baseline.
    • Session-based: clava cada sesión a una réplica para mantener su KV cache.
    • Prefix-aware: detecta prefijos compartidos entre peticiones y las enruta a la réplica que ya los tenga cacheados.
    • KV-aware: ve el gpu_cache_usage_perc de cada réplica y evita las saturadas.
    • Disaggregated-prefill con LMCache nativo: separa prefill y decode con LMCache como transport del KV cache entre ambos.
  3. Observability stack: Prometheus + Grafana con dashboards listos. Mide TTFT, TBT (Time-Between-Tokens), throughput, queue depth, GPU memory.

LMCache y el tiered KV

Una de las piezas más interesantes que mete el stack es LMCache, que añade un caché de KV con múltiples tiers: GPU HBM como L1, CPU RAM como L2, disco local como L3, y opcionalmente storage remoto como L4. Cuando un bloque de KV cache no cabe en HBM, en lugar de evictarlo y recalcularlo, LMCache lo baja a un tier inferior. Para cargas con prefijos compartidos y multi-turn, el ahorro es brutal.

LMCache se integra como sidecar de los engines y como parte del transport en disaggregated-prefill. El Production Stack lo trae habilitado por defecto en su Helm chart.

Manifest típico (values.yaml)

servingEngineSpec:
  modelSpec:
  - name: llama3-8b
    repository: vllm/vllm-openai
    tag: v0.6.3
    modelURL: meta-llama/Meta-Llama-3-8B-Instruct
    replicaCount: 3
    requestCPU: 4
    requestMemory: 16Gi
    requestGPU: 1
    vllmConfig:
      enablePrefixCaching: true
      kvCacheDtype: fp8
      maxModelLen: 32768
      enableChunkedPrefill: true

routerSpec:
  routingLogic: prefix-aware       # round-robin | session | prefix-aware | kv-aware
  sessionKey: x-user-id            # cuando routingLogic=session

cacheserverSpec:
  enabled: true                    # LMCache para tiered KV
  storageBackends:
  - cpu
  - disk                           # offload a disco local

observabilitySpec:
  prometheus:
    enabled: true
  grafana:
    enabled: true
    dashboards:
    - vllm-engine-metrics
    - lmcache-metrics

Esto es declarativo pero no son CRDs: son valores de un Helm chart. La diferencia con OME no es semántica (ambos parten de declaración) sino operacional: con Helm, los cambios pasan por helm upgrade; con CRDs, pasan por kubectl apply. Para equipos que ya viven en GitOps con Argo CD o Flux, ambos enfoques se integran limpiamente, pero los flujos son distintos.

Cuándo elegirlo

Si tu único runtime es vLLM y quieres lo más cercano a “el camino feliz que recomienda el proyecto”, esto. Es la versión productivizada y mantenida por la misma gente que escribe el motor. Las desventajas: ata a vLLM (no es genérico) y no resuelve algunos casos avanzados como multi-tenancy con cuotas estrictas o gang scheduling, donde OME u operators full-fledged son superiores.

NVIDIA Dynamo

NVIDIA Dynamo es el sucesor oficial de Triton Inference Server, anunciado en GTC 2025 y fusionado con la marca como Dynamo-Triton en marzo de ese año. Triton llevaba años siendo el motor de inferencia más usado en infraestructuras NVIDIA “serias”; Dynamo es lo que NVIDIA cree que la nueva generación necesita.

Qué es exactamente

Dynamo es un framework de inferencia distribuida, no exactamente un operator de Kubernetes. Tiene runtime propio (puede correr engines), scheduler (Grove), routing inteligente, gestión de KV cache multi-tier y disaggregation. Soporta como engines a SGLang, TensorRT-LLM y vLLM, pero los engines son ejecutados por Dynamo, no a la inversa: el modelo es “Dynamo gestiona, el engine ejecuta”.

En Kubernetes, Dynamo se despliega vía operator + CRDs propios, normalizados con la integración K8s que NVIDIA formalizó a finales de 2025 (la cubre esta nota de InfoQ). Los CRDs son específicos del producto: definen un DynamoCluster, una topología de prefill/decode workers, una política de routing.

Las cuatro contribuciones

Dynamo se vende sobre cuatro pilares, con números reportados por NVIDIA:

  1. Disaggregated serving built-in con scheduler propio.
  2. Smart routing basado en estado de cache: si un worker ya tiene cacheada la mayoría de un prompt, la petición va ahí.
  3. Multi-tier KV cache: análogo a LMCache, con HBM/RAM/SSD/NVMe.
  4. Autoscaling integrado con el scheduler de Dynamo.

El número marketing: hasta 30× más throughput que Triton legacy en el mismo hardware. Con todas las precauciones que merece un benchmark de vendor.

Grove: scheduler propio

Una decisión polémica de Dynamo es no apoyarse al 100% en el scheduler de Kubernetes y, en su lugar, traer un scheduler propio llamado Grove que entiende topologías de GPU. Grove decide qué worker corre en qué GPU física, qué interconexiones (NVLink/InfiniBand) son relevantes, y cómo distribuir tensor parallel entre nodos. Esto le da más control que kube-scheduler estándar.

Operacionalmente: si tu cluster es “puro Kubernetes” con kube-scheduler y workloads heterogéneos (no solo LLMs), Grove añade un componente adicional a operar. Si tu cluster es dedicado a inferencia LLM y ya hay equipo dedicado a operarlo, Grove te da más palancas.

Cuándo elegirlo

Dynamo tiene sentido si:

  • Tu infraestructura es NVIDIA-heavy (Hopper, Blackwell, GB200) y quieres aprovechar lo más reciente de TensorRT-LLM con la integración de Triton-de-toda-la-vida pero modernizado.
  • Ya eras usuario de Triton para inferencia legacy (visión, recomendación) y quieres mantener el ecosistema.
  • Tienes equipo SRE dedicado a inferencia y la complejidad operacional adicional de Grove no es un problema.

Es la opción vendor-specific del cuarteto. A cambio te da el soporte de NVIDIA y la integración de primera con su hardware. Si tu organización ya pelea con NVIDIA por GPUs, igual te llaman para ofrecer asistencia con Dynamo.

llm-d

llm-d es el más joven y el más “político” de los cuatro. En marzo de 2026, en KubeCon Europe Amsterdam, Red Hat, Google Cloud, IBM Research, CoreWeave y NVIDIA anunciaron la donación conjunta del proyecto a la CNCF como Sandbox, con soporte de AMD, Cisco, Hugging Face, Intel, Lambda, Mistral AI, UC Berkeley y University of Chicago. Una coalición de vendor-neutralidad explícita.

Filosofía

llm-d se posiciona como el “Kubernetes blueprint” vendor-neutral para inferencia distribuida. No es un runtime; es un sistema que se monta encima de vLLM (motor por defecto) y orquesta el plano de control.

Las primitivas que el proyecto pone sobre la mesa:

  • Routing inteligente con prefix-cache awareness y load-aware balancing.
  • Tiered KV cache con offload a CPU y disco para multi-turn.
  • Prefill/decode disaggregation sobre interconnects rápidos.
  • Wide expert-parallelism para servir Mixture-of-Experts (MoE) muy grandes —un patrón crítico que DeepSeek-V3 y Mixtral popularizaron— donde los expertos viven en distintas GPUs y hay que enrutar tokens al experto correcto.

Números

El release v0.5 valida ~3.1k tok/s por GPU de decode B200, y hasta 50k output tok/s en una topología 16×16 B200 prefill/decode. El benchmark más interesante: orden de magnitud de reducción de TTFT vs una baseline round-robin. Es decir, el routing inteligente vale lo que se dice.

CNCF y futuro

Donar a la CNCF como Sandbox significa gobernanza neutral: ningún vendor manda. Para una organización que recela de quedar atado a un único proveedor, llm-d es probablemente la apuesta más segura a medio plazo. El precio: como cualquier proyecto Sandbox, todavía no es “boring” en el sentido en que vLLM lo es. Hay churn de API, features que se mueven, documentación que va por detrás del código.

Cuándo elegirlo

llm-d tiene sentido si:

  • Quieres portabilidad multi-vendor sin ataduras a NVIDIA, Red Hat o Google.
  • Tu carga incluye MoE grandes (DeepSeek-V3, Mixtral 8x22B, Llama 4 Behemoth si confirma tamaño), donde wide expert parallelism es decisivo.
  • Tu organización ya está cómoda con CNCF Sandbox (proyectos en evolución activa, no aún 1.0 estable).
  • Quieres apostar por el proyecto que probablemente sea el estándar de facto en 2-3 años.

El antecesor común sigue ahí: KServe

Vale la pena reconectar antes de la comparativa: KServe sigue vivo y muy usado en organizaciones que sirven tanto LLMs como modelos tradicionales (scikit-learn, XGBoost, PyTorch CV). Su InferenceService es lo bastante genérico como para servir cualquier modelo, incluyendo vLLM o SGLang como ServingRuntime. Lo que no hace bien es lo específico de LLM: disaggregation, tensor parallel multi-nodo, routing con awareness de KV cache. Si tu organización ya tiene KServe en producción para otros modelos, añadir un operator específico de LLM al lado (OME, vLLM Stack o llm-d) es razonable. Pelearlo todo desde KServe puro no.

Mapa de decisión

DimensiónOMEvLLM Prod StackNVIDIA Dynamollm-d
FilosofíaOperator clásico K8s-idiomáticoHelm chart curadoFramework con scheduler propioBlueprint CNCF vendor-neutral
CRDs propiosSí (BaseModel, ServingRuntime, InferenceService…)No (Helm values)Sí (DynamoCluster)Sí (KServe-derived + extensions)
Runtime primarioSGLang (primera clase), también vLLM/TRT-LLM/TritonvLLM exclusivamenteTensorRT-LLM (primera clase), también SGLang/vLLMvLLM (primera clase)
PD-disaggregationSí, declarativoSí, con LMCacheSí, scheduler propioSí, nativo
Multi-nodo TPSí, via LWSLimitadoSí, via GroveSí, via LWS y MoE EP
Multi-modelo en clusterSí, multi-tenant maduroSí (lista de modelos en values)
Multi-LoRASí, primera clase (FineTunedWeight CRD)LimitadoEn roadmap
Tiered KV cacheVía LMCache (integración externa)LMCache nativoMulti-tier propioSí, nativo
Routing inteligenteCache-aware via SGLang routerPrefix-aware / KV-aware / session-basedSmart routing propioPrefix-cache + load-aware
Scheduler GPUkube-scheduler + Kueuekube-schedulerGrove (propio)kube-scheduler + Kueue
HardwareNVIDIA, AMD ROCm, IntelNVIDIA, AMD ROCmNVIDIA exclusivo (con énfasis)NVIDIA, AMD, Intel — neutral
Madurez (mid-2026)Joven, en evoluciónEstableEstable, vendor-drivenCNCF Sandbox, evolución rápida
GobernanzaLMSYS (académico-industrial)vLLM project (académico)NVIDIA (vendor)CNCF (neutral)
Curva de aprendizajeMedia (4 CRDs nuevos)Baja (Helm values familiar)Media-alta (Grove + CRDs propios)Media (similar a KServe extendido)

Cuándo elegir cada uno

Elige OME si:

  • SGLang es tu motor principal.
  • Necesitas multi-LoRA serving en producción.
  • Te encaja la abstracción jerárquica (BaseModel → ServingRuntime → InferenceService) y vienes de o convives con KServe.
  • Tienes appetito por un proyecto joven y muy activo.

Elige vLLM Production Stack si:

  • vLLM es tu único motor y quieres alinearte con lo que el proyecto recomienda.
  • Tu equipo ya vive en Helm y no quiere aprender CRDs nuevos.
  • LMCache + routing avanzado dentro de un solo Helm chart es exactamente lo que necesitas.
  • Tu escala es media (decenas de réplicas), no extrema.

Elige NVIDIA Dynamo si:

  • Tu infraestructura es NVIDIA-heavy y quieres el path más optimizado para Hopper/Blackwell.
  • Ya operabas Triton para inferencia legacy y la transición es natural.
  • Aceptas vendor lock-in a cambio de soporte directo NVIDIA.
  • Tu organización tiene equipo SRE dedicado a inferencia.

Elige llm-d si:

  • Quieres apostar por el estándar CNCF futuro, neutro entre vendors.
  • Tu carga incluye MoE grandes con wide expert parallelism.
  • Operas en multi-cloud o multi-hardware y la portabilidad es valiosa.
  • Aceptas la inmadurez de un proyecto Sandbox a cambio de la apuesta a futuro.

Elige KServe puro si:

  • Ya sirves modelos no-LLM y quieres unificar; los LLMs son una minoría de tu carga.
  • Necesitas el caso de uso más conservador y maduro.
  • Aceptas que features avanzadas de LLM (disaggregation, MoE EP, smart routing) te tocará añadirlas con piezas externas.

Escenarios concretos

Escenario A — Startup pequeña, 1-2 modelos, 1-3 nodos GPU. Probablemente no necesitas operator. Deployment + Service + HPA con métricas de KEDA, como en el artículo de vLLM en Kubernetes. Cuando crezcas a 5+ modelos, evalúa.

Escenario B — Empresa media, 5-15 modelos, multi-tenant interno. vLLM Production Stack o OME son las opciones razonables. Production Stack si vLLM es todo lo que vas a usar; OME si quieres flexibilidad de runtime y CRDs idiomáticos.

Escenario C — Plataforma interna corporativa o servicio externo a clientes finales. llm-d o Dynamo. llm-d si valoras vendor-neutralidad; Dynamo si vives en infraestructura NVIDIA y quieres el camino que ellos recomiendan.

Escenario D — Cluster mixto LLM + modelos tradicionales. KServe como base, operator de LLM al lado (OME es lo más natural por su parentesco conceptual).

Trampas comunes

“Voy a empezar con KServe puro porque es maduro”. Para LLMs medianos en adelante, KServe puro deja muchas optimizaciones sobre la mesa. Lo razonable es KServe como base si convives con otros modelos, pero operator LLM-específico al lado.

“Voy a montar todo a mano para entenderlo”. Razonable en PoC, suicida en producción. Hay 8 recursos derivados por modelo. Multiplica por 10 modelos. Estás escribiendo 80 YAMLs y manteniéndolos. Usa un operator.

“Voy a elegir el que más me gusta y luego pivoto si me equivoco”. Pivotar entre operators no es gratis: aunque la abstracción InferenceService se está homogeneizando, los detalles (cómo se modela LoRA, cómo se configura routing, cómo se exponen métricas) varían. Migrar de OME a Dynamo es un proyecto de semanas, no de días.

“Voy a poner Dynamo porque es de NVIDIA y mejor”. Solo si tu organización ya está alineada con su filosofía operacional (scheduler propio, vendor lock-in aceptable). Para muchos casos, vLLM Production Stack o llm-d dan 95% del valor con menos fricción.

“Helm chart vs operator es una decisión técnica”. Es una decisión cultural/operacional. Si tu equipo entrega vía Argo CD con Helm values en Git, Production Stack encaja sin fricción. Si tu equipo vive en kubectl apply -f directo y la idea de operators te resulta natural, OME o llm-d.

Lo que no hemos cubierto

  • Mooncake: el sistema de cache de KV compartido entre instancias que Kimi/Moonshot lleva en producción a cientos de millones de queries. Es un primitivo (no un operator completo), pero se integra como tier de cache con varios de los anteriores.
  • Ray Serve LLM: la oferta de Anyscale, en Kubernetes a través de KubeRay. Más vinculado al ecosistema Ray que a los CRDs nativos K8s. Útil si Ray ya es parte de tu infraestructura.
  • Fireworks AI, Modular MAX: plataformas comerciales con primitivos similares, pero hospedadas. No son operators K8s; son competidores en otra capa.
  • Gateway API Inference Extension: la propuesta sigwg para extender Gateway API con primitivos LLM (model-aware routing, sticky sessions, fairness). En 2026 está en alpha; los operators de arriba ya empiezan a soportarla. Cuando madure, el routing dejará de ser problema de cada operator y será parte del estándar de Kubernetes.
  • Inference observability stack genérico: Prometheus + Grafana se está estandarizando en torno a las métricas vllm:* que cubrimos en el artículo de vLLM. Hay esfuerzo de OpenTelemetry para LLMs (gen-ai semantic conventions) que probablemente sea el siguiente eslabón.

Cerrando la serie

Esta serie de cuatro artículos ha recorrido la inferencia LLM en producción de abajo arriba:

  1. KV cache: la memoria de trabajo que sostiene la inferencia LLM — por qué cada token consume VRAM y cuánto.
  2. vLLM en Kubernetes: la pieza de inferencia LLM que sí escala — cómo se sirve un modelo en producción con un Deployment serio.
  3. PagedAttention por dentro y el estado del arte del KV cache en 2026 — qué pasa dentro del motor a nivel del bloque, y qué ha llegado después.
  4. Este — cómo se orquestan muchos modelos en cluster.

Si has llegado aquí, tienes el vocabulario y el mapa para sentarte en una reunión donde cinco personas tiren siglas y reconocer cada una en su sitio. Y, lo más importante, para empezar a tomar decisiones razonadas sobre por dónde empezar.

Referencias

Operators y proyectos cubiertos:

Antecesores y primitivos:

Análisis y perspectivas: