Dev.to WebDev 🛠 Dev 👁 1 📖 11 min read

Amazon EKS na prática: arquitetura, funcionamento e boas práticas

Introdução: o que é o EKS e por que usar Rodar Kubernetes por conta própria exige manter etcd, API server, scheduler e controllers em alta disponibilidade, aplicar patches e fazer upgrades sem derrubar nada. O EKS tira

Amazon EKS na prática: arquitetura, funcionamento e boas práticas

Introdução: o que é o EKS e por que usar

Rodar Kubernetes por conta própria exige manter etcd, API server, scheduler e controllers em alta disponibilidade, aplicar patches e fazer upgrades sem derrubar nada. O EKS tira esse peso das suas costas: o control plane é gerenciado, distribuído em várias Zonas de Disponibilidade e atualizado pela AWS.

O EKS roda Kubernetes upstream e é certificado como conforme, então manifests, Helm charts e ferramentas do ecossistema funcionam sem adaptação. A diferença está na integração com a AWS: IAM, VPC, ELB, EBS/EFS, CloudWatch, ECR e Secrets Manager.

Por que adotar o EKS:

  • Alta disponibilidade do control plane, com SLA de 99,95% da AWS.
  • Integração nativa com IAM, VPC, Load Balancers e observabilidade.
  • Ecossistema Kubernetes: Helm, ArgoCD, Prometheus, Istio e operadores.
  • Flexibilidade de compute: EC2, Fargate, Spot e Karpenter.
  • Portabilidade: o mesmo manifest roda em outro Kubernetes, com menos lock-in.

O ponto de atenção é a complexidade. Para uma aplicação simples em containers, ECS pode ser suficiente. O EKS compensa quando há muitos serviços, necessidade de portabilidade, um ecossistema Kubernetes já adotado ou requisitos avançados de rede e escalabilidade.

Arquitetura do cluster: control plane e data plane

Um cluster EKS se divide em duas partes: o control plane, que a AWS gerencia, e o data plane, onde seus pods rodam.

Control plane (gerenciado pela AWS). Roda em uma VPC da própria AWS, separada da sua conta, e inclui:

  • API server: ponto de entrada de todo kubectl e de todos os componentes. Pode ter endpoint público, privado ou ambos.
  • etcd: banco chave-valor com o estado do cluster, replicado em três Zonas de Disponibilidade.
  • Scheduler: decide em qual nó cada pod vai rodar.
  • Controller manager: reconcilia o estado desejado com o estado real.

A AWS provisiona ao menos duas instâncias de API server e três de etcd em AZs diferentes e substitui automaticamente as que falharem. A comunicação com seus nós passa por ENIs (Elastic Network Interfaces) criadas nas suas subnets.

Data plane (sob sua responsabilidade). São os nós dentro da sua VPC. Em cada nó rodam:

  • kubelet: agente que mantém os pods no estado desejado.
  • kube-proxy: mantém as regras de rede que implementam os Services.
  • containerd: o container runtime.
  • VPC CNI: plugin que dá a cada pod um IP real da VPC.

Add-ons gerenciados. O EKS instala e atualiza componentes essenciais como add-ons: VPC CNI, CoreDNS, kube-proxy, EBS CSI Driver e o Pod Identity Agent.

O caminho de um deploy:

  1. O usuário ou o pipeline executa kubectl apply ou um deploy via Helm.
  2. A requisição chega ao API server, autenticada via IAM e autorizada via RBAC.
  3. O manifest é gravado no etcd.
  4. O scheduler escolhe um nó para o pod.
  5. O kubelet do nó puxa a imagem do ECR e inicia o container.
  6. O VPC CNI atribui um IP da VPC ao pod, e o kube-proxy atualiza as regras do Service.

Modelos de compute: managed node groups, Fargate e Karpenter

O EKS oferece formas diferentes de prover capacidade, e é comum combiná-las no mesmo cluster.

Managed node groups são a escolha padrão. A AWS cria as instâncias EC2 num Auto Scaling Group, usa AMIs otimizadas (Amazon Linux 2023 ou Bottlerocket) e faz upgrades com drenagem controlada dos nós. Indicado para cargas gerais, quando você quer controle sobre o tipo de instância. Em contrapartida, você dimensiona os grupos e escolhe as instâncias.

AWS Fargate roda cada pod em seu próprio ambiente isolado, sem nós para administrar. Você define quais pods usam Fargate por meio de Fargate profiles (namespace + labels). Indicado para cargas esporádicas ou com isolamento por pod. Limitações: não suporta DaemonSets nem GPU, e o custo por vCPU costuma ser maior.

Karpenter observa pods em estado Pending, escolhe a instância mais adequada ao pedido de CPU e memória e a cria em segundos. Também consolida nós subutilizados e remove os ociosos. Indicado para eficiência de custo, uso de Spot e diversidade de instâncias. Exige configurar NodePools e EC2NodeClasses.

Self-managed nodes deixam toda a operação com você: indicados só para casos especiais, como AMI customizada.

O EKS Auto Mode vai além e automatiza o gerenciamento de compute, rede e armazenamento para você.

Rede: VPC CNI, subnets, Services e Ingress

No EKS, cada pod recebe um IP real da VPC, sem overlay nem encapsulamento. Isso é feito pelo plugin Amazon VPC CNI e é o que torna a rede do EKS diferente da maioria dos clusters Kubernetes. O diagrama mostra um cluster em duas AZs (sa-east-1a e sa-east-1b), com um worker node por AZ.

Topologia da VPC

  • Subnets públicas (10.0.0.0/24 e 10.0.1.0/24): abrigam o Application Load Balancer e os NAT Gateways, com saída pelo Internet Gateway.
  • Subnets privadas (10.0.32.0/19 e 10.0.64.0/19): abrigam os worker nodes e os pods. Os /19 oferecem milhares de IPs, o que importa porque cada pod consome um.
  • Route tables privadas: tráfego local para 10.0.0.0/16 e 0.0.0.0/0 pelo NAT Gateway da mesma AZ.
  • ENIs do control plane: o EKS cria interfaces cross-account nas suas subnets para que o API server converse com o kubelet (porta 10250) e os nós com a API (443).

Como o VPC CNI funciona. Cada worker node tem uma ENI primária (eth0) e ENIs secundárias (eth1…) com IPs reservados para pods, o warm pool. Quando um pod é agendado, o plugin aws-node entrega um desses IPs, cria o par veth e adiciona uma rota /32 no namespace de rede do host. O número máximo de pods por nó depende do tipo da instância: ENIs × IPs por ENI. Quando isso limita, a prefix delegation atribui blocos /28 por ENI e aumenta bastante a densidade.

Os sete fluxos de comunicação do diagrama:

  1. Entrada: Internet → IGW → ALB nas subnets públicas → direto no IP do pod. Isso é possível porque o AWS Load Balancer Controller usa target-type: ip, sem passar por NodePort.
  2. Pod ↔ pod no mesmo nó: via veth e rotas /32 no host. O tráfego não sai do nó.
  3. Pod ↔ pod entre nós ou AZs: sai pela ENI e é roteado nativamente pela VPC, sem encapsulamento.
  4. Saída para a internet: pod → NAT Gateway → IGW, com SNAT para o Elastic IP.
  5. Serviços AWS: ECR, S3, STS e CloudWatch Logs via VPC Endpoints, com credenciais por IRSA ou Pod Identity.
  6. Control plane: o kubelet fala com a API pelas ENIs cross-account, e o kubectl de dev ou CI/CD usa o endpoint público ou privado na porta 443.
  7. Services e DNS: o pod acessa o ClusterIP (172.20.0.0/16), o kube-proxy faz DNAT para os IPs reais dos pods, e o CoreDNS resolve *.svc.cluster.local.

Services, Ingress e segurança de rede. Os Services são IPs virtuais: o ClusterIP não existe na VPC, só nas regras de iptables ou IPVS gravadas pelo kube-proxy. Para expor ao mundo, o AWS Load Balancer Controller transforma um Ingress em ALB (HTTP/HTTPS) e um Service do tipo LoadBalancer em NLB (TCP/UDP). A segurança de rede opera em três camadas:

  • Security Groups do nó e do cluster, no nível da VPC.
  • Security Groups for Pods (opcional), que aplicam SGs diretamente a pods específicos.
  • Network Policies, via VPC CNI ou Calico, para regras entre pods dentro do cluster.

Segurança e identidade: IAM, IRSA, Pod Identity e RBAC

O EKS usa duas camadas de controle: o IAM decide quem é você na AWS, e o RBAC do Kubernetes decide o que você pode fazer dentro do cluster.

Acesso ao cluster. As pessoas e pipelines se autenticam com IAM e são mapeados a permissões do Kubernetes. O mecanismo moderno são as EKS Access Entries, que substituem o antigo ConfigMap aws-auth: você associa um principal IAM a uma access policy ou a grupos RBAC, tudo pela API da AWS e versionável em Terraform.

Acesso dos pods à AWS. Pods não devem usar as credenciais do nó, porque todos os pods do nó herdariam as mesmas permissões. Há dois mecanismos para dar a cada workload um papel IAM próprio:

  • IRSA (IAM Roles for Service Accounts): usa o provedor OIDC do cluster e uma ServiceAccount anotada com o ARN da role. Boa escolha para clusters existentes e ampla compatibilidade.
  • EKS Pod Identity: add-on com agente no nó, associação feita pela API do EKS, sem OIDC por cluster. Indicado para novos clusters, com gestão mais simples e roles reutilizáveis entre clusters.

Em ambos os casos vale o princípio do menor privilégio: uma role por aplicação, com apenas as ações que ela precisa.

Boas práticas de segurança:

  • Endpoint privado do API server, ou público restrito por CIDR.
  • Nós em subnets privadas, com acesso à AWS por VPC Endpoints.
  • Secrets no AWS Secrets Manager, montados via Secrets Store CSI Driver, e criptografia de envelope com KMS.
  • Pod Security Standards para impedir containers privilegiados.
  • Network Policies para restringir comunicação entre namespaces.
  • Imagens do ECR com scan habilitado.
  • Audit logs do control plane enviados ao CloudWatch.

Integrando o EKS ao banco: exemplo com RDS

Bancos de dados raramente rodam dentro do cluster: o padrão é usar um serviço gerenciado como o Amazon RDS numa subnet de banco separada e deixar os pods se conectarem a ele pela rede da VPC.

  • Security Groups: o SG do banco libera a porta (5432 no PostgreSQL) apenas para o SG dos nós ou, com Security Groups for Pods, apenas para o SG dos pods da aplicação.
  • Endpoint estável: a aplicação usa o endpoint DNS do RDS, guardado num ConfigMap ou num Service do tipo ExternalName. Assim o nome interno fica independente do endpoint real.
  • Credenciais: usuário e senha no Secrets Manager, lidos pelo pod com IRSA ou Pod Identity, sem senha em manifest.

Observabilidade, escalabilidade e custos

Observabilidade. Um cluster em produção precisa de logs, métricas e traces:

  • Logs do control plane (api, audit, authenticator, controllerManager, scheduler): habilitados por cluster e enviados ao CloudWatch Logs.
  • Container Insights: métricas de CPU, memória e rede por nó, pod e namespace.
  • Prometheus e Grafana: o Amazon Managed Service for Prometheus e o Amazon Managed Grafana evitam operar essa stack.
  • Traces: OpenTelemetry com AWS X-Ray ou outro backend compatível.
  • Alarmes: pods em CrashLoopBackOff, nós NotReady e falhas de agendamento.

Escalabilidade. Há três níveis de escala, e eles trabalham juntos:

  1. HPA (Horizontal Pod Autoscaler): ajusta o número de réplicas por CPU, memória ou métricas customizadas.
  2. Karpenter ou Cluster Autoscaler: adiciona ou remove nós conforme pods pendentes ou capacidade ociosa.
  3. KEDA: escala por eventos externos, como o tamanho de uma fila SQS.

Defina sempre requests e limits de recursos: sem eles o scheduler decide às cegas, e o HPA por utilização não funciona.

Custos. O custo do EKS tem três componentes: a taxa fixa por hora do cluster, as instâncias EC2 ou o Fargate, e itens associados como NAT Gateway, load balancers, transferência entre AZs e volumes EBS. Para reduzir:

  • Spot para cargas tolerantes a interrupção.
  • Karpenter com consolidação de nós.
  • Graviton para muitas cargas, com bom custo-benefício.
  • VPC Endpoints para reduzir o tráfego pelo NAT Gateway.
  • Right-sizing de requests, com VPA ou Goldilocks.
  • Manter o cluster em versão suportada: versões antigas entram em suporte estendido, cobrado a mais.

Provisionando com Terraform e fazendo deploy com GitHub Actions

Em produção o cluster deve ser código: versionado, revisado e reproduzível.

Terraform. O caminho mais comum é o módulo terraform-aws-modules/eks/aws junto com o módulo de VPC. O exemplo é um esqueleto: confira versões e parâmetros na documentação dos módulos.

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  name    = "eks-vpc"
  cidr    = "10.0.0.0/16"
  azs     = ["sa-east-1a", "sa-east-1b"]

  public_subnets  = ["10.0.0.0/24", "10.0.1.0/24"]
  private_subnets = ["10.0.32.0/19", "10.0.64.0/19"]

  enable_nat_gateway = true
}

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  name    = "meu-cluster"

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  endpoint_public_access = true

  eks_managed_node_groups = {
    default = {
      instance_types = ["m6i.large"]
      min_size       = 2
      max_size       = 6
      desired_size   = 2
    }
  }
}

Boas práticas: state remoto em S3 com lock, módulos com versão fixa e plano revisado em pull request antes do apply.

GitHub Actions. O pipeline típico faz build da imagem, publica no ECR e atualiza o Deployment. Use OIDC entre o GitHub e a AWS, sem chaves de longa duração guardadas como secret.

name: deploy
on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::<conta>:role/github-deploy
          aws-region: sa-east-1
      - uses: aws-actions/amazon-ecr-login@v2
        id: ecr
      - name: Build e push
        run: |
          IMAGE=${{ steps.ecr.outputs.registry }}/api:${{ github.sha }}
          docker build -t $IMAGE .
          docker push $IMAGE
      - name: Deploy
        run: |
          aws eks update-kubeconfig --name meu-cluster
          kubectl set image deployment/api api=$IMAGE
          kubectl rollout status deployment/api

A role do pipeline recebe acesso ao cluster por uma Access Entry. Em ambientes maiores, vale considerar GitOps com ArgoCD ou Flux, em que o cluster puxa o estado desejado do Git.

Boas práticas e conclusão

O EKS entrega um control plane confiável e deixa para você as decisões que definem a qualidade da operação: rede, identidade, compute e observabilidade. Checklist de produção:

  • Cluster em pelo menos duas AZs, com nós em subnets privadas.
  • Subnets com IPs suficientes para os pods (CIDR /19 ou maior, ou prefix delegation).
  • Add-ons gerenciados (VPC CNI, CoreDNS, kube-proxy, EBS CSI) atualizados.
  • Access Entries para pessoas e pipelines, e IRSA ou Pod Identity para pods, sempre com menor privilégio.
  • Endpoint do API server restrito, secrets fora do etcd e criptografia com KMS.
  • Requests e limits em todos os workloads, com HPA e Karpenter ou Cluster Autoscaler.
  • PodDisruptionBudgets e topologySpreadConstraints para sobreviver a upgrades e falhas de AZ.
  • Logs do control plane, Container Insights e alarmes configurados.
  • Infraestrutura em Terraform e deploys por pipeline com OIDC ou GitOps.
  • Upgrades de versão planejados, um minor por vez, testados antes em ambiente não produtivo.

O EKS não é o caminho mais simples para rodar containers, mas é um dos mais completos quando o objetivo é um ambiente padronizado, seguro e escalável. Entender a arquitetura, em especial a rede baseada em ENIs e IPs reais da VPC, é o que separa um cluster que apenas funciona de um que se opera com previsibilidade.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.