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:
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
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
kubectl vai parar aqui. É uma REST API.Worker Nodes — os trabalhadores
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.
Container → Pod → ReplicaSet → Deployment → Service. Cada camada adiciona uma capacidade nova.
Pod — a unidade básica
Você já sabe que existe. Mas entendendo melhor:
localhost.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.
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.
| Tipo | Quando usar | Exemplo |
|---|---|---|
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
Rede no Kubernetes
Como os pods se encontram e conversam dentro e fora do cluster.
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:
# 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
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.
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
Integrações nativas da AWS
| Componente AWS | Para que serve no EKS |
|---|---|
| IAM | Controle de acesso. Pods podem assumir IAM Roles via IRSA (sem credenciais hardcoded) |
| VPC | Os pods recebem IPs reais da sua VPC (via CNI plugin). Você controla subnets públicas/privadas |
| ALB / NLB | Criados automaticamente quando você aplica um Ingress ou Service type:LoadBalancer |
| ECR | Registry privado para suas imagens Docker. Integração nativa com autenticação IAM |
| CloudWatch | Logs e métricas dos pods. Container Insights para dashboards automáticos |
| Secrets Manager | Injetar secrets do AWS Secrets Manager diretamente nos pods como variáveis de ambiente |
| Karpenter | Autoscaler de nodes mais inteligente que o cluster-autoscaler, nativo para AWS |
IRSA — como seus pods acessam a AWS sem credenciais
eks.amazonaws.com/role-arn: arn:aws:iam::123:role/minha-roleAWS_ACCESS_KEY hardcoded.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
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
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
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
# 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
| Termo | O que é | Analogia |
|---|---|---|
| Cluster | O conjunto de tudo: control plane + nodes | A empresa inteira |
| Node | Uma máquina (EC2) no cluster | Um escritório da empresa |
| Pod | Um ou mais containers rodando juntos | Uma mesa com funcionários |
| Deployment | Gerencia quantas réplicas de um pod existem | O RH que garante N vagas preenchidas |
| Service | IP fixo na frente dos pods, balanceia tráfego | A recepcionista que direciona chamadas |
| Ingress | Roteamento HTTP externo para Services | O porteiro do prédio que sabe onde cada andar fica |
| Namespace | Divisão lógica do cluster | Departamentos da empresa |
| ConfigMap | Configurações não-secretas | Manual de operações público |
| Secret | Dados sensíveis | Cofre com senhas |
| HPA | Autoscaler de pods | Contratação temporária em pico de demanda |
| IRSA | Permissão IAM para pods na AWS | Crachá de acesso por função, sem chave física |
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!