Cluster Autoscaler vs Karpenter: cuándo usar cada uno en 2026

Cluster Autoscaler vs Karpenter: cuándo usar cada uno en 2026

Cluster Autoscaler vs Karpenter: cuándo usar cada uno en Kubernetes (2026)

Tus pods están en estado Pending. Tu ingeniero de guardia está recibiendo alertas. En algún punto de la cadena entre «necesito más cómputo» y «el cómputo está disponible», algo va demasiado lento. Ese algo casi siempre es el aprovisionamiento de nodos — y la herramienta que elegiste para gestionarlo determina si ese retraso son 4 minutos o 45 segundos.

El autoescalado de nodos en Kubernetes es de esas decisiones de infraestructura que parecen sencillas hasta que las tienes corriendo en producción. Dos pods en estado Pending no significan solo un despliegue retrasado: significan picos de latencia, tráfico perdido, SLOs incumplidos e ingenieros depurando problemas que deberían haber sido invisibles. A escala, también significa quemar dinero en nodos sobreaprovisionados o jugársela con un submínimo de recursos en el peor momento posible.

Cluster Autoscaler (CA) ha sido la respuesta por defecto durante años. Karpenter emergió de AWS en 2021, alcanzó estado estable en 2023 y para 2025 ya era la recomendación mayoritaria para clusters nativos en AWS. En 2026, ambas herramientas están maduras, ampliamente desplegadas y son genuinamente buenas — pero resuelven el problema de forma diferente, y elegir la incorrecta para tu entorno tiene consecuencias reales.

Este artículo es una comparativa técnica en profundidad sobre autoescalado de nodos Kubernetes. Asume que ya sabes lo que es Kubernetes y que tienes criterio sobre infraestructura. El objetivo es darte una imagen clara de cómo funciona cada herramienta, dónde gana cada una, y un framework de decisión que puedas aplicar directamente.


Por qué el autoescalado de nodos es difícil

La tensión fundamental en el autoescalado es esta: quieres tener cómputo disponible antes de necesitarlo, pero no quieres pagar por cómputo que no estás usando. Estos objetivos están en conflicto directo, y todo sistema de autoescalado es un intento de encontrar el trade-off menos malo.

Sin autoescalado, estás haciendo una de estas dos cosas:

  1. Sobreaprovisionando — ejecutas suficientes nodos para gestionar la carga pico en todo momento. La utilización media se sitúa en el 20–30%, y estás pagando el otro 70–80% para que esté ocioso.
  2. Subaprovisionando — vas ajustado, y cuando el tráfico se dispara, los pods van a Pending. Tus SLOs se incumplen. Te llaman a las 3 de la mañana para escalar manualmente.

Un patrón de fallo habitual con un autoescalado mal ajustado es el de «estampida en el scale-up»: el HPA crea nuevos pods más rápido de lo que el autoescalado de nodos puede aprovisionar capacidad. La ventana de aprovisionamiento importa. Con CA y node groups respaldados por ASG en AWS, estás hablando de 4–8 minutos. Con Karpenter, 60–90 segundos. A 100 RPS y una ventana de 3 minutos, eso son 18.000 peticiones bajo condiciones degradadas.


Cluster Autoscaler: cómo funciona realmente

Cluster Autoscaler es un proyecto nativo de Kubernetes bajo el repositorio kubernetes/autoscaler, en producción desde 2016, con soporte para AWS, GCP, Azure, Alibaba, DigitalOcean y otros proveedores.

El modelo de node groups

CA opera sobre node groups — ASGs en AWS, MIGs en GCP, VMSSs en Azure. La función de CA es decidir cuándo aumentar o reducir la capacidad deseada de estos grupos. CA no aprovisiona nodos individuales. Escala node groups, y es el propio node group quien aprovisiona los nodos. Esta indirección añade latencia y reduce la flexibilidad.

Scale-up: detección de pods no programables

CA ejecuta un bucle de control (intervalo de escaneo por defecto: 10 segundos). Para cada pod en estado Pending con PodScheduled=False, CA simula añadir un nodo de cada tipo de node group conocido y comprueba si el pod podría programarse. Cuando se selecciona un node group, CA aplica un expander para elegir qué grupo escalar:

  • least-waste — minimiza el desperdicio de CPU/memoria tras la programación (mejor opción por defecto para coste)
  • most-pods — maximiza los pods programados por operación de scale-up
  • priority — permite definir un orden mediante ConfigMap
  • grpc — delega en un servicio gRPC externo
# Despliegue de Cluster Autoscaler — AWS, ajustado para producción
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cluster-autoscaler
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cluster-autoscaler
  template:
    metadata:
      labels:
        app: cluster-autoscaler
      annotations:
        cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: cluster-autoscaler
      containers:
        - image: registry.k8s.io/autoscaling/cluster-autoscaler:v1.30.3
          name: cluster-autoscaler
          resources:
            requests:
              cpu: 100m
              memory: 600Mi
            limits:
              cpu: 200m
              memory: 1Gi
          command:
            - ./cluster-autoscaler
            - --cloud-provider=aws
            - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/my-cluster
            - --expander=least-waste
            - --balance-similar-node-groups=true
            - --scale-down-delay-after-add=10m
            - --scale-down-unneeded-time=10m
            - --scale-down-utilization-threshold=0.5
            - --max-graceful-termination-sec=600
            - --scan-interval=10s

Scale-down: el enfoque conservador

Un nodo es candidato a scale-down solo si:
– La utilización de CPU y memoria (por requests) está por debajo del umbral (por defecto: 50%)
– Todos los pods podrían reprogramarse en otro nodo
– Ningún pod tiene la anotación cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
– El nodo ha estado infrautilizado durante al menos --scale-down-unneeded-time (por defecto: 10 minutos)

Este conservadurismo evita el churn — es una característica, no un defecto.

Hay un matiz importante que a menudo se pasa por alto: CA no distingue entre un nodo que tiene el 45% de uso de CPU y otro que tiene el 5%. Ambos son candidatos a eliminación si están por debajo del umbral. La granularidad es binaria (utilizado / no utilizado lo suficiente), no continua. Esto contrasta con el enfoque de consolidación activa de Karpenter, que veremos a continuación.


Karpenter: cómo funciona realmente

Karpenter es un proyecto en incubación de la CNCF, construido originalmente por AWS, donado a la CNCF en 2023 y con disponibilidad general (v1.0) a mediados de 2024. Existen providers para AWS (estable), Azure (estable) y GCP (beta).

La idea central: eliminar el node group de la ecuación

Karpenter llama directamente a la API RunInstances de EC2 — sin implicar ASGs. Esto significa:
– Cualquier tipo de instancia en una sola petición, sin necesidad de preconfigurar un node group
– Sin intermediarios: Karpenter → EC2 API → el nodo se une al cluster
– Nodos ajustados exactamente a lo que necesitan las cargas de trabajo, sobre el catálogo completo de instancias
– Karpenter gestiona el ciclo de vida completo del nodo, incluida su terminación

Esta diferencia arquitectónica es la que explica casi todas las ventajas de rendimiento y flexibilidad de Karpenter frente a CA. No es una cuestión de mejor algoritmo; es una cuestión de eliminar una capa completa de indirección.

NodePool y EC2NodeClass

La configuración de Karpenter se expresa mediante dos CRDs principales:

# EC2NodeClass — parámetros específicos del cloud
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: default
spec:
  amiSelectorTerms:
    - alias: al2023@latest
  role: "KarpenterNodeRole-my-cluster"
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: "my-cluster"
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: "my-cluster"
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 50Gi
        volumeType: gp3
        encrypted: true
  metadataOptions:
    httpTokens: required
    httpPutResponseHopLimit: 1
---
# NodePool — intención y restricciones
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: general-purpose
spec:
  template:
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand", "spot"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64", "arm64"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["c", "m", "r"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["5"]
        - key: karpenter.k8s.aws/instance-size
          operator: NotIn
          values: ["nano", "micro", "small", "medium", "large"]
      expireAfter: 720h
  limits:
    cpu: "1000"
    memory: 1000Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 5m
    budgets:
      - nodes: "5%"
        schedule: "0 8 * * mon-fri"
        duration: 10h
      - nodes: "25%"

La expresividad de este modelo de configuración es significativa: en lugar de mantener varios ASGs con tipos de instancia fijos, defines restricciones y dejas que Karpenter resuelva la instancia óptima en tiempo de ejecución. Para clusters con carga variable o diversa (batch, APIs sin estado, workloads GPU), esto elimina una cantidad enorme de gestión manual de configuración.

Aprovisionamiento just-in-time y bin packing

Cuando los pods van a Pending, Karpenter observa el evento (no hace polling) e inmediatamente:
1. Recopila todos los pods en Pending
2. Simula el bin packing — el mínimo número de nodos posible sobre el catálogo completo de instancias
3. Selecciona las instancias que satisfacen todos los requisitos de los pods
4. Llama a la EC2 API para aprovisionar las instancias óptimas

Disruption y consolidación

El valor diferencial de Karpenter: la consolidación activa del cluster. Evalúa si los nodos pueden eliminarse redistribuyendo los pods en otros, o reemplazándolos con un tipo de instancia más pequeño. Un c5.4xlarge ejecutando pods que consumen 4 vCPU se reemplaza por un c5.xlarge. Los equipos reportan habitualmente reducciones de coste de cómputo del 30–50%.

Las opciones de consolidationPolicy son:
WhenEmpty — solo elimina nodos sin pods de workload (más conservador)
WhenEmptyOrUnderutilized — también reemplaza nodos infrautilizados por instancias más pequeñas

La consolidación no es solo una mejora incremental sobre el scale-down de CA — es cualitativamente diferente. CA puede decirte «este nodo está infrautilizado, lo elimino». Karpenter puede decirte «estos tres nodos están infrautilizados, puedo consolidar todo en uno más pequeño, déjame hacerlo». La diferencia en ahorro de costes compuesto a lo largo del tiempo es sustancial.


Comparativa de arquitectura

DimensiónCluster AutoscalerKarpenter
Modelo de aprovisionamientoEscala node groups (ASG/MIG/VMSS)API cloud directa, sin node groups
Flexibilidad de instanciasTipos de node group predefinidosCatálogo completo en tiempo de ejecución
Trigger de scale-upPolling (intervalo de 10s)Watch de eventos (casi instantáneo)
Scale-downElimina nodos infrautilizadosElimina + consolida + ajusta tamaño
Gestión de spotVía ASG + AWS Node Termination HandlerNativa, first-class, sin NTH
Modelo de configuraciónFlags en el DeploymentCRDs declarativos
Soporte cloudTodos los principales + on-premAWS (GA), Azure (estable), GCP (beta)
ConsolidaciónNo
Madurez de la comunidadMuy madura (desde 2016)Madura (GA 2024)

Velocidad de escalado: los números reales

Esta es probablemente la diferencia más visible en producción, y merece un análisis secuencia por secuencia.

Cluster Autoscaler en AWS (típico)

  1. Pod en Pending → el escaneo de CA lo detecta (0–10s)
  2. Llamada API UpdateAutoScalingGroup al ASG (~15–30s)
  3. La instancia EC2 arranca (1–2 min)
  4. Bootstrap del nodo + registro del kubelet (30–60s)
  5. El pod se programa (5–10s)

Total: 3–6 minutos (hasta 12 minutos en períodos de alta demanda de capacidad EC2)

Karpenter en AWS (típico)

  1. Pod en Pending → el watch event se dispara (~1s)
  2. Llamada API EC2 RunInstances (~2–3s)
  3. La instancia EC2 arranca (el mismo hardware — 1–2 min)
  4. El nodo hace bootstrap y queda Ready (30–60s)
  5. El pod se programa (~5s)

Total: 90 segundos a 3 minutos

La diferencia de hardware es idéntica — el tiempo de arranque de EC2 es el mismo. La ventaja de Karpenter proviene de eliminar el polling del bucle de control y la capa ASG. A efectos prácticos, esto es una mejora de 2–4x en el tiempo de aprovisionamiento en condiciones normales, y de hasta 8x en condiciones de alta contención de capacidad.

Para workloads event-driven, batch o APIs con picos bruscos de tráfico, esta diferencia determina directamente si los SLOs se cumplen o se incumplen.


Optimización de costes: donde Karpenter toma ventaja

Right-sizing

CA requiere node groups predefinidos. Si tienes cargas de trabajo con necesidades de memoria muy variables — un pod de 2 GiB y otro de 14 GiB — necesitas node groups que cubran ambos casos, o desperdicias recursos. Karpenter selecciona la instancia mínima viable para el workload pendiente desde el catálogo completo, sin necesidad de preconfigurar.

Consolidación frente a scale-down

CA elimina nodos infrautilizados. Karpenter reemplaza un nodo grande infrautilizado por uno más pequeño que aún cabe con todos los pods. Esto produce un ahorro compuesto a lo largo del tiempo que CA estructuralmente no puede alcanzar.

Ejemplo concreto: tienes un m5.4xlarge (16 vCPU, 64 GiB) con pods que solo consumen 3 vCPU y 12 GiB. CA lo deja como está porque tiene pods. Karpenter lo reemplaza por un m5.xlarge (4 vCPU, 16 GiB) y redistribuye. El coste baja un 75% en ese nodo.

Gestión de instancias spot

Karpenter recibe los avisos de interrupción de EC2, pre-aprovisiona un nodo de reemplazo y drena el nodo afectado — todo dentro de la ventana de 2 minutos. No requiere AWS Node Termination Handler. Además, diversifica automáticamente las peticiones de spot entre tipos de instancia para reducir el riesgo de interrupciones simultáneas.

Con CA, gestionar instancias spot de forma fiable requiere: ASGs configurados con múltiples tipos de instancia (opción mixed instances policy), desplegar y mantener el AWS Node Termination Handler, y ajustar los interruptionHandlers en la configuración de CA. Con Karpenter, declaras capacity-type: spot en el NodePool y el resto es automático.


Soporte multicloud en 2026

CloudCluster AutoscalerKarpenter
AWSEstable en producciónEstable en producción (implementación de referencia)
GCPEstable en producciónBeta (karpenter-provider-gcp)
AzureEstable en producciónEstable (karpenter-provider-azure)
Alibaba CloudSoportadoSin provider
DigitalOceanSoportadoSin provider
On-premises / Cluster APISoportadoNo soportado

Esta tabla es probablemente el factor más determinante en la decisión para muchos equipos. Si tu organización no está en AWS o Azure, la decisión prácticamente se toma sola: Cluster Autoscaler es la opción razonable.

Una excepción notable: GKE en GCP tiene su propio mecanismo de autoescalado (Node Auto Provisioning / NAP) que es técnicamente superior a CA en ese entorno. Si estás en GKE, la respuesta suele ser «ninguno de los dos — usa NAP».


Cuándo Cluster Autoscaler sigue siendo la elección correcta

A pesar del innegable avance técnico de Karpenter, hay escenarios donde CA sigue siendo la respuesta correcta:

1. Entornos no-AWS
Si estás en GCP (sin GKE NAP), Alibaba, DigitalOcean o on-premises con Cluster API, Karpenter no es una opción viable. CA es la herramienta madura y bien soportada para esos entornos.

2. Arquitectura de node groups existente con inversión significativa
Si tienes años de diseño de ASGs, tooling de compliance vinculado a tags de ASG y pipelines de CI/CD que asumen la existencia de node groups específicos, el coste de migración puede superar fácilmente el beneficio. No migres por migrar.

3. Restricciones regulatorias
Algunos marcos de cumplimiento (PCI-DSS, entornos gubernamentales con requisitos específicos de auditoría) requieren trazabilidad de aprovisionamiento a través de ASGs. El modelo directo de Karpenter puede complicar las evidencias de auditoría en estos contextos.

4. Cluster API / bare metal
CA es la única opción madura para entornos con Cluster API o bare metal. Karpenter requiere un provider de cloud para funcionar.

5. Despliegues CA que funcionan bien y equipo sin tiempo para migrar
Si tu CA está bien configurado, los SLOs se cumplen y no tienes presión de costes urgente, la relación coste-beneficio de migrar puede no ser favorable a corto plazo. «Si funciona, no lo toques» es un principio válido de ingeniería.


Cuándo Karpenter es la elección correcta

1. Clusters AWS-nativos con prioridad de optimización de costes
La combinación de right-sizing + consolidación activa produce reducciones de coste reales y sostenidas. Si tu factura de cómputo en AWS es significativa, el ROI de migrar a Karpenter es generalmente positivo en semanas.

2. Workloads diversas y variables
Batch, spot, GPU, APIs sin estado — Karpenter gestiona todo esto con unos pocos NodePools bien definidos, sin la proliferación de ASGs que requeriría CA para el mismo nivel de flexibilidad.

3. Clusters spot-heavy
La gestión nativa de interrupciones de spot, con diversificación automática entre tipos de instancia y pre-aprovisionamiento de reemplazos, es cualitativamente superior al stack CA + NTH. Si más del 30–40% de tu capacidad es spot, Karpenter simplifica enormemente la operación.

4. Cultura infrastructure-as-code declarativa
Los NodePools se versionan limpiamente en Git, se revisan en pull requests, y expresan intención en lugar de configuración imperativa. Para equipos con GitOps maduro, esto es una mejora real en mantenibilidad.

5. Requisitos de escalado de baja latencia
Workloads event-driven, jobs desencadenados por KEDA, picos bruscos de tráfico. Si los 3–6 minutos de CA están dentro de tu ventana de incumplimiento de SLO, Karpenter soluciona el problema estructuralmente.


Ejecutar ambos: ruta de migración y gotchas

Hay escenarios válidos para ejecutar CA y Karpenter en paralelo — especialmente durante la migración o cuando tienes workloads con requisitos contradictorios. Lo más importante es que no gestionen los mismos nodos.

Separar la responsabilidad

Usa labels y taints para evitar que CA y Karpenter gestionen los mismos nodos:

# NodePool con taint — los pods gestionados por CA no tolerarán esto
spec:
  template:
    metadata:
      labels:
        provisioner: karpenter
    spec:
      taints:
        - key: karpenter.sh/provisioned
          value: "true"
          effect: NoSchedule

Migración gradual recomendada

Fase 1 — Karpenter gestiona workloads spot y batch. CA gestiona los nodos on-demand de producción. Esto valida Karpenter con workloads menos críticos.

Fase 2 — Migrar workloads spot completamente a Karpenter. Eliminar AWS NTH (ya no es necesario). Validar el comportamiento de consolidación.

Fase 3 — Migrar nodos on-demand. Reducir gradualmente la capacidad de los node groups de CA mientras se monitorizan los NodePool limits de Karpenter.

Fase 4 — Desmantelar CA una vez que todos los grupos están vacíos. Limpiar ASGs y tooling asociado.

Budget mínimo para una migración bien hecha en un cluster de tamaño medio: un sprint completo. Las prisas aquí tienen consecuencias directas en disponibilidad.

Gotchas que te van a costar tiempo

Karpenter consolidation + PDBs permisivos: maxUnavailable: 100% causará consolidación disruptiva. Audita tus PodDisruptionBudgets antes de habilitar WhenEmptyOrUnderutilized. Un PDB mal configurado puede provocar una interrupción de servicio durante la consolidación.

Los NodePool limits son paradas duras: cuando un NodePool alcanza su límite de CPU o memoria, los pods van a Pending indefinidamente. CA tiene el mismo problema, pero los equipos nuevos en Karpenter tienden a descubrirlo en producción. Monitoriza la utilización de los límites activamente.

AMI drift: el alias @latest selecciona nuevas AMIs en nuevos nodos. Esto significa que puedes tener nodos con AMIs diferentes conviviendo en el cluster. Para entornos con control de cambios estricto, considera anclar la versión de AMI o implementar tests de validación antes de actualizar el alias.

Conflictos de scale-down simultáneos: durante la migración, CA y Karpenter pueden intentar escalar hacia abajo al mismo tiempo. La segregación estricta por labels y taints es la única garantía real contra esto.


Framework de decisión

FactorCluster AutoscalerKarpenter
Soporte cloudTodos los clouds + on-premAWS (GA), Azure (estable), GCP (beta)
Velocidad de aprovisionamiento4–8 minutos60–120 segundos
Flexibilidad de instanciasRequiere preconfiguración de node groupsCatálogo completo, selección en tiempo de ejecución
Optimización de costesSolo scale-downScale-down + consolidación + right-sizing
Integración spotVía ASG + NTHNativa, first-class
Complejidad operativaMenorModerada
Cluster API / bare metalNo
Consolidación activaNo

El árbol de decisión simplificado:

¿Ejecutas en AWS?
├── No → ¿Azure? → Karpenter (estable) o CA
│        ¿GCP?   → CA o GKE NAP (preferido)
│        ¿Otro?  → Cluster Autoscaler
│
└── Sí → ¿Restricciones regulatorias que exigen ASG?
          ├── Sí → Cluster Autoscaler
          └── No → ¿Prioridad de optimización de costes o workloads diversas?
                   ├── Sí → Karpenter
                   └── No → Cualquiera (elige según preferencia del equipo)

Preguntas frecuentes

¿Es Karpenter un sustituto directo de Cluster Autoscaler?

No. Son modelos de configuración y conceptos diferentes. La migración requiere re-expresar la configuración de node groups como NodePools/NodeClasses, auditar PDBs y ejecutar ambos en paralelo durante la transición. Presupuesta al menos un sprint para un cluster de tamaño medio. No hay un botón de «migrar».

¿Puedo usar Karpenter en Kubernetes autogestionado (sin EKS)?

Sí, pero con trabajo extra. Karpenter requiere credenciales IAM (IRSA o equivalente) para llamar a las APIs de EC2. En clusters autogestionados, esto requiere más configuración que en EKS donde IRSA es nativo. Es viable, pero no es el camino de menor resistencia.

¿Cómo interactúa Karpenter con HPA y VPA?

Sin conflicto. El flujo es: HPA crea pods → los pods van a Pending si no hay nodos suficientes → Karpenter aprovisiona nodos → los pods se programan. VPA ajusta los resource requests de los pods, que Karpenter usa como inputs para el bin packing. Los tres pueden coexistir sin problemas.

¿Qué ocurre si Karpenter se cae?

Los nodos existentes y los pods continúan con normalidad. Los pods nuevos que requieran aprovisionamiento quedan en Pending hasta que Karpenter se recupere. El scale-down y la consolidación se pausan. Para producción, despliega múltiples réplicas con leader election.

¿Karpenter soporta nodos GPU?

Sí. Los tipos de instancia GPU (p3, p4, g4, g5) pueden incluirse en los requirements del NodePool. La recomendación es crear NodePools dedicados con taints apropiados para los pods que soliciten recursos GPU, manteniendo la separación clara de workloads GPU frente al resto.

¿Cómo gestiona Karpenter las actualizaciones de AMI?

El campo expireAfter fuerza la rotación de nodos. Cuando un nodo expira, Karpenter pre-aprovisiona un reemplazo con la AMI más reciente según el EC2NodeClass, luego drena y termina el nodo antiguo. Es efectivamente un mecanismo de rolling AMI update sin tooling adicional. La alternativa es anclar la versión de AMI explícitamente y gestionar las actualizaciones de forma controlada.

¿Cluster Autoscaler sigue con mantenimiento activo?

Sí. CA sigue en desarrollo activo bajo kubernetes/autoscaler, con releases que siguen las versiones minor de Kubernetes. No está siendo deprecado. Para entornos no-AWS y despliegues CA que funcionan bien, sigue siendo una elección completamente soportada y racional. La narrativa de «CA está muerto» es incorrecta — simplemente tiene un ámbito de aplicación más claro en 2026.


Conclusión

Ni Cluster Autoscaler ni Karpenter son la respuesta universal. Son herramientas diferentes para contextos diferentes, y en 2026 ambas están maduras.

Si estás en AWS y el coste de cómputo o la velocidad de escalado son prioridades reales, Karpenter es la elección técnicamente superior. La combinación de aprovisionamiento directo vía EC2 API, consolidación activa y gestión nativa de spot produce beneficios compuestos que CA estructuralmente no puede igualar.

Si no estás en AWS, tienes restricciones regulatorias específicas, o tu CA actual funciona bien y el equipo no tiene ancho de banda para una migración, Cluster Autoscaler sigue siendo la respuesta correcta. No migres por moda.

La pregunta que vale la pena hacerse no es «¿cuál es mejor?» sino «¿cuál resuelve mi problema concreto con el menor coste operativo?». Para la mayoría de clusters AWS en 2026, esa respuesta es Karpenter — pero solo si estás dispuesto a hacer la migración bien.


Validado con Kubernetes 1.28–1.32. API de Karpenter v1.x (GA). CA v1.30.x. Los ejemplos usan el provider de AWS; los detalles de los providers de Azure y GCP pueden diferir.

Requests y Limits en Kubernetes: Guía Completa para Producción

Requests y Limits en Kubernetes: Guía Completa para Producción

Tus pods mueren con OOMKill a las 3 de la madrugada. El p99 de latencia se dispara cada pocos minutos sin causa aparente. El scheduler coloca cargas de trabajo en nodos que no pueden sostenerlas. En la mayoría de los incidentes de producción con Kubernetes, los requests y limits mal configurados son o bien la causa directa o un factor que acelera el problema.

Esta no es una guía de «qué son los requests y los limits». Es una referencia técnica en profundidad para ingenieros que operan Kubernetes en producción y necesitan entender qué ocurre realmente dentro del kernel cuando se establecen estos valores — y cuáles son las consecuencias cuando se configuran mal.


Qué son realmente los Requests y los Limits

La documentación de Kubernetes explica requests y limits a nivel de API. Lo que no explica con suficiente detalle es el mecanismo de aplicación: cgroups.

Cuando el kubelet admite un pod en un nodo, crea una jerarquía de cgroups para ese pod bajo /sys/fs/cgroup/. Cada contenedor del pod recibe su propio cgroup. Los valores que defines en el spec del pod se traducen directamente en parámetros de cgroup:

CPU requestcpu.shares (cgroups v1) o cpu.weight (cgroups v2)
CPU limitcpu.cfs_quota_us y cpu.cfs_period_us
Memory requestmemory.soft_limit_in_bytes (orientativo, usado para scoring de evicción)
Memory limitmemory.limit_in_bytes (aplicación estricta, desencadena OOMKill)

El scheduler usa los requests para tomar decisiones de ubicación. No conoce la utilización real — conoce la capacidad comprometida. Un nodo con 4 cores donde los pods en ejecución tienen un total de CPU request de 3,5 cores tiene 0,5 cores de capacidad schedulable restante, aunque la utilización real de CPU sea del 15%.

Por eso puedes tener un clúster «totalmente utilizado» (según requests) donde los nodos están ociosos, y también puedes tener nodos al 95% de utilización de CPU que siguen aceptando nuevos pods porque sus requests son bajos.

El kubelet usa los limits para aplicar restricciones en tiempo de ejecución mediante esos parámetros de cgroup. El scheduler nunca ve los limits.


CPU vs Memoria: Por Qué Se Comportan de Forma Fundamentalmente Distinta

Esta es la diferencia más importante que hay que entender sobre la gestión de recursos en Kubernetes, y es algo que se malinterpreta sistemáticamente incluso entre ingenieros con experiencia.

La CPU es un Recurso Compresible

La CPU es un recurso compartido en el tiempo. Si tu contenedor intenta usar más CPU de la que su limit permite, el scheduler CFS de Linux simplemente lo throttlea — deja de recibir tiempo de CPU hasta el siguiente período de planificación. El proceso continúa. Solo espera.

Desde la perspectiva de la aplicación: las cosas van más lentas. La latencia aumenta. El throughput cae. Pero el proceso no muere.

La Memoria no es un Recurso Compresible

La memoria no se comparte en el tiempo. Si tu contenedor intenta asignar memoria por encima de su limit, no hay una «ruta de degradación gradual». El OOM killer de Linux selecciona un proceso en el cgroup y lo mata. El contenedor muere.

Desde la perspectiva de la aplicación: el proceso termina. Kubernetes reinicia el contenedor. Ves OOMKilled en kubectl describe pod.

PropiedadCPUMemoria
AplicaciónCFS throttlingOOM Kill
¿Sobrevive el proceso?Sí (rendimiento degradado)No (muerto y reiniciado)
¿Compresible?No
Visibilidad del schedulerSolo requestsSolo requests
Consecuencia por exceder el limitPicos de latenciaReinicio del contenedor
¿Recomendado poner limits?Situacional (ver más abajo)Siempre

Esta asimetría guía todas las recomendaciones del resto de esta guía.


Clases QoS: Prioridad de Evicción Bajo Presión

Kubernetes asigna a cada pod una clase Quality of Service (QoS) en función de los requests y limits establecidos en todos sus contenedores. Esta clase determina la prioridad de evicción cuando un nodo está bajo presión de memoria.

Guaranteed

Condición: Todos los contenedores tienen definidos requests y limits de CPU y memoria, y los requests son iguales a los limits tanto para CPU como para memoria.

resources:
  requests:
    cpu: "500m"
    memory: "512Mi"
  limits:
    cpu: "500m"
    memory: "512Mi"

Los pods Guaranteed son los últimos en ser eviccionados. El kubelet agotará los pods BestEffort y Burstable antes de tocar estos. Reciben la asignación de recursos más predecible en el nodo.

Advertencia: Guaranteed no significa «siempre disponible». Significa «el último en ser matado». En un nodo con sobrecarga severa, incluso los pods Guaranteed pueden ser eviccionados.

Burstable

Condición: Al menos un contenedor tiene definido un request o limit de CPU o memoria, pero el pod no cumple los criterios de Guaranteed.

resources:
  requests:
    cpu: "250m"
    memory: "256Mi"
  limits:
    cpu: "1000m"
    memory: "1Gi"

Los pods Burstable se eviccionan después de BestEffort pero antes que Guaranteed. Pueden superar su request cuando la capacidad está disponible, pero no están protegidos cuando el nodo está bajo presión.

BestEffort

Condición: Ningún contenedor del pod tiene definido ningún request ni limit de CPU ni de memoria.

# Sin bloque resources en absoluto

Los pods BestEffort son los primeros en ser eviccionados, siempre. Reciben la capacidad que queda después de que las cargas de trabajo planificadas consuman su parte solicitada. En un nodo con carga, pueden quedar completamente sin recursos.

En producción: nunca ejecutes cargas de trabajo con estado ni servicios críticos de negocio como BestEffort. El scheduler de Kubernetes los colocará en cualquier sitio, y el kubelet los matará primero.


Patrones de Mala Configuración y sus Consecuencias

Patrón 1: Sin Requests ni Limits

Efecto: QoS BestEffort. Primeros en ser eviccionados bajo presión de memoria. El scheduler coloca los pods de forma arbitraria — no tiene datos para tomar decisiones de ubicación, por lo que recurre a LeastRequestedPriority, lo que en la práctica significa que estos pods pueden acabar en los mismos nodos que cargas de trabajo muy cargadas.

Consecuencia real: Tus jobs de background «ligeros» matan tus servidores de API a las 3 de la madrugada cuando un pico de memoria desencadena evicción y los pods BestEffort resultan estar en el mismo nodo que ellos.

Patrón 2: Requests Iguales a Limits (QoS Guaranteed)

Este es el patrón «seguro» común recomendado en documentación antigua de Kubernetes. No es incorrecto, pero tiene una trampa:

CPU limits = CPU requests significa que el CPU throttling está garantizado que se activará. Tu pod será throttleado en el momento en que intente superar el request — durante el arranque, durante GC, durante un pico de tráfico — aunque el nodo tenga CPU libre abundante.

Para aplicaciones sensibles a la latencia, esto significa picos de throttling predecibles exactamente en los momentos en que más CPU necesitas.

Memoria: Establecer memory request = memory limit es apropiado y recomendable. El comportamiento es correcto: el pod funciona dentro de un presupuesto de memoria controlado.

Patrón 3: Limits Muy Superiores a los Requests (Burstable con Ratio Alto)

resources:
  requests:
    cpu: "100m"
    memory: "128Mi"
  limits:
    cpu: "4000m"
    memory: "4Gi"

Este es el extremo opuesto. El scheduler cree que este pod necesita 100m de CPU y 128Mi de memoria. Docenas de estos pueden planificarse en un solo nodo. Cuando todos hacen burst simultáneamente — que lo harán, durante un despliegue, un evento de tráfico o un ciclo de GC — el nodo queda sobrecargado, la presión de memoria desencadena cascadas de OOMKill, y el scheduler no tiene ni idea de que algo va mal porque la capacidad comprometida (según requests) parece correcta.

El ratio limit:request importa. Un ratio de memory limit:request de 10x o 20x en muchos pods es una receta para la inestabilidad del nodo. Un punto de partida razonable es 2x–4x para memoria, menos para CPU.

Patrón 4: CPU Limits Establecidos «Por Seguridad»

Esta es la mala configuración más sutil y la que tiene mayor impacto oculto en la latencia. La analizamos en profundidad en la siguiente sección.


El Problema del CPU Throttling: CFS Bandwidth y Latencia Oculta

Aquí es donde muchos despliegues de Kubernetes en producción tienen un problema de rendimiento silencioso que no es fácil de diagnosticar.

Cómo Funciona el CFS Bandwidth Throttling

El Linux Completely Fair Scheduler (CFS) aplica los CPU limits mediante control de ancho de banda. Los parámetros relevantes son:

  • cpu.cfs_period_us: el período de contabilización, por defecto 100ms
  • cpu.cfs_quota_us: cuántos microsegundos de tiempo de CPU puede usar el cgroup por período

Si estableces cpu: "500m" como limit, Kubernetes establece cpu.cfs_quota_us = 50000 (50ms por período de 100ms). Esto significa que el contenedor puede usar como máximo el 50% de un núcleo de CPU por ventana de 100ms.

El problema: la quota se aplica por período, no como media móvil. Si tu contenedor usa su asignación completa de 50ms en los primeros 60ms de un período, es throttleado durante los 40ms restantes — aunque el nodo tenga 7 CPUs ociosas. La CPU permanece inactiva. Tu contenedor espera.

Por Qué Esto Causa Picos de Latencia Incluso con Baja Utilización

Esto es contraintuitivo y el origen de muchos misterios en producción. Puedes tener un contenedor funcionando al 10% de utilización media de CPU que es throttleado regularmente, porque su uso instantáneo de CPU dentro de una sola ventana de 100ms supera su quota.

Las aplicaciones Java con garbage collection de la JVM son especialmente vulnerables. El GC provoca un burst de CPU de corta duración. Si ese burst supera la quota por período, la pausa de GC se alarga artificialmente por throttling — aunque el propio evento de GC hubiera sido breve.

Lo mismo ocurre con el procesamiento del event loop de Node.js, la importación de Python al arrancar, y cualquier aplicación con comportamiento de CPU en ráfagas (que son la mayoría).

La Evidencia de Cloudflare y Netflix

Cloudflare publicó resultados mostrando que el CPU throttling era responsable de incrementos significativos en la latencia de cola en sus cargas de trabajo en contenedores, y que eliminar los CPU limits redujo la latencia p99 sustancialmente para servicios que aparentemente tenían margen. Netflix ha documentado patrones similares en sus trabajos de capacity planning, señalando que la aplicación de quota por período no modela con precisión el comportamiento real de CPU de las aplicaciones.

La comunidad del kernel lleva años siendo consciente de esto. La solución — migrar a cgroups v2 con mejor integración del scheduler — ayuda pero no elimina el problema. Kubernetes 1.25+ con nodos cgroups v2 experimenta menos throttling bajo los mismos limits, pero el problema fundamental persiste: los CPU limits throttlean aplicaciones con ráfagas de forma impredecible.

La Recomendación: Considera No Establecer CPU Limits

Esto es controvertido pero está respaldado por la evidencia:

Para servicios sensibles a la latencia: no establezcas CPU limits. Establece CPU requests con precisión y confía en el scheduler para la ubicación.

El argumento:
– El CPU throttling es un modo de fallo suave que es difícil de observar y diagnosticar
– OOMKill es un modo de fallo duro que es visible y recuperable
– Los CPU requests dan al scheduler datos precisos de ubicación sin crear throttling
– Los nodos gestionan la sobresuscripción de CPU de forma elegante mediante time-sharing; no gestionan la sobresuscripción de memoria de forma elegante

Cuándo seguir estableciendo CPU limits:
– Clústeres multi-tenant donde el aislamiento de vecinos ruidosos (noisy neighbor) es crítico
– Cargas de trabajo batch donde la asignación predecible de CPU importa más que la latencia
– Cuando tu monitorización y alertas pueden detectar CPU starvation a nivel de nodo

Cuando no estableces CPU limits, debes establecer CPU requests con precisión. Un request de 100m para un servicio que normalmente usa 800m significa que el scheduler lo coloca en un nodo que realmente no puede sostenerlo. El resultado es starvation real de CPU, no throttling artificial — pero starvation de CPU igualmente.


Memoria: Establece Siempre los Limits

El contraste con la CPU es directo. La memoria es no compresible. Un contenedor que tiene una fuga de memoria o una asignación desbocada consumirá toda la memoria disponible del nodo si no tiene restricciones. Esto no degrada de forma elegante — activa el OOM killer, que puede matar procesos no relacionados en el nodo.

Establece siempre memory limits. Siempre.

La consecuencia — OOMKill — es visible, queda registrada, y Kubernetes la gestiona reiniciando el contenedor. Un código de salida OOMKilled es accionable: o tienes una fuga de memoria, o tu limit es demasiado bajo, o tu metodología de sizing es incorrecta. Los tres son diagnosticables.

La alternativa — sin memory limit — significa que un único pod con fuga puede desestabilizar un nodo entero y desencadenar cascadas de evicción que afectan a cargas de trabajo no relacionadas.

Establece los memory requests igual al uso en estado estable del p95 de tu aplicación. Establece los memory limits en 1,5x–2x el request para absorber picos de tráfico y presión de GC. Perfila tu aplicación bajo carga para establecer estas líneas base.


Vertical Pod Autoscaler (VPA)

El VPA es el componente de Kubernetes diseñado para resolver automáticamente el problema del sizing. Observa la utilización real de recursos y recomienda (o aplica) requests ajustados.

Cómo Funciona el VPA

El VPA tiene tres componentes:

  • Recommender: Observa métricas históricas y calcula requests recomendados basándose en la utilización observada. No modifica pods.
  • Updater: Evicta pods cuyos requests actuales difieren significativamente de las recomendaciones (cuando el modo VPA es Auto o Recreate).
  • Admission Controller: Muta los specs de pods en el momento de admisión para aplicar las recomendaciones del Recommender.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: api-server-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  updatePolicy:
    updateMode: "Off"   # Solo recomendar — no evictar pods
  resourcePolicy:
    containerPolicies:
    - containerName: api-server
      minAllowed:
        cpu: 100m
        memory: 128Mi
      maxAllowed:
        cpu: 4000m
        memory: 4Gi
      controlledResources: ["cpu", "memory"]
      controlledValues: RequestsAndLimits

Modos del VPA

ModoComportamiento
OffCalcula solo recomendaciones. Sin mutaciones de pods.
InitialAplica recomendaciones solo a pods nuevos. No evicta pods en ejecución.
RecreateEvicta pods cuando las recomendaciones cambian significativamente.
AutoActualmente equivalente a Recreate. Puede cambiar en versiones futuras.

Cuándo Usar el VPA

Right-sizing durante el despliegue inicial: Ejecuta VPA en modo Off durante 1–2 semanas en un servicio nuevo. Revisa las recomendaciones antes de aplicarlas. Este es el caso de uso más valioso.

Servicios con patrones de carga impredecibles o estacionales: El VPA adapta los requests según el comportamiento observado. Combinado con HPA para el escalado horizontal, obtienes réplicas bien dimensionadas que escalan hacia afuera horizontalmente.

El VPA y el HPA no pueden gestionar la misma métrica simultáneamente. Si el HPA está escalando por utilización de CPU, no uses VPA con controlledValues: RequestsAndLimits para CPU — entrarán en conflicto. Usa controlledValues: RequestsOnly y deja que el HPA gestione el escalado.

Limitaciones del VPA:
– Requiere reinicios de pods para aplicar recomendaciones (el Updater evicta pods)
– No funciona bien con cargas de trabajo con estado en ventanas de disponibilidad estrictas
– El Recommender necesita historial suficiente (al menos unos días) para producir recomendaciones fiables
– No tiene en cuenta picos de tráfico que todavía no se han observado


LimitRange y ResourceQuota: Salvaguardas a Nivel de Namespace

Los requests y limits en pods individuales resuelven el problema por carga de trabajo. LimitRange y ResourceQuota resuelven el problema de gobernanza a nivel de namespace y clúster.

LimitRange

LimitRange establece requests y limits por defecto para los contenedores de un namespace, y aplica límites mínimos y máximos. Cualquier pod admitido en el namespace que no tenga requests/limits explícitos recibirá los valores por defecto.

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: production
spec:
  limits:
  - type: Container
    default:
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:
      cpu: "100m"
      memory: "128Mi"
    max:
      cpu: "4000m"
      memory: "8Gi"
    min:
      cpu: "50m"
      memory: "64Mi"
  - type: Pod
    max:
      cpu: "8000m"
      memory: "16Gi"
  - type: PersistentVolumeClaim
    max:
      storage: "50Gi"
    min:
      storage: "1Gi"

Comportamientos clave:
default se aplica como limit para contenedores que establecen un request pero no un limit
defaultRequest se aplica como request para contenedores que no establecen ningún request
max y min causan que la admisión falle si se violan
– LimitRange se aplica en el momento de la admisión — cambiarla no afecta a los pods en ejecución

Usa LimitRange para:
– Prevenir que se admitan pods BestEffort (estableciendo valores de defaultRequest)
– Aplicar estándares organizativos para las especificaciones mínimas de recursos
– Proteger el clúster de pods que solicitan recursos sin límite

ResourceQuota

ResourceQuota limita la cantidad total de recursos que pueden consumir todos los pods de un namespace. Esta es la herramienta de gobernanza multi-tenant.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: production-quota
  namespace: production
spec:
  hard:
    requests.cpu: "20"
    requests.memory: "40Gi"
    limits.cpu: "40"
    limits.memory: "80Gi"
    pods: "100"
    persistentvolumeclaims: "20"
    requests.storage: "500Gi"
    count/deployments.apps: "50"
    count/services: "50"
    count/secrets: "100"
    count/configmaps: "100"

Interacción crítica con LimitRange: Cuando ResourceQuota está activo en un namespace, todos los pods deben tener requests y limits establecidos o serán rechazados. Por eso los valores por defecto de LimitRange son importantes — aseguran que los pods sin recursos explícitos no sean rechazados por el sistema de quotas.

Usa ResourceQuota para:
– Aplicar presupuestos de recursos por equipo/aplicación en clústeres compartidos
– Prevenir que despliegues desbocados consuman toda la capacidad del clúster
– Implementar políticas de chargeback (seguimiento del consumo de recursos por namespace)


Metodología Práctica de Sizing

Paso 1: Instrumenta Antes de Establecer Valores

Despliega inicialmente con solo requests establecidos (sin CPU limits, memory limits establecidos conservadoramente altos) y monitoriza durante 2–4 semanas bajo carga realista.

Consultas PromQL útiles para el sizing:

# Uso de CPU p95 en los últimos 7 días
histogram_quantile(0.95,
  rate(container_cpu_usage_seconds_total{
    container="api-server",
    namespace="production"
  }[5m])
)

# Memory working set p99 en los últimos 7 días
quantile_over_time(0.99,
  container_memory_working_set_bytes{
    container="api-server",
    namespace="production"
  }[7d]
)

# Ratio de CPU throttling (alertar si >5%)
rate(container_cpu_cfs_throttled_seconds_total{container="api-server"}[5m])
/
rate(container_cpu_cfs_periods_total{container="api-server"}[5m])

Paso 2: Establece los CPU Requests desde Observaciones del p95

Establece el CPU request = uso de CPU p95 bajo carga de producción realista. Para servicios sensibles a la latencia: no establezcas CPU limits. Para jobs batch o en background: establece CPU limits en 2x–4x el request.

Paso 3: Establece Memory Requests y Limits

Establece el memory request = memory working set p95 durante al menos 7 días. Establece el memory limit = max(pico observado, 1,5 × request). Para Java/Python con procesamiento intensivo, usa 2x.

# Ejemplo de producción: microservicio Java
resources:
  requests:
    cpu: "500m"       # p95 observado: ~420m
    memory: "768Mi"   # p95 observado: ~680Mi
  limits:
    # Sin CPU limit — servicio sensible a la latencia
    memory: "1.5Gi"   # 2x request, cubre presión de GC

Paso 4: Usa las Recomendaciones del VPA para Validar

Ejecuta VPA en modo Off junto a tus valores establecidos manualmente. Después de 1–2 semanas, compara las recomendaciones del VPA con tu configuración actual.

Paso 5: Ajusta para Eventos del Ciclo de Vida de la Carga de Trabajo

Ten en cuenta: el calentamiento de la JVM al arrancar (pico de CPU de 3–10x el estado estable), la superposición durante despliegues rolling (margen en la quota del namespace) y los picos de tráfico conocidos (dimensiona para el pico, no para la media).


Configurar Recursos en Kubernetes: Sizing por Tipo de Carga de Trabajo

Una de las preguntas más frecuentes al configurar recursos en Kubernetes para producción es qué valores poner según el tipo de servicio. No existe una respuesta única. El perfil de CPU y memoria de un microservicio Go es fundamentalmente distinto al de un job de procesamiento batch en Python.

La siguiente tabla recoge las recomendaciones según el tipo de carga de trabajo más habitual en entornos productivos:

Tipo de Carga de TrabajoCPU RequestCPU LimitMemory RequestMemory LimitQoS Objetivo
API sensible a latencia (Go, Java, Node)p95 observadoNo establecerp95 observado1,5–2x requestBurstable
Jobs batch / backgroundp50 observado2–4x requestp95 observado1,5x requestBurstable
Sistema crítico (coredns, metrics-server)ConservadorIgual al requestConservadorIgual al requestGuaranteed
Stateful / bases de datos (in-cluster)p95 observadoNo establecerp99 observado1,25x requestBurstable
Cargas de trabajo dev/testBajo (100m)2x requestBajo (128Mi)2x requestBurstable
Contenedores sidecar (envoy, otel-collector)Perfilar individualmenteContextualPerfilar individualmente1,5x requestIgual al principal

La columna CPU Limit merece una explicación adicional. Para APIs y servicios stateful, la recomendación de no establecer CPU limit no es un descuido — es una decisión deliberada fundamentada en el comportamiento del CFS throttling descrito anteriormente. En clústeres multi-tenant con requisitos de aislamiento estrictos, esta recomendación debe evaluarse caso a caso.


QoS Kubernetes en Profundidad: Interacción con el kubelet

El comportamiento del QoS no se limita a la evicción. Tiene implicaciones directas sobre cómo el kubelet gestiona la presión de memoria en el nodo y cómo interacciona con los umbrales de evicción configurados en la kubelet config.

Umbrales de Evicción y QoS

El kubelet tiene dos tipos de umbral de evicción:

  • Soft eviction: El nodo ha estado por encima de un umbral durante un período (eviction-soft-grace-period). El kubelet puede evictar pods Burstable y BestEffort.
  • Hard eviction: El nodo supera un umbral crítico de forma inmediata. El kubelet evicta pods sin período de gracia.

Dentro de cada clase QoS, el kubelet prioriza la evicción según cuánto ha excedido el pod su request. Un pod Burstable que usa el 180% de su memory request será eviccionado antes que uno que usa el 110%.

OOM Score Adjustment

El kernel de Linux asigna a cada proceso un oom_score_adj. El kubelet manipula este valor según la clase QoS:

  • Guaranteed: -998 (muy bajo, el OOM killer los evita casi siempre)
  • Burstable: valor proporcional al exceso sobre el request
  • BestEffort: 1000 (el OOM killer los selecciona primero)

Este mecanismo funciona independientemente de los memory limits — es el comportamiento del kernel Linux actuando sobre los procesos del contenedor directamente.


Monitorización y Alertas para Recursos en Kubernetes

Configurar recursos en Kubernetes para producción no termina en el despliegue inicial. Necesitas visibilidad continua sobre el comportamiento real de los recursos.

# OOMKill rate
- alert: ContainerOOMKilled
  expr: increase(kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}[5m]) > 0
  for: 0m
  labels:
    severity: warning

# CPU throttling >10%
- alert: CPUThrottlingHigh
  expr: |
    rate(container_cpu_cfs_throttled_seconds_total[5m])
    /
    rate(container_cpu_cfs_periods_total[5m])
    > 0.10
  for: 5m
  labels:
    severity: warning

# Memoria cerca del limit >85%
- alert: MemoryNearLimit
  expr: |
    container_memory_working_set_bytes
    /
    (container_spec_memory_limit_bytes > 0)
    > 0.85
  for: 5m
  labels:
    severity: warning

Además de estas alertas, es recomendable incluir en tus dashboards de Prometheus/Grafana:

  • Ratio de utilización de requests: container_cpu_usage_seconds_total / kube_pod_container_resource_requests{resource="cpu"} — si está consistentemente por encima de 0,8, el request está subdimensionado.
  • Headroom de memoria por nodo: cuánta memoria schedulable queda en cada nodo según los requests comprometidos, independientemente de la utilización real.
  • Distribución QoS del clúster: cuántos pods son BestEffort, Burstable y Guaranteed. Un porcentaje alto de BestEffort en namespaces de producción es una señal de alerta.

Preguntas Frecuentes sobre Requests y Limits en Kubernetes

Mi aplicación Java sigue muriendo con OOMKill aunque he establecido el limit al doble del uso medio. ¿Qué me estoy perdiendo?

El heap de la JVM (-Xmx) no es el único consumidor de memoria. Los buffers off-heap, el Metaspace, los stacks de threads y el overhead de la JVM añaden entre un 25% y un 40% adicional. Establece -Xmx al ~75% de tu memory limit del contenedor. Para un limit de 1Gi: -Xmx768m es un punto de partida seguro.

¿Debo establecer los mismos recursos en todos los entornos?

No. Dev/test puede usar valores más bajos. Pero el ratio entre request y limit debería ser similar, y el perfil de recursos debería ser lo suficientemente parecido como para detectar malas configuraciones antes de llegar a producción.

¿Puedo usar HPA y VPA juntos?

Sí, con cuidado. Usa HPA para el escalado de réplicas (CPU o métricas personalizadas) y VPA en modo Off o con controlledValues: RequestsOnly como guía de right-sizing. Nunca tengas a ambos gestionando la misma métrica simultáneamente.

Mi clúster usa cgroups v2. ¿El CPU throttling sigue siendo un problema?

Mejorado, pero no eliminado. cgroups v2 usa un scheduler basado en pesos que reduce los artefactos de throttling. Sin embargo, la aplicación de cpu.cfs_quota_us sigue existiendo cuando se establecen CPU limits. Para cargas de trabajo sensibles a la latencia, el argumento de no establecer CPU limits sigue siendo válido en cgroups v2.

¿Cuál es un ratio de sobrecompromiso (overcommit) realista para el clúster?

CPU: un overcommit de 5–10x (total de requests vs cores físicos) es habitual para cargas de trabajo mixtas con requests precisos. Memoria: un overcommit de 1,5–2x a nivel de clúster es manejable con ratios de request:limit de 1,5x. Por encima de 2x, los eventos de presión de memoria en los nodos se vuelven frecuentes.

LimitRange está configurado pero los pods siguen siendo admitidos sin recursos. ¿Por qué?

Los valores por defecto de LimitRange solo se aplican a contenedores sin ninguna especificación de recursos en absoluto. Si un contenedor especifica requests.cpu pero no limits.cpu, el default de LimitRange para CPU no rellena el limit que falta. Verifica también que el LimitRange esté en el namespace correcto: kubectl get limitrange -n <namespace>.

¿Qué le hace a un nodo un pod sin memory limit?

Puede consumir toda la memoria disponible del nodo sin restricciones. Esto activa el OOM killer de Linux a nivel de nodo, que puede matar procesos fuera del contenedor — incluyendo el propio kubelet en casos extremos. Los memory limits no son negociables en producción.

¿Cómo detectar CPU throttling en producción si no tengo alertas configuradas?

El primer indicador es una latencia p99 inusualmente alta en servicios que aparentemente tienen baja utilización media de CPU. Para confirmar, consulta directamente: kubectl exec -it <pod> -- cat /sys/fs/cgroup/cpu/cpu.stat (cgroups v1) o kubectl exec -it <pod> -- cat /sys/fs/cgroup/cpu.stat (cgroups v2). La métrica throttled_time muestra el tiempo acumulado de throttling.


Checklist de Configuración de Recursos para Producción

Antes de poner un servicio en producción, verifica:

  • [ ] Todos los contenedores tienen requests.memory y limits.memory definidos
  • [ ] El ratio limits.memory / requests.memory está entre 1,5x y 2x
  • [ ] Los requests.cpu están basados en datos de utilización real (p95), no en estimaciones
  • [ ] Se ha tomado una decisión explícita sobre limits.cpu (no establecido por defecto para APIs)
  • [ ] El namespace tiene LimitRange configurado con valores defaultRequest razonables
  • [ ] El namespace tiene ResourceQuota si es un entorno compartido
  • [ ] Hay alertas activas para OOMKill, CPU throttling y memoria cerca del limit
  • [ ] El VPA está configurado en modo Off para observar recomendaciones durante las primeras semanas
  • [ ] La clase QoS resultante es la esperada (kubectl get pod <name> -o yaml | grep qosClass)

Validado contra Kubernetes 1.28–1.32. El comportamiento de cgroups v2 se indica donde difiere de v1. Los ejemplos de VPA usan la API autoscaling.k8s.io/v1 (VPA 0.14+).

Integrar Kyverno CLI en pipelines CI/CD con GitHub Actions

Integrar Kyverno CLI en pipelines CI/CD con GitHub Actions

Integrar Kyverno CLI en Pipelines CI/CD con GitHub Actions para Validación de Políticas Kubernetes

Introducción

A medida que Kubernetes se convierte en el estándar de facto para orquestar cargas de trabajo en entornos empresariales, garantizar el cumplimiento de políticas de seguridad y configuración deja de ser una opción para convertirse en una necesidad operativa. En muchos equipos, la validación de los manifiestos se hace de forma manual o directamente en el clúster, cuando el daño ya está hecho: un recurso mal configurado ha llegado a producción, ha violado una política de seguridad o ha consumido recursos de forma descontrolada.

Kyverno es un motor de políticas nativo de Kubernetes que permite definir, aplicar y auditar reglas de configuración directamente en formato YAML, sin necesidad de aprender un lenguaje específico como Rego. Y lo más importante: su interfaz de línea de comandos, el Kyverno CLI, puede integrarse en cualquier pipeline CI/CD para interceptar esos problemas antes de que lleguen al clúster.

En este artículo veremos cómo integrar Kyverno CLI en un pipeline de GitHub Actions para validar automáticamente manifiestos Kubernetes en cada pull request o push. El resultado es una capa de cumplimiento automatizada que refuerza la seguridad y la calidad del código de infraestructura sin fricciones para el equipo de desarrollo.


¿Qué es Kyverno CLI?

Kyverno es una herramienta de gestión de políticas nativa de Kubernetes. A diferencia de Open Policy Agent (OPA), que utiliza Rego como lenguaje de políticas, Kyverno define sus reglas en YAML puro, lo que lo hace mucho más accesible para equipos que ya trabajan con Kubernetes a diario.

El proyecto cuenta con dos modalidades de uso principales:

  • Kyverno como admission controller: se despliega como un webhook en el clúster y evalúa los recursos en tiempo de admisión, bloqueando o mutando los manifiestos antes de que sean persistidos.
  • Kyverno CLI: una herramienta de línea de comandos que permite aplicar y testear políticas contra manifiestos YAML localmente o en pipelines CI/CD, sin necesidad de un clúster activo.

Esta segunda modalidad es la que nos interesa aquí. El Kyverno CLI permite ejecutar el mismo motor de evaluación de políticas que usarías en el clúster, pero en un contexto offline, lo que lo convierte en la herramienta perfecta para el shift-left en validación de seguridad Kubernetes.

Casos de uso del Kyverno CLI en CI/CD

  • Validar que ningún manifiesto usa imágenes con el tag latest
  • Verificar que todos los contenedores definen requests y limits de CPU y memoria
  • Comprobar que los Deployments tienen configurado readinessProbe y livenessProbe
  • Asegurarse de que no se desplieguen contenedores en modo privilegiado
  • Validar labels obligatorios en todos los recursos (por ejemplo, app, team, environment)
  • Rechazar el uso de hostNetwork: true o hostPID: true

Beneficios de Integrar Kyverno CLI en un Pipeline CI/CD

1. Validación de políticas de forma automática y temprana

El principal beneficio es detectar violaciones de políticas en la fase más temprana posible del ciclo de desarrollo: en el mismo momento en que el desarrollador abre un pull request. Esto es lo que se conoce como shift-left security: mover los controles de seguridad lo más a la izquierda posible en el pipeline, cuando el coste de corrección es mínimo.

Si la violación se detecta en el clúster mediante el admission controller, ya hay contexto de ejecución involucrado, posiblemente un despliegue fallido, y hay que identificar el problema, comunicarlo al equipo y esperar a que lo corrijan. Si se detecta en el pipeline CI/CD, el desarrollador recibe feedback inmediato en su PR y puede corregirlo en segundos.

2. Consistencia entre entornos

Cuando el mismo conjunto de políticas se aplica tanto en el admission controller del clúster como en el pipeline CI/CD, se garantiza que lo que pasa en CI también pasa en producción. No hay sorpresas al desplegar: si el pipeline verde, el clúster también lo aceptará.

3. Separación de responsabilidades

Los equipos de plataforma o de seguridad pueden definir y mantener las políticas en Kyverno, mientras que los equipos de desarrollo las consumen de forma transparente a través del pipeline. Esto crea un modelo de gobernanza claro sin necesidad de bloquear el flujo de trabajo de los desarrolladores.

4. Sin dependencias de clúster en CI

A diferencia de otros enfoques que requieren un clúster de Kubernetes activo para validar (con herramientas como kubectl apply --dry-run=server), el Kyverno CLI opera completamente en local. Esto lo hace más rápido, más barato y más portable.

5. Desarrollo más ágil

Recibir feedback inmediato sobre violaciones de políticas acelera el ciclo de desarrollo. En lugar de descubrir problemas en la fase de despliegue o, peor aún, en producción, los desarrolladores pueden corregirlos mientras el código todavía está fresco en su mente.


Configuración de Kyverno CLI en GitHub Actions

Paso 1: Instalar el Kyverno CLI

Lo primero es añadir un step en el workflow de GitHub Actions que descargue e instale el binario del Kyverno CLI. El binario está disponible en las releases oficiales del repositorio GitHub de Kyverno.

El siguiente ejemplo muestra un workflow completo con la instalación incluida:

name: CI Pipeline con validación de políticas Kyverno

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  kyverno-policy-check:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout del código
        uses: actions/checkout@v4

      - name: Instalar Kyverno CLI
        run: |
          curl -LO https://github.com/kyverno/kyverno/releases/download/v1.13.0/kyverno-cli_v1.13.0_linux_x86_64.tar.gz
          tar -xzf kyverno-cli_v1.13.0_linux_x86_64.tar.gz
          sudo mv kyverno /usr/local/bin/
          kyverno version

Nota sobre versiones: Sustituye v1.13.0 por la versión que necesites para tu proyecto. Se recomienda fijar una versión concreta en lugar de usar latest para garantizar reproducibilidad en el pipeline. Puedes consultar las versiones disponibles en la página de releases de Kyverno.

Instalación alternativa mediante Krew

Si el runner ya tiene Krew instalado (el gestor de plugins de kubectl), también puedes instalar el CLI así:

kubectl krew install kyverno

Sin embargo, en runners de GitHub Actions la instalación directa del binario es más rápida y no requiere dependencias adicionales.


Paso 2: Definir las políticas de validación

Las políticas de Kyverno son recursos YAML estándar de Kubernetes. Para el CI/CD, la práctica recomendada es almacenarlas en el propio repositorio, bajo un directorio dedicado. Una estructura habitual es la siguiente:

.
└── .github
    └── policies
        ├── disallow-latest-tag.yaml
        └── require-requests-limits.yaml

De esta forma, las políticas viajan junto al código y están sujetas al mismo proceso de revisión mediante pull requests.

Política 1: Prohibir el uso del tag latest

El uso de latest en imágenes de contenedor es una práctica desaconsejada porque elimina la reproducibilidad: dos despliegues con la misma definición pueden usar versiones distintas de la imagen. Esta política rechaza cualquier Deployment, DaemonSet, StatefulSet o Pod que utilice imágenes sin tag o con el tag latest:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-latest-tag
  annotations:
    policies.kyverno.io/title: Prohibir tag latest en imágenes
    policies.kyverno.io/description: >-
      El tag 'latest' hace que los despliegues no sean reproducibles.
      Todos los contenedores deben usar un tag de versión específico.
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: require-image-tag
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Las imágenes de contenedor deben especificar un tag distinto de 'latest'."
        pattern:
          spec:
            containers:
              - image: "!*:latest"

Política 2: Requerir requests y limits de recursos

Sin límites de recursos, un contenedor defectuoso o malicioso puede consumir todos los recursos del nodo y provocar una interrupción de servicio. Esta política garantiza que todos los contenedores definen explícitamente sus requests y limits:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-requests-limits
  annotations:
    policies.kyverno.io/title: Requerir requests y limits de recursos
    policies.kyverno.io/description: >-
      Todos los contenedores deben definir requests y limits de CPU y memoria
      para garantizar una planificación predecible y evitar el agotamiento de recursos.
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: validate-resources
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Los contenedores deben definir resources.requests y resources.limits."
        pattern:
          spec:
            containers:
              - resources:
                  requests:
                    memory: "?*"
                    cpu: "?*"
                  limits:
                    memory: "?*"
                    cpu: "?*"

Política 3: Prohibir contenedores privilegiados

Una política de seguridad crítica en cualquier entorno de producción es evitar que los contenedores se ejecuten en modo privilegiado, ya que esto les otorga acceso casi completo al host:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged-containers
  annotations:
    policies.kyverno.io/title: Prohibir contenedores privilegiados
    policies.kyverno.io/description: >-
      Los contenedores privilegiados tienen acceso completo al host.
      Esta política prohibe el uso de securityContext.privileged: true.
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: no-privileged
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Los contenedores no pueden ejecutarse en modo privilegiado."
        pattern:
          spec:
            containers:
              - =(securityContext):
                  =(privileged): "false"

Paso 3: Añadir el step de validación al workflow

Con las políticas definidas y almacenadas en el repositorio, el siguiente paso es añadir al workflow de GitHub Actions el step que ejecuta la validación. El comando kyverno apply aplica las políticas del directorio indicado contra todos los manifiestos del directorio de recursos:

      - name: Validar manifiestos Kubernetes con Kyverno
        run: |
          kyverno apply .github/policies/ -r manifests/

El flag -r (o --resource) indica el directorio o fichero que contiene los manifiestos a validar. Puedes especificar múltiples rutas o usar globs.

Gestión de fallos con notificaciones

Para mejorar la visibilidad, puedes añadir un step condicional que notifique al equipo cuando se detecte una violación de política:

      - name: Notificar violación de política
        if: failure()
        run: echo "Se han detectado violaciones de política. Revisa los manifiestos antes de mergear."

En entornos más avanzados, este step podría enviar una notificación a Slack, crear un comentario en el PR o publicar los resultados como artefacto del workflow.


Paso 4: Workflow completo integrado

Aquí tienes el workflow de GitHub Actions completo, integrando instalación, validación y notificación:

name: Validación de políticas Kyverno

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  kyverno-policy-check:
    name: Kyverno Policy Check
    runs-on: ubuntu-latest

    steps:
      - name: Checkout del código
        uses: actions/checkout@v4

      - name: Instalar Kyverno CLI
        run: |
          KYVERNO_VERSION="v1.13.0"
          curl -LO "https://github.com/kyverno/kyverno/releases/download/${KYVERNO_VERSION}/kyverno-cli_${KYVERNO_VERSION}_linux_x86_64.tar.gz"
          tar -xzf "kyverno-cli_${KYVERNO_VERSION}_linux_x86_64.tar.gz"
          sudo mv kyverno /usr/local/bin/
          kyverno version

      - name: Validar manifiestos Kubernetes con Kyverno
        run: |
          kyverno apply .github/policies/ -r manifests/

      - name: Informar sobre violaciones de política
        if: failure()
        run: |
          echo "::error::Se han detectado violaciones de política Kyverno."
          echo "Revisa los manifiestos en el directorio 'manifests/' y corrígelos antes de continuar."

Ejemplo práctico: Detectando una violación

Supongamos que un desarrollador hace push de un Deployment de nginx con la siguiente configuración:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest  # Esto debería activar una violación

Este manifiesto viola la política disallow-latest-tag. Cuando el pipeline ejecuta kyverno apply .github/policies/ -r manifests/, el resultado sería algo similar a:

Applying 2 policy rule(s) to 1 resource(s)...

policy disallow-latest-tag -> resource default/Deployment/nginx-deployment
  Rule require-image-tag failed 🚫
  -> Las imágenes de contenedor deben especificar un tag distinto de 'latest'.
  -> Image nginx:latest violates the constraint

pass: 0, fail: 1, warn: 0, error: 0, skip: 0

El pipeline falla con código de salida no cero, bloqueando el merge del PR hasta que el desarrollador corrija la imagen. La solución sería usar un tag de versión específico:

          image: nginx:1.27.3

Buenas prácticas para Kyverno CLI en CI/CD

Separar políticas de audit y enforce

En entornos donde todavía se está adoptando Kyverno, puede ser útil diferenciar entre políticas en modo Audit (que informan pero no bloquean) y políticas en modo Enforce (que bloquean el pipeline). Esto permite una adopción progresiva sin interrumpir el flujo de trabajo:

spec:
  validationFailureAction: Audit  # O Enforce

En el pipeline CI/CD, puedes mantener ambos conjuntos de políticas en directorios separados (por ejemplo, .github/policies/enforce/ y .github/policies/audit/) y ejecutarlos de forma independiente, tratando los fallos de audit como warnings y los de enforce como errores que bloquean el pipeline.

Cachear el binario de Kyverno CLI

Para acelerar el pipeline, puedes cachear el binario de Kyverno entre ejecuciones usando la acción actions/cache:

      - name: Cachear Kyverno CLI
        uses: actions/cache@v4
        with:
          path: /usr/local/bin/kyverno
          key: kyverno-cli-v1.13.0

      - name: Instalar Kyverno CLI (si no está en caché)
        run: |
          if ! command -v kyverno &> /dev/null; then
            curl -LO "https://github.com/kyverno/kyverno/releases/download/v1.13.0/kyverno-cli_v1.13.0_linux_x86_64.tar.gz"
            tar -xzf kyverno-cli_v1.13.0_linux_x86_64.tar.gz
            sudo mv kyverno /usr/local/bin/
          fi

Usar kyverno test para políticas más complejas

Para políticas más complejas que requieren testear tanto casos válidos como inválidos, Kyverno CLI ofrece el subcomando kyverno test. Este comando permite definir fixtures con el resultado esperado para cada recurso, lo que resulta muy útil en pipelines de CI para los propios repositorios de políticas:

kyverno test .github/policies/tests/

La estructura de un test de Kyverno incluye:
– El fichero de política
– Los manifiestos de recursos a testear
– Un fichero kyverno-test.yaml que define qué resultado se espera para cada combinación de política y recurso

Integración con repositorios de políticas centralizados

En organizaciones grandes, lo habitual es mantener las políticas en un repositorio centralizado separado del código de aplicación. En ese caso, el workflow de CI puede clonar ese repositorio de políticas como parte del pipeline:

      - name: Clonar repositorio de políticas
        uses: actions/checkout@v4
        with:
          repository: mi-org/kyverno-policies
          path: kyverno-policies
          token: ${{ secrets.POLICIES_REPO_TOKEN }}

      - name: Validar manifiestos contra políticas corporativas
        run: |
          kyverno apply kyverno-policies/enforce/ -r manifests/

Relación entre Kyverno CLI y el Admission Controller

Un punto importante a tener en cuenta es que Kyverno CLI y el admission controller de Kyverno son complementarios, no sustitutos.

CaracterísticaKyverno CLI (CI/CD)Kyverno Admission Controller
Cuándo actúaEn el pipeline, antes del despliegueEn el clúster, en tiempo de admisión
Requiere clústerNo
Velocidad de feedbackInmediata (en el PR)Al intentar desplegar
Puede mutar recursosNo
Coste de correcciónMínimoMayor

La estrategia óptima es aplicar ambas capas: el CLI en CI/CD para detección temprana y el admission controller en el clúster como última línea de defensa. De esta forma, incluso si alguien intenta saltarse el pipeline y desplegar directamente con kubectl apply, el clúster seguirá protegido.


Troubleshooting habitual

El CLI no encuentra los manifiestos

Asegúrate de que la ruta especificada con -r existe y contiene ficheros YAML válidos. Puedes verificarlo con un step previo:

      - name: Listar manifiestos
        run: find manifests/ -name "*.yaml" -type f

Las políticas no se aplican a todos los recursos

Kyverno evalúa las políticas según el kind especificado en la regla. Si tus políticas apuntan a Pod pero tus manifiestos son Deployment, puede que necesites ajustar el match o saber que Kyverno CLI en modo apply evalúa los recursos tal como están definidos, no las plantillas de pod anidadas. En algunos casos puede ser necesario incluir los kinds de nivel superior:

      match:
        any:
          - resources:
              kinds:
                - Deployment
                - StatefulSet
                - DaemonSet
                - Pod

El pipeline falla pero no se ven los detalles del error

Añade el flag --detailed-results al comando de Kyverno para obtener más información sobre cada violación:

kyverno apply .github/policies/ -r manifests/ --detailed-results

Conclusión

Integrar Kyverno CLI en un pipeline de GitHub Actions es una de las formas más eficaces de aplicar el principio de shift-left security en entornos Kubernetes. Con una inversión mínima — unas pocas líneas de YAML en el workflow y un directorio de políticas en el repositorio — se obtiene una capa de validación automática que:

  • Detecta violaciones de políticas de seguridad y configuración antes de que lleguen al clúster
  • Proporciona feedback inmediato a los desarrolladores en cada pull request
  • Mantiene la consistencia entre los entornos de desarrollo, staging y producción
  • Reduce el coste de corrección al desplazar los controles a la fase más temprana posible

El Kyverno CLI no reemplaza al admission controller desplegado en el clúster, sino que lo complementa formando una estrategia de defensa en profundidad. Juntos, garantizan que los recursos de Kubernetes cumplan con las políticas corporativas tanto en el momento de revisión del código como en el momento del despliegue.

Para profundizar más en Kubernetes y sus patrones de seguridad, consulta la guía completa de Kubernetes Architecture Patterns donde encontrarás todos los conceptos fundamentales y avanzados explicados paso a paso.

Node Affinity en Kubernetes: Reglas, Trade-offs y Buenas Prácticas

Node Affinity en Kubernetes: Reglas, Trade-offs y Buenas Prácticas

Node Affinity en Kubernetes: Reglas de Scheduling, Trade-offs y Buenas Prácticas

El scheduling de pods en Kubernetes puede parecer un proceso automático y transparente. Y durante la mayor parte del tiempo, lo es. El scheduler elige un nodo disponible con recursos suficientes y la carga de trabajo arranca. Sin problemas. Sin configuración adicional. Sin que el equipo tenga que intervenir.

El problema aparece cuando ese comportamiento por defecto ya no es suficiente. Cuando tienes nodos con hardware especializado —GPUs, SSDs NVMe, instancias de alta memoria— y necesitas garantizar que ciertos workloads acaben en los nodos correctos. O cuando regulaciones de licencias obligan a aislar determinadas cargas de trabajo. O cuando simplemente quieres colocar los pods de una aplicación en la misma zona de disponibilidad que su base de datos para minimizar la latencia.

Ahí es exactamente donde entra en juego node affinity en Kubernetes: el mecanismo que te permite expresar, con mayor o menor grado de obligatoriedad, en qué nodos quieres que el scheduler coloque tus pods.

Este artículo cubre todo lo que necesitas saber para usar node affinity de forma efectiva: conceptos fundamentales, diferencias con nodeSelector, los dos tipos de reglas, sus trade-offs reales en producción y buenas prácticas para no encontrarte con sorpresas cuando falle un nodo a las 3 de la madrugada.


Qué es Node Affinity en Kubernetes

Node affinity es una funcionalidad del scheduler de Kubernetes que permite definir restricciones sobre en qué nodos pueden programarse los pods, basándose en las etiquetas (labels) de esos nodos.

En la práctica, es la respuesta de Kubernetes a una pregunta muy concreta: «¿cómo le digo al scheduler que este pod solo debe ir a nodos con esta característica?» La respuesta, antes de node affinity, era nodeSelector. Y aunque nodeSelector sigue funcionando y es perfectamente válido para casos simples, node affinity expande notablemente esa capacidad.

Node Affinity vs nodeSelector: cuál es la diferencia

nodeSelector es el mecanismo más básico de scheduling por etiquetas. Añades un campo nodeSelector al spec del pod con los labels que debe tener el nodo, y el scheduler filtra en consecuencia. Funciona. Es directo. Pero tiene limitaciones importantes:

  • Solo permite igualdad exacta (key: value). No puedes expresar «cualquier valor de esta lista» o «que NO tenga este label».
  • No distingue entre restricciones obligatorias y preferentes. O se cumple, o el pod no se programa.
  • La semántica de error no es especialmente informativa cuando el scheduling falla.

Node affinity resuelve estas limitaciones con una API más expresiva:

  • Soporta operadores como In, NotIn, Exists, DoesNotExist, Gt y Lt.
  • Distingue entre reglas required (obligatorias) y preferred (preferentes).
  • Se integra mejor con las demás restricciones del scheduler, como pod affinity, pod anti-affinity y taints/tolerations.

La recomendación general es usar nodeSelector para casos muy simples donde la igualdad directa es suficiente, y migrar a node affinity en cuanto necesitas más expresividad o cuando el comportamiento ante fallos importa.


Los dos tipos de reglas de Node Affinity

Node affinity se configura en el campo affinity.nodeAffinity del spec del pod, y distingue dos modos fundamentales:

1. requiredDuringSchedulingIgnoredDuringExecution

Esta es la regla obligatoria (hard constraint). El scheduler solo colocará el pod en nodos que cumplan exactamente los criterios definidos. Si ningún nodo disponible satisface la regla, el pod permanece en estado Pending indefinidamente.

El nombre completo merece atención: IgnoredDuringExecution significa que, si un nodo cambia sus labels después de que el pod ya está ejecutándose, Kubernetes no lo desaloja. El pod sigue corriendo. La regla solo se aplica en el momento del scheduling inicial.

Ejemplo de configuración:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: node-type
              operator: In
              values:
                - database
                - storage-optimized

Con esta configuración, el pod solo se programará en nodos que tengan el label node-type con valor database o storage-optimized. En cualquier otro nodo, no se programará.

2. preferredDuringSchedulingIgnoredDuringExecution

Esta es la regla preferente (soft constraint). El scheduler intentará colocar el pod en nodos que cumplan los criterios, pero si no hay ninguno disponible, lo programará en cualquier otro nodo elegible.

Cada regla preferente tiene un campo weight (1-100) que permite ponderar su importancia relativa cuando hay varias reglas preferentes simultáneas. El scheduler suma los pesos de las reglas satisfechas por cada nodo y elige el nodo con mayor puntuación.

affinity:
  nodeAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
            - key: topology.kubernetes.io/zone
              operator: In
              values:
                - eu-west-1a
      - weight: 20
        preference:
          matchExpressions:
            - key: node-type
              operator: In
              values:
                - compute-optimized

En este ejemplo, el scheduler intentará colocar el pod en nodos de la zona eu-west-1a (peso 80) y preferentemente de tipo compute-optimized (peso 20), pero si no existen nodos que cumplan ninguna de las dos condiciones, el pod se programará igualmente en otro nodo.

Pueden combinarse

Nada impide usar ambas reglas simultáneamente. Un caso habitual: la regla required asegura que el pod solo va a nodos de un tipo determinado, y la regla preferred optimiza dentro de ese subconjunto por zona de disponibilidad o tier de hardware.

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: workload-class
              operator: In
              values:
                - gpu
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        preference:
          matchExpressions:
            - key: gpu-model
              operator: In
              values:
                - nvidia-a100

Trade-offs reales: Required vs Preferred en producción

Aquí está el núcleo del artículo, y la parte que mucha documentación glosa demasiado rápido. Porque node affinity no es simplemente «elige la opción que más se adapte a tu caso de uso». Cada elección tiene implicaciones directas sobre la disponibilidad, la operabilidad y el comportamiento ante fallos.

Para ilustrarlo, consideremos un escenario concreto: una base de datos distribuida —etcd, ZooKeeper o Cassandra— desplegada con tres réplicas para garantizar quórum y tolerancia a fallos. El equipo ha designado tres nodos específicos del clúster para alojar estos workloads y ha configurado los labels correspondientes. La pregunta es: ¿required o preferred?

El problema con required en este escenario

Si defines la regla como required, el scheduler solo programará las réplicas en los tres nodos etiquetados. Mientras todo funciona, perfecto: cada réplica está exactamente donde debería estar.

Pero imagina que uno de esos tres nodos cae por un fallo de hardware o una actualización. El pod que corría en ese nodo necesita ser reprogramado. ¿Dónde puede ir? Solo a otro de los nodos etiquetados. Si esos dos nodos ya tienen sus réplicas respectivas, y además tienes configurado pod anti-affinity para garantizar que cada réplica esté en un host diferente, el pod queda en Pending.

El clúster de base de datos está ahora con dos de tres réplicas activas. Si tienes quórum con dos, sigues funcionando. Pero si el nodo caído no vuelve pronto y otro falla, pierdes quórum. Y el pod sigue en Pending porque no puede ir a ningún nodo no etiquetado.

La combinación de required node affinity + pod anti-affinity puede ser más restrictiva de lo que parece a primera vista, y puede dejarte sin capacidad de recuperación automática en situaciones donde más la necesitas.

El problema con preferred en este escenario

Ahora supón que optas por preferred. El pod siempre se programará, incluso si ningún nodo etiquetado está disponible. Resuelves el problema de disponibilidad, ¿verdad?

En parte, sí. Pero introduces otro problema: la opacidad del estado del clúster. Si uno de los nodos etiquetados tiene problemas esporádicos de recursos, el scheduler podría empezar a colocar pods en nodos no etiquetados silenciosamente. Al cabo de un tiempo, tienes réplicas de tu base de datos crítica repartidas entre nodos etiquetados y no etiquetados, sin que ningún mecanismo te haya avisado explícitamente.

Administrar esa situación es mucho más difícil. No puedes garantizar que el workload está donde tiene que estar. Las asunciones sobre aislamiento de recursos o rendimiento del hardware se rompen.

El escenario más peligroso: preferred + taints

El caso más problemático aparece cuando combinas preferred node affinity con nodos que tienen taints. Considera este setup:

  • Los tres nodos etiquetados para tu base de datos tienen un taint dedicated=database:NoSchedule para evitar que otros workloads los invadan.
  • Los pods de la base de datos tienen la toleration correspondiente.
  • La regla de node affinity es preferred.

Si los nodos etiquetados están saturados, el scheduler intentará programar los pods en otros nodos. Pero esos otros pods —los que no son la base de datos— no tienen toleration para los nodos etiquetados con taint, y si los nodos sin etiquetar también se están llenando, el scheduler puede quedarse sin opciones.

Resultado: los pods de la base de datos acaban en nodos aleatorios que no son los designados, y otros workloads no pueden usar los nodos designados porque están tainteados. Tienes un clúster desorganizado donde ni el aislamiento ni la distribución están funcionando como esperabas. Y lo que es peor: todo esto puede estar pasando silenciosamente, sin alarmas obvias.


Prepararse para los fallos inesperados

La conclusión práctica de todo lo anterior es sencilla pero importante: las decisiones de scheduling que tomas en tiempo de diseño se manifiestan en tiempo de fallo. Mientras el clúster funciona con normalidad, tanto required como preferred se comportan igual de bien. La diferencia emerge exactamente cuando las cosas van mal.

Esto significa que antes de definir una regla de node affinity en producción, deberías hacerte estas preguntas:

¿Qué ocurre si uno de los nodos etiquetados falla?
– Con required: ¿hay suficientes nodos etiquetados para absorber la carga? ¿El pod anti-affinity no va a bloquearlo?
– Con preferred: ¿es aceptable que el workload acabe en nodos no designados? ¿Qué impacto tiene en rendimiento o compliance?

¿Cuántos nodos etiquetados tengo y cuántos necesito para tolerar fallos?
Si tienes tres réplicas y tres nodos etiquetados, un fallo deja el sistema al límite. Si tienes cuatro nodos etiquetados, tienes margen de maniobra con required.

¿Tengo taints en estos nodos? ¿Qué tolerations tienen los pods?
Tener claro el mapa completo de taints/tolerations antes de definir affinity rules evita los escenarios de deadlock descritos arriba.

¿Cómo monitorizo si los pods están donde se supone que deben estar?
Con preferred especialmente, necesitas alertas o dashboards que confirmen que el workload está realmente en los nodos designados, no solo que está programado y corriendo.


Node Affinity e interacción con Taints y Tolerations

Node affinity y el sistema de taints/tolerations son mecanismos complementarios, pero operan en fases distintas del proceso de scheduling.

El scheduler aplica primero las reglas de node affinity para filtrar el conjunto de nodos candidatos. Una vez tiene ese subconjunto, aplica el filtro de taints y tolerations: solo los nodos cuyos taints el pod puede tolerar son elegibles. Un pod solo acaba en un nodo que supera ambos filtros.

Entender este orden es clave. Si un nodo tiene el label correcto para tu affinity rule pero también tiene un taint que el pod no tolera, el pod no va a ese nodo. No importa cuánto peso le hayas dado a la preferred rule.

La tabla siguiente resume la interacción:

Pod tiene affinity ruleNodo tiene label correctoNodo tiene taintPod tolera el taintResultado
RequiredNoN/AProgramado
RequiredProgramado
RequiredNoNo programado
RequiredNoN/AN/ANo programado (Pending)
PreferredNoN/AProgramado (nodo preferido)
PreferredNoNoN/AProgramado (nodo no preferido)
PreferredNoNo programado en ese nodo; busca alternativa

La recomendación es diseñar siempre affinity rules y taints/tolerations como un sistema coherente, no como capas independientes. Mapea explícitamente: qué nodos tienen qué labels, qué nodos tienen qué taints, y qué pods tienen qué tolerations y qué affinity rules. Un diagrama simple de esto puede evitar horas de debugging cuando el scheduler no hace lo que esperas.


Buenas prácticas para definir Node Affinity en producción

Usa labels descriptivos y consistentes

Los labels son el contrato entre tus workloads y tus nodos. Defínelos con cuidado:

  • Prefiere los well-known labels de Kubernetes cuando existan: topology.kubernetes.io/zone, topology.kubernetes.io/region, kubernetes.io/arch, node.kubernetes.io/instance-type. Son más portables y compatibles con herramientas del ecosistema.
  • Para labels personalizados, usa un prefijo de dominio propio: workload.mycompany.com/class: database es mejor que simplemente class: database. Evita colisiones con otros sistemas.
  • Documenta el propósito de cada label custom en tu wiki o en anotaciones del propio nodo. Los labels sin documentar se convierten en deuda técnica.

Dimensiona los nodos etiquetados pensando en fallos

Si vas a usar required node affinity para un workload con N réplicas, necesitas al menos N+1 nodos etiquetados para que el sistema pueda recuperarse ante un fallo sin quedarse en Pending. Idealmente N+2 si quieres tolerancia a dos fallos simultáneos.

No etiquetes el mínimo indispensable. Etiqueta con margen.

Combina con pod anti-affinity con cuidado

La combinación de required node affinity + pod anti-affinity es especialmente poderosa para garantizar distribución, pero también especialmente peligrosa si no se dimensiona bien. Cada regla adicional reduce el espacio de nodos elegibles para el scheduler. Haz el cálculo explícito: con X nodos etiquetados, Y réplicas, y anti-affinity de host, ¿cuántos fallos puedo absorber antes de que el scheduler se bloquee?

Prefiere preferred para optimización, required para compliance

Una heurística útil: usa required cuando el incumplimiento de la regla es inaceptable (restricciones de licencia, compliance regulatorio, hardware imprescindible como GPU). Usa preferred cuando es una optimización (latencia, coste, rendimiento) que puede sacrificarse temporalmente si la disponibilidad lo requiere.

Simula fallos antes de ir a producción

No te fíes únicamente del razonamiento teórico. Con herramientas como kubectl cordon o kubectl drain puedes simular la indisponibilidad de un nodo en staging y observar exactamente qué hace el scheduler. ¿Los pods quedan en Pending? ¿Se van a nodos no esperados? ¿Cuánto tardan en reprogramarse?

Esta validación debería ser parte del proceso de revisión antes de mergear cambios en la configuración de scheduling.

Monitoriza el estado real del placement

Especialmente con preferred rules, implementa alertas que verifiquen que los pods están en los nodos esperados, no solo que están en estado Running. Un simple script que compare los labels del nodo donde corre cada pod contra los labels esperados, ejecutado periódicamente, puede darte esa visibilidad. Herramientas como Prometheus + kube-state-metrics facilitan este tipo de queries.


Ejemplo completo: base de datos distribuida con node affinity

Para cerrar con algo concreto, aquí está un ejemplo de configuración para el escenario de la base de datos distribuida con un enfoque razonado:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: distributed-db
spec:
  replicas: 3
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: workload.mycompany.com/class
                    operator: In
                    values:
                      - database
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              preference:
                matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                      - eu-west-1a
                      - eu-west-1b
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - distributed-db
                topologyKey: kubernetes.io/hostname
      tolerations:
        - key: "dedicated"
          operator: "Equal"
          value: "database"
          effect: "NoSchedule"

Observa las decisiones deliberadas aquí:

  • La node affinity required garantiza que los pods solo van a nodos etiquetados como database. Es una restricción de compliance/aislamiento que no queremos que se rompa.
  • La preferencia de zona es preferred, no required, porque si una zona tiene problemas, preferimos que el pod se programe en otra zona a que quede en Pending.
  • El pod anti-affinity también es preferred (no required), lo que permite al scheduler romper la restricción de un-pod-por-host si es necesario para garantizar disponibilidad. Puede que dos réplicas acaben en el mismo host en un escenario de fallo extremo, pero al menos estarán corriendo.
  • Los nodos de base de datos tienen un taint dedicated=database:NoSchedule y el pod tiene la toleration correspondiente.

Este diseño prioriza disponibilidad sobre aislamiento perfecto, que es la elección correcta para la mayoría de workloads en producción.


Preguntas frecuentes sobre Node Affinity en Kubernetes

¿Cuál es la diferencia entre nodeSelector y node affinity?

nodeSelector es un campo simple que requiere que el nodo tenga exactamente los labels especificados. Node affinity es una API más expresiva que soporta operadores como In, NotIn, Exists y DoesNotExist, y distingue entre restricciones hard (required) y soft (preferred). Usa nodeSelector para necesidades básicas de igualdad directa; usa node affinity para cualquier lógica de scheduling más compleja.

¿Cuándo usar required y cuándo preferred?

Usa required cuando el incumplimiento es inaceptable: hardware específico (GPU, FPGA), restricciones de licencia, compliance regulatorio, segmentación de red. Usa preferred cuando la regla es una optimización que puede sacrificarse: colocación en la misma zona de disponibilidad para reducir latencia, preferencia por instancias de un determinado tipo. Ten en cuenta que required puede dejar pods en Pending ante fallos de nodo, mientras que preferred puede no garantizar el placement esperado.

¿Qué riesgos tiene usar required node affinity?

El riesgo principal es el bloqueo de scheduling. Si ningún nodo satisface las reglas required (por fallo, mantenimiento o cambio de labels), el pod queda en Pending indefinidamente. Este riesgo se amplifica cuando se combina con pod anti-affinity, que reduce aún más el conjunto de nodos elegibles. La solución es dimensionar correctamente los nodos etiquetados para tener capacidad de sobra ante fallos.

¿Cómo interactúan node affinity y taints/tolerations?

Operan en fases distintas del scheduling. Primero, el scheduler filtra nodos según las affinity rules. Después, del conjunto resultante, filtra los nodos cuyos taints el pod no puede tolerar. Un pod solo se programa en un nodo que pasa ambos filtros. Diseña siempre ambos mecanismos como un sistema coherente.

¿Qué buenas prácticas debo seguir al definir labels para node affinity?

Usa well-known labels de Kubernetes cuando existan (topology.kubernetes.io/zone, node.kubernetes.io/instance-type). Para labels propios, usa un prefijo de dominio para evitar colisiones. Documenta el propósito de cada label. Dimensiona los nodos etiquetados con margen para tolerar fallos. Valida el comportamiento del scheduler simulando indisponibilidad de nodos antes de pasar a producción.

¿Puedo combinar required y preferred en la misma definición?

Sí. Es un patrón habitual: la regla required establece un filtro duro (solo nodos de un determinado tipo), y las reglas preferred optimizan dentro de ese subconjunto (preferir la zona más cercana, el hardware más rápido, etc.). El scheduler siempre respeta primero las reglas required y después puntúa los candidatos según las preferred.


Conclusión

Node affinity en Kubernetes es una herramienta poderosa para controlar el scheduling de workloads con precisión. Pero esa precisión tiene un coste: introduce fragilidad si no se diseña pensando en los escenarios de fallo.

La clave está en entender que la elección entre required y preferred no es solo una decisión de «qué quiero», sino de «qué pasa cuando las cosas fallan». Required te da certeza a cambio de disponibilidad. Preferred te da disponibilidad a cambio de certeza. Ninguna de las dos es incorrecta: depende del contrato de tu workload con el negocio.

Antes de definir cualquier regla de node affinity en producción, mapea explícitamente el conjunto de nodos etiquetados, sus taints, las tolerations de los pods, y simula al menos un escenario de fallo. Ese análisis previo vale más que cualquier configuración perfecta en papel que nadie ha probado bajo presión.


Este artículo forma parte de la guía completa de patrones de arquitectura Kubernetes en alexandre-vazquez.com.

Drivers de Helm explicados: Secrets, ConfigMaps y almacenamiento de estado

Drivers de Helm explicados: Secrets, ConfigMaps y almacenamiento de estado

Cuando trabajas en serio con Helm en entornos de producción, uno de los temas menos discutidos —pero con mayor impacto operativo— es cómo Helm almacena y gestiona el estado de los releases. Aquí es donde entran en juego los drivers de Helm. Entender este mecanismo no es un ejercicio académico: afecta directamente a la seguridad, la escalabilidad, la resolución de problemas y las estrategias de recuperación ante desastres.

Los drivers de Helm son una pieza fundamental que todo equipo que gestione Kubernetes en producción debería conocer en profundidad. En este artículo desgranaremos qué son, cómo han evolucionado, cuándo usar cada uno y qué consecuencias prácticas tiene elegir mal el backend de almacenamiento.


Qué es un driver de Helm y cómo se configura

Un driver de Helm define el mecanismo de almacenamiento backend que Helm utiliza para persistir la información de cada release: manifiestos generados, valores aplicados e historial de revisiones. Todo release de Helm tiene estado, y ese estado tiene que residir en algún lugar. El driver determina dónde y cómo se guarda esa información.

Los drivers de Helm se configuran mediante la variable de entorno HELM_DRIVER. Si no se establece explícitamente, Helm utiliza por defecto Kubernetes Secrets:

export HELM_DRIVER=secrets

Esta elección, aparentemente trivial, puede tener consecuencias operativas profundas, especialmente en entornos regulados o en clusters de gran escala donde la seguridad, la auditabilidad y el rendimiento son requisitos no negociables.

A diferencia de otras configuraciones de Helm que se establecen en ficheros de valores o en el propio chart, el driver opera a nivel de proceso del cliente Helm. Esto significa que distintos operadores o pipelines de CI/CD podrían, en teoría, utilizar drivers distintos sobre el mismo cluster si no se establece una política coherente. Esa inconsistencia puede llevar a situaciones confusas en las que Helm no encuentra el estado de un release simplemente porque el driver activo no coincide con el que se usó al instalar.


Los drivers de Helm disponibles

Helm ofrece actualmente tres drivers estables: secrets, configmaps y memory. Cada uno tiene un perfil de uso distinto y unas implicaciones de seguridad específicas que conviene conocer.

Driver Secrets (predeterminado)

El driver secrets almacena la información de los releases de Helm como Kubernetes Secrets en el namespace de destino. Es el driver por defecto desde la introducción de Helm 3 y la opción recomendada para la mayoría de entornos de producción.

Los Secrets en Kubernetes están codificados en base64. Si bien base64 no es cifrado en sí mismo, los clusters que tienen activado el cifrado en reposo (encryption at rest) de la API de Kubernetes cifrarán estos objetos antes de escribirlos en etcd. Esto convierte al driver secrets en la opción alineada con los modelos de seguridad nativos de Kubernetes.

Además, los Secrets se integran de forma natural con RBAC (Role-Based Access Control). Se puede restringir quién tiene acceso de lectura o escritura a los Secrets del namespace donde se gestiona el release, lo que permite aplicar el principio de mínimo privilegio sobre la información de estado de Helm.

Cada release almacenado por este driver genera un Secret con un nombre de la forma sh.helm.release.v1.<release-name>.v<revision>. Helm mantiene un historial de revisiones, y cada revisión tiene su propio Secret. El flag --history-max de Helm permite limitar cuántas revisiones se retienen:

helm upgrade my-release ./chart --history-max 5

Sin ese límite, en releases con muchos upgrades, el número de Secrets puede crecer indefinidamente y saturar el namespace o generar presión innecesaria sobre etcd.

Cuándo usarlo: prácticamente siempre en producción. Es el estándar de facto y el que mejor encaja con las políticas de seguridad empresariales.


Driver ConfigMaps

El driver configmaps almacena el estado de los releases de Helm como Kubernetes ConfigMaps. Funcionalmente, el comportamiento es muy similar al driver secrets: se crean objetos por release y revisión, se integra con RBAC y permite gestionar el historial de upgrades.

La diferencia fundamental está en la confidencialidad. Los ConfigMaps no tienen ningún tratamiento especial de privacidad en Kubernetes. Su contenido es texto plano legible para cualquier actor con permisos de lectura sobre el namespace. Esto incluye operadores, scripts de auditoría, herramientas de backup o cualquier proceso que liste recursos del cluster.

export HELM_DRIVER=configmaps

Para activar el driver de forma puntual en un comando:

HELM_DRIVER=configmaps helm list -n production

La legibilidad humana de los ConfigMaps —a diferencia de los Secrets, que requieren decodificar el base64— puede ser ventajosa en escenarios de depuración. Si un upgrade ha fallado y necesitas inspeccionar el manifiesto que Helm intentó aplicar, hacerlo desde un ConfigMap es más directo:

HELM_DRIVER=configmaps helm get manifest my-release -n staging

Sin embargo, esa misma legibilidad es un riesgo en entornos donde los valores del release contienen información sensible: credenciales de base de datos, tokens de acceso, configuración de conexiones a servicios externos. En esos casos, exponer esos valores en ConfigMaps es inadmisible desde el punto de vista de seguridad.

Cuándo usarlo: en entornos de desarrollo, staging sin datos sensibles, o cuando necesitas hacer troubleshooting específico del estado de un release. Nunca en producción si los valores contienen secretos.


Driver Memory

El driver memory almacena el estado de los releases únicamente en memoria RAM del proceso Helm. En el momento en que el proceso Helm termina —ya sea porque el comando completó o porque falló—, todo el estado se pierde irrecuperablemente.

export HELM_DRIVER=memory

A primera vista, un driver que no persiste nada puede parecer inútil. Sin embargo, tiene un nicho de uso muy concreto y valioso: pipelines de CI/CD donde no se quiere contaminar el cluster con estado de prueba.

Considera un pipeline de integración continua que valida un chart antes de desplegarlo:

HELM_DRIVER=memory helm upgrade --install test ./chart --dry-run

Con el driver memory, el proceso de Helm puede simular un upgrade, renderizar los manifiestos, validar los templates y ejecutar los hooks de pre-upgrade sin escribir nada en el cluster. Una vez que el proceso termina, no queda ningún rastro en etcd, ningún Secret ni ConfigMap que limpiar, ninguna revisión que gestionar.

Esto es especialmente útil en entornos de CI con permisos limitados sobre el cluster, o donde múltiples pipelines paralelas ejecutan validaciones simultáneamente sobre el mismo namespace y podrían colisionar si cada una intentara escribir su estado en Kubernetes.

El driver memory también es relevante en escenarios de testing local donde simplemente se quiere probar el renderizado de un chart sin necesidad de un cluster en absoluto —aunque en ese caso, helm template suele ser suficiente.

Cuándo usarlo: exclusivamente en CI/CD para validaciones, dry-runs, o testing de charts sin necesidad de persistencia. Nunca en despliegues reales.


Almacenamiento de estado en Helm: qué se guarda y por qué importa

Para entender por qué la elección del driver tiene consecuencias reales, es útil saber exactamente qué información persiste Helm en cada release.

Cada objeto de estado generado por Helm (sea un Secret o un ConfigMap) contiene:

  • El manifiesto renderizado: los manifiestos YAML de todos los recursos Kubernetes que componen el release en esa revisión.
  • Los valores aplicados: el resultado de la fusión de los valores por defecto del chart con los values sobrescritos por el operador. Esto incluye cualquier valor pasado con --set, --set-string o -f values.yaml.
  • Metadatos del release: nombre del release, namespace, versión del chart, timestamps, estado (deployed, failed, superseded…) y número de revisión.
  • Los hooks: definición de los hooks del chart para esa revisión.

La presencia de los valores aplicados en el estado es lo que hace que la elección del driver sea una decisión de seguridad. Si esos valores incluyen una contraseña de base de datos o un token de API, ese secreto queda persistido en el objeto de estado de Helm. Con el driver secrets y cifrado en reposo activo, esto es aceptable. Con el driver configmaps en texto plano, es un problema de seguridad.

Esto también explica por qué comandos como helm get values my-release pueden recuperar los valores que se usaron en el último upgrade: Helm los lee directamente del objeto de estado almacenado por el driver activo.


Evolución histórica de los drivers de Helm

Para entender el diseño actual de los drivers, hay que conocer la historia de Helm 2 y la decisión arquitectónica central que motivó Helm 3.

Helm 2 y Tiller: el origen del problema

Helm 2 utilizaba un componente servidor llamado Tiller, que se desplegaba como un Pod en el cluster Kubernetes, normalmente en el namespace kube-system. Tiller era el responsable de gestionar el estado de los releases y de aplicar los cambios al cluster.

En Helm 2, el driver por defecto era ConfigMaps, y Tiller era el único que tenía acceso a ellos. Esto simplificaba el modelo de seguridad —solo Tiller necesitaba permisos sobre esos objetos— pero a costa de convertir a Tiller en un punto único de fallo y, más problemáticamente, en un vector de escalada de privilegios.

Tiller solía desplegarse con permisos de cluster-admin para poder gestionar recursos en cualquier namespace. Esto era conveniente pero representaba un riesgo de seguridad inaceptable en entornos empresariales: comprometer el Pod de Tiller equivalía a comprometer todo el cluster.

Helm 3: eliminación de Tiller y Secrets como default

La llegada de Helm 3 en noviembre de 2019 supuso una reescritura significativa de la arquitectura. Las decisiones clave:

  1. Eliminación de Tiller: Helm 3 opera únicamente como cliente. No existe componente servidor. Helm habla directamente con la API de Kubernetes usando las credenciales del cliente (kubeconfig).

  2. Cambio del driver por defecto: de ConfigMaps a Secrets. Dado que ahora era el cliente Helm —con sus propias credenciales de usuario o service account— quien escribía el estado directamente en el cluster, tenía sentido usar Secrets para que esa información tuviera al menos el nivel de protección que Kubernetes ofrece para ese tipo de objeto.

  3. Arquitectura de drivers pluggable: la capa de almacenamiento se abstrajo mediante una interfaz interna limpia, lo que teóricamente permite implementar drivers alternativos (SQL, almacenamiento externo) sin modificar el núcleo de Helm.

Desde Helm 3, las mejoras en los drivers han sido incrementales: mejor manejo de errores, optimizaciones de rendimiento en clusters con muchos releases, y ajustes en la lógica de limpieza del historial. La abstracción central no ha cambiado de forma sustancial, lo que es una señal de madurez del diseño.


Implicaciones de seguridad: Helm Secrets vs ConfigMaps

La distinción entre el driver secrets y el driver configmaps va más allá de la nomenclatura. Tiene consecuencias prácticas en varios vectores de seguridad:

Control de acceso (RBAC)

Tanto los Secrets como los ConfigMaps son objetos de la API de Kubernetes y están sujetos a RBAC. La diferencia es que en muchas organizaciones los Secrets tienen políticas de acceso más restrictivas que los ConfigMaps por convención.

Si tu organización aplica políticas que limitan quién puede leer Secrets en namespaces de producción, usar el driver secrets se beneficia automáticamente de esas restricciones. Con ConfigMaps, cualquier rol con get/list sobre ConfigMaps en el namespace tendría acceso al estado de Helm, incluyendo valores sensibles.

Cifrado en reposo

Los Kubernetes Secrets son elegibles para cifrado en reposo mediante la configuración EncryptionConfiguration en el API server. Esta funcionalidad no aplica a los ConfigMaps: no existe un mecanismo nativo de Kubernetes para cifrar ConfigMaps en reposo.

# Ejemplo de configuración de cifrado en reposo para Secrets
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-key>
      - identity: {}

Con esta configuración activa, los objetos de estado de Helm almacenados con el driver secrets se cifran antes de escribirse en etcd. Los valores sensibles en el estado de Helm quedan protegidos incluso si alguien obtiene acceso directo a la base de datos de etcd.

Auditoría y trazabilidad

En entornos regulados (PCI-DSS, ENS, ISO 27001), los accesos a Secrets suelen registrarse en los audit logs de Kubernetes con mayor granularidad. Esto permite auditar quién accedió al estado de un release de Helm y cuándo, lo cual es un requisito común en auditorías de seguridad.


Casos prácticos y cuándo usar cada driver

Producción: siempre Secrets

En clusters de producción, el driver secrets debe ser el estándar sin excepciones. Las razones son claras:

  • Se integra con las políticas RBAC existentes.
  • Soporta cifrado en reposo.
  • Es el default de Helm, por lo que herramientas del ecosistema (Helm Operator, ArgoCD con Helm, Flux CD) lo esperan.
  • Minimiza la superficie de exposición de valores sensibles.

Si tu pipeline de despliegue en producción usa un service account de Kubernetes, asegúrate de que ese service account tenga permisos para crear, leer, actualizar y borrar Secrets en el namespace de destino:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: helm-release-manager
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

Desarrollo y troubleshooting: ConfigMaps con precaución

En entornos locales o de desarrollo donde no se manejan valores sensibles, el driver configmaps puede simplificar la inspección del estado. Ver el contenido de un ConfigMap con kubectl get configmap es más directo que decodificar un Secret.

Para inspeccionar el manifiesto de un release en un entorno de desarrollo:

HELM_DRIVER=configmaps helm get manifest my-app -n development

O para listar todos los releases almacenados como ConfigMaps:

HELM_DRIVER=configmaps helm list -n development

La clave es no usar este driver en entornos con valores sensibles y asegurarse de que el equipo es consciente del driver activo para evitar situaciones en las que Helm “no encuentra” un release porque el driver configurado no coincide con el que se usó al instalarlo.

CI/CD: Memory para validaciones sin efectos secundarios

En pipelines de integración continua, el driver memory permite ejecutar validaciones de charts sin escribir nada en el cluster:

# Validación de templates en CI
HELM_DRIVER=memory helm upgrade --install \
  --dry-run \
  --namespace ci-validation \
  my-chart ./charts/my-chart \
  -f values-ci.yaml

Este patrón es especialmente útil cuando el pipeline de CI tiene acceso al cluster (para poder hacer el dry-run contra la API real y validar los manifiestos), pero no se quiere dejar rastro de las ejecuciones de CI en etcd.

Otra aplicación: validar que un chart funciona con múltiples combinaciones de valores sin acumular historial de revisiones:

for env in dev staging prod; do
  HELM_DRIVER=memory helm upgrade --install test ./chart \
    -f values-${env}.yaml \
    --dry-run \
    --namespace validation 2>&1 | grep -E "(HOOK|MANIFEST|ERROR)"
done

Gestión del historial de revisiones y su impacto en almacenamiento

Un aspecto que muchos equipos descubren tarde es el crecimiento del número de objetos de estado en clusters con releases activos durante meses. Cada upgrade, rollback o instalación genera un nuevo objeto Secret (o ConfigMap) en el namespace.

Por defecto, Helm mantiene las últimas 10 revisiones. Esto se puede configurar al instalar o al actualizar:

helm install my-app ./chart --history-max 3
helm upgrade my-app ./chart --history-max 3

O de forma global mediante la variable de entorno:

export HELM_MAX_HISTORY=3

Para verificar cuántos objetos de estado ha generado Helm en un namespace:

kubectl get secrets -n production -l owner=helm | wc -l

En clusters con decenas de releases y años de historial sin limpiar, es habitual encontrar cientos o incluso miles de Secrets relacionados con Helm. Esto no es un problema crítico de rendimiento en Kubernetes, pero sí genera ruido en las herramientas de monitorización y puede complicar las auditorías de seguridad si nadie ha revisado ese estado en meses.


Migración entre drivers: consideraciones importantes

Una pregunta frecuente en equipos que adoptan estas buenas prácticas tardíamente es: ¿cómo migro los releases existentes de ConfigMaps a Secrets?

La respuesta corta es que Helm no proporciona un comando de migración nativo entre drivers. El cambio de driver no hace que Helm “adopte” automáticamente el estado existente en el formato anterior.

La aproximación práctica para migrar es:

  1. Exportar el estado actual de los releases relevantes:
    bash
    HELM_DRIVER=configmaps helm get values my-release -n production > values-backup.yaml

  2. Documentar la revisión actual:
    bash
    HELM_DRIVER=configmaps helm history my-release -n production

  3. Cambiar el driver a secrets en todos los entornos del equipo y en el pipeline de CI/CD.

  4. Hacer un upgrade del release (que puede ser idempotente, con los mismos valores) para que Helm cree el primer objeto de estado con el nuevo driver:
    bash
    HELM_DRIVER=secrets helm upgrade my-release ./chart -f values-backup.yaml -n production

  5. Limpiar manualmente los ConfigMaps de estado anteriores:
    bash
    kubectl get configmaps -n production -l owner=helm
    kubectl delete configmap sh.helm.release.v1.my-release.v1 -n production
    # Repetir para cada revisión

Este proceso requiere coordinación en equipos donde múltiples personas ejecutan comandos Helm sobre el mismo cluster, precisamente para evitar que alguien con el driver antiguo configurado ejecute un comando que no encuentre el estado o genere entradas duplicadas en el formato incorrecto.


Herramientas del ecosistema y drivers de Helm

Las herramientas GitOps más populares que usan Helm internamente —ArgoCD, Flux CD, Helmfile— tienen su propia gestión del driver:

  • ArgoCD usa el driver secrets por defecto cuando gestiona releases de Helm. No expone directamente la configuración del driver al usuario, lo que en la práctica significa que siempre usarás secrets si gestionas releases a través de ArgoCD.

  • Flux CD con HelmRelease también usa secrets por defecto a través del Helm Controller.

  • Helmfile respeta la variable de entorno HELM_DRIVER del shell donde se ejecuta.

Esto tiene una implicación importante: si gestionas un cluster con una mezcla de releases instalados directamente con Helm CLI y releases gestionados por ArgoCD, ambos usarán el driver secrets siempre que no hayas cambiado la configuración por defecto. La consistencia aquí es positiva.


Reflexión final: el driver como decisión arquitectónica

Los drivers de Helm raramente aparecen en las revisiones de arquitectura ni en los runbooks de los equipos de plataforma. Y sin embargo, influyen en la fiabilidad, la seguridad y la observabilidad de todos los flujos de trabajo que dependen de Helm.

Tratar la elección del driver como una decisión arquitectónica deliberada —y no como una configuración por defecto que nadie ha cuestionado— es uno de esos detalles pequeños que diferencian una plataforma Kubernetes madura de una automatización improvisada.

Las recomendaciones prácticas para cualquier equipo:

  • Estandariza el driver secrets en producción y documéntalo en el runbook del equipo.
  • Establece un límite de historial razonable (--history-max 5 o 10) para evitar la acumulación de objetos de estado.
  • Activa el cifrado en reposo de Secrets en el API server si manejas valores sensibles en tus releases de Helm.
  • Usa el driver memory en CI para validaciones y dry-runs que no deben persistir estado.
  • Audita periódicamente los objetos de estado de Helm en tus namespaces con kubectl get secrets -l owner=helm.

Estos pasos no requieren herramientas adicionales ni cambios en los charts. Son configuraciones operativas que cualquier equipo puede aplicar hoy y que reducen la superficie de riesgo y el ruido operativo de forma inmediata.


Este artículo forma parte de la guía completa de gestión de paquetes con Helm en alexandre-vazquez.com.

MinIO en modo mantenimiento: alternativas S3 open source para 2026

MinIO en modo mantenimiento: alternativas S3 open source para 2026

MinIO en modo mantenimiento: qué significa y cuáles son las mejores alternativas S3 open source

Si llevas tiempo usando MinIO como capa de almacenamiento de objetos en tu infraestructura —ya sea en Kubernetes, en bare metal o en un entorno híbrido— probablemente ya hayas visto el aviso: el repositorio upstream de la Community Edition ha pasado a modo mantenimiento. Sin nuevas funcionalidades, sin binarios oficiales, sin imágenes de contenedor.

La pregunta que está sobre la mesa en muchos equipos de infraestructura ahora mismo no es técnica, sino estratégica: ¿qué hago a partir de ahora?

Este artículo analiza qué ha cambiado exactamente, cuál es el impacto real según tu caso de uso y cuáles son las alternativas de almacenamiento de objetos compatibles con S3 más sólidas disponibles hoy. Con especial atención al contexto europeo: soberanía del dato, cumplimiento del RGPD y opciones reales para entornos on-premise en España y Europa.


MinIO fue durante años la referencia de facto para el almacenamiento de objetos compatible con S3 en entornos self-hosted. Su popularidad se asentó sobre tres pilares:

  • Compatibilidad con la API S3 de AWS: cualquier cliente o herramienta que hablase con S3 hablaba sin cambios con MinIO.
  • Facilidad de despliegue: un solo binario, una imagen Docker, y en minutos tenías un almacén de objetos operativo.
  • Rendimiento: optimizado para cargas de trabajo de alta concurrencia y grandes volúmenes de datos.

Era el componente predeterminado para backups, artefactos de CI/CD, logs, almacenamiento interno en Kubernetes (MLflow, Loki, Tempo, Thanos…) y cualquier carga de trabajo que necesitase un endpoint S3 sin depender de AWS.

A finales de 2025, MinIO anunció que la Community Edition pasaba a modo mantenimiento y que la distribución sería solo de código fuente, sin binarios ni imágenes de contenedor oficiales. Ese anuncio reabrió el debate sobre sostenibilidad del open source, gobierno de proyectos y los riesgos de depender de una infraestructura controlada por un único proveedor privado.


Qué ha cambiado exactamente

1. Modo mantenimiento: lo que implica en la práctica

«Modo mantenimiento» no significa que el proyecto esté muerto, pero sí marca un cambio fundamental en el contrato implícito con la comunidad:

  • Sin nuevas funcionalidades: el roadmap de MinIO Community Edition está cerrado.
  • Sin mejoras planificadas: las evoluciones de rendimiento, nuevas APIs o integraciones son exclusivas de la edición comercial.
  • Correcciones limitadas: solo se esperan parches para problemas críticos, no mantenimiento rutinario.
  • Sin revisión activa de pull requests: las contribuciones de la comunidad quedan en el aire.

El resultado práctico es una base de código estable pero estancada. Toda la innovación queda explícitamente reservada para las ofertas comerciales de MinIO Inc. El modelo de negocio es legítimo, pero cambia radicalmente el cálculo para los equipos que usaban la Community Edition como infraestructura crítica.

2. Distribución solo de código fuente

Este punto es el que genera más fricción operativa en el día a día. Si antes bastaba con un docker pull minio/minio, ahora:

  • No hay imágenes de contenedor oficiales para la Community Edition.
  • No hay binarios pre-compilados publicados por el proyecto.
  • Los equipos deben compilar MinIO desde el código fuente, mantener sus propias imágenes, gestionarlas en un registro privado y encargarse de todo el ciclo: firma, escaneo de vulnerabilidades y trazabilidad de procedencia.

Para muchos equipos, esto convierte lo que era un «componente plug-and-play» en una dependencia con carga operativa significativa. En entornos regulados —banca, sanidad, administración pública— justificar el uso de una dependencia de infraestructura sin soporte upstream activo ni distribución oficial se vuelve muy complicado.


Impacto real según tu caso de uso

No todas las organizaciones se ven afectadas igual. El impacto depende fundamentalmente de cómo estás usando MinIO.

Si usas MinIO como servicio S3 externo

Tienes una aplicación que apunta a un endpoint S3. Da igual si detrás hay AWS, MinIO u otra cosa. En este caso:

  • El impacto es moderado.
  • La migración es principalmente operativa: cambiar el endpoint y las credenciales.
  • El código de aplicación normalmente no requiere cambios.
  • El riesgo principal es el operativo: compilar y mantener tus propias imágenes mientras planificas la migración.

Si embutes o redistribuyes MinIO

Si tu producto:

  • Incluye MinIO como componente interno.
  • Construye pasarelas o funcionalidades sobre los internos de MinIO.
  • Depende del tooling operativo específico de MinIO.

Entonces el impacto es alto:

  • Heredas toda la responsabilidad de mantenimiento y seguridad.
  • A medio plazo, un fork interno se vuelve casi inevitable.
  • Las implicaciones de la licencia AGPL v3 deben revisarse cuidadosamente: distribuir software que incluye código AGPL sin cumplir sus condiciones es un riesgo legal nada trivial.

Para ISVs y vendors que embuten MinIO en sus productos, esto no es un ajuste táctico: es una reevaluación estratégica del componente de almacenamiento.


Seguridad y cumplimiento: el contexto europeo importa

En España y Europa, este cambio tiene una dimensión adicional que los equipos de infraestructura no pueden ignorar.

RGPD y soberanía del dato

El Reglamento General de Protección de Datos exige, entre otras cosas, que las organizaciones puedan demostrar el control efectivo sobre los sistemas que tratan datos personales. Usar software de infraestructura crítica sin soporte upstream activo ni distribución oficial verificable complica esta demostración, especialmente en auditorías.

Los equipos de seguridad y compliance que ya tenían dificultades para justificar el uso de software «comunitario» en entornos de producción con datos personales ahora tienen un argumento adicional para acelerar la migración hacia alternativas con gobernanza más clara.

Proveedores europeos de cloud y alternativas soberanas

En el ecosistema europeo existen alternativas relevantes:

  • Scaleway Object Storage (Francia): compatible con S3, infraestructura 100% en Europa.
  • Exoscale (Suiza/Austria): enfocado en soberanía del dato y cumplimiento europeo.
  • OVHcloud Object Storage (Francia): compatible con S3, con capacidad de despliegue en múltiples regiones europeas.
  • Hetzner Object Storage (Alemania): opción económica y sólida para cargas no críticas.

Para entornos self-hosted que necesitan permanecer on-premise, las alternativas open source analizadas más abajo son la respuesta natural.

Entornos regulados: la posición ha cambiado

En sectores como banca, sanidad o administración pública, donde los requisitos de seguridad y auditoría son más estrictos, la situación ha cambiado sustancialmente. No se trata solo de que MinIO Community Edition sea inseguro —no lo es por defecto— sino de que el modelo de responsabilidad compartida ha cambiado radicalmente. La organización ahora asume una carga que antes correspondía al proveedor upstream.


Forks y reacción de la comunidad

A fecha de publicación de este artículo, la situación de los forks es la siguiente:

  • Existen varios forks comunitarios centrados en preservar la experiencia de la consola web de MinIO (la UI).
  • No existe un fork de servidor ampliamente adoptado que sustituya plenamente al servidor MinIO con mantenimiento activo y comunidad consolidada.
  • El debate en la comunidad, refleja cautela: la mayoría de organizaciones no están apostando por forks apresurados sino por migraciones planificadas.

La ausencia de un fork de servidor sólido es significativa. Mantener un fork de un sistema de almacenamiento distribuido de alta complejidad requiere un nivel de compromiso en seguridad, corrección de bugs y evolución que pocas comunidades pueden sostener sin financiación. La señal del mercado es clara: migrar es preferible a forkear.


Las mejores alternativas de almacenamiento de objetos compatibles con S3

La respuesta del sector no está en encontrar «el nuevo MinIO» —un sustituto drop-in perfecto—, sino en seleccionar sistemas de almacenamiento cuyo modelo de gobernanza y mantenimiento encaje mejor con las necesidades a largo plazo. Aquí están las opciones más relevantes.

Ceph RGW (RADOS Gateway)

Mejor para: entornos empresariales que requieren alta disponibilidad y escalabilidad masiva.

Ceph es el sistema de almacenamiento distribuido open source más maduro y ampliamente desplegado en entornos de producción exigentes. Su componente RADOS Gateway (RGW) ofrece una API compatible con S3 (y también con Swift) sobre la capa de almacenamiento de objetos RADOS.

Puntos fuertes:

  • Ecosistema muy maduro, con más de una década de uso en producción.
  • Comunidad enorme y gobernanza sólida bajo la Linux Foundation.
  • Alta disponibilidad real: diseñado desde cero para resistir fallos de discos, nodos y racks.
  • Compatible con la mayoría de herramientas del ecosistema S3.
  • Soporte comercial disponible de múltiples proveedores (Red Hat, SUSE, etc.).

Consideraciones:

  • La complejidad operativa es real y no debe subestimarse. Ceph tiene una curva de aprendizaje pronunciada.
  • No es una opción para equipos pequeños sin experiencia en sistemas de almacenamiento distribuido o sin recursos para invertir en formación.
  • El despliegue mínimo recomendado implica varios nodos y discos dedicados.

Veredicto: si necesitas la opción más robusta y con mejor gobernanza a largo plazo para un entorno Kubernetes on-premise con requisitos serios de HA, Ceph RGW es la elección más sólida.


SeaweedFS

Mejor para: equipos que buscan simplicidad, rendimiento y licencia permisiva.

SeaweedFS es un sistema de almacenamiento de objetos y archivos distribuido que ha ganado tracción significativa como alternativa a MinIO, especialmente por su licencia Apache 2.0 —mucho más permisiva que la AGPL de Ceph o Garage— y su desarrollo activo.

Puntos fuertes:

  • Licencia Apache 2.0: sin las restricciones copyleft de AGPL, relevante para productos comerciales y OEMs.
  • Desarrollo activo y mantenimiento regular.
  • API S3 integrada, relativamente completa.
  • Arquitectura orientada al rendimiento para escrituras y lecturas masivas.
  • Más sencillo de operar que Ceph para casos de uso moderados.
  • Soporte para volúmenes FUSE y otras interfaces además de S3.

Consideraciones:

  • La compatibilidad S3 tiene algunas lagunas en casos extremos y operaciones avanzadas (Object Lock, ciertos comportamientos de versionado…).
  • La comunidad es activa pero más pequeña que la de Ceph.
  • Menor historial en entornos de producción de alto nivel que Ceph.

Veredicto: excelente punto de partida para equipos que migran desde MinIO y valoran la simplicidad operativa. La licencia Apache 2.0 es un diferenciador importante si estás construyendo un producto.


Garage

Mejor para: entornos self-hosted distribuidos geográficamente, homelab avanzado y proyectos con enfoque en resiliencia.

Garage es un proyecto relativamente joven pero con una filosofía muy bien definida: almacenamiento de objetos diseñado para la resiliencia en entornos distribuidos geográficamente, incluso con conectividad intermitente entre nodos. Es particularmente relevante para organizaciones que operan en múltiples ubicaciones físicas o que quieren el nivel máximo de control sobre su infraestructura de datos.

Puntos fuertes:

  • Arquitectura pensada desde cero para distribución geo-redundante: nodos en diferentes ubicaciones físicas, zonas o incluso países.
  • Desarrollo abierto y activo, con gobernanza transparente.
  • Muy ligero en recursos: puede correr en hardware modesto.
  • Compatible con la API S3 para operaciones habituales.
  • Filosofía «infraestructura soberana»: sin dependencia de servicios externos.

Consideraciones:

  • Licencia AGPL v3: las mismas consideraciones que con Ceph para productos comerciales que distribuyen el software.
  • Más joven que Ceph y SeaweedFS: menor historial en producción de gran escala.
  • La compatibilidad S3 es funcional pero no completa al nivel de Ceph.
  • Comunidad más pequeña, aunque activa y comprometida.

Veredicto: si operas en múltiples ubicaciones físicas o tu requisito principal es la resiliencia ante fallos de conectividad entre sitios, Garage merece una evaluación seria. También es una opción sólida para homelabs avanzados donde la soberanía del dato es prioritaria.


Zenko / CloudServer (Scality)

Mejor para: arquitecturas multi-cloud y casos de uso orientados a la federación de almacenamiento.

CloudServer (anteriormente S3 Server, parte del proyecto Zenko de Scality) es una implementación open source de la API S3. Scality es una empresa francesa con fuerte presencia en el mercado europeo de almacenamiento empresarial.

Puntos fuertes:

  • Implementación open source de la API S3, con buen nivel de compatibilidad.
  • Contexto europeo: Scality es una empresa francesa, relevante para organizaciones que valoran el origen del proveedor.
  • Orientado a escenarios multi-cloud y federación de backends de almacenamiento.

Consideraciones:

  • Las asunciones arquitectónicas son diferentes a las de MinIO: no es un reemplazo directo.
  • Requiere evaluación específica según el caso de uso.
  • El proyecto Zenko en su conjunto es más complejo que una simple capa S3.

Veredicto: interesante para casos de uso de federación multi-cloud o cuando el contexto empresarial europeo es relevante para la decisión de compra.


Estrategias recomendadas según tu situación

No hay una respuesta única. La estrategia correcta depende de dónde estés hoy y hacia dónde necesitas ir.

Si necesitas reducir el riesgo de forma inmediata

El primer paso no es migrar, sino estabilizar:

  1. Congela la versión de MinIO que estás usando hoy. No actualices de forma irreflexiva; en modo mantenimiento, cualquier cambio es tu responsabilidad.
  2. Construye, escanea y firma tus propias imágenes si estás en contenedores. Integra el proceso en tu CI/CD.
  3. Define y ensaya un plan de migración. No tienes que ejecutarlo mañana, pero sí tenerlo listo.
  4. Monitoriza los advisories de seguridad del proyecto de forma proactiva. Sin upstream activo, la detección temprana depende de ti.

Si operas Kubernetes on-premise con requisitos de alta disponibilidad

Ceph RGW es habitualmente la opción más sólida a largo plazo. La inversión en aprender Ceph es significativa, pero el retorno en estabilidad, gobernanza y ecosistema lo justifica para entornos de producción críticos.

Alternativa: si Ceph es demasiado complejo para tu equipo hoy, considera SeaweedFS como paso intermedio mientras creces en madurez operativa.

Si la flexibilidad de licencia es crítica (OEMs, ISVs)

Empieza la evaluación con SeaweedFS (Apache 2.0). Evita por defecto las opciones AGPL (Ceph, Garage) hasta tener claridad jurídica sobre las implicaciones para tu modelo de distribución.

Si operas en múltiples ubicaciones físicas o necesitas distribución geográfica real

Garage es el candidato natural. Evalúa si su nivel de compatibilidad S3 cubre tus casos de uso específicos antes de comprometerte.

Si el foco está en la soberanía del dato y el cumplimiento europeo

  • Para self-hosted: cualquiera de las opciones anteriores, con preferencia por las que tienen gobernanza más transparente (Ceph, Garage).
  • Para managed: considera proveedores europeos como Scaleway, OVHcloud o Exoscale antes de recurrir a AWS S3.

Si la UX operativa es un factor clave

No dependas de la consola web como infraestructura crítica. Los forks de la UI de MinIO son interesantes, pero:

  • Trata la UI como herramienta secundaria, no como componente core.
  • Invierte en workflows de automatización: infraestructura como código, pipelines de gestión, dashboards propios sobre las APIs de la alternativa elegida.
  • La dependencia de una UI web específica es precisamente el tipo de lock-in que te llevó a esta situación.

Preguntas frecuentes

¿Qué significa exactamente el modo mantenimiento para MinIO Community Edition?

Significa que la base de código upstream está efectivamente congelada. No habrá nuevas funcionalidades, solo correcciones de bugs críticos, y los pull requests de la comunidad no serán revisados activamente. Además, ya no se publican binarios precompilados ni imágenes de contenedor oficiales: los usuarios deben compilar desde el código fuente y mantener sus propias distribuciones.

¿Sigue siendo seguro usar MinIO Community Edition?

El código en sí no es inherentemente inseguro, pero el modelo de responsabilidad compartida ha cambiado. Los parches de seguridad para problemas no críticos serán más lentos o inexistentes. En producción —especialmente en entornos regulados o que manejan datos personales bajo RGPD— ahora debes monitorizar activamente los advisories, construir y escanear tus propias imágenes, y asumir una carga operativa que antes recaía en el upstream. Eso eleva el riesgo operativo de forma objetiva.

¿Cuál es la mejor alternativa open source a MinIO para Kubernetes?

Depende del caso de uso. Para entornos de alta disponibilidad a nivel empresarial, Ceph RGW es la opción más robusta. Para simplicidad y licencia Apache 2.0, SeaweedFS es excelente. Para distribución geo-redundante y resiliencia ante fallos de conectividad entre sitios, evalúa Garage. No existe un reemplazo drop-in universal: cada alternativa requiere evaluación específica.

¿Debo forkear MinIO o migrar a otra solución?

Para la mayoría de organizaciones, migrar es claramente preferible a forkear. Mantener un fork de un sistema de almacenamiento distribuido de alta complejidad implica un compromiso a largo plazo con seguridad, corrección de bugs y potencial backporting de funcionalidades que pocas comunidades pueden sostener. La tendencia del sector apunta inequívocamente hacia la migración a sistemas con desarrollo upstream activo y gobernanza clara.

¿Cómo afecta esto a productos que embuten MinIO (uso OEM)?

El impacto para OEMs e ISVs es alto. Heredáis toda la responsabilidad de mantenimiento y seguridad. A medio plazo, un fork interno se vuelve casi inevitable, con todo el coste que eso implica. Y las implicaciones de la licencia AGPL v3 deben revisarse con asesoramiento jurídico: distribuir software que incluye código AGPL sin cumplir sus condiciones es un riesgo legal real. Esto no es un ajuste táctico; es una reevaluación estratégica del componente de almacenamiento.

¿Qué opciones existen para entornos con requisitos de soberanía del dato en Europa?

Para entornos self-hosted, las alternativas open source analizadas (Ceph, SeaweedFS, Garage) son todas válidas, con diferente perfil de complejidad y licencia. Para entornos managed que necesitan permanecer en infraestructura europea, proveedores como Scaleway, OVHcloud, Exoscale o Hetzner ofrecen almacenamiento de objetos compatible con S3 con centros de datos exclusivamente en Europa, lo que simplifica el cumplimiento del RGPD y las auditorías de localización de datos.


Conclusión: no es una crisis, pero sí un punto de inflexión

El cambio de MinIO Community Edition a modo mantenimiento no supone una rotura técnica inmediata. No hay un día D en que todo deje de funcionar. El riesgo no es técnico a corto plazo; es de gobernanza y sostenibilidad a medio y largo plazo.

La pregunta real es: ¿quieres que tu infraestructura de almacenamiento de objetos sea un componente que gestionas activamente y cuya evolución controlas, o prefieres depender de un upstream que ha decidido reservar su desarrollo para una oferta comercial?

Para muchos equipos, este momento es la oportunidad natural de hacer algo que probablemente debería haberse hecho antes: tratar el almacenamiento de objetos como infraestructura crítica real, con todos los criterios de gobernanza, seguridad y sostenibilidad que eso implica.

Las opciones están sobre la mesa. La decisión no puede postergarse indefinidamente.

Testing de Helm Charts en Producción: Capas, Herramientas y Pipeline CI Mínimo

Testing de Helm Charts en Producción: Capas, Herramientas y Pipeline CI Mínimo

Cuando un Helm chart falla en producción, el impacto es inmediato y visible. Una ServiceAccount mal configurada, una errata en una clave de ConfigMap, o un condicional sin probar en los templates pueden desencadenar incidentes que se propagan en cascada por todo el pipeline de despliegue. La paradoja es que la mayoría de los equipos invierten considerablemente en el testing del código de aplicación, mientras tratan los Helm charts como “simples ficheros de configuración”.

El testing de charts es fundamental para despliegues Helm de calidad en producción. Para una cobertura completa del testing junto con el resto de mejores prácticas Helm, consulta nuestra guía completa de Helm.

Los Helm charts son código de infraestructura. Definen cómo se ejecutan, escalan e integran tus aplicaciones dentro del clúster. Tratarlos con menos rigor que la lógica de aplicación es un riesgo que la mayoría de entornos productivos no pueden permitirse.


El Coste Real de los Charts sin Testear

A finales de 2024, una empresa SaaS de tamaño medio sufrió una interrupción de 4 horas porque una actualización de chart introdujo un cambio incompatible en los permisos RBAC. El chart se había probado localmente con helm install --dry-run, pero la validación de dry-run no interactúa con la capa RBAC del API server. El despliegue tuvo éxito a nivel sintáctico, pero falló operacionalmente.

El incidente reveló tres carencias en su flujo de trabajo:

  1. Sin validación de esquema contra la versión de Kubernetes objetivo
  2. Sin integration tests en un clúster real
  3. Sin aplicación de políticas para las líneas base de seguridad

Estas carencias son habituales. Según una encuesta de la CNCF sobre prácticas GitOps de 2024, menos del 40% de las organizaciones testean Helm charts de forma sistemática antes del despliegue en producción.

El problema no es la falta de herramientas; es comprender qué capa aborda cada herramienta.


Capas de Testing: Qué Valida Cada Nivel

El testing de Helm charts no es una operación única. Requiere validación en múltiples capas, cada una detectando distintas clases de errores.

Capa 1: Validación de Sintaxis y Estructura

Qué detecta: YAML malformado, estructura de chart inválida, campos obligatorios ausentes

Herramientas:

Ejemplo de fallo detectado:

# Una indentación incorrecta rompe el chart
resources:
  limits:
      cpu: "500m"
    memory: "512Mi"  # Indentación incorrecta

Limitación: No valida si los manifiestos renderizados son objetos Kubernetes válidos.


Capa 2: Validación de Esquema

Qué detecta: Manifiestos que serían rechazados por el API de Kubernetes

Herramienta principal: kubeconform

Kubeconform es el sucesor activamente mantenido del obsoleto kubeval. Valida contra los esquemas OpenAPI para versiones específicas de Kubernetes y admite CRDs personalizadas.

Perfil del proyecto:

  • Mantenimiento: Activo, impulsado por la comunidad
  • Puntos fuertes: Soporte de CRDs, validación multi-versión, ejecución rápida
  • Por qué importa: helm lint valida la estructura del chart, pero no si los manifiestos renderizados son conformes con los esquemas de Kubernetes

Ejemplo de fallo detectado:

apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: app
        image: nginx:latest
# Campo obligatorio ausente: spec.selector

Ejemplo de configuración:

helm template my-chart . | kubeconform \
  -kubernetes-version 1.30.0 \
  -schema-location default \
  -schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' \
  -summary

Integración en CI:

#!/bin/bash
set -e

KUBE_VERSION="1.30.0"

echo "Renderizando chart..."
helm template my-release ./charts/my-chart > manifests.yaml

echo "Validando contra Kubernetes $KUBE_VERSION..."
kubeconform \
  -kubernetes-version "$KUBE_VERSION" \
  -schema-location default \
  -summary \
  -output json \
  manifests.yaml | jq -e '.summary.invalid == 0'

Alternativa: kubectl --dry-run=server (requiere acceso al clúster, valida contra el API server real)


Capa 3: Unit Testing

Qué detecta: Errores lógicos en templates, condicionales incorrectos, interpolación errónea de valores

Los unit tests validan que, dada una serie de valores de entrada, el chart produce los manifiestos esperados. Es donde se verifica la lógica de los templates antes de llegar al clúster.

Herramienta principal: helm-unittest

helm-unittest es el framework de unit testing más ampliamente adoptado para Helm charts.

Perfil del proyecto:

  • GitHub: Más de 3.300 estrellas, ~100 contribuidores
  • Mantenimiento: Activo (releases cada 2-3 meses)
  • Maintainer principal: Quentin Machu (originalmente @QubitProducts, ahora independiente)
  • Respaldo comercial: Ninguno
  • Bus Factor: Medio-Alto (sin respaldo institucional, pero con comunidad activa)

Puntos fuertes:

  • Ejecución rápida (no requiere clúster)
  • Sintaxis de test familiar (similar a Jest/Mocha)
  • Soporte de snapshot testing
  • Buena documentación

Limitaciones:

  • No valida el comportamiento en tiempo de ejecución
  • No puede testear interacciones con admission controllers
  • Sin validación contra el API real de Kubernetes

Ejemplo de test:

# tests/deployment_test.yaml
suite: test deployment
templates:
  - deployment.yaml
tests:
  - it: should set resource limits when provided
    set:
      resources.limits.cpu: "1000m"
      resources.limits.memory: "1Gi"
    asserts:
      - equal:
          path: spec.template.spec.containers[0].resources.limits.cpu
          value: "1000m"
      - equal:
          path: spec.template.spec.containers[0].resources.limits.memory
          value: "1Gi"

  - it: should not create HPA when autoscaling disabled
    set:
      autoscaling.enabled: false
    template: hpa.yaml
    asserts:
      - hasDocuments:
          count: 0

Alternativa: Terratest (módulo Helm)

Terratest es un framework de testing en Go de Gruntwork con soporte de primera clase para Helm. A diferencia de helm-unittest, Terratest despliega charts en clústeres reales y permite aserciones programáticas en Go.

Ejemplo de test con Terratest:

func TestHelmChartDeployment(t *testing.T) {
    kubectlOptions := k8s.NewKubectlOptions("", "", "default")
    options := &helm.Options{
        KubectlOptions: kubectlOptions,
        SetValues: map[string]string{
            "replicaCount": "3",
        },
    }

    defer helm.Delete(t, options, "my-release", true)
    helm.Install(t, options, "../charts/my-chart", "my-release")

    k8s.WaitUntilNumPodsCreated(t, kubectlOptions, metav1.ListOptions{
        LabelSelector: "app=my-app",
    }, 3, 30, 10*time.Second)
}

Cuándo usar Terratest frente a helm-unittest:

  • Usa helm-unittest para validación rápida centrada en templates en CI
  • Usa Terratest cuando necesites integration testing completo con la flexibilidad de Go

Capa 4: Integration Testing

Qué detecta: Fallos en tiempo de ejecución, conflictos de recursos, comportamiento real de Kubernetes

Los integration tests despliegan el chart en un clúster real (o efímero) y verifican que funciona de extremo a extremo.

Herramienta principal: chart-testing (ct)

chart-testing es el proyecto oficial de Helm para testear charts en clústeres activos.

Perfil del proyecto:

  • Propietario: Proyecto oficial de Helm (CNCF)
  • Maintainers: Equipo de Helm (contribuidores de Microsoft, IBM, Google)
  • Gobernanza: Respaldado por la CNCF con roadmap público
  • LTS: Alineado con el ciclo de releases de Helm
  • Bus Factor: Bajo (el respaldo institucional de la CNCF ofrece garantías sólidas a largo plazo)

Puntos fuertes:

  • Estándar de facto para charts Helm públicos
  • Testing de upgrade integrado (valida las migraciones)
  • Detecta qué charts han cambiado en un PR (eficiente para monorepos)
  • Integración con GitHub Actions mediante acción oficial

Limitaciones:

  • Requiere un clúster Kubernetes activo
  • Configuración inicial más compleja que el unit testing
  • No incluye security scanning

Qué valida ct:

  • El chart se instala correctamente
  • Los upgrades funcionan sin romper el estado
  • El linting supera las comprobaciones
  • Se respetan las restricciones de versión

Ejemplo de configuración de ct:

# ct.yaml
target-branch: main
chart-dirs:
  - charts
chart-repos:
  - bitnami=https://charts.bitnami.com/bitnami
helm-extra-args: --timeout 600s
check-version-increment: true

Workflow típico en GitHub Actions:

name: Lint and Test Charts

on: pull_request

jobs:
  lint-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Set up Helm
        uses: azure/setup-helm@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Set up chart-testing
        uses: helm/chart-testing-action@v2

      - name: Run chart-testing (lint)
        run: ct lint --config ct.yaml

      - name: Create kind cluster
        uses: helm/kind-action@v1

      - name: Run chart-testing (install)
        run: ct install --config ct.yaml

Cuándo ct resulta imprescindible:

  • Repositorios de charts públicos (esperado por la comunidad)
  • Charts con rutas de upgrade complejas
  • Repositorios multi-chart con necesidades de optimización de CI

Capa 5: Validación de Seguridad y Políticas

Qué detecta: Configuraciones de seguridad incorrectas, violaciones de políticas, problemas de cumplimiento normativo

Esta capa impide desplegar charts que superan los tests funcionales pero violan las líneas base de seguridad organizativas o contienen vulnerabilidades.

Aplicación de Políticas: Conftest (Open Policy Agent)

Conftest es la interfaz CLI de Open Policy Agent para validación de políticas-como-código.

Perfil del proyecto:

  • Proyecto padre: Open Policy Agent (Proyecto Graduado de la CNCF)
  • Gobernanza: Sólido respaldo de la CNCF, soporte multi-vendor
  • Adopción en producción: Netflix, Pinterest, Goldman Sachs
  • Bus Factor: Bajo (proyecto CNCF graduado con respaldo multi-vendor)

Puntos fuertes:

  • Políticas escritas en Rego (reutilizables y componibles)
  • Funciona con cualquier entrada YAML/JSON (no específico de Helm)
  • Puede aplicar estándares organizativos de forma programática
  • Integración con admission controllers (Gatekeeper)

Ejemplo de política en Rego:

package main

import future.keywords.in

deny[msg] {
  input.kind == "Deployment"
  container := input.spec.template.spec.containers[_]
  not container.resources.limits.memory
  msg := sprintf("El contenedor '%s' debe definir límites de memoria", [container.name])
}

deny[msg] {
  input.kind == "Deployment"
  container := input.spec.template.spec.containers[_]
  not container.resources.limits.cpu
  msg := sprintf("El contenedor '%s' debe definir límites de CPU", [container.name])
}

Ejecutar la validación:

helm template my-chart . | conftest test -p policy/ -

Alternativa: Kyverno

Kyverno ofrece aplicación de políticas usando manifiestos nativos de Kubernetes en lugar de Rego. Las políticas se escriben en YAML y pueden validar, mutar o generar recursos.

Ejemplo de política Kyverno:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-resource-limits
spec:
  validationFailureAction: Enforce
  rules:
  - name: check-container-limits
    match:
      resources:
        kinds:
        - Pod
    validate:
      message: "Todos los contenedores deben tener límites de CPU y memoria"
      pattern:
        spec:
          containers:
          - resources:
              limits:
                memory: "?*"
                cpu: "?*"

Conftest vs Kyverno:

  • Conftest: Políticas ejecutadas en CI, flexible para cualquier YAML
  • Kyverno: Aplicación en tiempo de ejecución dentro del clúster, nativo de Kubernetes

Ambos pueden coexistir: Conftest en CI para retroalimentación temprana, Kyverno en el clúster para aplicación en tiempo de ejecución.

Análisis de Vulnerabilidades: Trivy

Trivy de Aqua Security ofrece análisis de seguridad integral para Helm charts.

Perfil del proyecto:

  • Maintainer: Aqua Security (respaldo comercial con núcleo open source)
  • Alcance: Análisis de vulnerabilidades + detección de configuraciones incorrectas
  • Integración Helm: Comando oficial trivy helm
  • Bus Factor: Bajo (respaldo comercial + fuerte adopción open source)

Qué analiza Trivy en Helm charts:

  • Vulnerabilidades en las imágenes de contenedores referenciadas
  • Configuraciones incorrectas (similar a Conftest pero con reglas predefinidas)
  • Secretos comprometidos accidentalmente en los templates

Ejemplo de análisis:

trivy helm ./charts/my-chart --severity HIGH,CRITICAL --exit-code 1

Ejemplo de salida:

myapp/templates/deployment.yaml (helm)
====================================

Tests: 12 (SUCCESSES: 10, FAILURES: 2)
Failures: 2 (HIGH: 1, CRITICAL: 1)

HIGH: Container 'app' of Deployment 'myapp' should set 'securityContext.runAsNonRoot' to true
════════════════════════════════════════════════════════════════════════════════
Ensure containers run as non-root users

See https://kubernetes.io/docs/concepts/security/pod-security-standards/
────────────────────────────────────────────────────────────────────────────────
 myapp/templates/deployment.yaml:42

Otras Herramientas de Seguridad

Polaris (Fairwinds)

Polaris puntúa los charts en función de las mejores prácticas de seguridad y fiabilidad. A diferencia de las herramientas de aplicación, proporciona una puntuación de salud y recomendaciones accionables.

Caso de uso: Dashboard para la calidad de charts en toda una plataforma.

Checkov (Bridgecrew/Palo Alto)

Similar a Trivy pero con un enfoque IaC más amplio (Terraform, CloudFormation, Kubernetes, Helm). Políticas predefinidas para marcos de cumplimiento normativo (CIS, PCI-DSS).

Cuándo usar Checkov:
– Entorno multi-IaC (no solo Helm)
– Requisitos de validación orientados al cumplimiento normativo


Criterios de Selección para Entornos Enterprise

Bus Factor y Viabilidad a Largo Plazo

Para infraestructura productiva, la sostenibilidad de las herramientas importa tanto como las funcionalidades. Los canales de soporte comunitario como el Slack de Helm en la CNCF (#helm-users, #helm-dev) y el CNCF TAG Security ofrecen información valiosa sobre qué proyectos tienen comunidades de maintainers activas.

Preguntas que debes hacerte:

  • ¿Está el proyecto respaldado por una fundación (CNCF, Linux Foundation)?
  • ¿Contribuyen varias empresas?
  • ¿Lo usan en producción organizaciones reconocibles?
  • ¿Hay un roadmap público?

Clasificación de riesgos:

HerramientaGobernanzaBus FactorNotas
chart-testingCNCFBajoProyecto oficial de Helm
Conftest/OPACNCF GraduadoBajoRespaldo multi-vendor
TrivyAqua SecurityBajoRespaldo comercial + OSS
kubeconformComunidadMedioActivo, pero un solo maintainer
helm-unittestComunidadMedio-AltoSin respaldo institucional
PolarisFairwindsMedioOSS patrocinado por empresa

Compatibilidad con Versiones de Kubernetes

Las herramientas deben soportar explícitamente las versiones de Kubernetes que ejecutas en producción.

Señales de alerta:

  • Sin matriz de compatibilidad documentada
  • Dependencias codificadas en versiones antiguas de K8s
  • Sin testing contra múltiples versiones de K8s en su propio CI

Ejemplo de comprobación de compatibilidad:

# ¿Soporta la herramienta tu versión de K8s?
kubeconform --help | grep -A5 "kubernetes-version"

Para herramientas como ct, verifica siempre que testean contra una matriz de versiones de Kubernetes en su propio CI.

Opciones de Soporte Comercial

Cuándo importa el soporte comercial:

  • Requisitos de cumplimiento normativo (SOC2, HIPAA, ENS, etc.)
  • Experiencia interna limitada
  • Operaciones con SLA

Opciones disponibles:

  • Trivy: Aqua Security ofrece Trivy Enterprise
  • OPA/Conftest: Styra ofrece OPA Enterprise
  • Terratest: Gruntwork ofrece consultoría y módulos premium

La mayoría de equipos no necesitan soporte comercial específicamente para el testing de charts, pero resulta valioso en industrias reguladas donde las auditorías exigen SLAs de proveedor.

Integración de Escáneres de Seguridad

Para pipelines enterprise, las herramientas de testing de charts deben integrarse limpiamente con:

  • Plataformas SIEM/SOAR
  • Sistemas de notificación de CI/CD
  • Dashboards de seguridad (p.ej., Grafana, Datadog)

Funcionalidades necesarias:

  • Formatos de salida estructurados (JSON, SARIF)
  • Códigos de salida para fallo en CI
  • Soporte de políticas personalizadas
  • Webhook o API para streaming de eventos

Ejemplo: Integrar Trivy con un SIEM

# .github/workflows/security.yaml
- name: Run Trivy scan
  run: trivy helm ./charts --format json --output trivy-results.json

- name: Send to SIEM
  run: |
    curl -X POST https://siem.empresa.com/api/events \
      -H "Content-Type: application/json" \
      -d @trivy-results.json

Arquitectura del Pipeline CI/CD de Testing

Un pipeline de Helm chart de calidad para producción combina múltiples capas:

┌─────────────────────────────────────────────────────────┐
│  PRE-COMMIT (Developer)                                  │
│  helm lint + yamllint                                    │
└──────────────────────┬──────────────────────────────────┘
                       │
┌──────────────────────▼──────────────────────────────────┐
│  CI PIPELINE (PR)                                        │
│  ┌─────────────────┐   ┌─────────────────────────────┐  │
│  │  kubeconform    │   │  helm-unittest               │  │
│  │  (schema)       │   │  (unit tests)                │  │
│  └────────┬────────┘   └──────────────┬──────────────┘  │
│           └──────────────┬────────────┘                  │
│                          │                               │
│              ┌───────────▼──────────┐                   │
│              │  trivy helm          │                   │
│              │  (security scan)     │                   │
│              └───────────┬──────────┘                   │
└──────────────────────────┼──────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────┐
│  PRE-PRODUCTION (Staging)                                │
│  chart-testing (ct) - clúster efímero                   │
└─────────────────────────────────────────────────────────┘

Principios de eficiencia del pipeline CI Helm:

  • Fail fast: Los errores de sintaxis y esquema nunca deben llegar a los integration tests
  • Ejecución paralela donde sea posible (unit tests + security scans)
  • Cachear imágenes de clústeres efímeros para reducir el tiempo de configuración
  • Omitir charts sin cambios (detección de cambios integrada en ct)

Matriz de Decisión: Cuándo Usar Cada Herramienta

Escenario 1: Equipo Pequeño / Startup en Fase Inicial

Requisitos: Mínima sobrecarga, iteración rápida, seguridad razonable

Stack recomendado:

Linting:      helm lint + yamllint
Validación:   kubeconform
Seguridad:    trivy helm

Opcional: helm-unittest (si la lógica de templates se vuelve compleja)

Razonamiento: Línea base sin dependencias externas que detecta el 80% de los problemas sin complejidad operativa.


Escenario 2: Enterprise con Requisitos de Cumplimiento Normativo

Requisitos: Auditable, validación completa, soporte comercial disponible

Stack recomendado:

Linting:       helm lint + yamllint
Validación:    kubeconform
Unit Tests:    helm-unittest
Seguridad:     Trivy Enterprise + Conftest (políticas personalizadas)
Integration:   chart-testing (ct)
Runtime:       Kyverno (admission control)

Opcional: Terratest para escenarios de upgrade complejos

Razonamiento: Defensa en múltiples capas con aplicación tanto en pre-despliegue como en tiempo de ejecución. Soporte comercial disponible para componentes de seguridad.


Escenario 3: Plataforma Interna Multi-Tenant

Requisitos: Evitar que charts defectuosos afecten a otros tenants, aplicar estándares a escala

Stack recomendado:

Pipeline CI:
  • helm lint → kubeconform → helm-unittest → ct
  • Conftest (aplicar resource quotas, namespaces, network policies)
  • Trivy (bloquear vulnerabilidades críticas)

Runtime:
  • Kyverno o Gatekeeper (aplicar políticas en admission)
  • ResourceQuotas por namespace
  • NetworkPolicies por defecto

Herramientas adicionales: Dashboard Polaris para puntuación de calidad de charts, admission webhooks personalizados para reglas específicas de plataforma.

Razonamiento: Los entornos multi-tenant no pueden tolerar validación “blanda”. La aplicación en tiempo de ejecución es obligatoria.


Escenario 4: Charts Open Source Públicos

Requisitos: Confianza de la comunidad, testing transparente, amplia compatibilidad

Stack recomendado:

Imprescindible:
  • chart-testing (estándar esperado)
  • CI público (GitHub Actions con logs completos)
  • Test contra múltiples versiones de K8s

Recomendable:
  • helm-unittest con alta cobertura
  • Generación automatizada de changelog
  • Values de ejemplo para escenarios comunes

Razonamiento: Los charts públicos se juzgan por la transparencia del testing. La ausencia de ct es una señal de alarma para los usuarios potenciales.


El Stack de Testing Mínimo Viable

Para cualquier entorno que despliegue Helm charts en producción, esta es la línea base del pipeline CI Helm:

Capa 1: Pre-Commit (Máquina del Desarrollador)

helm lint charts/my-chart
yamllint charts/my-chart

Capa 2: Pipeline CI (Automático en PR)

# Validación rápida
helm template my-chart ./charts/my-chart | kubeconform \
  -kubernetes-version 1.30.0 \
  -summary

# Línea base de seguridad
trivy helm ./charts/my-chart --exit-code 1 --severity CRITICAL,HIGH

Capa 3: Pre-Producción (Entorno de Staging)

# Integration test con clúster real
ct install --config ct.yaml --charts charts/my-chart

Inversión de tiempo:

  • Configuración inicial: 4-8 horas
  • Sobrecarga por PR: 3-5 minutos
  • Mantenimiento: ~1 hora/mes

Cálculo de ROI:

Coste medio de un incidente de producción causado por un chart sin testear:
– Detección: 15 minutos
– Triaje: 30 minutos
– Rollback: 20 minutos
– Post-mortem: 1 hora
Total: ~2,5 horas de tiempo de ingeniería

Si el testing de charts evita un solo incidente por trimestre, se amortiza en el primer mes.


Anti-Patrones Habituales que Debes Evitar

Anti-Patrón 1: Usar únicamente --dry-run

helm install --dry-run valida la sintaxis, pero omite:

  • Lógica de admission controllers
  • Validación RBAC
  • Creación real de recursos

Mejor enfoque: Combinar dry-run con kubeconform y al menos un integration test.


Anti-Patrón 2: Testear solo en clústeres similares a producción

“Testeamos en staging, que es idéntico a producción.”

El problema: Los clústeres de staging raramente coinciden exactamente con producción (número de nodos, storage classes, network policies). Los integration tests deben ejecutarse en entornos aislados y efímeros.


Anti-Patrón 3: Security scanning sin aplicación

Ejecutar trivy helm sin que los hallazgos críticos provoquen el fallo del build es teatro de seguridad.

Mejor enfoque: Establecer --exit-code 1 y aplicarlo en CI.


Anti-Patrón 4: Ignorar las rutas de upgrade

La mayoría de los fallos de charts ocurren durante los upgrades, no en las instalaciones iniciales. Chart-testing aborda esto con ct install --upgrade.


Preguntas Frecuentes sobre Testing de Helm Charts

¿Qué es el testing de Helm charts y por qué es importante en producción?

El testing de Helm charts garantiza que los manifiestos de Kubernetes generados a partir de los templates Helm sean sintácticamente correctos, conformes con el esquema, seguros y funcionen correctamente al desplegarse. En producción, los charts sin testear pueden provocar interrupciones del servicio, incidentes de seguridad o upgrades fallidos, aunque el propio código de aplicación sea estable.

¿Es helm lint suficiente para validar un Helm chart?

No. helm lint solo valida la estructura del chart y las mejores prácticas básicas. No valida los manifiestos renderizados contra los esquemas de la API de Kubernetes, no prueba la lógica de los templates ni verifica el comportamiento en tiempo de ejecución. El testing orientado a producción requiere capas adicionales: validación de esquema, unit tests e integration tests.

¿Cuál es la diferencia entre los unit tests y los integration tests de Helm?

Los unit tests (p.ej., con helm-unittest) validan la lógica de los templates afirmando la salida esperada para unos valores de entrada dados, sin desplegar nada. Los integration tests (p.ej., con chart-testing o Terratest) despliegan los charts en un clúster Kubernetes real y validan el comportamiento en tiempo de ejecución, los upgrades y las interacciones con el API server.

¿Qué herramientas se recomiendan para validar Helm charts contra los esquemas de Kubernetes?

La herramienta más recomendada es kubeconform, que valida los manifiestos renderizados contra los esquemas OpenAPI de Kubernetes para versiones específicas y admite CRDs. Una alternativa es kubectl --dry-run=server, que valida contra un API server activo.

¿Cómo puede el testing de Helm charts evitar interrupciones en producción?

El testing detecta los modos de fallo más habituales antes del despliegue: selectores ausentes en Deployments, permisos RBAC inválidos, condicionales incorrectos o versiones de API incompatibles. Muchas interrupciones de producción tienen su origen en errores de configuración y lógica de charts, no en bugs de la aplicación.

¿Cuál es el papel del security scanning en el testing de Helm charts?

El security scanning detecta configuraciones incorrectas, violaciones de políticas y vulnerabilidades que los tests funcionales pueden pasar por alto. Herramientas como Trivy y Conftest (OPA) ayudan a aplicar líneas base de seguridad, prevenir valores por defecto inseguros y bloquear despliegues que vulneren los requisitos organizativos o normativos.

¿Es chart-testing (ct) necesario para charts Helm privados?

Aunque no es estrictamente obligatorio, chart-testing es muy recomendable para cualquier chart desplegado en producción. Se considera el estándar de facto para los integration tests, especialmente para charts con upgrades, múltiples dependencias o entornos de clúster compartidos.

¿Cuál es el pipeline CI Helm mínimo viable?

Como mínimo, un pipeline listo para producción debe incluir:
helm lint para validación estructural
kubeconform para validación de esquema
trivy helm para security scanning

Los integration tests se pueden añadir a medida que los charts ganen en complejidad o criticidad.


Conclusión: El Testing es Madurez de Infraestructura

La brecha entre los equipos que testean Helm charts y los que no lo hacen no se debe a la disponibilidad de herramientas, sino a tratar el código de infraestructura con la misma disciplina que el código de aplicación.

El coste del testing se mide en minutos por PR. El coste de no testear se mide en horas de incidentes de producción, confianza erosionada en la automatización y equipos que vuelven a los despliegues manuales porque “Helm es demasiado arriesgado”.

El stack de testing que elijas importa menos que el hecho de tener uno. Empieza con el stack mínimo viable (lint + schema + seguridad), ejecútalo de forma consistente y amplíalo a medida que tus charts se vuelvan más complejos.

Al implementar un pipeline CI de testing de Helm charts estructurado, detectas el 95% de los problemas antes de que lleguen a producción. El 5% restante son casos límite que requieren observabilidad en producción, no más capas de testing.

El testing de Helm charts no consiste en alcanzar la perfección: consiste en eliminar los fallos prevenibles que socavan la confianza en tu pipeline de despliegue.

FreeLens vs OpenLens vs Lens (2026): ¿Cuál es el mejor IDE para Kubernetes?

FreeLens vs OpenLens vs Lens (2026): ¿Cuál es el mejor IDE para Kubernetes?

Si llevas un tiempo gestionando clústeres Kubernetes, probablemente ya sabes que las decisiones de herramientas no se quedan como “solo herramientas” durante mucho tiempo.

Lo que empieza como una comodidad para el equipo de desarrollo puede convertirse rápidamente en:

  • una conversación sobre licencias con el departamento legal,
  • un problema de adquisición,
  • o un estándar de plataforma con el que te quedas atascado durante años.

El ecosistema de IDEs para Kubernetes es un ejemplo de manual de este fenómeno.

Muchos equipos adoptaron Lens porque realmente mejoraba las operaciones del día a día. Luego cambió la licencia. Luego aparecieron restricciones. Luego empezaron los forks.

Hoy, la pregunta real no es “¿Cuál tiene mejor interfaz?”, sino:

  • ¿Cuál se mantiene activamente?
  • ¿Cuál es seguro de usar en una empresa?
  • ¿Por qué existe un fork de un fork?
  • ¿Siguen siendo técnicamente compatibles?
  • ¿Cuánto cuesta realmente cambiar?

Vamos a responder todo esto desde una perspectiva de ingeniería de plataforma y operaciones en producción.


La historia de los forks: cómo hemos llegado hasta aquí

Entender el árbol genealógico importa, porque explica por qué FreeLens existe en absoluto.

Lens: el producto original

Lens comenzó como un IDE Kubernetes open-core con una comunidad muy activa. Con el tiempo, evolucionó hacia un producto comercial con:

  • licencia propietaria,
  • funcionalidades de pago para empresas,
  • y restricciones en el uso gratuito en entornos corporativos.

Este cambio era perfectamente legítimo desde el punto de vista de negocio, pero rompió el contrato implícito que muchos equipos asumían cuando lo estandarizaron como herramienta interna.

OpenLens: el primer fork

OpenLens nació para preservar:

  • licencias open-source,
  • uso comercial sin restricciones,
  • compatibilidad con las extensiones de Lens.

Durante un tiempo, OpenLens fue la alternativa evidente para los equipos que querían mantenerse en código abierto sin sacrificar funcionalidad.

FreeLens: el fork del fork

FreeLens apareció más adelante, y aquí es donde mucha gente frunce el ceño.

¿Por qué hacer un fork de OpenLens?

Porque el desarrollo de OpenLens empezó a ralentizarse:

  • la cadencia de releases se volvió irregular,
  • los cambios del upstream de Kubernetes llegaban tarde,
  • la gobernanza y la continuidad a largo plazo quedaban en el aire.

FreeLens existe porque algunos contribuidores no estaban dispuestos a apostar sus operaciones de producción diarias en un proyecto con un momentum incierto.

No era ideología. Era gestión del riesgo operacional.


¿Siguen mantenidos los tres proyectos?

Respuesta corta: sí, pero no igual.

Lens

  • Desarrollo activo
  • Respaldado por un proveedor comercial (Mirantis)
  • Adopción rápida de nuevas funcionalidades de Kubernetes

Contrapartidas:

  • Restricciones de licencia
  • Funcionalidades de pago
  • Requiere revisión legal en la mayoría de las empresas

OpenLens

  • Aún mantenido
  • Base de contribuidores más pequeña
  • Velocidad de releases más lenta

Funciona, pero ya no se siente como un estándar seguro a largo plazo para los equipos de plataforma.

FreeLens

  • Mantenimiento activo
  • Enfoque explícito en apertura a largo plazo
  • Prioriza compatibilidad y estabilidad con la API de Kubernetes

Ahora mismo, FreeLens muestra el equilibrio más sano entre mantenimiento e independencia.


Compatibilidad técnica: ¿puedes cambiar sin dolor?

Aquí viene la buena noticia: sí, en su mayor parte.

Acceso al clúster y configuración

Los tres herramientas:

  • usan ficheros kubeconfig estándar,
  • soportan múltiples contextos y clústeres,
  • trabajan con RBAC, CRDs y namespaces de la misma forma.

No se requiere ningún cambio en el lado del clúster.

Extensiones y plugins

  • La mayoría de extensiones de Lens funcionan en OpenLens.
  • La mayoría de extensiones de OpenLens funcionan en FreeLens.
  • Las extensiones propietarias exclusivas de Lens son la principal excepción.

En el uso real:

  • Aproximadamente el 90 % de los flujos de trabajo habituales son idénticos
  • Las diferencias aparecen solo en casos límite o en funcionalidades de pago

Diferencias de UX

Hay algunas diferencias de interfaz:

  • branding,
  • estructura de menús,
  • bloqueo de funcionalidades por plan en Lens.

Nada que requiera reentrenamiento del equipo ni actualización de documentación.


Consideraciones legales y de licencia (aquí suele romperse todo)

Este es, con frecuencia, el factor decisivo en entornos empresariales.

Lens

  • Requiere comprobaciones de cumplimiento de licencia
  • El uso gratuito puede violar las políticas internas de muchas empresas
  • Se requieren planes de pago para una adopción más amplia

Si operas en un entorno regulado o sujeto a auditorías, esto solo ya puede ser un bloqueante definitivo.

OpenLens

  • Licencia open-source
  • Generalmente seguro para uso corporativo
  • Ligera incertidumbre por la reducción de actividad del proyecto

FreeLens

  • Explícitamente open-source
  • Sin restricciones de uso
  • Intención clara de mantenerse gratuito para uso comercial

Si Legal pregunta: “¿Podemos estandarizar esto en toda la empresa?”
FreeLens es la respuesta más fácil de defender.


Comparativa rápida: FreeLens vs OpenLens vs Lens

CriterioFreeLensOpenLensLens
LicenciaOpen-sourceOpen-sourcePropietaria / comercial
Uso corporativoSin restriccionesSin restriccionesRequiere revisión legal
Mantenimiento activoParcialSí (Mirantis)
Velocidad de releasesRegularLentaAlta
Compatibilidad kubeconfigTotalTotalTotal
Soporte de extensiones~90 % compatibilidad~90 % compatibilidadExtenso (algunas de pago)
Coste de cambioMuy bajoMuy bajoBajo (desde open-source)
Soporte empresarialNoNoSí (de pago)
Riesgo a largo plazoBajoMedioMedio-alto (licencia)

¿Cuál deberías usar en una empresa?

Una recomendación pragmática:

Usa Lens si:

  • quieres soporte respaldado por un proveedor,
  • estás dispuesto a pagar,
  • ya has estandarizado las herramientas de Mirantis.

Usa OpenLens si:

  • ya lo estás usando,
  • cubre tus necesidades actuales,
  • aceptas un ritmo de actualizaciones más lento.

Usa FreeLens si:

  • quieres cero riesgo de licencia,
  • quieres un estándar open-source,
  • te importa el mantenimiento a largo plazo,
  • necesitas algo que puedas estandarizar con seguridad.

Para la mayoría de los equipos de plataforma y DevOps, FreeLens es actualmente la opción de menor riesgo.


Coste del cambio: ¿cuánto cuesta realmente migrar?

Sorprendentemente poco.

Una migración típica implica:

  • instalar el nuevo binario,
  • reutilizar los kubeconfigs existentes,
  • reinstalar extensiones si es necesario.

Lo que no necesitas hacer:

  • cambios en el clúster,
  • modificaciones en CI/CD,
  • refactorización de plataforma.

Tiempo de inactividad: ninguno
Rollback: trivial

Este es uno de esos casos poco frecuentes en los que cambiar pronto es barato. Si estás usando Lens con restricciones de licencia, o OpenLens y te preocupa su ritmo de mantenimiento, no hay motivo para esperar.


¿Es un “fork de un fork” una señal de alerta?

Normalmente, sí.

En este caso, no.

FreeLens existe porque:

  • el mantenimiento importaba más que la marca,
  • la apertura importaba más que la monetización,
  • la predictibilidad importaba más que las promesas del roadmap.

Irónicamente, esto está muy alineado con cómo evolucionó el propio Kubernetes.

Los proyectos open-source saludables hacen fork cuando la gobernanza falla o cuando los objetivos del proyecto divergen del uso real. Eso es exactamente lo que ocurrió aquí. No es un drama de GitHub — es el proceso funcionando tal como está diseñado.


FreeLens en la práctica: lo que encontrarás al usarlo

Si nunca has instalado FreeLens, aquí va un resumen de lo que puedes esperar.

Instalación: disponible como binario para macOS, Linux y Windows. Sin dependencias raras ni configuración compleja.

Primera ejecución: detecta automáticamente tus contextos de ~/.kube/config. Si tienes múltiples clústeres, aparecen todos. No necesitas reconfigurar nada.

Interfaz: muy similar a OpenLens y Lens. La curva de aprendizaje para alguien que venga de cualquiera de los otros dos es prácticamente nula.

Extensiones: la mayoría de extensiones que instalabas en OpenLens funcionan sin cambios. Las extensiones propietarias de pago de Lens son la única excepción relevante.

Actualizaciones: FreeLens publica releases de forma regular y sigue el upstream de Kubernetes con más agilidad que OpenLens en su etapa actual.

Para los equipos de plataforma que ya tienen flujos de trabajo establecidos, la transición es casi transparente.


Herramientas de gestión Kubernetes en 2026: el contexto más amplio

Vale la pena mencionar que estas tres herramientas no son las únicas opciones para la gestión de Kubernetes. Existen alternativas como k9s (CLI), Headlamp (web-based, open-source) o Rancher Desktop, cada una con su propio enfoque.

¿Por qué sigue siendo relevante la comparativa FreeLens vs OpenLens vs Lens?

Porque estas tres herramientas comparten el mismo árbol de código, la misma base de usuarios y el mismo modelo de uso. Para los equipos que ya están en este ecosistema, la migración entre ellas es real y barata. Para los que vienen de fuera, la discusión es diferente.

Si estás construyendo tu stack de gestión Kubernetes desde cero en 2026, FreeLens es un punto de partida sólido. Si ya usas Lens o OpenLens, la pregunta es cuándo moverse, no si moverse.


Veredicto: respuesta clara, aburrida y segura para producción

Si separamos el ruido de GitHub del análisis:

  • Lens optimiza para ingresos y funcionalidades empresariales.
  • OpenLens preservó la apertura, pero ha perdido momentum.
  • FreeLens optimiza para sostenibilidad y libertad.

Desde la perspectiva de la ingeniería de plataforma:

“FreeLens es el IDE Kubernetes por defecto más seguro hoy en día para la mayoría de organizaciones.”

Bajo coste de cambio, alta compatibilidad, sin sorpresas legales.

Y en entornos de producción, lo aburrido y predecible casi siempre gana.


Publicado originalmente en inglés el 16 de enero de 2026. Adaptación al español de Alexandre Vazquez.

Alternativas al Kubernetes Dashboard en 2026: Headlamp, Portainer, Rancher y más

Alternativas al Kubernetes Dashboard en 2026: Headlamp, Portainer, Rancher y más

Alternativas al Kubernetes Dashboard en 2026: Headlamp, FreeLens y las mejores interfaces web

El Kubernetes Dashboard ha sido archivado oficialmente y ya no recibe mantenimiento. Si todavía dependes de él para gestionar tus clústeres, es el momento de buscar una alternativa seria. El ecosistema Kubernetes ha madurado muchísimo: los entornos modernos exigen gestión multi-clúster, integración con GitOps y capacidades de RBAC avanzadas que el dashboard original jamás fue capaz de ofrecer.

En este artículo repasamos las mejores alternativas disponibles en 2026, tanto interfaces web como herramientas de escritorio y CLI, para que puedas elegir la que mejor encaja con tu equipo y tu infraestructura.


Por qué el Kubernetes Dashboard quedó obsoleto

El dashboard original de Kubernetes cumplió bien su función durante años, pero tenía limitaciones estructurales difíciles de superar:

  • Foco en un único clúster: en un mundo donde lo habitual es gestionar varios clústeres simultáneamente (desarrollo, staging, producción, multi-cloud), esta restricción se convirtió en un cuello de botella real.
  • RBAC limitado: las capacidades de control de acceso basado en roles eran insuficientes para entornos corporativos que necesitan permisos granulares por equipo o proyecto.
  • Sin integración GitOps: la gestión declarativa de configuración a través de herramientas como Argo CD o Flux se ha convertido en estándar, y el dashboard no ofrecía ningún punto de integración.
  • Observabilidad mínima: más allá de listar recursos, el dashboard apenas proporcionaba métricas ni visibilidad real del estado del clúster.
  • Preocupaciones de seguridad: la arquitectura de seguridad del dashboard requería una configuración muy cuidadosa para no exponer vectores de ataque innecesarios, algo que muchos equipos pasaban por alto.

El resultado fue inevitable: el proyecto fue archivado y el grupo SIG UI de Kubernetes recomendó migrar a alternativas más modernas.


Las mejores alternativas al Kubernetes Dashboard en 2026

1. Headlamp: el sucesor oficial

Headlamp es la herramienta recomendada oficialmente por el grupo Kubernetes SIG UI como sucesora del dashboard deprecado. Es un proyecto CNCF con respaldo comunitario sólido, lo que le da una posición privilegiada en este listado.

Características principales:

  • Interfaz web moderna con diseño intuitivo, muy similar al dashboard original en cuanto a curva de aprendizaje
  • Sistema de plugins extensible: puedes añadir funcionalidad sin tocar el núcleo
  • Opciones de despliegue flexibles: dentro del clúster (in-cluster) o como aplicación de escritorio
  • Autenticación mediante kubeconfig y soporte para OpenID Connect (OIDC) para SSO empresarial
  • Operaciones de lectura y escritura completamente gobernadas por RBAC

Instalación mediante Helm:

helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
helm install my-headlamp headlamp/headlamp --namespace kube-system

# Como addon de Minikube
minikube addons enable headlamp
minikube service headlamp -n headlamp

Ideal para: equipos que migran desde el dashboard original y buscan una experiencia comparable con soporte oficial y arquitectura moderna. También es el punto de partida lógico si no tienes requisitos especiales de multi-clúster o CI/CD integrado.

Pros:
– Aval oficial del proyecto Kubernetes
– Curva de aprendizaje baja para quienes ya conocen el dashboard
– Arquitectura de plugins permite crecer con las necesidades del equipo
– Activamente mantenido y con comunidad creciente

Contras:
– El ecosistema de plugins todavía es menor comparado con herramientas más maduras
– No incluye funcionalidades de CI/CD ni GitOps de forma nativa


2. Portainer: gestión multi-clúster para empresas

Portainer empezó como una solución para gestionar contenedores Docker, pero ha evolucionado hasta convertirse en una plataforma completa de gestión Kubernetes. Si necesitas una interfaz web Kubernetes con capacidades empresariales y gestión centralizada de múltiples clústeres, Portainer es una opción muy sólida.

Características principales:

  • Gestión de múltiples clústeres desde una única interfaz unificada
  • RBAC empresarial con controles de acceso granulares por equipo, proyecto o namespace
  • Despliegue y escalado visual de workloads sin necesidad de tocar YAML directamente
  • Soporte para integración GitOps
  • Auditoría completa de operaciones
  • Compatible tanto con Kubernetes como con Docker y Docker Swarm

Ideal para: organizaciones que gestionan múltiples clústeres en entornos heterogéneos y necesitan RBAC centralizado, control empresarial y una sola herramienta para gobernar toda su infraestructura de contenedores.

Pros:
– Solución unificada para Docker y Kubernetes
– RBAC muy granular y completo
– Versión Community Edition gratuita con funcionalidades básicas
– Interfaz muy pulida y fácil de usar

Contras:
– Las funcionalidades más avanzadas requieren la versión Business (de pago)
– Puede resultar excesivo para equipos pequeños con un único clúster


3. Skooner (antes K8Dash): ligero y rápido

Skooner es la alternativa para quienes valoran la simplicidad por encima de todo. Mantiene la filosofía del dashboard original —una interfaz web limpia para visualizar y gestionar recursos del clúster— pero con mejoras de rendimiento y actualizaciones en tiempo real.

Características principales:

  • Actualizaciones de recursos en tiempo real sin necesidad de refrescar la página
  • Interfaz minimalista y limpia, sin funcionalidades superfluas
  • Instalación sencilla con configuración mínima
  • Visualización de métricas básicas en tiempo real
  • Autenticación OIDC integrada

Ideal para: equipos que necesitan una vista directa y sin complicaciones de su clúster, sin los overheads de plataformas más completas. Perfecto también como herramienta de monitorización rápida o para entornos de desarrollo.

Pros:
– Instalación y configuración muy rápidas
– Rendimiento excelente incluso con clústeres grandes
– Curva de aprendizaje prácticamente inexistente

Contras:
– Funcionalidades limitadas respecto a alternativas más completas
– Comunidad más pequeña y ritmo de desarrollo más pausado


4. Devtron: plataforma DevOps completa

Devtron va mucho más allá de ser una simple interfaz web para Kubernetes. Es una plataforma de entrega de aplicaciones completa que incluye visualización del clúster, pipelines CI/CD integrados, escaneo de seguridad y gestión de despliegues. Si tu equipo está construyendo una plataforma interna para desarrolladores (IDP), Devtron merece una evaluación seria.

Características principales:

  • Despliegue de aplicaciones multi-clúster
  • Pipelines CI/CD integrados nativamente en la plataforma
  • Escaneo de seguridad y funcionalidades de cumplimiento normativo
  • Vistas centradas en aplicaciones en lugar de en recursos individuales
  • Soporte para siete proveedores SSO diferentes
  • Tienda de Helm charts para despliegues gestionados

Ideal para: equipos de plataforma que construyen entornos de desarrollo interno (IDP) y necesitan pipelines de despliegue completos junto con la visibilidad del clúster en una sola herramienta.

Pros:
– Plataforma todo-en-uno: elimina la necesidad de herramientas separadas para CI/CD
– Vista centrada en aplicaciones muy útil para equipos de desarrollo
– Funcionalidades de seguridad integradas

Contras:
– Curva de aprendizaje considerable
– Infraestructura propia más pesada que un simple dashboard
– Puede ser excesivo si solo necesitas visualizar recursos


5. KubeSphere: plataforma de contenedores full-stack

KubeSphere se define a sí mismo como «un sistema operativo distribuido para aplicaciones cloud-native, usando Kubernetes como núcleo». No es simplemente una interfaz web Kubernetes —es una plataforma completa con arquitectura multi-tenant, observabilidad integrada, service mesh y mucho más.

Características principales:

  • Arquitectura multi-tenant con gestión de equipos y proyectos
  • Flujos de trabajo DevOps integrados
  • Integración con service mesh (Istio)
  • Federación multi-clúster
  • Observabilidad y monitorización integradas (Prometheus, Grafana, etc.)
  • Arquitectura plug-and-play para añadir o quitar módulos

Ideal para: organizaciones que quieren construir una plataforma de contenedores completa con todo incluido de serie, sin necesitar integrar múltiples herramientas por separado.

Pros:
– Solución verdaderamente integral
– Observabilidad y monitorización integradas sin configuración adicional
– Comunidad activa y buena documentación

Contras:
– Consumo de recursos considerable
– La complejidad de la plataforma puede ser un obstáculo para equipos pequeños
– Curva de aprendizaje significativa para sacar partido a todas sus capacidades


6. Rancher: la plataforma empresarial consolidada

Rancher, de SUSE, es una de las plataformas de gestión Kubernetes más maduras disponibles. Lleva años en producción en entornos empresariales de gran escala y ha demostrado su fiabilidad en escenarios multi-cloud complejos.

Características principales:

  • Gestión de cualquier distribución Kubernetes: EKS, GKE, AKS, RKE, K3s, on-premises…
  • Autenticación centralizada e RBAC unificado para todos los clústeres
  • Monitorización integrada con Prometheus y Grafana
  • Catálogo de aplicaciones con Helm charts
  • Gestión de políticas y escaneo de seguridad

Ideal para: empresas que gestionan entornos Kubernetes heterogéneos a gran escala, con múltiples proveedores cloud y necesidades de cumplimiento normativo.

Pros:
– Soporte empresarial de SUSE para entornos críticos
– Muy maduro y probado en producción a gran escala
– Gestión unificada de clústeres en cualquier proveedor
– Funcionalidades de seguridad y compliance muy completas

Contras:
– Despliegue y configuración inicial complejos
– Puede ser excesivo para entornos pequeños o medianos
– Rancher Management Server requiere sus propios recursos y mantenimiento


7. Octant: exploración del clúster orientada al desarrollador

Octant, desarrollado originalmente por VMware, pone el foco en el desarrollador más que en el administrador de clústeres. Es ideal para equipos de desarrollo que necesitan visibilidad de lo que está ejecutándose en el clúster sin necesitar acceso completo de administración.

Características principales:

  • Modelo de extensibilidad basado en plugins
  • Visualización de relaciones entre recursos del clúster
  • Port forwarding directamente desde la interfaz
  • Streaming de logs en tiempo real
  • Inspección de recursos con contexto completo

Ideal para: desarrolladores de aplicaciones que necesitan visibilidad del clúster sin responsabilidades de administración, y para equipos que quieren herramientas orientadas al ciclo de vida de la aplicación.

Pros:
– Orientado al flujo de trabajo del desarrollador
– Port forwarding y streaming de logs muy útiles en el día a día
– Ligero y fácil de instalar localmente

Contras:
– El desarrollo ha ralentizado desde la adquisición de VMware por Broadcom
– Funcionalidades de administración limitadas respecto a otras alternativas


Alternativas de escritorio y CLI

No todo tiene que ser una interfaz web. Para muchos equipos, las herramientas de escritorio o línea de comandos ofrecen ventajas claras: acceso offline, mejor rendimiento y una integración más estrecha con el flujo de trabajo local.

FreeLens, OpenLens y Lens

El ecosistema Lens es probablemente la alternativa de escritorio más popular para gestionar clústeres Kubernetes. Lens IDE fue durante años la referencia absoluta, pero cambios en su política de licencias llevaron a la aparición de forks como OpenLens y FreeLens.

  • Lens IDE: el original, ahora bajo Mirantis con una versión gratuita (Lens Personal) y planes de pago.
  • OpenLens: fork open source del código base de Lens, sin telemetría ni restricciones de licencia.
  • FreeLens: alternativa mantenida por la comunidad, más ligera y con foco en la funcionalidad esencial.

Las tres ofrecen una experiencia de escritorio muy pulida con gestión multi-clúster, visualización de recursos, streaming de logs y terminal integrada.

K9s: la interfaz de terminal definitiva

K9s es una interfaz de usuario para terminales (TUI) que permite gestionar clústeres Kubernetes sin salir de la línea de comandos. Si pasas el día en la terminal, K9s puede ser más eficiente que cualquier interfaz web.

Sus atajos de teclado, la navegación rápida entre recursos y la vista en tiempo real del estado del clúster la convierten en una herramienta imprescindible en el toolkit de cualquier SRE o administrador de Kubernetes.


Tabla comparativa

HerramientaTipoMulti-clústerRBACGitOpsCI/CDOpen Source
HeadlampWebParcialNoNo
PortainerWebAvanzadoNoCE gratuita
SkoonerWebNoBásicoNoNo
DevtronWeb
KubeSphereWebAvanzado
RancherWebAvanzadoNo nativoCE gratuita
OctantWeb/LocalNoDelegadoNoNo
FreeLensEscritorioDelegadoNoNo
K9sCLI/TUIDelegadoNoNo

Cómo elegir la alternativa adecuada

La elección correcta depende fundamentalmente del tamaño de tu equipo, la complejidad de tu infraestructura y el caso de uso principal.

Elige Headlamp si:

  • Buscas el sucesor oficial con respaldo comunitario y del proyecto Kubernetes
  • Quieres una experiencia similar al dashboard original pero actualizada
  • La extensibilidad mediante plugins es importante para el futuro
  • Priorizas proyectos open source bajo el paraguas CNCF

Elige Portainer si:

  • Gestionas múltiples clústeres Kubernetes desde un único panel
  • El RBAC empresarial es un requisito crítico
  • Tu equipo también gestiona entornos Docker y quieres una herramienta unificada
  • Necesitas audit logging completo para cumplimiento normativo

Elige Skooner si:

  • La simplicidad y el rendimiento son prioritarios
  • Solo necesitas visualización y gestión básica de recursos
  • Quieres una instalación rápida sin configuración compleja

Elige Devtron o KubeSphere si:

  • Estás construyendo una plataforma interna para desarrolladores (IDP)
  • Necesitas pipelines CI/CD integrados junto con la gestión del clúster
  • Las vistas centradas en aplicaciones son más útiles para tu equipo que las vistas por recurso

Elige Rancher si:

  • Gestionas Kubernetes a escala empresarial con múltiples proveedores cloud
  • Necesitas soporte comercial y SLAs garantizados
  • La gestión de políticas y el compliance son requisitos no negociables

Considera FreeLens o K9s si:

  • Trabajas principalmente desde un entorno de desarrollo local
  • Necesitas acceso al estado del clúster sin conexión
  • Prefieres la eficiencia de una aplicación de escritorio o una TUI sobre una interfaz web

Consideraciones para la migración

Migrar desde el Kubernetes Dashboard no es simplemente instalar una nueva herramienta. Hay varios aspectos que debes evaluar antes de hacer el cambio:

  1. Compatibilidad de autenticación: verifica que la nueva herramienta es compatible con tu proveedor de identidad actual (LDAP, Active Directory, OIDC, etc.) antes de comprometerte con una opción.

  2. Traducción de configuración RBAC: los ClusterRole y RoleBinding que tenías configurados para el dashboard deberán adaptarse a la nueva herramienta. Documenta los permisos actuales antes de migrar.

  3. Automatizaciones existentes: si tienes scripts o pipelines que apuntan a URLs del dashboard para healthchecks u otras operaciones, necesitarán actualizarse.

  4. Formación del equipo: cada herramienta tiene su propia curva de aprendizaje. Incluye tiempo de formación en tu planificación, especialmente para herramientas más completas como Rancher o KubeSphere.

  5. Reconfiguración de Ingress: si tenías el dashboard expuesto externamente a través de un Ingress, necesitarás reconfigurarlo para la nueva herramienta, revisando también los certificados TLS y las reglas de autenticación.

  6. Validación en entorno no productivo: siempre prueba la nueva herramienta en un clúster de desarrollo o staging antes de desplegarla en producción. Comprueba especialmente los permisos RBAC y los flujos de autenticación.


Preguntas frecuentes

¿Está el Kubernetes Dashboard oficialmente deprecado?

Sí. El proyecto ha sido archivado oficialmente y ya no recibe actualizaciones de seguridad, correcciones de errores ni nuevas funcionalidades. Usarlo en entornos de producción supone un riesgo de seguridad real.

¿Cuál es el sustituto oficial?

Headlamp es el sucesor recomendado oficialmente por el grupo Kubernetes SIG UI.

¿Headlamp está listo para producción?

Sí. Headlamp soporta autenticación OIDC, RBAC granular y está siendo adoptado progresivamente en entornos de producción. Con la configuración adecuada de acceso, es una opción válida para producción.

¿Existe alguna alternativa ligera como el dashboard original?

Skooner es la opción más próxima en filosofía al dashboard original: interfaz web sencilla, instalación mínima y gestión básica de recursos.

¿Es obligatorio usar una interfaz web?

No. Muchos equipos prefieren herramientas de escritorio como FreeLens u OpenLens, o directamente la TUI de K9s, que ofrecen mejor rendimiento y acceso offline. La elección depende del flujo de trabajo de cada equipo.

¿Es seguro exponer un dashboard Kubernetes públicamente en Internet?

Requiere precauciones muy serias: autenticación robusta (OIDC o equivalente), RBAC estricto con permisos de mínimo privilegio, restricciones de red, VPN o listas de IPs permitidas, y terminación TLS. La exposición sin estas medidas ha sido el origen de múltiples brechas de seguridad documentadas.

¿Puede un dashboard sustituir a kubectl?

No. Los dashboards son herramientas complementarias que facilitan la visualización y las operaciones habituales. Para operaciones avanzadas, automatización y flujos GitOps, kubectl y las herramientas CLI siguen siendo imprescindibles.

¿Qué dashboard es mejor para desarrolladores?

Octant y Devtron están diseñados con el desarrollador en mente, ofreciendo vistas centradas en aplicaciones y funcionalidades como port forwarding y streaming de logs que son especialmente útiles en el ciclo de desarrollo.

¿Qué herramienta es mejor para gestión multi-clúster?

Portainer, Rancher y KubeSphere están diseñadas específicamente para gestionar múltiples clústeres desde una interfaz centralizada. Para entornos enterprise a gran escala, Rancher suele ser la opción más completa y madura.


Conclusión

El archivo del Kubernetes Dashboard marca el final de una era, pero también es una señal clara de la madurez del ecosistema. Las alternativas disponibles en 2026 no son simples sustitutos —son plataformas mucho más potentes que abordan las necesidades reales de los equipos de plataforma modernos.

Si solo puedes recordar tres cosas de este artículo:

  1. Headlamp es el sucesor oficial recomendado por el proyecto Kubernetes. Si buscas una migración sencilla, empieza por aquí.
  2. Portainer o Rancher son las opciones a evaluar si gestionas múltiples clústeres en entornos empresariales.
  3. FreeLens y K9s merecen un lugar en el toolkit de cualquier administrador Kubernetes, independientemente de qué interfaz web elijas para el equipo.

La clave está en evaluar tus necesidades reales: tamaño del equipo, número de clústeres, requisitos de compliance y flujos de trabajo existentes. No existe una respuesta única válida para todos los casos.


¿Usas alguna de estas herramientas en tu infraestructura? ¿Te quedas con alguna opción no mencionada aquí? Déjalo en los comentarios.

Versiones Gateway API Kubernetes: Guía Completa de Compatibilidad 2026

Versiones Gateway API Kubernetes: Guía Completa de Compatibilidad 2026

Versiones Kubernetes Gateway API: Guía Completa de Compatibilidad y Actualización

Publicado: 2 de febrero de 2026 · Por Alexandre Vazquez


La Kubernetes Gateway API ha madurado a un ritmo notable: de sus orígenes experimentales ha pasado a convertirse en el estándar de facto para la gestión del tráfico de ingress y service mesh. Sin embargo, con varias versiones publicadas y distintos niveles de madurez en cada una de ellas, entender qué versión utilizar, cómo se relaciona con tu clúster de Kubernetes y cuándo actualizar puede resultar complejo.

Esta guía de referencia cubre en profundidad las versiones de Gateway API disponibles, su relación con las versiones de Kubernetes, los niveles de soporte de los principales proveedores y la filosofía de actualización que te permitirá tomar decisiones fundamentadas para tu infraestructura.


Entendiendo el modelo de versionado de Gateway API

El modelo de versionado de Gateway API es deliberadamente distinto al de las APIs nativas de Kubernetes. Mientras que los recursos integrados en Kubernetes están ligados a una versión concreta del clúster, los CRDs de Gateway API se instalan de forma independiente siempre que el clúster cumpla los requisitos mínimos.

Esta independencia tiene implicaciones prácticas importantes: puedes actualizar Gateway API sin necesidad de actualizar Kubernetes y, a la inversa, actualizar Kubernetes sin que eso fuerce un cambio en tus CRDs de Gateway API. Son dos ciclos de vida desacoplados que hay que gestionar de forma coordinada, pero no sincronizada obligatoriamente.

Requisitos mínimos de versión de Kubernetes

A partir de Gateway API v1.1 y versiones posteriores, el requisito mínimo es Kubernetes 1.26 o superior. El proyecto se compromete a mantener soporte para un mínimo de las últimas 5 versiones menores de Kubernetes, lo que ofrece una ventana razonable para planificar las actualizaciones del clúster.

Esto significa que si ejecutas Kubernetes 1.26, 1.27, 1.28, 1.29 o 1.30, puedes instalar la última versión de Gateway API sin preocuparte por incompatibilidades. Para la mayoría de los equipos que mantienen sus clústeres relativamente actualizados, esta restricción rara vez supone un problema.


Canales de publicación: Standard y Experimental

Gateway API utiliza dos canales de publicación diferenciados para equilibrar estabilidad e innovación. Comprender cuándo usar cada uno es fundamental antes de instalar o actualizar los CRDs.

Canal Standard

El canal Standard contiene únicamente recursos y campos a nivel GA (Generally Available, v1) y Beta (v1beta1). Al instalar desde el canal Standard obtienes:

  • Garantías de estabilidad: no se introducen cambios disruptivos una vez que un recurso alcanza Beta o GA
  • Compatibilidad hacia atrás: es seguro actualizar entre versiones menores sin modificar tus configuraciones existentes
  • Preparación para producción: funcionalidades ampliamente probadas con múltiples implementaciones
  • Cobertura de conformance: las pruebas de conformance completas garantizan portabilidad entre implementaciones

Los recursos incluidos en el canal Standard son GatewayClass, Gateway, HTTPRoute y ReferenceGrant a nivel v1, además de recursos estabilizados como GRPCRoute.

Canal Experimental

El canal Experimental incluye todo lo del canal Standard más recursos Alpha y campos experimentales. Este canal está orientado a:

  • Pruebas tempranas de funcionalidades: acceder a nuevas capacidades antes de que se estabilicen
  • Funcionalidad de vanguardia: probar las últimas novedades de Gateway API
  • Sin garantías de estabilidad: pueden producirse cambios disruptivos entre versiones
  • Retroalimentación al proyecto: contribuir a dar forma a la API mediante la prueba de características experimentales

Las funcionalidades pueden graduarse del canal Experimental al Standard, o bien ser descartadas, en función de la experiencia de implementación y la retroalimentación de la comunidad.

Recomendación: salvo que tengas una necesidad concreta de una característica experimental, utiliza siempre el canal Standard en entornos de producción.


Historial de versiones y funcionalidades de Gateway API

v1.0 (octubre de 2023)

La versión 1.0 marcó un hito importante al graduar los recursos principales al nivel GA. Este lanzamiento incluyó:

  • Gateway, GatewayClass y HTTPRoute a nivel v1 (estables)
  • Garantías de compatibilidad hacia atrás para los recursos v1
  • Estado de preparación para producción en la gestión del tráfico de ingress
  • Múltiples implementaciones conformes de distintos fabricantes

Con v1.0 se estableció que Gateway API estaba lista para cargas de trabajo productivas, dejando de ser un experimento para convertirse en una apuesta seria del ecosistema Kubernetes.

v1.1 (mayo de 2024)

La versión 1.1 amplió significativamente la API con soporte para service mesh:

  • GRPCRoute: soporte nativo para el enrutamiento de tráfico gRPC
  • Capacidades de service mesh: gestión del tráfico este-oeste junto al norte-sur
  • Múltiples implementaciones: tanto Istio como otros service mesh alcanzaron conformance
  • Funcionalidades mejoradas: criterios de coincidencia adicionales y capacidades de enrutamiento avanzadas

Esta versión cerró la brecha entre los controladores de ingress tradicionales y las implementaciones completas de service mesh, consolidando Gateway API como una solución unificada para ambos casos de uso.

v1.2 y v1.3

Estas versiones intermedias introdujeron ciclos de publicación más estructurados y funcionalidades adicionales:

  • Refinamiento de las pruebas de conformance
  • BackendTLSPolicy (experimental en v1.3)
  • Mejoras en observabilidad y depuración
  • Enrutamiento entre namespaces mejorado

v1.4 (octubre de 2025)

La última versión GA disponible en el momento de escribir esta guía, v1.4.0, incorporó:

  • Refinamiento continuado de la API
  • Funcionalidades experimentales adicionales para la comunidad
  • Perfiles de conformance mejorados
  • Documentación y guías de migración más completas

Matriz de compatibilidad: Gateway API vs. Kubernetes

La siguiente tabla muestra la relación entre versiones de Gateway API y versiones de Kubernetes:

Versión Gateway APIKubernetes mínimoKubernetes recomendadoFecha de publicación
v1.0.x1.251.26+Octubre 2023
v1.1.x1.261.27+Mayo 2024
v1.2.x1.261.28+2024
v1.3.x1.261.29+2024
v1.4.x1.261.30+Octubre 2025

La conclusión clave de esta tabla es que Gateway API v1.1 y versiones posteriores requieren Kubernetes 1.26 como mínimo. Esto significa que en cualquier clúster medianamente actualizado puedes ejecutar la última versión de Gateway API sin restricciones de compatibilidad con Kubernetes en sí.


Niveles de soporte de los proveedores

Los distintos proveedores (implementaciones de Gateway API) soportan versiones y conjuntos de funcionalidades diferentes. Entender el nivel de soporte de tu proveedor es tan importante como conocer la versión de Gateway API que quieres instalar.

Niveles de conformance

Gateway API define tres niveles de conformance para las funcionalidades:

  1. Core: funcionalidades que toda implementación debe soportar para afirmar conformance. Son portables entre todas las implementaciones.
  2. Extended: funcionalidades opcionales estandarizadas. Las implementaciones indican soporte Extended de forma separada al Core.
  3. Implementation-specific: funcionalidades propias del fabricante sin requisitos de conformance.

Esta jerarquía te permite razonar sobre portabilidad: si usas únicamente funcionalidades Core, puedes cambiar de proveedor sin reescribir tus recursos de Gateway API.

Soporte de los principales proveedores

Istio

Istio alcanzó el soporte GA de Gateway API en su versión 1.22 (mayo de 2024). Istio ofrece:

  • Soporte completo del canal Standard (recursos v1)
  • Gestión del tráfico de service mesh (este-oeste) mediante GAMMA
  • Control del tráfico de ingress (norte-sur)
  • Soporte experimental de BackendTLSPolicy a partir de Istio 1.26

Istio es la opción preferida para organizaciones que necesitan tanto ingress como service mesh en una única solución, dado su nivel de madurez y su amplia adopción.

Envoy Gateway

Envoy Gateway sigue de cerca las publicaciones de Gateway API. La versión 1.4.0 incluye:

  • Soporte de Gateway API v1.3.0
  • Matriz de compatibilidad con versiones de Envoy Proxy
  • Enfoque en casos de uso de ingress
  • Fuerte adopción de funcionalidades experimentales

Es importante consultar la matriz de compatibilidad de Envoy Gateway para asegurarse de que la versión de Envoy Proxy instalada es coherente con la versión de Gateway API y de Kubernetes en uso.

Cilium

Cilium integra Gateway API de forma profunda con su implementación CNI:

  • Arquitectura de proxy Envoy por nodo
  • Aplicación de políticas de red para el tráfico gestionado por Gateway
  • Soporte tanto de ingress como de service mesh
  • Procesamiento de paquetes basado en eBPF

La arquitectura singular de Cilium lo convierte en una opción muy potente para organizaciones que ya utilizan Cilium para la red del clúster, al poder unificar en un mismo componente la red, la seguridad y el enrutamiento del tráfico de aplicaciones.

Contour

Contour v1.31.0 implementa Gateway API v1.2.1, con soporte de:

  • Todos los recursos v1 del canal Standard
  • La mayoría de los recursos v1alpha2 (TLSRoute, TCPRoute, GRPCRoute)
  • Soporte de BackendTLSPolicy

Cómo verificar la conformance de tu proveedor

Antes de decidir qué versión de Gateway API instalar, sigue estos pasos para validar el soporte de tu proveedor:

  1. Visita la página oficial de implementaciones: el proyecto Gateway API mantiene una lista actualizada de implementaciones con sus niveles de conformance.
  2. Consulta la documentación del proveedor: la mayoría de los proveedores publican matrices de compatibilidad que relacionan versiones de Gateway API, Kubernetes y proxy.
  3. Revisa los informes de conformance: los proveedores envían resultados de pruebas de conformance que detallan exactamente qué funcionalidades Core y Extended soportan.
  4. Prueba en entornos no productivos: antes de actualizar producción, valida tus casos de uso específicos en un entorno de staging.

Filosofía de actualización: cuándo y cómo actualizar

Una de las preguntas más frecuentes sobre Gateway API es: ¿necesito ejecutar siempre la última versión? La respuesta depende de tus necesidades concretas y tu tolerancia al riesgo.

Permanecer en versiones antiguas

No es necesario ejecutar siempre la última versión de Gateway API. Es perfectamente válido:

  • Mantenerse en una versión estable más antigua si cubre tus necesidades
  • Actualizar solo cuando necesites funcionalidades específicas de una versión posterior
  • Esperar a que tu proveedor soporte oficialmente las versiones más recientes
  • Priorizar la estabilidad frente a tener las últimas novedades

Las garantías de compatibilidad hacia atrás del canal Standard aseguran que, cuando finalmente actualices, tus configuraciones existentes seguirán funcionando sin modificaciones.

Cuándo considerar la actualización

Conviene plantearse una actualización cuando:

  1. Necesitas una funcionalidad específica: un nuevo matcher de HTTPRoute, soporte de GRPCRoute u otra capacidad disponible únicamente en versiones más recientes.
  2. Tu proveedor lo recomienda: los proveedores suelen optimizar su soporte para versiones concretas de Gateway API; seguir sus recomendaciones es una práctica sensata.
  3. Consideraciones de seguridad: aunque es infrecuente, pueden surgir vulnerabilidades que justifiquen una actualización urgente.
  4. Actualización del clúster Kubernetes: al actualizar Kubernetes, verifica que tu versión de Gateway API es compatible con la nueva versión del clúster.

Prácticas seguras de actualización

1. Utiliza siempre el canal Standard

El uso de los CRDs del canal Standard simplifica y hace más seguras las actualizaciones. Las funcionalidades experimentales pueden introducir cambios disruptivos entre versiones, mientras que las del canal Standard mantienen compatibilidad.

2. Actualiza una versión menor a la vez

Aunque en general es seguro saltarse versiones, la ruta de actualización más probada es la incremental. Pasar de v1.2 a v1.3 y después a v1.4 es más seguro que saltar directamente de v1.2 a v1.4.

3. Prueba siempre antes de actualizar en producción

Valida las actualizaciones en entornos no productivos antes de aplicarlas en producción:

# Instalar una versión específica de Gateway API en el clúster de pruebas
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml

4. Revisa las notas de publicación

Cada versión de Gateway API publica notas detalladas que incluyen:

  • Nuevas funcionalidades y capacidades
  • Graduación de características experimentales al canal Standard
  • Avisos de deprecación
  • Consideraciones específicas de la actualización

No omitas este paso: las notas de publicación son la fuente más fiable para anticipar cualquier impacto en tus configuraciones existentes.

5. Verifica la compatibilidad del proveedor primero

Antes de actualizar los CRDs de Gateway API, confirma que tu controlador de Gateway soporta la versión objetivo. Instalar Gateway API v1.4 no aporta ningún beneficio si tu controlador solo soporta v1.2; en el peor de los casos, puede generar comportamientos inesperados.

6. Nunca sobreescribas CRDs de un canal diferente

Las implementaciones no deben sobreescribir CRDs de Gateway API que pertenezcan a un canal diferente. Lleva un registro de si estás usando una instalación del canal Standard o Experimental y mantén la coherencia.

Gestión de CRDs: comandos útiles

La gestión de los CRDs de Gateway API requiere atención al detalle. Estos comandos te ayudarán a verificar el estado actual de tu instalación:

# Comprobar la versión instalada de Gateway API
kubectl get crd gateways.gateway.networking.k8s.io -o yaml | \
  grep 'gateway.networking.k8s.io/bundle-version'

# Verificar qué canal está instalado
kubectl get crd gateways.gateway.networking.k8s.io -o yaml | \
  grep 'gateway.networking.k8s.io/channel'

Ejecuta estos comandos antes de cualquier actualización para tener una línea de base clara de lo que tienes instalado.


Mantenerse informado sobre nuevas versiones

Gateway API sigue un ciclo de publicación estructurado con canales de comunicación claros. Aquí tienes las fuentes más relevantes para estar al día:

Fuentes para seguir las publicaciones

  1. Página de releases en GitHub: sigue el repositorio kubernetes-sigs/gateway-api para recibir notificaciones de nuevas versiones en el momento en que se publican.
  2. Blog oficial de Kubernetes: las publicaciones mayores de Gateway API se anuncian en el blog oficial de Kubernetes con explicaciones detalladas de las novedades.
  3. Listas de correo y Slack: únete a los canales de la comunidad Gateway API para debates y anuncios anticipados.
  4. Anuncios del proveedor: los proveedores de Gateway anuncian el soporte de nuevas versiones de Gateway API a través de sus propios canales; suscríbete a los de tu proveedor específico.

Cadencia de publicación

Gateway API sigue una cadencia de publicación trimestral para las versiones menores, con versiones de parche según sea necesario para correcciones de errores y problemas de seguridad. Esta cadencia predecible facilita la planificación de actualizaciones en los equipos de infraestructura.


Marco de decisión práctico

Este marco te ayudará a decidir qué versión de Gateway API ejecutar en función de tu situación concreta.

Para nuevos despliegues

  • Cargas de trabajo de producción: usa la última versión GA soportada por tu proveedor, instalada desde el canal Standard.
  • Entornos orientados a la innovación: considera el canal Experimental si necesitas funcionalidades de vanguardia y puedes asumir posibles cambios disruptivos.
  • Enfoque conservador: usa v1.1 o posterior con el canal Standard; es un punto de partida seguro y funcional para la mayoría de los casos de uso.

Para despliegues existentes

  • Si todo funciona correctamente: mantente en tu versión actual hasta que necesites nuevas funcionalidades. La estabilidad tiene valor.
  • Si el proveedor recomienda actualizar: sigue las indicaciones del proveedor, especialmente si hay implicaciones de seguridad.
  • Si tienes planificada una actualización de Kubernetes: verifica la compatibilidad con antelación; puede que necesites actualizar Gateway API antes o simultáneamente al clúster.

Actualizaciones motivadas por funcionalidades

NecesidadVersión mínima requerida
Soporte de service mesh (GAMMA)v1.1
GRPCRoute establev1.1
BackendTLSPolicyv1.3+ (canal Experimental) + soporte del proveedor
Perfiles de conformance refinadosv1.4

Preguntas frecuentes sobre compatibilidad de Gateway API

¿Cuál es la diferencia entre Kubernetes Ingress y Gateway API?

Kubernetes Ingress es una API heredada centrada principalmente en el tráfico HTTP(S) con capacidades de extensión limitadas. Gateway API es su sucesor, y ofrece un modelo más expresivo y orientado a roles que soporta múltiples protocolos, enrutamiento avanzado, mejor separación de responsabilidades y un comportamiento coherente entre implementaciones. Si empiezas un nuevo proyecto hoy, Gateway API es la elección correcta.

¿Qué versión de Gateway API debería usar en producción hoy?

Para la mayoría de los entornos de producción, lo recomendable es usar la última versión GA (v1.x) soportada por tu proveedor de Gateway, instalada desde el canal Standard. Esto garantiza estabilidad, compatibilidad hacia atrás y las garantías de conformance, sin renunciar a las mejoras continuas del proyecto.

¿Puedo actualizar Gateway API sin actualizar mi clúster Kubernetes?

Sí. Los CRDs de Gateway API se instalan de forma independiente a Kubernetes. Mientras tu clúster cumpla el requisito mínimo de versión de Kubernetes (1.26+ para versiones recientes), puedes actualizar Gateway API sin tocar el clúster.

¿Qué ocurre si mi proveedor no soporta la última versión de Gateway API?

Si tu proveedor va por detrás de las últimas versiones, debes mantenerte en la última versión soportada oficialmente por ese proveedor. Instalar CRDs de Gateway API más nuevos de lo que soporta tu controlador puede dar lugar a funcionalidades no disponibles o a comportamientos indefinidos. La compatibilidad con el proveedor siempre debe tener prioridad sobre ejecutar la versión más reciente de la API.

¿Es seguro actualizar los CRDs de Gateway API sin tiempo de inactividad?

En la mayoría de los casos, sí, cuando se utiliza el canal Standard. Gateway API ofrece garantías sólidas de compatibilidad hacia atrás para los recursos GA y Beta. No obstante, siempre deberías probar las actualizaciones en entornos no productivos y verificar que tu proveedor soporta la versión objetivo antes de aplicarlas en producción.

¿Qué son los perfiles de conformance en Gateway API?

Los perfiles de conformance son conjuntos predefinidos de pruebas que agrupan funcionalidades por caso de uso (por ejemplo, ingress HTTP, service mesh, etc.). Permiten a los proveedores declarar su nivel de soporte de forma granular y a los usuarios comparar implementaciones de forma objetiva. Se introdujeron en versiones recientes de Gateway API y siguen evolucionando.


Conclusión

Kubernetes Gateway API representa el futuro de la gestión del tráfico en Kubernetes: una API estandarizada, extensible y orientada a roles tanto para ingress como para service mesh. Entender el modelo de versionado, los requisitos de compatibilidad y la filosofía de actualización te permite tomar decisiones fundamentadas que equilibran innovación y estabilidad.

Los puntos clave de esta guía:

  • Los CRDs de Gateway API se instalan de forma independiente a Kubernetes; solo requieren la versión 1.26 o superior para versiones recientes.
  • El canal Standard ofrece estabilidad y compatibilidad; el canal Experimental da acceso anticipado a nuevas funcionalidades con el coste de posibles cambios disruptivos.
  • No es necesario ejecutar siempre la última versión: actualiza cuando necesites funcionalidades específicas o cuando tu proveedor lo recomiende.
  • Verifica siempre la compatibilidad del proveedor antes de actualizar los CRDs de Gateway API.
  • Sigue prácticas seguras de actualización: prueba primero, actualiza de forma incremental, revisa las notas de publicación.

Siguiendo estas pautas, podrás desplegar y mantener Gateway API en tu infraestructura Kubernetes con confianza, tomando decisiones de actualización que se ajusten a las necesidades y la tolerancia al riesgo de tu organización.


Referencias