El coste fantasma de la nube, una entidad insidiosa que se esconde en las sombras de la infraestructura elástica, ha mutado. En 2026, las empresas que operan infraestructuras en Kubernetes en AWS se enfrentan a un dilema cada vez más acuciante: cómo escalar dinámicamente sus cargas de trabajo sin incurrir en una sangría presupuestaria. Las estrategias de escalado tradicionales, si bien funcionales, ya no son suficientes para optimizar la ecuación coste-rendimiento en el actual panorama de la computación distribuida.
La complacencia con configuraciones subóptimas de escalado no es una opción; es un lastre directo para la rentabilidad y la competitividad. Este artículo desglosará las estrategias de escalado automático más avanzadas para AWS EKS en 2026, centrándose en la sinergia de Karpenter, Horizontal Pod Autoscaler (HPA) y KEDA. No solo aprenderá a implementar estas herramientas, sino que comprenderá las sutilezas que permiten reducir significativamente los costes operativos, manteniendo la resiliencia y el rendimiento.
Optimización de Costes en AWS EKS con Escalado Automático en 2026
La optimización de costes en Kubernetes, especialmente en AWS EKS, reside en una orquestación inteligente de los recursos a nivel de pod y de nodo. En 2026, la capacidad de reaccionar con precisión a la demanda, tanto al alza como a la baja, es lo que diferencia a una infraestructura eficiente de una derrochadora.
Karpenter: El Provionador Dinámico de Nodos Líder en 2026
Karpenter, el provisionador de nodos de código abierto de AWS, ha consolidado su posición en 2026 como el pilar fundamental para el escalado de nodos en EKS. A diferencia del Cluster Autoscaler (CAS), que reacciona a los pods pendientes, Karpenter actúa como un "observador inteligente" de los eventos de Kubernetes. Cuando detecta pods que no pueden ser programados debido a la falta de recursos, Karpenter se comunica directamente con la API de EC2 para provisionar el nodo exacto necesario, minimizando el desperdicio.
Sus características clave para la optimización de costes incluyen:
- Provisionamiento Just-in-Time: Provee nodos solo cuando son necesarios, y del tamaño preciso para acomodar los pods pendientes.
- Selección Óptima de Instancias: Utiliza información en tiempo real sobre la capacidad de EC2 para seleccionar el tipo de instancia más adecuado y económico (incluyendo instancias Graviton y Spot), considerando los requisitos de los pods (arquitectura, recursos, zonas de disponibilidad).
- Consolidación de Nodos: De forma proactiva, Karpenter reordena los pods para liberar nodos subutilizados y terminarlos, ahorrando costes de forma continua. Esta característica, madura en 2026, es un game-changer para entornos con cargas de trabajo fluctuantes.
- Escalado a Cero: Con una configuración adecuada, puede reducir la infraestructura de nodos a cero cuando no hay pods programables.
Horizontal Pod Autoscaler (HPA) v2: Escalado Reactivo Centrado en la Aplicación
HPA se encarga de ajustar el número de réplicas de un Deployment o StatefulSet basándose en métricas. En 2026, la apiVersion: autoscaling/v2 es el estándar, permitiendo escalar no solo por CPU y memoria, sino también por métricas personalizadas y externas.
- Métricas de Recursos (CPU/Memoria): HPA monitorea el uso de recursos de los pods y ajusta las réplicas para mantener un objetivo de utilización promedio.
- Métricas Personalizadas: Permite escalar basándose en métricas expuestas por un servicio como Prometheus (ej., QPS, latencia).
- Métricas Externas: Permite escalar basándose en métricas de servicios externos a Kubernetes (ej., longitud de una cola SQS, mensajes de Kafka), lo cual es crucial para cargas de trabajo orientadas a eventos.
La configuración de behavior en HPA v2 ofrece un control granular sobre las políticas de escalado ascendente y descendente, incluyendo ventanas de estabilización, lo que permite un comportamiento más predecible y evita el "thrashing" (escalado y desescalado rápido y repetitivo).
KEDA (Kubernetes Event-Driven Autoscaling): Escalado Reactivo Extremo Impulsado por Eventos
KEDA complementa a HPA llevando el escalado reactivo a otro nivel. Mientras que HPA se basa en métricas generalmente continuas, KEDA está diseñado específicamente para cargas de trabajo impulsadas por eventos. Permite a los pods escalar desde cero (o un número mínimo) hasta un máximo, basándose en la profundidad de colas de mensajes, el número de eventos en un stream, o la longitud de bases de datos.
- Escalado a Cero (Scale-to-Zero): La capacidad más potente de KEDA para la optimización de costes. Si no hay eventos, KEDA puede reducir las réplicas de un Deployment a cero, liberando completamente los recursos. Cuando llegan nuevos eventos, KEDA los detecta y escala rápidamente las réplicas para procesarlos.
- Amplia Variedad de Triggers: En 2026, KEDA soporta más de 60 tipos de triggers, incluyendo SQS, Kafka, Azure Service Bus, Redis, Prometheus y muchas más. Esto lo hace increíblemente versátil para casi cualquier carga de trabajo asíncrona.
- Integra con HPA: KEDA se integra con HPA. Cuando KEDA detecta un cambio en un evento que requiere escalar, actualiza un HPA detrás de escena, que luego realiza el escalado de los pods.
Vertical Pod Autoscaler (VPA): Optimizando el Tamaño Correcto de los Pods
Aunque no es un escalador de nodos o réplicas per se, VPA es un complemento vital para la eficiencia de costes. VPA monitorea el uso de recursos de los contenedores y recomienda (o ajusta automáticamente) los requests y limits de CPU y memoria de los pods.
- Recomendaciones Inteligentes: VPA ayuda a asignar los recursos justos a los pods, evitando el sobreaprovisionamiento que se traduce en nodos infrautilizados.
- Mejora la Eficiencia de Karpenter: Al asegurar que los pods solicitan solo lo que necesitan, VPA facilita que Karpenter empaquete más pods en un solo nodo, o que provisione nodos más pequeños y económicos.
Nuevas Herramientas y Tendencias en 2026
- AWS Compute Optimizer para EKS: Esta herramienta analiza el consumo de recursos de tus pods y nodos EKS y ofrece recomendaciones personalizadas para optimizar los tipos de instancia de EC2 y las configuraciones de HPA/VPA. Se integra directamente con AWS Cost Explorer para mostrar el potencial ahorro de costes.
- eBPF para Observabilidad Avanzada: En 2026, eBPF (Extended Berkeley Packet Filter) se ha consolidado como una tecnología clave para la observabilidad de Kubernetes. Herramientas como Cilium e Inspector Gadget permiten monitorizar el rendimiento de la red, el sistema de archivos y la CPU a un nivel granular, lo que ayuda a identificar cuellos de botella y optimizar el uso de recursos.
- FinOps como Práctica Estándar: La práctica de FinOps se ha convertido en un pilar fundamental para la gestión de costes en la nube. Las empresas están adoptando plataformas de FinOps y automatizando procesos para monitorizar, optimizar y predecir los gastos de la nube. Esto incluye la implementación de políticas de gobernanza de costes, el establecimiento de presupuestos y la creación de informes detallados sobre el uso de recursos.
La combinación de HPA/KEDA para el escalado de pods, con VPA para el rightsizing de pods y Karpenter para el escalado óptimo de nodos, AWS Compute Optimizer, eBPF para observabilidad, y las prácticas de FinOps, crea un ciclo de optimización de costes excepcionalmente potente y sensible a la demanda. HPA/KEDA responden a la carga de la aplicación, VPA asegura que cada pod sea eficiente, y Karpenter asegura que solo se pague por los nodos necesarios para ejecutar esos pods eficientes.
Implementación Práctica: Orquestando el Escalado Inteligente
Implementar esta sinergia de escalado requiere una configuración cuidadosa. Asumiremos que ya tienes un cluster EKS funcional. Nos centraremos en la instalación y configuración de Karpenter, y luego en la definición de HPA y KEDA para una aplicación de ejemplo.
Paso 1: Configuración de Karpenter en EKS
Primero, asegúrate de tener las herramientas kubectl, helm y aws-cli configuradas para tu cluster EKS.
1.1 Crear un Perfil de Instancia para Nodos de Karpenter
Karpenter necesita un perfil de instancia IAM para los nodos que provisionará.
# Define el nombre de tu cluster y la región
CLUSTER_NAME="my-eks-cluster-2026"
AWS_REGION="us-east-1"
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# Crea el rol de IAM para los nodos provisionados por Karpenter
aws iam create-role --role-name KarpenterNodeRole-${CLUSTER_NAME} --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}'
# Adjunta políticas a KarpenterNodeRole
aws iam attach-role-policy --role-name KarpenterNodeRole-${CLUSTER_NAME} --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
aws iam attach-role-policy --role-name KarpenterNodeRole-${CLUSTER_NAME} --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
aws iam attach-role-policy --role-name KarpenterNodeRole-${CLUSTER_NAME} --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore # Para acceso vía SSM si lo necesitas
# Crea un perfil de instancia para el rol
aws iam create-instance-profile --instance-profile-name KarpenterNodeInstanceProfile-${CLUSTER_NAME}
aws iam add-role-to-instance-profile --instance-profile-name KarpenterNodeInstanceProfile-${CLUSTER_NAME} --role-name KarpenterNodeRole-${CLUSTER_NAME}
echo "Perfil de instancia KarpenterNodeInstanceProfile-${CLUSTER_NAME} creado."
1.2 Configurar el Rol de Servicio de Karpenter
Karpenter necesita permisos para llamar a las APIs de EC2 y EKS.
# Crea un rol de IAM para el controlador de Karpenter
aws iam create-role --role-name KarpenterControllerRole-${CLUSTER_NAME} --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::'${ACCOUNT_ID}':oidc-provider/oidc.eks.'${AWS_REGION}'.amazonaws.com/id/'$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)'"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.'${AWS_REGION}'.amazonaws.com/id/'$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)'":aud": "sts.amazonaws.com",
"oidc.eks.'${AWS_REGION}'.amazonaws.com/id/'$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)'":sub": "system:serviceaccount:karpenter:karpenter"
}
}
}]
}'
# Adjunta políticas a KarpenterControllerRole. ¡CRÍTICO para su funcionamiento!
# Esta política incluye los permisos necesarios para interactuar con EC2, EKS, etc.
# En un entorno de producción, revisa esta política y aplica el principio de mínimo privilegio.
aws iam put-role-policy --role-name KarpenterControllerRole-${CLUSTER_NAME} --policy-name KarpenterControllerPolicy --policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateLaunchTemplate",
"ec2:CreateFleet",
"ec2:RunInstances",
"ec2:CreateTags",
"ec2:TerminateInstances",
"ec2:DeleteLaunchTemplate",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeInstances",
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DeleteTags",
"ec2:DescribeTags",
"ec2:DescribeInstanceTypes",
"ec2:DescribeImages",
"ec2:DescribeSpotPriceHistory",
"ssm:GetParameter"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::'${ACCOUNT_ID}':role/KarpenterNodeRole-${CLUSTER_NAME}"
},
{
"Effect": "Allow",
"Action": "eks:DescribeCluster",
"Resource": "arn:aws:eks:'${AWS_REGION}':'${ACCOUNT_ID}':cluster/'${CLUSTER_NAME}'"
},
{
"Effect": "Allow",
"Action": [
"tag:GetResources",
"tag:TagResources",
"tag:UntagResources"
],
"Resource": "*"
}
]
}'
echo "Rol de controlador de Karpenter KarpenterControllerRole-${CLUSTER_NAME} creado y políticas adjuntas."
1.3 Instalar Karpenter con Helm
# Añade el repositorio de Helm de Karpenter
helm repo add karpenter https://aws.github.io/karpenter/
helm repo update
# Encuentra el ID de la subred del EKS (esto puede variar, ajusta según tu VPC)
# Ojo: Asegúrate que las subredes tengan el tag 'kubernetes.io/cluster/${CLUSTER_NAME}: shared' o similar
# para que Karpenter pueda descubrirlas.
# Este comando es solo un ejemplo, puede que necesites un enfoque más específico.
SUBNET_IDS=$(aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.resourcesVpcConfig.vpcId" --output text)" "Name=tag:kubernetes.io/cluster/${CLUSTER_NAME},Values=shared" --query "Subnets[].SubnetId" --output text | tr '\t' ',')
if [ -z "$SUBNET_IDS" ]; then
echo "ERROR: No se encontraron subredes con el tag esperado. Asegúrate de que tus subredes de EKS estén correctamente tagueadas."
exit 1
fi
# Encuentra el ID del Security Group del cluster (ajusta si tienes múltiples)
SECURITY_GROUP_IDS=$(aws ec2 describe-security-groups --filters "Name=tag:kubernetes.io/cluster/${CLUSTER_NAME},Values=owned" "Name=group-name,Values=*EKSClusterSG*" --query "SecurityGroups[].GroupId" --output text | tr '\t' ',')
if [ -z "$SECURITY_GROUP_IDS" ]; then
echo "ERROR: No se encontraron Security Groups para el cluster. Asegúrate de que tus SGs de EKS estén correctamente tagueados."
exit 1
fi
# Instala Karpenter
helm upgrade --install karpenter karpenter/karpenter --namespace karpenter --create-namespace \
--set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"="arn:aws:iam::${ACCOUNT_ID}:role/KarpenterControllerRole-${CLUSTER_NAME}" \
--set clusterName=${CLUSTER_NAME} \
--set clusterEndpoint=$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output text) \
--set aws.defaultInstanceProfile=KarpenterNodeInstanceProfile-${CLUSTER_NAME} \
--set aws.defaultLaunchTemplateName="karpenter-default-${CLUSTER_NAME}" \
--set controller.resources.requests.cpu=100m \
--set controller.resources.requests.memory=128Mi \
--set controller.resources.limits.cpu=500m \
--set controller.resources.limits.memory=512Mi \
--wait
Nota: En 2026, las configuraciones de
clusterEndpoint,aws.defaultInstanceProfileyaws.defaultLaunchTemplateNameen el Helm chart de Karpenter son cruciales. Asegúrate de que eldefaultLaunchTemplateNamesea un nombre que Karpenter usará para generar sus propias plantillas.
1.4 Configurar el Provisioner de Karpenter (Clave para el Coste)
Este Provisioner es donde se define la estrategia de escalado de nodos para optimizar costes.
# karpenter-provisioner.yaml
apiVersion: karpenter.sh/v1beta1
kind: Provisioner
metadata:
name: default
spec:
# Definición de las etiquetas y tipos de capacidad que Karpenter considerará
# ¡Aquí es donde se ahorra dinero!
requirements:
- key: "kubernetes.io/arch" # Preferir ARM64 (Graviton) por su relación coste/rendimiento
operator: In
values: ["amd64", "arm64"]
- key: "karpenter.sh/capacity-type" # Preferir instancias Spot por su coste inferior
operator: In
values: ["spot", "on-demand"]
- key: "karpenter.k8s.aws/instance-category" # Preferir instancias de propósito general (m, r, c)
operator: In
values: ["m", "c", "r"]
- key: "karpenter.k8s.aws/instance-family" # Priorizar familias modernas de instancias
operator: In
values: ["m6i", "m7i", "r6i", "r7i", "c6i", "c7i", "t3", "t4g", "m6g", "m7g"] # t4g, m6g, m7g son Graviton
# Límites de recursos que este Provisioner puede crear (para control de gastos)
limits:
resources:
cpu: "1000" # Limita la capacidad total de CPU que este provisioner puede crear
memory: "2048Gi" # Limita la memoria total
# TTL (Time To Live) para nodos vacíos.
# CRÍTICO para el coste: Apaga nodos rápidamente cuando ya no son necesarios.
ttlSecondsAfterEmpty: 60 # Termina nodos 60 segundos después de quedar vacíos.
# Consolidation: Karpenter intentará reubicar pods para liberar nodos subutilizados y terminarlos.
# Imprescindible para la optimización continua de costes.
consolidation:
enabled: true
# Especifica cuándo Karpenter puede consolidar
# throttle: "1s" # (Optional) Tiempo mínimo entre consolidaciones
# period: "30s" # (Optional) Período para buscar consolidaciones
# Define la plantilla de nodos que Karpenter usará, haciendo referencia a un AWSNodeTemplate
providerRef:
name: default # Hace referencia al AWSNodeTemplate llamado 'default'
---
apiVersion: karpenter.k8s.aws/v1beta1
kind: AWSNodeTemplate
metadata:
name: default
spec:
amiFamily: AL2023 # Usar la última AMI de Amazon Linux 2023 por seguridad y rendimiento
instanceProfile: KarpenterNodeInstanceProfile-${CLUSTER_NAME} # El perfil IAM que creamos
subnetSelector: # Asegúrate de que Karpenter solo use las subredes de tu cluster EKS
karpenter.sh/discovery: ${CLUSTER_NAME}
securityGroupSelector: # Lo mismo para los security groups
karpenter.sh/discovery: ${CLUSTER_NAME}
tags: # Etiquetado de recursos para la asignación de costes y gobernanza
Environment: "Production"
ManagedBy: "Karpenter"
CostCenter: "DevOps"
Aplica este Provisioner:
envsubst < karpenter-provisioner.yaml | kubectl apply -f -
Explicación:
requirements: Aquí defines los filtros para los tipos de instancias. Priorizamosarm64(instancias Graviton) por su mejor relación rendimiento/coste en 2026 yspotpara un ahorro significativo.limits: Establece límites para controlar el gasto máximo.ttlSecondsAfterEmpty: Un valor bajo (e.g., 60-300 segundos) es clave para desescalar rápidamente los nodos inactivos y ahorrar dinero.consolidation.enabled: true: Habilita la característica que reempaca pods para eliminar nodos infrautilizados.AWSNodeTemplate: Configura la AMI, el perfil de instancia y los selectores de subred/grupos de seguridad. El etiquetado es fundamental para la visibilidad de costes en AWS Cost Explorer.
Paso 2: Despliegue de una Aplicación de Ejemplo con HPA y KEDA
Ahora, vamos a desplegar una aplicación simple (un servidor web NGINX de ejemplo) y configurar HPA y KEDA para que la escalen de forma eficiente. Para el ejemplo de KEDA, usaremos un escalador basado en SQS, que es un patrón muy común para cargas de trabajo asíncronas.
2.1 Despliegue de la Aplicación (NGINX)
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cost-optimized-webapp
labels:
app: cost-optimized-webapp
spec:
replicas: 1 # Comenzamos con una réplica, KEDA la puede llevar a cero.
selector:
matchLabels:
app: cost-optimized-webapp
template:
metadata:
labels:
app: cost-optimized-webapp
spec:
containers:
- name: nginx-container
image: public.ecr.aws/nginx/nginx:1.25 # Utilizando una imagen de NGINX de ECR Public
resources: # ¡CRÍTICO para HPA y Karpenter! Solicita lo que realmente necesitas.
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "128Mi"
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: cost-optimized-webapp-svc
spec:
selector:
app: cost-optimized-webapp
ports:
- protocol: TCP
port: 80
targetPort: 80
Aplica: kubectl apply -f app-deployment.yaml
2.2 Configuración del Horizontal Pod Autoscaler (HPA)
Escalaremos por uso de CPU para la carga de trabajo general.
# hpa-config.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: cost-optimized-webapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: cost-optimized-webapp
minReplicas: 1 # KEDA puede llevarlo a 0, HPA lo mantiene en 1 si está activo.
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # Escalar cuando la CPU promedio de los pods exceda el 50%
behavior: # Ajustes avanzados para un escalado más suave y eficiente
scaleDown:
stabilizationWindowSeconds: 300 # Esperar 5 minutos antes de desescalar
policies:
- type: Pods
value: 1
periodSeconds: 60 # Desescalar 1 pod por minuto
- type: Percent
value: 10
periodSeconds: 60 # O desescalar 10% de pods por minuto
scaleUp:
stabilizationWindowSeconds: 0 # Escalar de inmediato ante la demanda
policies:
- type: Pods
value: 4
periodSeconds: 60 # Escalar 4 pods por minuto
- type: Percent
value: 100
periodSeconds: 60 # O escalar 100% de pods por minuto (doblar)
Aplica: kubectl apply -f hpa-config.yaml
Explicación: El HPA monitoreará el uso de CPU. Cuando la utilización promedio de CPU de los pods del
cost-optimized-webappexceda el 50%, HPA aumentará el número de réplicas. Elbehaviorestá ajustado para escalar rápidamente pero desescalar de forma más conservadora, crucial para la estabilidad y evitar costes innecesarios por "reflashing".
2.3 Instalación de KEDA
Necesitamos instalar el operador KEDA en el cluster.
# Añade el repositorio de Helm de KEDA
helm repo add keda https://kedacore.github.io/charts
helm repo update
# Instala KEDA
kubectl create namespace keda
helm install keda keda/keda --namespace keda
2.4 Configuración de KEDA (Ejemplo con SQS)
Para este ejemplo, KEDA necesita acceso a la cola SQS. Esto se logra con IAM Roles for Service Accounts (IRSA).
Primero, crea una cola SQS y un rol IAM para que el Service Account de KEDA pueda leer de ella.
# Crea una cola SQS de ejemplo
SQS_QUEUE_NAME="keda-example-queue-2026"
aws sqs create-queue --queue-name ${SQS_QUEUE_NAME}
SQS_QUEUE_URL=$(aws sqs get-queue-url --queue-name ${SQS_QUEUE_NAME} --query "QueueUrl" --output text)
echo "Cola SQS creada: ${SQS_QUEUE_URL}"
# Crea un Service Account para KEDA y un rol IAM para él.
# Este rol permitirá a KEDA acceder a la cola SQS.
# Primero, crea la política de acceso a SQS.
aws iam create-policy --policy-name KEDASQSReadPolicy --policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sqs:GetQueueUrl",
"sqs:GetQueueAttributes",
"sqs:ReceiveMessage",
"sqs:ListQueues"
],
"Resource": "arn:aws:sqs:'${AWS_REGION}':'${ACCOUNT_ID}':'${SQS_QUEUE_NAME}'"
}
]
}'
# Crea un Service Account de Kubernetes para KEDA
kubectl create serviceaccount keda-sqs-sa --namespace default
# Anota el Service Account con el ARN del rol de IAM que KEDA usará
# Crea el rol IAM para el SA de KEDA (IRSA)
eksctl create iamserviceaccount \
--cluster=${CLUSTER_NAME} \
--namespace=default \
--name=keda-sqs-sa \
--attach-policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/KEDASQSReadPolicy \
--approve \
--override-existing-serviceaccounts
# Asegúrate de que la anotación se ha aplicado correctamente al Service Account
# kubectl describe sa keda-sqs-sa -n default
Ahora, define el ScaledObject de KEDA.
# keda-scaledobject-sqs.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: cost-optimized-webapp-keda
labels:
deploymentName: cost-optimized-webapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: cost-optimized-webapp
pollingInterval: 15 # KEDA revisará la cola SQS cada 15 segundos
minReplicas: 0 # ¡CRÍTICO para el ahorro de costes! Permite escalar a cero.
maxReplicas: 20
cooldownPeriod: 300 # Tiempo en segundos antes de desescalar a 0 una vez que la cola está vacía.
triggers:
- type: aws-sqs
metadata:
queueURL: "${SQS_QUEUE_URL}" # URL de tu cola SQS
queueLength: "5" # Escalar un pod por cada 5 mensajes en la cola
awsRegion: "${AWS_REGION}"
identityOwner: pod # Indica que la identidad se obtiene a nivel de pod
podIdentityArn: "arn:aws:iam::${ACCOUNT_ID}:role/eksctl-${CLUSTER_NAME}-addon-iamserviceaccount-default-keda-sqs-sa-Role" # El ARN del rol IAM para el SA creado con eksctl
authenticationRef:
name: keda-trigger-authentication-sqs # Referencia al objeto TriggerAuthentication
---
# keda-trigger-authentication-sqs.yaml
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: keda-trigger-authentication-sqs
spec:
podIdentity:
provider: aws-eks # Usar la identidad de pod de EKS (IRSA)
Aplica: envsubst < keda-scaledobject-sqs.yaml | kubectl apply -f -
kubectl apply -f keda-trigger-authentication-sqs.yaml
Explicación:
scaleTargetRef: Apunta a nuestrocost-optimized-webappDeployment.minReplicas: 0: Esta es la clave del ahorro con KEDA. Si la cola SQS está vacía y elcooldownPeriodha pasado, KEDA reducirá las réplicas del Deployment a cero. Karpenter, al ver cero pods, terminará el nodo asociado.triggers: Define el escaladoraws-sqs.queueLength: "5"significa que se creará un nuevo pod por cada 5 mensajes en la cola.podIdentity: Utiliza IRSA para que los pods de KEDA puedan autenticarse con AWS. Es la forma segura y recomendada en 2026.
Con estos pasos, has configurado una infraestructura de escalado altamente optimizada. Karpenter provisionará nodos económicos (priorizando Spot y Graviton) según la demanda de pods generada por HPA y KEDA. HPA reaccionará a la utilización de recursos interna de la aplicación, y KEDA permitirá que las cargas de trabajo impulsadas por eventos escalen a cero cuando estén inactivas, minimizando los costes.
💡 Consejos de Experto: Optimizando al Máximo y Evitando Trampas
La teoría es una cosa, la experiencia en producción es otra. Aquí tienes trucos y consideraciones que solo se aprenden "en la trinchera" para maximizar tus ahorros y estabilidad en 2026.
-
Priorización de Instancias Graviton (ARM64): En 2026, las instancias Graviton (ARM64) de AWS ofrecen un rendimiento-por-coste significativamente superior para muchas cargas de trabajo. Configura tus
Provisionerde Karpenter para priorizararm64y asegura que tus imágenes de contenedor soporten múltiples arquitecturas o sean específicas para ARM. La migración puede reducir los costes de EC2 en un 20-40%. -
Gestión Inteligente de Instancias Spot:
- Workloads Tolerantes a Interrupciones: Utiliza
karpenter.sh/capacity-type: spotpara cargas de trabajo que pueden tolerar interrupciones (ej., microservicios sin estado, trabajos por lotes, colas de procesamiento). - Pod Disruption Budgets (PDBs): Asegúrate de definir PDBs para tus aplicaciones críticas. Esto permite que Karpenter, al terminar una instancia Spot, lo haga de forma segura, garantizando un número mínimo de pods en ejecución y una reubicación grácil.
- Múltiples Familias de Instancias: En tu
Provisionerde Karpenter, lista una variedad deinstance-familyyinstance-sizecompatibles. Cuantas más opciones le des a Karpenter, más fácil será encontrar capacidad Spot disponible y barata.
- Workloads Tolerantes a Interrupciones: Utiliza
-
Resource Requests & Limits Precisos: Es la base de un escalado eficiente. Si tus pods solicitan más recursos de los que necesitan (
requests), Karpenter provisionará nodos más grandes o más nodos de los necesarios. Si no tienenlimitsadecuados, un pod errante puede consumir todos los recursos del nodo y afectar a otros. Utiliza VPA en modoRecommenderpara obtener sugerencias precisas antes de aplicar losrequests/limits. -
Monitoreo de Costes y Rendimiento:
- AWS Cost Explorer/Cost Anomaly Detection: Utiliza estas herramientas para monitorear tus gastos de EKS y recibir alertas sobre anomalías. El etiquetado de recursos (visto en Karpenter
AWSNodeTemplate) es fundamental para desglosar estos costes. - OpenCost/Kubecost: Herramientas de código abierto que te dan visibilidad granular de los costes a nivel de pod, namespace y cluster. Te permiten identificar dónde se gasta el dinero y dónde hay oportunidades de optimización.
- AWS Cost Explorer/Cost Anomaly Detection: Utiliza estas herramientas para monitorear tus gastos de EKS y recibir alertas sobre anomalías. El etiquetado de recursos (visto en Karpenter




