Orquestração de containers: por quê
Esta aula explica por que a orquestração de containers é essencial em ambientes DevOps, abordando os limites do Docker isolado, a necessidade de escalabilidade, auto-healing e os cenários práticos que demandam essa tecnologia.
A orquestração de containers é um dos pilares do DevOps moderno. Embora o Docker tenha revolucionado a forma como empacotamos e executamos aplicações, ele sozinho não resolve problemas de larga escala, como distribuição de carga, failover automático e gerenciamento de múltiplos hosts. Nesta aula, vamos explorar os motivos pelos quais a orquestração se tornou indispensável, analisando seus limites, benefícios e quando você realmente precisa dela.
Vamos começar entendendo o que o Docker oferece e onde ele para, para então mergulhar nos conceitos de escalabilidade e auto-healing, que são os grandes diferenciais de orquestradores como Kubernetes, Docker Swarm e Nomad. Ao final, você terá clareza para decidir quando adotar essa tecnologia em seus projetos.
Limites do Docker sozinho
O Docker é uma ferramenta fantástica para criar e executar containers de forma isolada. Com ele, você pode empacotar uma aplicação com todas as suas dependências e rodá-la em qualquer máquina que tenha o Docker instalado. No entanto, quando falamos de ambientes de produção com múltiplos serviços, alta disponibilidade e tráfego variável, o Docker sozinho rapidamente mostra suas limitações.
Uma das principais limitações é que o Docker gerencia containers em um único host. Se esse host falhar, todos os containers que estavam rodando nele ficam indisponíveis. Não há mecanismo nativo para reiniciar esses containers em outra máquina automaticamente. Além disso, o Docker não oferece balanceamento de carga entre containers de um mesmo serviço distribuídos em diferentes hosts, nem descobrimento de serviço automático. Você teria que configurar manualmente redes, proxies e registros de serviço, o que se torna inviável em escala.
Outra limitação é o gerenciamento de configurações e segredos. Em um ambiente com dezenas de containers, cada um pode precisar de variáveis de ambiente, arquivos de configuração e segredos (como senhas e chaves). O Docker fornece mecanismos básicos como docker run -e e volumes, mas não há uma forma centralizada de gerenciar e atualizar essas configurações em lote, nem de garantir que todos os containers estejam com a versão correta.
Vejamos um exemplo simples de como seria tentar escalar manualmente com Docker:
# Subir um container de uma aplicação web
$ docker run -d -p 8080:80 --name web1 minha-imagem:1.0
# Para escalar, seria preciso subir outro container em outra porta e configurar um proxy manualmente
$ docker run -d -p 8081:80 --name web2 minha-imagem:1.0
# E ainda assim, se web1 cair, ninguém reinicia automaticamente
Esse processo manual é propenso a erros e não atende à demanda de elasticidade que aplicações modernas exigem.
Escalabilidade
Escalabilidade é a capacidade de aumentar ou diminuir os recursos de uma aplicação conforme a demanda. Em um ambiente de containers, isso significa poder adicionar ou remover instâncias de um serviço rapidamente, sem interrupção. Orquestradores como Kubernetes fazem isso de forma declarativa: você define o estado desejado (por exemplo, "quero 3 réplicas deste serviço") e o orquestrador se encarrega de atingir e manter esse estado.
A escalabilidade pode ser vertical (aumentar recursos de uma máquina) ou horizontal (adicionar mais máquinas ou containers). A orquestração foca principalmente na horizontal, pois é mais flexível e resiliente. Com o Kubernetes, você pode usar o Horizontal Pod Autoscaler (HPA) para ajustar automaticamente o número de pods com base em métricas como CPU, memória ou tráfego HTTP.
Além disso, a orquestração permite escalar não apenas a quantidade de réplicas, mas também distribuir essas réplicas por diferentes nós (máquinas físicas ou virtuais), garantindo melhor utilização dos recursos. Por exemplo, se você tem um cluster com 5 nós, o orquestrador pode colocar pods em nós com mais recursos disponíveis.
Aqui está um exemplo de um manifesto Kubernetes que define um Deployment com 3 réplicas:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
Com esse arquivo, você aplica com kubectl apply -f deployment.yaml e o Kubernetes cria 3 pods. Se um pod cair, ele recria imediatamente. Se você quiser escalar para 5, basta alterar o número de réplicas e aplicar novamente, ou usar kubectl scale deployment web --replicas=5.
Essa automação é crucial para lidar com picos de acesso, como em promoções ou eventos, sem intervenção manual.
Auto-healing
Auto-healing é a capacidade de um sistema detectar falhas e se recuperar automaticamente, sem intervenção humana. Em um ambiente de containers, isso significa que se um container morrer, o orquestrador deve iniciar um novo, possivelmente em outro nó, e redirecionar o tráfego para ele. Isso garante alta disponibilidade e resiliência.
O Docker sozinho oferece um mecanismo simples de reinício com a política --restart, mas ela atua apenas no mesmo host e não considera falhas de máquina. Já os orquestradores monitoram a saúde dos containers através de health checks (como liveness e readiness probes no Kubernetes). O liveness probe verifica se o container está vivo; se falhar, o container é reiniciado. O readiness probe verifica se o container está pronto para receber tráfego; se falhar, ele é retirado do balanceador de carga até que se recupere.
Além disso, o orquestrador monitora os nós do cluster. Se um nó ficar inacessível, os pods que estavam rodando nele são reprogramados em outros nós saudáveis. Isso é feito pelo controlador de replicação, que sempre tenta garantir o número desejado de réplicas.
Exemplo de um Deployment com liveness e readiness probes:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 2
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: minha-app:1.0
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
Com essas configurações, o Kubernetes verifica periodicamente se a aplicação está saudável. Se o liveness falhar, o container é reiniciado; se o readiness falhar, ele não recebe tráfego até ficar pronto. Assim, o sistema se auto-recupera de forma transparente.
Quando você precisa
Nem todo projeto precisa de orquestração de containers. Para aplicações pequenas, com poucos serviços e baixo tráfego, o Docker Compose pode ser suficiente. Docker Compose permite definir e executar múltiplos containers em um único host, com redes e volumes configurados. É uma ótima ferramenta para desenvolvimento e testes.
No entanto, você precisa de um orquestrador quando:
- Você tem múltiplos hosts: se precisa rodar containers em várias máquinas para alta disponibilidade ou balanceamento de carga, o Docker sozinho não gerencia isso.
- Você precisa de escalabilidade dinâmica: se o número de instâncias precisa variar automaticamente com base na demanda, o orquestrador é essencial.
- Você quer auto-healing: se não pode ficar acordado à noite para reiniciar containers que caíram, o orquestrador faz isso por você.
- Você tem muitos serviços: gerenciar dezenas de containers manualmente é inviável; orquestradores oferecem controle centralizado.
- Você precisa de rolling updates e rollbacks: orquestradores permitem atualizar aplicações sem downtime, distribuindo novas versões gradualmente e revertendo se algo der errado.
Por exemplo, se você está desenvolvendo uma aplicação que será usada por milhares de usuários, com requisitos de SLA elevados, a orquestração é obrigatória. Já para um projeto pessoal ou um MVP com pouco tráfego, Docker Compose pode ser suficiente.
Vejamos um comparativo prático:
# Com Docker Compose, você define serviços para um host
# docker-compose.yml
version: '3'
services:
web:
image: nginx
ports:
- "80:80"
db:
image: postgres
environment:
POSTGRES_PASSWORD: secret
# Com Kubernetes, você define um cluster com vários nós
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx
ports:
- containerPort: 80
A escolha entre Docker Compose e um orquestrador depende do estágio do projeto e dos requisitos de infraestrutura.
Boas práticas e observações finais
Ao adotar orquestração, comece com ferramentas mais simples, como Docker Swarm, se você já está familiarizado com Docker, e avance para Kubernetes conforme a necessidade. O Kubernetes é o padrão de fato, mas tem uma curva de aprendizado maior. Independente da ferramenta, siga boas práticas:
- Defina recursos (CPU/memória) para cada container, para evitar que um serviço consuma tudo.
- Use health checks (liveness e readiness) em todos os serviços críticos.
- Faça logging centralizado, coletando logs de todos os containers em um sistema como ELK ou Loki.
- Configure segredos de forma segura, usando recursos como Kubernetes Secrets ou ferramentas externas como Vault.
- Automatize deploys com CI/CD, integrando o pipeline ao cluster.
Orquestração de containers é um investimento que traz robustez e eficiência, mas deve ser adotada com critério, avaliando custo e complexidade.
Referências
- Documentação oficial do Docker Compose
- O que é Kubernetes - Documentação oficial
- Kubernetes Deployments
- Configurando Liveness, Readiness e Startup Probes
- Docker Swarm - Documentação oficial
- Nomad - Tutorial oficial da HashiCorp
- Horizontal Pod Autoscaler no Kubernetes
Exercícios
- Explique com suas palavras duas limitações do Docker quando usado sozinho em produção.
- O que é escalabilidade horizontal e como um orquestrador ajuda a alcançá-la?
- Diferencie liveness probe e readiness probe no Kubernetes.
- Cite três cenários em que você definitivamente precisa de orquestração de containers.
- Qual a diferença entre Docker Compose e um orquestrador como Kubernetes?