English

Karpenter + EKS: Target Groups fantasma y cómo estabilizarlos sin downtime

Nota de campo sobre un patrón frecuente en EKS: ALBs manuales, IPs de nodo en Target Groups y Karpenter. Cómo TargetGroupBinding (AWS Load Balancer Controller) recupera estabilidad sin reconstruir el API Gateway.

Por el equipo de QSTools — notas de campo compostas a partir de trabajo en EKS. Detalles generalizados a propósito.

En setups multi-cuenta AWS con EKS + Karpenter, aparece un fallo recurrente después de una migración apurada EC2→EKS: cada rotación de nodos tira el tráfico. Casi nunca es “culpa de Karpenter”. El data path sigue clavando IPs de nodo estáticas en Target Groups clásicos detrás de un ALB legacy.

Resumen

Señal Causa raíz Remedio
Caídas al reescalar / deploy TG con IPs de nodo estáticas TargetGroupBinding + targetType: ip
Muchos tickets de soporte API Gateway → ALB legacy sin LBC Mantener ALB/Gateway; automatizar el TG
Miedo a tocar prod Sin ventana de mantenimiento Transición por fases, casi 0s de corte
Deuda pendiente Nodos EKS en subredes públicas Más seguro cuando el TG ya no depende de IPs de nodo

El patrón: crecimiento más rápido que la gobernanza de red

Los equipos suelen empezar bien—cuentas separadas, Terraform, plantillas EKS—y después la velocidad de producto deja atrás la capa de exposición:

  1. Servicios todavía frente a ALBs manuales (nacidos para EC2).
  2. Migración a EKS sin modernizar ese modelo ALB/TG.
  3. API Gateway (VPC Link) pegado a esos ALBs.
  4. Target Groups con IPs de nodos hardcodeadas.
  5. Karpenter entra por costo/escala… y recicla esos nodos.

Antes: API Gateway → ALB manual → Target Group estático → nodos EKS rotados por Karpenter

Día a día: cada deploy o reescalado = targets perdidos (“nodos fantasma”). La remediación suele tener una restricción dura: sin downtime en caminos críticos.

Diagnóstico en una frase

Karpenter hacía su trabajo. El TG seguía apuntando a IPs que ya no existían.

Solución en tres fases (cero downtime como restricción)

Fases: TargetGroupBinding → health checks → estandarización en Helm

Fase 1 — Desacople con TargetGroupBinding

Usá el CRD TargetGroupBinding del AWS Load Balancer Controller (LBC) para que el controlador gestione el TG existente, sin recrear ALBs ni reescribir rutas del API Gateway.

apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
  name: tgb-servicio-critico
  namespace: produccion
spec:
  serviceRef:
    name: svc-servicio-critico
    port: 8080
  targetGroupARN: arn:aws:elasticloadbalancing:region:123456789012:targetgroup/tg-critico/abcdef123456
  targetType: ip

(ARN de ejemplo; en prod usá el de tu TG real.)

Fase 2 — Puertos y health checks

Alineá puerto del Service y path de health check para que el LBC registre pods (targetType: ip). En el incidente que documentamos, la reconciliación fue en vivo con interrupción prácticamente nula.

Fase 3 — Gobernanza en Helm

Con prod estable, meté anotaciones del LBC en los Service de los charts para que los próximos deploys no vuelvan al modo manual:

metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "external"
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"

Después: mismo ALB/Gateway, Target Group actualizado por LBC hacia IPs de pod

Antes vs después

Situación inicial Después del cambio
Pérdida de tráfico al rotar nodos Registro dinámico de endpoints por el LBC
Tickets en cada deploy / scale Deploys estables sin retocar TGs a mano
Mantenimiento manual de Target Groups Targeting a IP de pod (targetType: ip)
Parálisis por miedo al downtime Cambio transparente en producción
Mismo patrón frágil copiado entre cuentas Patrón repetible de chart/TGB por cluster

Qué enseña esto (y qué queda abierto)

  • Autoscaling ≠ magia de red. Si el data path asume IPs de nodo, Karpenter va a “romper” lo que ya estaba frágil.
  • TargetGroupBinding es un puente excelente cuando no podés rediseñar API Gateway + ALB en una sola ventana.
  • Siguiente paso típico: migrar nodos EKS de subredes públicas a privadas—después de que los targets no dependan de IPs de nodo.

Si estás en este lío (EKS + ALB legacy + Karpenter), el orden importa: estabilizar el TG primero, estandarizar Helm después, subredes privadas cuando el tráfico ya no dependa de IPs de nodo.