
Orquestração de Capacidade Just-in-Time: Elasticidade Extrema no Amazon EKS com Karpenter e Spot Instances
Uma dissecação arquitetônica sobre a substituição do Cluster Autoscaler tradicional pelo Karpenter em ambientes Amazon Elastic Kubernetes Service (EKS). O artigo explora o provisionamento direto de nós de computação sem servidor (group-less), a maximização do uso de instâncias Spot através de diversificação de frota e a implementação de adaptadores de resiliência em aplicações Python para tolerar interrupções voláteis.
A dependência de instâncias sob demanda em clusters Kubernetes estáticos consome vastas fatias do orçamento de infraestrutura corporativa. Quando o Cluster Autoscaler nativo tenta mitigar esse desperdício, sua arquitetura legada, estritamente atrelada a Auto Scaling Groups (ASGs) homogêneos e rígidos, reage com lentidão excruciante aos pods pendentes. Isso resulta em empacotamento ineficiente (bin-packing), subutilização crônica de memória e degradação severa da disponibilidade durante picos vertiginosos de tráfego. A implementação do Karpenter no Amazon Elastic Kubernetes Service (EKS) resolve definitivamente essa ineficiência estrutural. Ao contornar completamente os ASGs e interagir diretamente com a API do Amazon EC2, o Karpenter avalia as restrições matemáticas de agendamento dos pods e provisiona a capacidade de computação exata (right-sizing) em frações de segundo. Acoplar este mecanismo de provisionamento contínuo com instâncias Spot entrega escalabilidade instantânea e reduz os custos computacionais radicalmente, viabilizando operações corporativas de altíssimo rendimento na AWS sem sacrificar a resiliência.
Pré-requisitos
A construção desta infraestrutura de autoscale exige profundo conhecimento sobre os mecanismos de agendamento (kube-scheduler) do Kubernetes e tolerâncias a falhas distribuídas. O ambiente deve ser provisionado através do Terraform versão 1.7.0 ou superior, utilizando o provedor AWS versão 5.40.0 e o provedor Helm para a injeção do controlador. O cluster Amazon EKS deve rodar a versão 1.28 ou superior. A camada de aplicação necessita do Python 3.12 para implementar os tratadores de interrupção em nível de sistema operacional (OS signals). Um provedor OpenID Connect (OIDC) deve estar obrigatoriamente habilitado no EKS para suportar IAM Roles for Service Accounts (IRSA).
Passo a Passo
Delegação de Autoridade Computacional via IAM e IRSA
A transição para um modelo de provisionamento just-in-time inicia com a concessão de privilégios de criação de frota diretamente a um pod de controlador operando dentro do cluster. Provisionamos uma função IAM dedicada (IAM Role) vinculada à conta de serviço do Kubernetes (Service Account) do Karpenter utilizando o padrão IRSA. A justificativa técnica para essa abstração de permissões é a minimização da superfície de ataque e o abandono definitivo das credenciais de nó (Node IAM Role) para operações de plano de controle. O Karpenter exige permissões granulares, como
ec2:RunInstances e ec2:TerminateInstances, para gerenciar o ciclo de vida da infraestrutura de forma autônoma. Ao isolar essas permissões estritamente no namespace karpenter, garantimos que nenhuma outra carga de trabalho comprometida no cluster possa instanciar instâncias EC2 ilícitas para mineração de criptomoedas ou exfiltração de dados. O módulo Terraform abaixo consolida essa relação de confiança criptográfica entre o plano de dados do EKS e o provedor de identidade da AWS.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module "karpenter_irsa" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
version = "~> 5.30"
role_name = "karpenter-controller-production"
attach_karpenter_controller_policy = true
karpenter_controller_cluster_name = var.cluster_name
karpenter_controller_node_iam_role_arns = [aws_iam_role.karpenter_node_role.arn]
oidc_providers = {
ex = {
provider_arn = module.eks.oidc_provider_arn
namespace_service_accounts = ["karpenter:karpenter"]
}
}
}
resource "aws_iam_role" "karpenter_node_role" {
name = "karpenter-node-production"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = { Service = "ec2.amazonaws.com" }
}]
})
}
resource "aws_iam_role_policy_attachment" "karpenter_ssm" {
role = aws_iam_role.karpenter_node_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
Se o controlador agora possui a capacidade de criar qualquer tipo de instância no Amazon EC2 sob demanda, como impomos limites arquitetônicos rigorosos para evitar que ele provisione instâncias extremamente caras ou utilize arquiteturas de processador incompatíveis com nossos contêineres?
Diversificação de Frota e Configuração de NodePools
Impomos as fronteiras computacionais definindo Custom Resource Definitions (CRDs) do tipo
NodePool e EC2NodeClass diretamente na API do Kubernetes. O NodePool atua como o motor de regras, determinando os requisitos de agendamento que o Karpenter tem permissão para atender. O raciocínio arquitetônico vital nesta etapa é maximizar a disponibilidade de instâncias Spot (Spot capacity pools). Se o cluster solicitar exclusivamente o tipo m5.large, uma interrupção localizada dessa família de instâncias na zona de disponibilidade paralisará o autoscale. Para evitar isso, configuramos o NodePool para aceitar uma matriz vasta de instâncias flexíveis (por exemplo, permitindo instâncias baseadas em Graviton, x86_64, de múltiplas gerações e variados tamanhos). O Karpenter chamará a API Fleet do EC2 utilizando uma estratégia de alocação price-capacity-optimized, que descobre e lança o tipo de instância com o menor preço e a menor probabilidade de interrupção (reclaim) no momento exato do provisionamento.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: spot-compute-pool
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot"]
- key: kubernetes.io/arch
operator: In
values: ["amd64", "arm64"]
- key: karpenter.k8s.aws/instance-family
operator: In
values: ["c5", "c6g", "m5", "m6g", "r5", "r6g"]
- key: karpenter.k8s.aws/instance-size
operator: NotIn
values: ["nano", "micro", "small"]
nodeClassRef:
name: default-ec2-class
limits:
cpu: "1000"
memory: 1000Gi
disruption:
consolidationPolicy: WhenUnderutilized
expireAfter: 720h
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: default-ec2-class
spec:
amiFamily: AL2
role: "karpenter-node-production"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "production-cluster"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "production-cluster"
Uma vez que baseamos nossa economia em nós Spot que podem ser confiscados pela AWS com um aviso prévio de apenas dois minutos, como a camada de aplicação evita o corrompimento de dados e a queda de transações em andamento quando o servidor desaparece repentinamente?
Resiliência Graciona e Interceptação de Sinais OS (SIGTERM)
Blindamos as transações em andamento implementando manipuladores de sinais de sistema operacional (Signal Handlers) nas portas hexagonais primárias das aplicações em execução nos pods. Quando a AWS decide retomar uma instância Spot, o Karpenter recebe o aviso via SQS, imediatamente isola o nó (Cordon) e inicia o processo de drenagem (Drain). O kubelet reage enviando um sinal
SIGTERM para o processo principal (PID 1) do contêiner Python. O raciocínio crítico é que aplicações modernas não podem simplesmente morrer ao receber este sinal. O adaptador da aplicação deve interceptar o SIGTERM, parar de aceitar novas requisições da rede (falhando sondagens de prontidão), e iniciar uma contagem regressiva controlada. Durante este período de tolerância (Grace Period), a aplicação conclui as transações em andamento no banco de dados, efetua a liberação (flush) de logs e encerra os pools de conexão de forma limpa antes de fechar o processo principal e receber o inevitável SIGKILL.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import signal
import sys
import time
from typing import Any
from aws_lambda_powertools import Logger
logger = Logger(service="CheckoutAPI")
class GracefulShutdownAdapter:
def __init__(self, domain_service: Any):
self.domain_service = domain_service
self._shutdown_requested = False
# Intercepta o sinal SIGTERM enviado pelo Kubernetes (via Karpenter drain)
signal.signal(signal.SIGTERM, self._sigterm_handler)
signal.signal(signal.SIGINT, self._sigterm_handler)
def _sigterm_handler(self, signum: int, frame: Any) -> None:
logger.warning(f"Sinal de término {signum} recebido. Iniciando drenagem graciosa...")
self._shutdown_requested = True
# 1. Sinaliza falha nas sondagens de prontidão (Readiness Probe)
self.domain_service.disable_ingress_traffic()
# 2. Aguarda a conclusão das transações transbordadas do Ingress Controller
logger.info("Aguardando 10 segundos para escoamento de conexões pendentes do ALB...")
time.sleep(10)
# 3. Fecha conexões seguras com banco de dados
self.domain_service.close_database_pools()
logger.info("Drenagem concluída. Encerrando processo em segurança.")
sys.exit(0)
def is_shutting_down(self) -> bool:
return self._shutdown_requested
# Inicialização fictícia do adaptador de aplicação
class CheckoutDomainService:
def disable_ingress_traffic(self): pass
def close_database_pools(self): pass
domain = CheckoutDomainService()
shutdown_handler = GracefulShutdownAdapter(domain)
# Loop principal de evento da aplicação
while not shutdown_handler.is_shutting_down():
# Processamento normal
time.sleep(1)
Solução de Problemas Comuns
Uma interrupção severa da orquestração ocorre quando o Karpenter falha repetidamente ao tentar lançar novos nós e os logs do pod do controlador relatam a exceção
UnauthorizedOperation ao invocar a API do EC2. Isso frequentemente não é uma falha na política do IAM associada ao IRSA (karpenter-controller-role), mas sim a ausência do perfil de instância (Instance Profile) atrelado à karpenter-node-role. O Karpenter necessita deste perfil para injetar os privilégios corretos no nó físico inicializado. Verifique se o recurso aws_iam_instance_profile foi mapeado e associado corretamente no Terraform e referenciado no EC2NodeClass.Outra anomalia silenciosa afeta a resolução de rede topológica. Se o Karpenter registrar mensagens indicando que não encontrou sub-redes válidas (
no subnets matched selector), o problema reside puramente no tagueamento de infraestrutura (Infrastructure Tagging). O mecanismo de descoberta do Karpenter não analisa tabelas de roteamento; ele lê chaves de tag (Tags) associadas às sub-redes e grupos de segurança (Security Groups) da VPC. Certifique-se de que o Terraform aplicou as tags de descoberta exatas (por exemplo, karpenter.sh/discovery: cluster-name) em pelo menos uma sub-rede privada por zona de disponibilidade. A omissão de uma única tag na zona us-east-1a forçará o provisionamento ineficiente e restrito às zonas remanescentes.Conclusão
A transição de Autoscaling Groups estáticos para a elasticidade preditiva do Karpenter reimagina o paradigma de gerenciamento de capacidade no Kubernetes. Ao tratar a frota de instâncias não como grupos isolados, mas como um espectro heterogêneo de computação bruta, as organizações maximizam a adoção de instâncias Spot, otimizando o orçamento operacional massivamente. A implementação acoplada a mecanismos de desligamento gracioso na aplicação blinda a disponibilidade do sistema contra as dinâmicas de mercado das nuvens. Em estratégias multicloud em evolução, este paradigma de agendamento ágil sem nós (node-less) pode ser traduzido conceitualmente para serviços comparáveis, como o Azure Kubernetes Service (AKS) com suporte ativado a conjuntos de instâncias de máquinas virtuais do tipo Spot e provisionamento automático avançado.
Referências
Burns, B., Beda, J., & Hightower, K. (2019). Kubernetes: Up and running: Dive into the future of infrastructure. O'Reilly Media.
Amazon Web Services. (2024). Karpenter best practices. AWS Architecture Center. https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/
Google Cloud. (2020). Site reliability engineering: Graceful graceful degradation and capacity planning. Google SRE Books.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article