Entendendo Deployments em Kubernetes
Um Deployment é um controlador do Kubernetes que gerencia a criação, atualização e escalabilidade de Pods de forma declarativa. Diferente de criar Pods manualmente, um Deployment garante que o estado desejado seja mantido constantemente — se um Pod falhar, outro será criado automaticamente. Ele utiliza ReplicaSets internamente para gerenciar múltiplas réplicas da mesma aplicação.
Quando você define um Deployment, você descreve qual container executar, quantas réplicas deseja, recursos necessários e políticas de atualização. O Kubernetes então trabalha continuamente para manter aquele estado desejado. Isso é especialmente crítico em produção, onde você não pode parar a aplicação para atualizações.
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: webapp:v1.0.0
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
Este exemplo básico cria 3 réplicas de um container webapp. O seletor garante que apenas Pods com a label app: webapp sejam gerenciados por este Deployment. O livenessProbe reinicia o container se deixar de responder.
Estratégias de Atualização
Kubernetes oferece duas principais estratégias para atualizar aplicações: RollingUpdate (padrão) e Recreate. A escolha depende de seus requisitos de disponibilidade e recursos.
RollingUpdate: Atualizações sem downtime
Na estratégia RollingUpdate, o Kubernetes substitui Pods antigos pelos novos gradualmente. Você controla quantos Pods podem ser indisponíveis (maxUnavailable) e quantos novos podem ser criados além do desejado (maxSurge). Isso permite que sua aplicação permaneça acessível durante a atualização.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 2
selector:
matchLabels:
app: api-service
template:
metadata:
labels:
app: api-service
spec:
containers:
- name: api
image: api-service:v2.0.0
ports:
- containerPort: 3000
terminationGracePeriodSeconds: 30
Com maxUnavailable: 1, apenas um Pod pode estar indisponível por vez. Com maxSurge: 2, até 6 Pods podem estar rodando simultaneamente durante a atualização (4 desejados + 2 extras). O terminationGracePeriodSeconds dá tempo para requisições em andamento terminarem antes do Pod ser desligado.
Recreate: Atualização rápida com downtime
Recreate encerra todos os Pods antigos e cria novos imediatamente. Útil em ambientes de teste ou quando downtime é aceitável, pois é mais rápido e consome menos recursos.
apiVersion: apps/v1
kind: Deployment
metadata:
name: batch-processor
spec:
replicas: 2
strategy:
type: Recreate
selector:
matchLabels:
app: batch-processor
template:
metadata:
labels:
app: batch-processor
spec:
containers:
- name: processor
image: batch-processor:v3.1.0
env:
- name: BATCH_SIZE
value: "1000"
Use Recreate quando a aplicação não suporta múltiplas versões rodando simultaneamente ou quando o downtime é previsível e aceitável.
Rollbacks e Revision History
Kubernetes mantém automaticamente um histórico de revisões do seu Deployment. Cada vez que a especificação do template de Pod muda, uma nova revisão é criada. Você pode consultar esse histórico e reverter para qualquer revisão anterior.
Visualizando o histórico de revisões
kubectl rollout history deployment/api-service -n production
Este comando lista todas as revisões, mostrando um identificador de revisão e a descrição (se fornecida). O número de revisões mantidas é controlado por revisionHistoryLimit (padrão é 10).
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
spec:
revisionHistoryLimit: 15
replicas: 3
selector:
matchLabels:
app: api-service
template:
metadata:
labels:
app: api-service
annotations:
deployment.kubernetes.io/revision: "5"
spec:
containers:
- name: api
image: api-service:v2.1.5
Aumentar revisionHistoryLimit permite manter mais histórico, útil quando você precisa reverter para versões muito antigas. Por outro lado, cada revisão consome espaço no etcd.
Executando um rollback
Quando algo dá errado com a nova versão, você pode reverter instantaneamente:
# Reverter para a revisão anterior
kubectl rollout undo deployment/api-service -n production
# Reverter para uma revisão específica
kubectl rollout undo deployment/api-service --to-revision=8 -n production
O rollback cria uma nova revisão (não volta literalmente para o passado), garantindo que você tenha rastreabilidade completa de todas as mudanças.
Monitorando o status de um rollout
# Ver progresso em tempo real
kubectl rollout status deployment/api-service -n production --watch
# Ver detalhes de uma revisão específica
kubectl rollout history deployment/api-service --revision=5 -n production
Casos Práticos e Cenários Avançados
Cenário 1: Atualização com problemas detectados
Imagine que você atualizou sua aplicação e novos Pods começam a falhar nos health checks:
# Ver o status
kubectl get deployment webapp -n prod
# Verificar logs do Pod problemático
kubectl logs -l app=webapp -n prod --tail=50
# Se necessário, reverter instantaneamente
kubectl rollout undo deployment/webapp -n prod
# Verificar a reversão
kubectl rollout status deployment/webapp -n prod --watch
Cenário 2: Atualização com validação manual
Para estratégias mais conservadoras, você pode pausar o rollout entre atualizações:
# Iniciar atualização com nova imagem
kubectl set image deployment/webapp webapp=webapp:v2.0.0 -n prod --record
# Pausar o rollout
kubectl rollout pause deployment/webapp -n prod
# Executar testes (pode ser automático via tests)
# Se passou, retomar
kubectl rollout resume deployment/webapp -n prod
# Se falhou, reverter
kubectl rollout undo deployment/webapp -n prod
Cenário 3: Garantindo revisão anterior sempre disponível
Você pode usar minReadySeconds para garantir que um Pod esteja pronto antes de prosseguir com as próximas atualizações:
apiVersion: apps/v1
kind: Deployment
metadata:
name: critical-app
spec:
replicas: 5
minReadySeconds: 60
progressDeadlineSeconds: 600
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: critical-app
template:
metadata:
labels:
app: critical-app
spec:
containers:
- name: app
image: critical-app:v1.5.0
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
failureThreshold: 3
O minReadySeconds: 60 força esperar 60 segundos após um Pod reportar ready antes de considerar a atualização bem-sucedida. progressDeadlineSeconds: 600 aborta a atualização se não completar em 10 minutos, prevenindo hang indefinido.
Conclusão
O domínio de Deployments em Kubernetes é fundamental para qualquer engenheiro de plataforma ou DevOps. Você aprendeu que RollingUpdate oferece atualizações contínuas mantendo disponibilidade, enquanto Recreate é apropriado para casos específicos. Mais importante ainda, o Kubernetes mantém automaticamente um histórico de revisões que permite rollbacks em segundos, eliminando o pânico de deployments errados. Na prática, combine essas estratégias com health checks robustos e automação de testes para ter confiança nas suas atualizações em produção.