Containers · Kubernetes & EKS

Kubernetes & EKS
Do Zero ao Entendimento

Você já sabe que existem pods. Agora vamos entender tudo ao redor deles: do conceito de Pod ao cluster completo, com Control Plane e Worker Nodes trabalhando juntos. Cobrimos os principais objetos (Deployments, Services, ConfigMaps), a rede interna e o Ingress, as integrações nativas do EKS na AWS (IRSA, node groups) e exemplos práticos de YAML e kubectl para o dia a dia.

Kubernetes do zero

O problema que o Kubernetes resolve

Imagine que você tem uma aplicação em Docker. Ela roda perfeitamente na sua máquina. Mas e quando você precisar de:

📈
Escalar automaticamente
Quando o tráfego sobe, subir mais instâncias. Quando cai, reduzir. Sem intervenção manual.
💀
Recuperar de falhas
Se um container morrer, alguém precisa perceber e subir outro. Quem faz isso sem K8s?
🚀
Deploy sem downtime
Atualizar a versão 1 para v2 sem que os usuários percebam nenhuma interrupção.
🖥️
Múltiplas máquinas
Distribuir os containers entre vários servidores e decidir quem vai para qual máquina.
Definição simples

Kubernetes (K8s) é um orquestrador de containers. Ele pega seus containers Docker e decide: onde rodam, quantas cópias existem, como se comunicam, e o que acontece quando algo dá errado.

A analogia da companhia aérea

Pense assim: seus containers são os passageiros. As máquinas (servidores) são os aviões. O Kubernetes é o sistema de controle do aeroporto — ele sabe quais aviões estão disponíveis, quantas vagas tem cada um, e distribui os passageiros de forma inteligente.

Kubernetes vs Docker — qual a diferença?

🐳 Docker

  • Empacota e roda um container
  • Funciona em uma máquina só
  • Você gerencia manualmente
  • Ótimo para desenvolvimento local
  • docker run minha-app

☸ Kubernetes

  • Orquestra muitos containers
  • Funciona em um cluster de máquinas
  • Gerencia automaticamente
  • Ótimo para produção
  • kubectl apply -f app.yaml
💡 Resumo de uma linha

Docker = roda um container. Kubernetes = gerencia centenas de containers em múltiplas máquinas.

Arquitetura do Kubernetes

Um cluster K8s tem dois tipos de máquinas: o cérebro (Control Plane) e os trabalhadores (Nodes).

┌─────────────────────────────────────────────────────────┐
│                    CLUSTER KUBERNETES                   │
│                                                         │
│  ┌──────────────────────────────────────────────────┐  │
│  │              CONTROL PLANE (o cérebro)           │  │
│  │                                                  │  │
│  │  ┌───────────┐  ┌──────────┐  ┌──────────────┐  │  │
│  │  │ API Server│  │Scheduler │  │   etcd       │  │  │
│  │  │(porta de  │  │(decide   │  │(banco de     │  │  │
│  │  │ entrada)  │  │ onde vai)│  │ dados do K8s)│  │  │
│  │  └───────────┘  └──────────┘  └──────────────┘  │  │
│  │                    ┌─────────────────┐            │  │
│  │                    │ Controller Mgr  │            │  │
│  │                    │(garante estado) │            │  │
│  │                    └─────────────────┘            │  │
│  └──────────────────────────────────────────────────┘  │
│                          │                              │
│          ┌───────────────┼───────────────┐             │
│          ▼               ▼               ▼             │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐  │
│  │   NODE 1     │ │   NODE 2     │ │   NODE 3     │  │
│  │  (máquina)   │ │  (máquina)   │ │  (máquina)   │  │
│  │  ┌────────┐  │ │  ┌────────┐  │ │  ┌────────┐  │  │
│  │  │  Pod   │  │ │  │  Pod   │  │ │  │  Pod   │  │  │
│  │  │ [app]  │  │ │  │ [app]  │  │ │  │  [db]  │  │  │
│  │  └────────┘  │ │  └────────┘  │ │  └────────┘  │  │
│  │  ┌────────┐  │ │  ┌────────┐  │ │              │  │
│  │  │  Pod   │  │ │  │kubelet │  │ │  ┌────────┐  │  │
│  │  │[cache] │  │ │  │(agente)│  │ │  │kubelet │  │  │
│  │  └────────┘  │ │  └────────┘  │ │  │(agente)│  │  │
│  │  kubelet     │ │              │ │  └────────┘  │  │
│  └──────────────┘ └──────────────┘ └──────────────┘  │
└─────────────────────────────────────────────────────────┘
      

Control Plane — o cérebro

🚪
API Server
Único ponto de entrada do cluster. Todo comando kubectl vai parar aqui. É uma REST API.
🗄️
etcd
Banco de dados chave-valor distribuído. Guarda todo o estado do cluster: quais pods existem, em qual nó, qual é o estado desejado.
📅
Scheduler
Quando um novo pod precisa ser criado, o Scheduler decide em qual Node ele vai rodar, baseado em recursos disponíveis (CPU/RAM).
🔁
Controller Manager
Fica em loop perguntando: "o estado atual é igual ao estado desejado?" Se não, age para corrigir. É o guardião da configuração.

Worker Nodes — os trabalhadores

🤖
kubelet
Agente que roda em cada Node. Recebe ordens do Control Plane e garante que os pods estejam rodando corretamente naquela máquina.
🌐
kube-proxy
Gerencia as regras de rede do Node. Permite que os pods se comuniquem entre si e com o mundo externo.
🐳
Container Runtime
Quem realmente roda os containers. Normalmente é o containerd (ou Docker). O K8s não roda containers diretamente.
🔑 Conceito-chave: Estado Desejado vs Estado Atual

O K8s funciona com a ideia de "reconciliação". Você diz o que quer (ex: 3 réplicas da minha app), e o sistema fica eternamente tentando garantir que isso seja verdade. Se um pod morrer, ele sobe outro. Se uma máquina cair, ele move os pods. Isso é o coração do Kubernetes.

Objetos do Kubernetes

Os "blocos de construção" que você vai usar no dia a dia.

Como funciona a hierarquia

Container → Pod → ReplicaSet → Deployment → Service. Cada camada adiciona uma capacidade nova.

Pod — a unidade básica

Você já sabe que existe. Mas entendendo melhor:

📦
O que é
Um Pod é o menor objeto deployável no K8s. Ele agrupa um ou mais containers que compartilham rede e armazenamento.
🌐
Rede compartilhada
Containers dentro do mesmo pod compartilham o mesmo IP e podem se comunicar via localhost.
⚡
Efêmero por natureza
Pods são descartáveis. Quando morrem, não voltam. Por isso você não gerencia pods diretamente — usa Deployments.

Deployment — gerenciador de pods

O objeto que você vai mais usar. Você descreve quantas réplicas do seu pod quer, e o Deployment garante isso.

1
Você cria um Deployment
"Quero 3 réplicas da minha-app:v2"
2
Deployment cria um ReplicaSet
Um ReplicaSet é responsável por manter exatamente N cópias rodando
3
ReplicaSet cria os Pods
3 pods são criados e distribuídos nos Nodes pelo Scheduler
4
Monitoramento contínuo
Se um pod morrer, o ReplicaSet cria outro automaticamente. Sempre 3.
5
Rolling Update
Ao atualizar para v3, o Deployment sobe novos pods antes de derrubar os antigos — zero downtime.

Service — descoberta e balanceamento

Pods têm IPs que mudam o tempo todo (quando morrem e reiniciam). O Service é um IP fixo que fica na frente dos pods e balanceia o tráfego.

TipoQuando usarExemplo
ClusterIP padrão Comunicação interna entre serviços (dentro do cluster) Sua API chamando o banco de dados
NodePort Expor para fora do cluster, via porta no Node Testes locais / ambientes simples
LoadBalancer AWS Expor para internet, cria um LB automaticamente (NLB/ALB na AWS) API pública de produção

Outros objetos importantes

⚙️
ConfigMap
Armazena configurações não-sensíveis (URLs, feature flags) separadas do código. Injetadas como variáveis de ambiente nos pods.
🔐
Secret
Igual ao ConfigMap, mas para dados sensíveis (passwords, tokens, certificados). Armazenado com encoding base64.
🗂️
Namespace
Divisão lógica dentro do cluster. Use para separar ambientes (prod, staging, dev) ou times dentro do mesmo cluster.
📊
HPA
Horizontal Pod Autoscaler. Aumenta ou diminui o número de réplicas automaticamente baseado em CPU/memória ou métricas customizadas.
📁
PersistentVolume
Armazenamento persistente para pods. Ao contrário dos pods, não é efêmero. Usado por bancos de dados.
🚪
Ingress
Roteamento HTTP/HTTPS para dentro do cluster. Um único ponto de entrada que roteia para vários Services por path ou hostname.

Rede no Kubernetes

Como os pods se encontram e conversam dentro e fora do cluster.

A regra fundamental do K8s networking

Todo pod pode se comunicar com qualquer outro pod, em qualquer Node, sem NAT. Cada pod tem seu próprio IP único no cluster.

Fluxo de uma requisição externa

Internet
   │
   ▼
┌─────────────────┐
│   LoadBalancer  │  ← criado pelo Service type:LoadBalancer
│  (AWS NLB/ALB)  │    ou pelo Ingress Controller
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│    Ingress      │  ← roteia por path: /api → svc-api
│   Controller    │                    /web → svc-web
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│    Service      │  ← IP fixo, seleciona pods por label
│  (ClusterIP)    │
└────────┬────────┘
         │  (balanceia entre as réplicas)
    ┌────┴────┐
    ▼         ▼
┌──────┐  ┌──────┐
│ Pod  │  │ Pod  │  ← pods com label app=minha-api
│  #1  │  │  #2  │
└──────┘  └──────┘
      

DNS interno — como pods se encontram

O K8s tem um DNS interno (CoreDNS). Cada Service ganha automaticamente um nome DNS no formato:

DNS — formato do Service
# Formato completo
nome-do-service.namespace.svc.cluster.local

# Exemplos práticos
minha-api.production.svc.cluster.local
postgres.default.svc.cluster.local

# Dentro do mesmo namespace, pode abreviar
minha-api        # funciona!
postgres:5432    # funciona!

Ingress — roteamento HTTP

O Ingress é um objeto que define regras de roteamento HTTP. Mas ele precisa de um Ingress Controller para funcionar (ex: nginx, AWS ALB Controller).

Ingress Rules:
  host: api.meudominio.com
    /v1/*   → service: api-svc, port: 8080
    /admin  → service: admin-svc, port: 9090

  host: web.meudominio.com
    /*      → service: web-svc, port: 3000
      
Na AWS com EKS

Você pode usar o AWS Load Balancer Controller que faz Ingress virar um ALB automaticamente, com suporte a HTTPS (ACM), regras por path, autenticação via Cognito/OIDC, e muito mais.

Amazon EKS

Kubernetes gerenciado pela AWS — sem precisar operar o Control Plane.

O que a AWS faz por você no EKS

A AWS opera e escala o Control Plane (API Server, etcd, Scheduler...). Você não vê essas máquinas, não paga por elas separadamente (paga $0.10/hora pelo cluster), e a AWS garante alta disponibilidade do cérebro do cluster.

K8s puro vs EKS

☸ Kubernetes puro (self-managed)

  • Você instala e mantém o Control Plane
  • Você atualiza o etcd, API Server...
  • Você cuida do backup do etcd
  • Você garante HA do Control Plane
  • Mais controle, mais trabalho

☁️ EKS (managed)

  • AWS opera o Control Plane
  • Atualizações com um clique
  • etcd gerenciado automaticamente
  • HA garantida pela AWS (multi-AZ)
  • Integração nativa com IAM, VPC, ALB...

Tipos de Node no EKS

🔧
Managed Node Groups
EC2s gerenciadas pela AWS. A AWS cuida do provisionamento, update e termination dos nodes. Você define o tipo de instância e o autoscaling.
⚡
Fargate
Serverless. Sem EC2, sem gerenciar nodes. Cada pod recebe seus próprios recursos dedicados. Você paga por CPU/RAM por segundo do pod.
🛠️
Self-managed Nodes
EC2s que você mesmo provisiona e registra no cluster. Máximo de controle, máximo de responsabilidade.

Integrações nativas da AWS

Componente AWSPara que serve no EKS
IAMControle de acesso. Pods podem assumir IAM Roles via IRSA (sem credenciais hardcoded)
VPCOs pods recebem IPs reais da sua VPC (via CNI plugin). Você controla subnets públicas/privadas
ALB / NLBCriados automaticamente quando você aplica um Ingress ou Service type:LoadBalancer
ECRRegistry privado para suas imagens Docker. Integração nativa com autenticação IAM
CloudWatchLogs e métricas dos pods. Container Insights para dashboards automáticos
Secrets ManagerInjetar secrets do AWS Secrets Manager diretamente nos pods como variáveis de ambiente
KarpenterAutoscaler de nodes mais inteligente que o cluster-autoscaler, nativo para AWS

IRSA — como seus pods acessam a AWS sem credenciais

1
Você cria uma IAM Role com uma trust policy
A trust policy permite que um ServiceAccount do K8s assuma essa Role
2
Você anota o ServiceAccount com o ARN da Role
eks.amazonaws.com/role-arn: arn:aws:iam::123:role/minha-role
3
O pod usa esse ServiceAccount
O EKS injeta um token JWT no pod automaticamente
4
SDK da AWS troca o JWT por credenciais temporárias
Via STS AssumeRoleWithWebIdentity. O pod acessa S3, DynamoDB, etc. sem nenhum AWS_ACCESS_KEY hardcoded.
🔑 IRSA é essencial para produção

Nunca passe AWS_ACCESS_KEY_ID como variável de ambiente no pod. Use IRSA — é mais seguro, as credenciais são temporárias e rotacionadas automaticamente.

YAML na prática

Como tudo isso se traduz em código real.

Deployment completo anotado

YAML
apiVersion: apps/v1           # versão da API do K8s para este objeto
kind: Deployment              # tipo do objeto
metadata:
  name: minha-api
  namespace: production
spec:
  replicas: 3                   # quero 3 cópias rodando
  selector:
    matchLabels:
      app: minha-api            # este Deployment gerencia pods com esse label
  template:                      # template dos pods que serão criados
    metadata:
      labels:
        app: minha-api
    spec:
      serviceAccountName: minha-api-sa  # para IRSA
      containers:
      - name: app
        image: 123.dkr.ecr.us-east-1.amazonaws.com/minha-api:v2
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:              # busca de um Secret do K8s
              name: db-secrets
              key: url
        resources:                      # SEMPRE defina limites!
          requests:
            cpu: "100m"               # 0.1 vCPU garantido
            memory: "256Mi"
          limits:
            cpu: "500m"               # máximo 0.5 vCPU
            memory: "512Mi"
        readinessProbe:                 # K8s só manda tráfego quando estiver pronto
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5

Service

YAML
apiVersion: v1
kind: Service
metadata:
  name: minha-api-svc
  namespace: production
spec:
  type: ClusterIP             # apenas interno — use LoadBalancer para expor
  selector:
    app: minha-api            # encaminha tráfego para pods com esse label
  ports:
  - port: 80                  # porta que outros serviços chamam
    targetPort: 8080          # porta que o container escuta

HPA — autoscaling automático

YAML
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: minha-api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: minha-api
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70   # escala quando CPU > 70%

Comandos kubectl essenciais

BASH
# Aplicar qualquer YAML
kubectl apply -f meu-deploy.yaml

# Ver pods rodando
kubectl get pods -n production

# Ver logs de um pod
kubectl logs -f minha-api-abc123 -n production

# Entrar no shell de um pod
kubectl exec -it minha-api-abc123 -n production -- /bin/sh

# Ver eventos do cluster (ótimo para debug)
kubectl get events -n production --sort-by=.lastTimestamp

# Descrever um pod (ver por que não está subindo)
kubectl describe pod minha-api-abc123 -n production

# Escalar manualmente
kubectl scale deployment minha-api --replicas=5 -n production

# Ver uso de CPU/RAM dos pods
kubectl top pods -n production

Mapa Mental — tudo junto

Como as peças se encaixam no seu contexto de arquitetura AWS.

                          INTERNET
                             │
                        ┌────┴────┐
                        │  ALB    │ ← criado pelo AWS LB Controller
                        └────┬────┘
                             │
                    ┌────────┴────────┐
                    │  Ingress (K8s)  │
                    │ /api → svc-api  │
                    └────────┬────────┘
                             │
              ┌──────────────┼──────────────┐
              │              │              │
        ┌─────┴─────┐  ┌─────┴─────┐  ┌────┴──────┐
        │  Service  │  │  Service  │  │  Service  │
        │ supervisor│  │  agents   │  │   bffs    │
        └─────┬─────┘  └─────┬─────┘  └────┬──────┘
              │              │              │
        ┌─────┴──────┐  ┌────┴───────┐  ┌──┴────────┐
        │ Deployment │  │ Deployment │  │ Deployment│
        │ (LangGraph)│  │(Specialists│  │  (BFFs)   │
        │ 2 réplicas │  │) 3 réplicas│  │ 2 réplicas│
        └─────┬──────┘  └────┬───────┘  └──┬────────┘
              │              │              │
              └──────────────┼──────────────┘
                             │
                      REDIS (ElastiCache)
                   memória de sessão / checkpointer

Cada Deployment:
  • usa ServiceAccount com IRSA (acesso IAM sem credenciais)
  • tem ConfigMap com configs não-sensíveis
  • tem Secrets para tokens/passwords
  • tem HPA para autoscaling
  • tem readinessProbe para zero-downtime deploys
      

Glossário rápido

TermoO que éAnalogia
ClusterO conjunto de tudo: control plane + nodesA empresa inteira
NodeUma máquina (EC2) no clusterUm escritório da empresa
PodUm ou mais containers rodando juntosUma mesa com funcionários
DeploymentGerencia quantas réplicas de um pod existemO RH que garante N vagas preenchidas
ServiceIP fixo na frente dos pods, balanceia tráfegoA recepcionista que direciona chamadas
IngressRoteamento HTTP externo para ServicesO porteiro do prédio que sabe onde cada andar fica
NamespaceDivisão lógica do clusterDepartamentos da empresa
ConfigMapConfigurações não-secretasManual de operações público
SecretDados sensíveisCofre com senhas
HPAAutoscaler de podsContratação temporária em pico de demanda
IRSAPermissão IAM para pods na AWSCrachá de acesso por função, sem chave física
🎯 Próximos passos recomendados

1. Instale o kubectl e o eksctl localmente. 2. Crie um cluster EKS de teste com eksctl create cluster. 3. Faça deploy de uma app simples com Deployment + Service. 4. Adicione um Ingress com AWS LB Controller. 5. Configure IRSA para acesso ao S3 ou DynamoDB. Aí o resto é prática!