Voltar para o blog

Guia de upgrade para Amazon EKS 1.37: checklist, testes e rollback seguro

Introdução

Atualizar um cluster Amazon Elastic Kubernetes Service (Amazon EKS) não deve ser tratado como simplesmente alterar a versão no Terraform ou executar aws eks update-cluster-version.

Em produção, o processo envolve várias camadas:

Aplicações
   ↓
Kubernetes APIs
   ↓
EKS Control Plane
   ↓
Controllers / Operators / Webhooks
   ↓
Worker Nodes
   ↓
CNI / DNS / CSI / kube-proxy
   ↓
AWS

Uma incompatibilidade em qualquer uma delas pode fazer o control plane terminar o upgrade com sucesso enquanto workloads começam a apresentar erros minutos ou horas depois.

Para a migração:

EKS 1.36 → EKS 1.37

uma estratégia mais segura é:

Inventário
   ↓
Upgrade Insights
   ↓
Compatibilidade
   ↓
Backup
   ↓
Staging
   ↓
Control Plane 1.37
   ↓
Smoke Tests
   ↓
Bake Period
   ↓
Node Groups
   ↓
Add-ons
   ↓
Validação final

O EKS também permite retornar o control plane para a versão menor anterior durante os sete dias seguintes ao upgrade, desde que os requisitos de rollback sejam atendidos. Isso reduz o risco operacional, mas não reverte automaticamente Managed Node Groups, add-ons ou workloads.

1. O que significa atualizar o EKS

O Amazon EKS divide a responsabilidade do cluster em duas grandes camadas.

Control plane

Gerenciado pela AWS, contém componentes como:

  • kube-apiserver;
  • scheduler;
  • controller manager;
  • etcd gerenciado.

Quando executamos:

aws eks update-cluster-version \
  --name production \
  --kubernetes-version 1.37 \
  --region us-east-1

estamos atualizando principalmente essa camada.

Data plane

Continua sob responsabilidade da plataforma e inclui:

  • Managed Node Groups;
  • nodes self-managed;
  • nodes provisionados por Karpenter;
  • Fargate;
  • EKS Auto Mode;
  • aplicações;
  • operadores;
  • add-ons.

Portanto:

Control Plane = 1.37

não significa automaticamente:

Nodes = 1.37
CoreDNS = atualizado
VPC CNI = atualizado
CSI = atualizado
Controllers = compatíveis

Essa separação é central para planejar o upgrade e o rollback.

2. Version skew e ordem do upgrade

O Kubernetes permite determinado descompasso entre versões.

Com kube-apiserver 1.37, o kubelet pode estar em:

1.37
1.36
1.35
1.34

desde que as demais regras de version skew sejam respeitadas.

Já o kubectl deve permanecer, em geral, dentro de uma versão menor para cima ou para baixo em relação ao API Server.

Isso permite uma estratégia importante:

Control Plane: 1.37
Nodes:         1.36

por um período controlado.

Esse intervalo funciona como bake period: o novo control plane recebe tráfego real enquanto os nodes ainda permanecem na versão anterior.

A atualização também deve seguir versões consecutivas:

1.35 → 1.36 → 1.37

e não:

1.35 → 1.37

3. O que revisar especificamente no Kubernetes 1.37

Além do release note do EKS, revise as mudanças upstream do Kubernetes e as dependências instaladas no cluster.

Isso inclui principalmente:

VPC CNI
CoreDNS
kube-proxy
EBS/EFS CSI
AWS Load Balancer Controller
Karpenter
KEDA
cert-manager
Kyverno
External Secrets
Prometheus Operator
StackGres
Argo CD
Traefik
service meshes
controllers internos

A pergunta não deve ser apenas:

O Kubernetes 1.37 funciona?

Mas:

As versões dos componentes instalados no meu cluster suportam Kubernetes 1.37?

Liste CRDs e admission webhooks:

kubectl get crd

kubectl get apiservices

kubectl get validatingwebhookconfigurations

kubectl get mutatingwebhookconfigurations

Controllers antigos são uma fonte comum de problemas porque podem continuar funcionando normalmente no Kubernetes atual e falhar somente após a mudança da API.

4. Checklist pré-upgrade

Antes da janela de mudança, registre o estado atual.

Cluster e nodes

kubectl version

kubectl get nodes \
  -o custom-columns='NODE:.metadata.name,KUBELET:.status.nodeInfo.kubeletVersion,OS:.status.nodeInfo.osImage,RUNTIME:.status.nodeInfo.containerRuntimeVersion'

Confira o EKS:

aws eks describe-cluster \
  --name production \
  --region us-east-1 \
  --query 'cluster.{Version:version,Status:status,Platform:platformVersion}'

O cluster deve estar:

Status: ACTIVE

Upgrade Insights

Execute:

aws eks list-insights \
  --cluster-name production \
  --region us-east-1

Os Upgrade Insights ajudam a identificar condições como APIs incompatíveis e problemas relacionados às versões dos componentes. A AWS mantém histórico de uso de APIs depreciadas em uma janela móvel, então corrigir uma API não significa necessariamente que o alerta desaparecerá imediatamente.

Depois de corrigir problemas:

aws eks start-insights-refresh \
  --cluster-name production \
  --region us-east-1

Add-ons

Liste:

aws eks list-addons \
  --cluster-name production \
  --region us-east-1

Verifique compatibilidade individualmente:

aws eks describe-addon-versions \
  --kubernetes-version 1.37 \
  --addon-name vpc-cni

Repita para:

vpc-cni
coredns
kube-proxy
aws-ebs-csi-driver

Sempre consulte as versões no momento da mudança em vez de fixar números obtidos de artigos antigos.

Capacidade

Garanta espaço suficiente para:

  • nodes novos coexistirem temporariamente com antigos;
  • Pods serem reagendados;
  • DaemonSets iniciarem;
  • volumes serem remontados;
  • autoscaling responder.

Revise também disponibilidade de IPs nas subnets do cluster.

5. Backup e estratégia de recuperação

Rollback de Kubernetes não é backup.

Antes do upgrade, confirme proteção para:

Objetos Kubernetes
CRDs
ConfigMaps
Secrets
PVCs
EBS
EFS
PostgreSQL
RabbitMQ
outros dados stateful

Bancos devem possuir estratégia própria.

Por exemplo:

PostgreSQL
   ↓
backup físico/lógico
   ↓
armazenamento externo
   ↓
restore testado

A parte mais importante não é saber que existe um backup, mas saber que ele pode ser restaurado.

Um rollback do control plane preserva o estado atual do etcd; ele não transforma o cluster automaticamente em uma fotografia anterior à mudança.

6. Preparando os workloads para o upgrade

Um workload produtivo deve tolerar substituição gradual dos nodes.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payments-api
  namespace: production
spec:
  replicas: 3

  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1

  selector:
    matchLabels:
      app: payments-api

  template:
    metadata:
      labels:
        app: payments-api

    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: payments-api

      containers:
        - name: api
          image: example/payments-api:2.4.1

          ports:
            - containerPort: 8080

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

          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            periodSeconds: 5

          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 20
            periodSeconds: 10

          startupProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 5
            failureThreshold: 30

---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: payments-api
  namespace: production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: payments-api

Nesse exemplo:

  • três réplicas reduzem impacto da substituição de Pods;
  • maxUnavailable: 0 mantém capacidade durante rollout;
  • topologySpreadConstraints distribui réplicas;
  • probes impedem tráfego para containers indisponíveis;
  • o PodDisruptionBudget (PDB) mantém pelo menos duas réplicas durante disrupções voluntárias.

Os valores devem ser ajustados para cada workload.

Um erro comum é criar:

minAvailable: 100%

sem considerar que isso pode impedir o drain de nodes.

7. Testes antes de produção

Staging deve reproduzir o comportamento relevante de produção.

Valide pelo menos:

ÁreaTeste
APIcreate/update/delete de recursos
DNSresolução interna e externa
Servicecomunicação ClusterIP
IngressHTTP/HTTPS
Storageattach/mount de PVC
AutoscalingHPA/KEDA sob carga
IAMPod acessando AWS
Operatorsreconciliação de CRDs
Admissionwebhooks funcionando
Observabilidademétricas, logs e traces
Nodescordon/drain/reagendamento
CI/CDdeploy completo

Teste o processo de drain:

kubectl drain <node> \
  --ignore-daemonsets \
  --delete-emptydir-data

Depois:

kubectl uncordon <node>

Esse teste costuma revelar problemas de PDB, workloads com uma única réplica, StatefulSets e dependências de node que passam despercebidas em verificações superficiais.

8. Upgrade do control plane e bake period

Com o preflight concluído:

aws eks update-cluster-version \
  --name production \
  --kubernetes-version 1.37 \
  --region us-east-1

A operação retorna um update.id.

Monitore:

aws eks describe-update \
  --name production \
  --region us-east-1 \
  --update-id <UPDATE_ID>

Aguarde:

Successful

Depois:

kubectl version
kubectl get nodes
kubectl get pods -A

Neste momento, manter temporariamente:

Control plane: 1.37
Nodes:         1.36

pode ser intencional.

Bake period

Não avance imediatamente para nodes e add-ons.

Um fluxo possível:

T0       Control plane 1.37
T+15m    smoke tests
T+1h     métricas e logs
T+4h     comportamento sob tráfego real
T+24h    decisão sobre data plane

A duração depende da criticidade da plataforma.

Durante esse período, evite introduzir recursos que dependam exclusivamente do Kubernetes 1.37, pois isso pode dificultar um eventual retorno para 1.36.

9. Upgrade dos nodes e add-ons

Após o bake period, atualize os Managed Node Groups progressivamente.

aws eks list-nodegroups \
  --cluster-name production \
  --region us-east-1

Exemplo:

aws eks update-nodegroup-version \
  --cluster-name production \
  --nodegroup-name prod-app \
  --kubernetes-version 1.37 \
  --region us-east-1

Não atualize todos ao mesmo tempo.

Uma estratégia pode ser:

pool canário
   ↓
workloads menos críticos
   ↓
prod-app
   ↓
nodes especiais/stateful

Depois avance os add-ons necessários:

aws eks describe-addon-versions \
  --kubernetes-version 1.37 \
  --addon-name coredns

e:

aws eks update-addon \
  --cluster-name production \
  --addon-name coredns \
  --addon-version <VERSAO_COMPATIVEL> \
  --region us-east-1

Faça uma alteração de cada vez.

Evite atualizar simultaneamente:

Control Plane
+ Nodes
+ CNI
+ DNS
+ CSI
+ Ingress
+ Service Mesh

Se houver regressão, identificar a origem será muito mais difícil.

10. Validação e observabilidade

Depois de cada etapa:

kubectl get nodes
kubectl get pods -A
kubectl get deployments -A
kubectl get statefulsets -A
kubectl get daemonsets -A
kubectl get pdb -A
kubectl get apiservices

Eventos:

kubectl get events -A \
  --sort-by=.metadata.creationTimestamp

Pods fora do estado esperado:

kubectl get pods -A \
  --field-selector=status.phase!=Running,status.phase!=Succeeded

Mas Running não significa aplicação saudável.

Acompanhe também:

HTTP 5xx
latência p95/p99
restarts
Pods Pending
CPU/memória
CPU throttling
DNS errors
queue backlog
database connections
controller errors
SLO burn rate

Com Prometheus:

sum(rate(kube_pod_container_status_restarts_total[5m]))
count(kube_pod_status_phase{phase="Pending"} == 1)

Com Loki, procure padrões como:

timeout
connection refused
failed mount
failed scheduling
forbidden
admission webhook
context deadline exceeded

Se houver OpenTelemetry, compare traces pré e pós-upgrade para encontrar regressões em dependências que não aparecem imediatamente na infraestrutura.

O ideal é trabalhar com:

baseline antes do upgrade
          ↓
comparação
          ↓
dados pós-upgrade

e não apenas olhar valores isolados.

11. Rollback para EKS 1.36

Após um upgrade in-place:

1.36 → 1.37

o EKS permite solicitar:

1.37 → 1.36

durante uma janela de sete dias.

O rollback é limitado a uma minor version e depende das condições de elegibilidade do cluster.

O que não volta automaticamente

O rollback não reverte:

etcd data
workloads
EKS add-ons
persistent volumes
self-managed nodes
Managed Node Groups
hybrid nodes

Por isso, existe diferença entre rollback do control plane e rollback da plataforma inteira.

Rollback Readiness

Após o upgrade:

aws eks list-insights \
  --cluster-name production \
  --region us-east-1 \
  --filter '{"categories":["ROLLBACK_READINESS"]}'

Os checks analisam, entre outras coisas:

  • API compatibility;
  • cluster health;
  • kubelet version skew;
  • kube-proxy version skew;
  • add-on compatibility.

Os insights permanecem disponíveis durante a janela de elegibilidade para rollback.

12. Estratégias de rollback

Cenário A — nodes continuam em 1.36

Control plane: 1.37
Nodes:         1.36

Esse é o cenário mais simples.

Depois de avaliar Rollback Readiness:

aws eks update-cluster-version \
  --name production \
  --kubernetes-version 1.36 \
  --region us-east-1

Esse é um dos principais benefícios de manter um bake period antes de atualizar o data plane.

Cenário B — nodes já foram para 1.37

Control plane: 1.37
Nodes:         1.37

Como o kubelet não deve ser mais novo que o API Server, primeiro retorne os Managed Node Groups:

aws eks update-nodegroup-version \
  --cluster-name production \
  --nodegroup-name prod-app \
  --kubernetes-version 1.36 \
  --region us-east-1

Depois valide:

kubectl get nodes

Revise também os add-ons.

Se algum add-on atualizado não suportar 1.36, selecione uma versão compatível antes de retornar o control plane.

Finalmente:

aws eks update-cluster-version \
  --name production \
  --kubernetes-version 1.36 \
  --region us-east-1

13. Quando usar --force

É possível executar rollback utilizando:

aws eks update-cluster-version \
  --name production \
  --kubernetes-version 1.36 \
  --force \
  --region us-east-1

Mas --force apenas ignora determinados checks de Rollback Insights.

Ele não ignora requisitos rígidos, como:

  • janela de sete dias expirada;
  • cluster criado originalmente na versão atual;
  • rollback de mais de uma minor version;
  • incompatibilidade de determinadas features EKS.

A AWS informa explicitamente que não pode garantir a segurança do rollback quando os checks são ignorados.

Em produção, --force deve ser utilizado como medida excepcional de incidente, não como procedimento padrão.

14. Segurança e FinOps durante o upgrade

O change também é uma oportunidade para revisar:

kubectl get clusterrolebindings
kubectl get rolebindings -A
kubectl get networkpolicy -A

Verifique:

  • RBAC com menor privilégio;
  • ServiceAccounts;
  • IAM Roles for Service Accounts ou EKS Pod Identity;
  • NetworkPolicies;
  • Secrets;
  • Pod Security;
  • seccomp;
  • permissões dos node roles;
  • admission policies.

Do ponto de vista de custo, upgrades de nodes normalmente criam um período de coexistência:

nodes antigos
+
nodes novos

Logo, considere capacidade e custo temporários.

Requests superdimensionados também aumentam o impacto:

requests:
  cpu: "4"
  memory: 8Gi

quando o workload consome, por exemplo:

500m CPU
1.5 GiB RAM

pode obrigar o cluster a provisionar muito mais capacidade do que realmente precisa durante a substituição dos nodes.

O objetivo é equilibrar:

velocidade do rollout
x
capacidade temporária
x
risco de indisponibilidade

15. Troubleshooting

Node não fica Ready

kubectl describe node <node>

kubectl get events -A \
  --sort-by=.metadata.creationTimestamp

Verifique:

AMI
container runtime
kubelet
bootstrap
IAM
VPC CNI
security groups
DNS

Pods presos em ContainerCreating

kubectl describe pod <pod> -n <namespace>

Procure principalmente problemas de:

volume mount
CSI
CNI
Secrets
ConfigMaps
SELinux

Node Group não consegue drenar nodes

kubectl get pdb -A
kubectl describe pdb <pdb> -n <namespace>

Procure PDBs excessivamente restritivos.

DNS

kubectl get pods \
  -n kube-system \
  -l k8s-app=kube-dns

Teste:

kubectl run dns-test \
  --image=busybox:1.36 \
  --restart=Never \
  -- nslookup kubernetes.default.svc.cluster.local

Admission Webhooks

kubectl get validatingwebhookconfigurations
kubectl get mutatingwebhookconfigurations

Controllers como Kyverno, cert-manager e Gatekeeper podem bloquear alterações no cluster mesmo quando o API Server está saudável.

16. Desenvolvimento x produção

Em desenvolvimento pode ser aceitável:

menos réplicas
janela curta
upgrade mais rápido
backup simplificado

Em produção, espere pelo menos:

alta disponibilidade
PodDisruptionBudget
readiness/liveness/startup probes
topology spread
capacity headroom
backup e restore testados
SLOs
smoke tests
bake period
Rollback Readiness
observabilidade
plano de rollback

A diferença principal está na necessidade de diagnóstico e reversibilidade.

17. In-place ou blue/green?

O upgrade in-place funciona bem quando o cluster possui:

  • IaC confiável;
  • staging representativo;
  • boa observabilidade;
  • controllers homologados;
  • automação de testes;
  • backups;
  • procedimento de rollback.

Por outro lado, considere criar um novo cluster quando o upgrade também envolver mudanças profundas como:

nova VPC
novo CNI
troca de Ingress
troca de Service Mesh
nova arquitetura ARM/x86
mudança de sistema operacional
mudança de estratégia de storage
várias versões de Kubernetes

Nesse cenário:

EKS antigo
   ↓
EKS 1.37 novo
   ↓
Deploy
   ↓
Smoke tests
   ↓
Canary
   ↓
Migração de tráfego

O blue/green possui custo temporariamente maior, mas reduz o acoplamento entre upgrade de Kubernetes e mudanças estruturais.

18. Checklist operacional final

Antes

[ ] Cluster atual validado
[ ] Nodes alinhados à versão atual
[ ] Cluster ACTIVE
[ ] Upgrade Insights revisados
[ ] APIs depreciadas analisadas
[ ] CRDs e webhooks validados
[ ] Operators compatíveis com 1.37
[ ] Add-ons compatíveis
[ ] Backup executado
[ ] Restore validado
[ ] PDBs revisados
[ ] Probes revisadas
[ ] Capacidade/IPs disponíveis
[ ] Staging testado
[ ] Baseline de observabilidade registrado

Upgrade

[ ] Control plane → 1.37
[ ] Smoke tests
[ ] Métricas/logs/traces
[ ] Bake period
[ ] Rollback Readiness
[ ] Node Groups progressivamente → 1.37
[ ] Add-ons necessários

Depois

[ ] DNS validado
[ ] Storage validado
[ ] Autoscaling validado
[ ] Controllers reconciliando
[ ] CI/CD funcionando
[ ] SLOs dentro da baseline
[ ] Backlog de componentes antigos registrado

Resumo prático

O upgrade pode ser resumido em:

Preflight
   ↓
Backup
   ↓
Staging
   ↓
Control Plane 1.37
   ↓
Smoke Tests
   ↓
Bake Period
   ↓
Rollback Readiness
   ↓
Nodes
   ↓
Add-ons
   ↓
SLO Validation

Se houver uma regressão:

Nodes ainda 1.36?
      │
      ├── Sim
      │    ↓
      │ Rollback control plane
      │
      └── Não
           ↓
       Rollback nodes
           ↓
       Revisar add-ons
           ↓
       Rollback control plane

Conclusão

Um upgrade de EKS não termina quando a API da AWS retorna Successful.

O processo só pode ser considerado concluído quando aplicações, networking, storage, controllers, autoscaling, observabilidade e SLOs continuam funcionando dentro dos parâmetros esperados.

A possibilidade de rollback para a minor version anterior durante sete dias melhora significativamente a reversibilidade dos upgrades do Amazon EKS, mas não substitui testes, backups ou uma estratégia gradual. Managed Node Groups e add-ons continuam exigindo planejamento independente.

Em uma operação madura de Platform Engineering, o upgrade deixa de ser uma alteração manual e passa a funcionar como um processo repetível:

Compatibilidade → Teste → Upgrade → Observar → Expandir → Validar
                           │
                           └── se necessário → Rollback

Essa abordagem reduz blast radius, melhora troubleshooting e transforma upgrades de Kubernetes em mudanças controladas por evidência, observabilidade e reversibilidade.

Quer aplicar isso no seu ambiente?

Agende uma conversa de 30 minutos sem compromisso. Eu olho o seu cenário e digo por onde começar.

Agendar uma conversa

Receba os novos artigos por e-mail

Um e-mail quando sair artigo novo sobre infraestrutura, backend e IA. Sem spam, cancele quando quiser.