Migrar o Kubernetes compartilhado para AWS EKS

TLDR: Substituir o cluster Kubernetes gerido pela DigitalOcean por um EKS na conta AWS shared, com a VPC compartilhada entre as contas da Organization via RAM e o ECR como registry de container.

Contexto

O cluster Kubernetes compartilhado rodava na DigitalOcean. A migração para EKS na conta shared (AWS Organizations) habilita VPC compartilhada com as outras contas via AWS Resource Access Manager (RAM), ECR como registry, e rede AWS-nativa consistente em todos os projetos.

A migração é um cutover direto, não blue/green, por urgência. Janela de indisponibilidade aceita.

Objetivos

  • VPC compartilhada na conta shared, com RAM habilitado para as contas da Organization.
  • Cluster EKS com node pools equivalentes: um geral e um dedicado ao gateway, com taint.
  • Migrar todos os Helm releases: ingress-nginx, cert-manager, metrics-server.
  • Migrar o RBAC (ClusterRoles, ServiceAccounts — reaproveitados, são agnósticos de provedor).
  • Repositórios ECR para todos os serviços ativos, e pipelines de CI/CD dando push nele.
  • Manter os nomes dos outputs de remote state, com valores novos, para que todo projeto consumidor pegue o cluster novo automaticamente no próximo apply.

Fora de escopo

  • Migração do Datadog — adiada para um follow-up.
  • Descomissionar o cluster antigo: só depois de 24h estável, em spec própria.

Mudanças

Novo: src/stacks/shared/network/terraform/ (VPC AWS)

aws_vpc, subnets pública e privada multi-AZ, IGW, NAT gateway, route tables, mais aws_ram_resource_share + aws_ram_resource_association para compartilhar as subnets com as contas da Organization. Outputs: vpc_id, private_subnet_ids, public_subnet_ids.

Modificado: src/stacks/shared/kubernetes/terraform/

Arquivo Mudança
versions.tf remove o provider da DigitalOcean, adiciona hashicorp/aws ~> 5.0
main.tf cluster gerido substituído por aws_eks_cluster + aws_iam_role (cluster e node) + dois aws_eks_node_group (geral e gateway com taint)
providers.tf contexto dos providers kubernetes/helm/kubectl vindo do aws eks update-kubeconfig
variables.tf remove as variáveis do provedor antigo; adiciona aws_region, eks_cluster_version, eks_cluster_name
data.tf remote state passa a apontar para a VPC AWS
outputs.tf mesmos nomes: kubernetes_cluster_endpoint, kubernetes_cluster_token, kubernetes_cluster_ca_certificate, kubernetes_cluster_id, ingress_loadbalancer_ip
rbac.tf, helm.tf sem mudança de lógica — só o contexto de kubeconfig

Novo: src/stacks/shared/ecr/terraform/

Um aws_ecr_repository por serviço ativo, política de lifecycle mantendo as 10 últimas imagens, outputs com a URL de cada repositório.

Makefiles, scripts e CI

  • shared.network.{plan,apply} e shared.ecr.{plan,apply}; targets de kubernetes apontando para os scripts novos.
  • Scripts network/{deploy,status}.sh, ecr/deploy.sh; o kubernetes/deploy.sh troca o save de kubeconfig pelo aws eks update-kubeconfig.
  • Pipelines: push para ECR em vez do registry antigo; referência de imagem passa a <account_id>.dkr.ecr.<region>.amazonaws.com/<app>.

Ordem de deploy

  1. shared.network.apply — VPC + RAM
  2. shared.ecr.apply — repositórios
  3. shared.kubernetes.apply — cluster + RBAC + Helm
  4. aws eks update-kubeconfig --name <cluster> local
  5. Aplicar os overlays de kustomize por projeto (redeploy dos workloads)
  6. Apontar o DNS no Cloudflare para o IP do ingress novo (TTL baixado para 60s antes do cutover)
  7. terraform apply em cada projeto consumidor, para pegar os valores novos de remote state
  8. Descomissionar o cluster antigo após 24h estável

Como verificar

  • kubectl get nodes no contexto novo mostra todos os node groups saudáveis.
  • kubectl get pods -A mostra ingress-nginx, cert-manager e metrics-server rodando.
  • O ingress de cada projeto resolve pelo IP do load balancer novo.
  • Certificado TLS emitido pelo Let’s Encrypt (ClusterIssuer do cert-manager ativo).
  • O pipeline de pelo menos um projeto dá push no ECR e deploya com sucesso.
  • terraform output num projeto consumidor devolve o endpoint do EKS.

Documentação