O Docker resolve o problema de empacotar e executar uma aplicação em um único container. O Docker Compose resolve o problema de orquestrar múltiplos containers em uma única máquina. Mas quando a aplicação cresce além de uma máquina — quando são necessários dezenas de instâncias distribuídas em múltiplos servidores, com failover automático, atualizações sem downtime e escala dinâmica baseada em demanda — uma nova categoria de problema emerge: a orquestração de containers em escala.
O Kubernetes — frequentemente abreviado como K8s — é o sistema de orquestração de containers que se tornou o padrão da indústria para gerenciar cargas de trabalho containerizadas em ambientes de produção. Originado no Google, que orquestrou containers em escala por mais de uma década antes de abrir o projeto, o Kubernetes foi doado à Cloud Native Computing Foundation em 2014 e desde então se tornou o projeto de infraestrutura de código aberto mais ativo do mundo.
A proposta central do Kubernetes é declarativa: o engenheiro descreve o estado desejado do sistema — "quero cinco réplicas desta aplicação, cada uma com 512MB de memória, acessíveis pela porta 80" — e o Kubernetes trabalha continuamente para garantir que o estado real corresponde ao declarado. Se um container morre, o Kubernetes inicia um novo. Se um nó falha, as cargas de trabalho são reagendadas em nós saudáveis. Se o tráfego aumenta, novas réplicas são criadas automaticamente.
Arquitetura do Kubernetes
Um cluster Kubernetes é composto por dois tipos de máquinas com responsabilidades distintas.
O Plano de Controle
O plano de controle é o cérebro do cluster — o conjunto de componentes que gerencia o estado desejado e toma decisões sobre o cluster.
kube-apiserver — o único ponto de entrada para todas as operações no cluster. Toda comunicação — do kubectl, dos outros componentes do plano de controle, dos agentes nos nós — passa pela API. É stateless e pode ser escalado horizontalmente.
etcd — o banco de dados distribuído de chave-valor que armazena todo o estado do cluster. É o componente mais crítico — perder o etcd sem backup significa perder o cluster inteiro. Em produção, o etcd é executado em um cluster de três ou cinco instâncias para tolerância a falhas.
kube-scheduler — observa pods recém-criados que ainda não têm um nó atribuído e seleciona o nó mais adequado baseado em recursos disponíveis, afinidades, taints e tolerations.
kube-controller-manager — executa os controladores que implementam a lógica de reconciliação. O controlador de réplicas garante que o número correto de pods está em execução. O controlador de endpoints atualiza a lista de IPs nos Services. O controlador de jobs garante que jobs completam com sucesso.
Os Nós Worker
Os nós worker são as máquinas que executam as cargas de trabalho — os containers da aplicação.
kubelet — o agente que roda em cada nó. Recebe especificações de pods do kube-apiserver e garante que os containers descritos estão rodando e saudáveis. Reporta o estado dos containers de volta ao plano de controle.
kube-proxy — mantém as regras de rede em cada nó, implementando o conceito de Services — abstrações que expõem um conjunto de pods como um endpoint de rede estável.
Container Runtime — o software que executa os containers. O Kubernetes suporta qualquer runtime compatível com a CRI — Container Runtime Interface. O containerd é o runtime padrão na maioria das distribuições modernas.
┌─────────────────────────────────────────────────────────────┐
│ PLANO DE CONTROLE │
│ │
│ ┌──────────────┐ ┌──────┐ ┌────────────┐ ┌──────────┐ │
│ │ kube-apiserver│ │ etcd │ │ scheduler │ │controller│ │
│ └──────────────┘ └──────┘ └────────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │
┌──────┴──────┐ ┌─────┴──────┐
│ NÓ 1 │ │ NÓ 2 │
│ │ │ │
│ kubelet │ │ kubelet │
│ kube-proxy │ │ kube-proxy │
│ │ │ │
│ ┌─────────┐ │ │ ┌────────┐ │
│ │ Pod A │ │ │ │ Pod B │ │
│ │ Pod C │ │ │ │ Pod D │ │
│ └─────────┘ │ │ └────────┘ │
└─────────────┘ └────────────┘
Instalando um Cluster Local com kind
Para aprendizado e desenvolvimento local, o kind (Kubernetes in Docker) cria um cluster Kubernetes completo usando containers Docker como nós — sem precisar de máquinas virtuais:
# Instala o kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
# Instala o kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/kubectl
# Cria um cluster com configuração personalizada
cat > kind-config.yml << 'EOF'
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker
- role: worker
EOF
kind create cluster --config kind-config.yml --name meu-cluster
# Verifica que o cluster está funcionando
kubectl cluster-info
kubectl get nodes
Os Objetos Fundamentais do Kubernetes
O Kubernetes é operado inteiramente através de objetos — recursos declarados em arquivos YAML que descrevem o estado desejado do sistema. Cada objeto tem quatro campos obrigatórios: apiVersion, kind, metadata e spec.
Pod: A Unidade Atômica
O Pod é o objeto mais básico do Kubernetes — um grupo de um ou mais containers que compartilham o mesmo namespace de rede e podem compartilhar volumes. Containers dentro de um pod se comunicam via localhost.
Na prática, pods raramente são criados diretamente. Eles são gerenciados por objetos de nível superior — Deployments, StatefulSets, Jobs — que garantem que o número correto de pods está sempre em execução.
# pod.yml — apenas para entender a estrutura; use Deployments em produção
apiVersion: v1
kind: Pod
metadata:
name: minha-api
namespace: default
labels:
app: minha-api
versao: "1.5.0"
spec:
containers:
- name: api
image: ghcr.io/minha-empresa/minha-api:1.5.0
ports:
- containerPort: 3000
protocol: TCP
env:
- name: NODE_ENV
value: production
- name: PORT
value: "3000"
resources:
requests: # Mínimo garantido pelo scheduler
memory: "128Mi"
cpu: "100m" # 100 millicores = 0.1 CPU
limits: # Máximo permitido
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
restartPolicy: Always
Deployment: Gerenciando Réplicas com Atualizações Controladas
O Deployment é o objeto mais usado para cargas de trabalho stateless. Ele gerencia um ReplicaSet — que por sua vez gerencia os pods — e orquestra atualizações com estratégias de rollout configuráveis:
# deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: minha-api
namespace: producao
labels:
app: minha-api
annotations:
kubernetes.io/change-cause: "Deploy versão 1.5.0 — feature: checkout redesign"
spec:
replicas: 3
selector:
matchLabels:
app: minha-api
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Máximo de pods extras durante atualização
maxUnavailable: 0 # Zero pods indisponíveis — zero downtime
template:
metadata:
labels:
app: minha-api
versao: "1.5.0"
spec:
# Distribui pods entre nós diferentes para resiliência
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: minha-api
# Graceful shutdown — aguarda conexões ativas terminarem
terminationGracePeriodSeconds: 30
containers:
- name: api
image: ghcr.io/minha-empresa/minha-api:1.5.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
- name: PORT
value: "3000"
# Injeta variáveis de ambiente a partir de Secrets
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: minha-api-secrets
key: database-url
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: minha-api-secrets
key: redis-url
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
# Garante que o processo recebe SIGTERM ao terminar
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"]
# Contexto de segurança — sem root
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
# Volume para arquivos temporários (filesystem read-only)
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
# Pull de imagem privada
imagePullSecrets:
- name: ghcr-credentials
Service: Expondo Pods com IP Estável
Pods têm IPs efêmeros — quando um pod morre e é recriado, recebe um IP diferente. O Service resolve esse problema fornecendo um IP e nome DNS estáveis para um conjunto de pods selecionados por labels:
# service.yml
apiVersion: v1
kind: Service
metadata:
name: minha-api
namespace: producao
spec:
selector:
app: minha-api # Seleciona pods com este label
ports:
- name: http
port: 80 # Porta do Service
targetPort: 3000 # Porta do container
protocol: TCP
type: ClusterIP # Acessível apenas dentro do cluster
Os tipos de Service disponíveis:
ClusterIP — padrão. Acessível apenas dentro do cluster. Usado para comunicação interna entre serviços.
NodePort — expõe o Service em uma porta estática em cada nó do cluster. Acessível externamente via IP_DO_NO:NODEPORT. Raramente usado em produção diretamente.
LoadBalancer — solicita ao cloud provider a criação de um load balancer externo. Na AWS, cria um Network Load Balancer ou Classic Load Balancer. É a forma mais comum de expor serviços em clusters gerenciados como EKS.
ConfigMap e Secret: Configuração Separada do Código
# configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: minha-api-config
namespace: producao
data:
NODE_ENV: "production"
LOG_LEVEL: "info"
PORT: "3000"
# Arquivo de configuração completo como entrada no ConfigMap
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://localhost:3000;
}
}
# secret.yml
apiVersion: v1
kind: Secret
metadata:
name: minha-api-secrets
namespace: producao
type: Opaque
# Valores em base64 — não é criptografia, apenas encoding
# Em produção, use External Secrets Operator ou Sealed Secrets
data:
database-url: cG9zdGdyZXNxbDovL... # base64 da string
redis-url: cmVkaXM6Ly9...
jwt-secret: c2VjcmV0b211aXRvc2VndXJv...
Ingress: Roteamento HTTP de Entrada
O Ingress define regras de roteamento HTTP/HTTPS para o tráfego de entrada no cluster. Requer um Ingress Controller — um pod que implementa as regras definidas pelo Ingress:
# ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minha-api
namespace: producao
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
cert-manager.io/cluster-issuer: "letsencrypt-producao"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.empresa.com
secretName: api-empresa-tls
rules:
- host: api.empresa.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minha-api
port:
number: 80
Comandos Essenciais do kubectl
# ── Contextos e clusters ──────────────────────────
kubectl config get-contexts # Lista clusters configurados
kubectl config use-context meu-cluster # Muda de cluster
# ── Inspecionando recursos ────────────────────────
kubectl get pods -n producao # Lista pods no namespace producao
kubectl get pods -A # Lista pods em todos os namespaces
kubectl get all -n producao # Todos os recursos do namespace
kubectl describe pod minha-api-abc -n producao # Detalhes de um pod
kubectl logs minha-api-abc -n producao # Logs de um pod
kubectl logs minha-api-abc -n producao -f # Logs em tempo real
kubectl logs minha-api-abc -n producao --previous # Logs da instância anterior
# ── Aplicando configurações ───────────────────────
kubectl apply -f deployment.yml # Cria ou atualiza recursos
kubectl apply -f ./manifests/ # Aplica todos os YAMLs de um diretório
kubectl delete -f deployment.yml # Remove recursos descritos no arquivo
# ── Operações em pods ─────────────────────────────
kubectl exec -it minha-api-abc -n producao -- /bin/sh # Shell interativo
kubectl port-forward pod/minha-api-abc 8080:3000 # Port forward local
# ── Rollout e atualizações ────────────────────────
kubectl rollout status deployment/minha-api -n producao
kubectl rollout history deployment/minha-api -n producao
kubectl rollout undo deployment/minha-api -n producao # Rollback
kubectl set image deployment/minha-api api=ghcr.io/empresa/api:1.6.0 -n producao
# ── Escalando ─────────────────────────────────────
kubectl scale deployment/minha-api --replicas=5 -n producao
# ── Diagnóstico ───────────────────────────────────
kubectl top pods -n producao # Uso de CPU e memória dos pods
kubectl top nodes # Uso de CPU e memória dos nós
kubectl get events -n producao --sort-by='.lastTimestamp'
Horizontal Pod Autoscaler
O HPA escala automaticamente o número de réplicas baseado em métricas — CPU, memória ou métricas customizadas via Prometheus Adapter:
# hpa.yml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: minha-api
namespace: producao
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: minha-api
minReplicas: 3
maxReplicas: 20
metrics:
# Escala por CPU
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
# Escala por memória
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
# Escala por métrica customizada do Prometheus
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"
behavior:
scaleUp:
stabilizationWindowSeconds: 60 # Aguarda 60s antes de escalar para cima
policies:
- type: Pods
value: 4
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300 # Aguarda 5min antes de escalar para baixo
policies:
- type: Pods
value: 1
periodSeconds: 60
Namespaces: Isolamento Lógico no Cluster
Os Namespaces dividem um cluster em ambientes virtuais isolados. É uma forma eficiente de separar equipes, ambientes ou projetos sem precisar de clusters separados:
# Cria os namespaces para diferentes ambientes
kubectl create namespace producao
kubectl create namespace staging
kubectl create namespace monitoring
# Define o namespace padrão para o contexto atual
kubectl config set-context --current --namespace=producao
# network-policy.yml — isola o namespace de produção
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: isolamento-producao
namespace: producao
spec:
podSelector: {} # Aplica a todos os pods do namespace
policyTypes:
- Ingress
- Egress
ingress:
# Permite tráfego apenas do Ingress Controller
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
egress:
# Permite saída para DNS
- ports:
- protocol: UDP
port: 53
# Permite saída para o namespace de banco de dados
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: databases
O Que Vem a Seguir
O próximo artigo aprofunda o Kubernetes em produção com o Amazon EKS — o serviço gerenciado de Kubernetes da AWS. Serão cobertos o provisionamento do cluster via Terraform, a gestão de node groups com Karpenter para auto scaling eficiente e as práticas de segurança essenciais para clusters EKS em produção.
Referências para Aprofundamento
Documentação oficial - Kubernetes Documentation — kubernetes.io — Documentação oficial completa do Kubernetes, incluindo conceitos, tutoriais e referência da API. O ponto de partida obrigatório para qualquer estudo sério de K8s. - kubectl Cheat Sheet — kubernetes.io — Referência rápida dos comandos kubectl mais usados, organizada por categoria de operação.
Aprendizado prático - kind Documentation — kind.sigs.k8s.io — Documentação do kind para criação de clusters locais, incluindo configurações avançadas de multi-node e networking. - Killercoda Kubernetes Playgrounds — killercoda.com — Ambiente interativo online para praticar Kubernetes sem instalação local, com cenários guiados e cluster real no navegador.
Livros e cursos de referência - Kubernetes: Up and Running — O'Reilly — Livro de referência escrito pelos criadores do Kubernetes, cobrindo desde os fundamentos até operações avançadas em produção. - CNCF Landscape — landscape.cncf.io — Mapa interativo do ecossistema Cloud Native, mostrando todas as ferramentas e projetos organizados por categoria. Essencial para entender o ecossistema ao redor do Kubernetes.