Ir para o conteúdo

Pods, ReplicaSets e Deployments: como Kubernetes pensa sua aplicação

Entenda como Pods, ReplicaSets e Deployments representam workloads no Kubernetes, por que Pods são efêmeros e como controllers reconciliam o estado desejado.

Palavras: 2064Tempo de Leitura: 11 Minutos

No artigo anterior, vimos que Kubernetes começa a fazer sentido quando o problema deixa de ser apenas executar containers e passa a ser manter workloads distribuídos no estado desejado.

Agora vem a pergunta prática de arquitetura: qual é exatamente a unidade que Kubernetes gerencia e como ele mantém essa intenção ao longo do tempo?

A resposta passa por três conceitos que aparecem juntos o tempo todo — Pods, ReplicaSets e Deployments — mas que representam responsabilidades diferentes.

Se você tentar aprender os três apenas como blocos de YAML, Kubernetes parece burocrático. Quando entende o modelo de controle por trás deles, o desenho fica muito mais previsível.

Por que Kubernetes não quer que você cuide de Pods individuais

Em uma administração tradicional de servidor, é comum pensar em processos específicos: “esta instância da aplicação está rodando nesta máquina”. Quando algo quebra, alguém reinicia aquele processo ou aquela VM.

Kubernetes trabalha melhor com outra ideia: workloads devem ser substituíveis. A identidade importante não é necessariamente aquela instância específica, mas o estado que o sistema precisa manter.

Se você precisa de três réplicas de uma API, o objetivo não é preservar três Pods concretos para sempre. O objetivo é manter três unidades equivalentes que atendam ao template e às regras declaradas.

Isso prepara o terreno para entender por que Pods são efêmeros e por que controllers existem.

O que é um Pod e por que ele é efêmero

Um Pod é a menor unidade computável implantável em Kubernetes. Ele pode conter um ou mais containers que compartilham contexto de execução, como rede e volumes associados ao Pod.

Na maioria das aplicações web comuns, um Pod acaba carregando um container principal da aplicação e, quando necessário, containers auxiliares com relação muito próxima ao mesmo ciclo de vida. Isso não transforma Pod em sinônimo de container. O Pod é a unidade de execução que Kubernetes agenda e acompanha; os containers vivem dentro dela.

O ponto mais importante é que Pods não devem ser tratados como servidores de estimação.

Eles podem desaparecer porque:

  • o processo falhou;
  • o nó onde estavam rodando ficou indisponível;
  • uma atualização substituiu workloads antigos;
  • uma mudança de escala alterou a quantidade desejada;
  • uma política ou operação do cluster provocou remanejamento.

Quando isso acontece, um novo Pod pode surgir com outra identidade e outro endereço de rede.

Por isso, guardar estado essencial apenas “dentro daquele Pod” ou depender de seu IP como identidade permanente é um desenho frágil. Essa efemeridade não é um acidente do Kubernetes; ela faz parte do modelo que permite substituir unidades quebradas e evoluir a aplicação.

Estado desejado × estado observado

Considere uma API cuja intenção seja manter três instâncias.

estado desejado: 3 réplicas
estado observado: 3 réplicas
                 ↓
               estável

Agora uma delas falha:

estado desejado: 3
estado observado: 2
                 ↓
             diferença
                 ↓
          controller reage
                 ↓
           nova réplica

Essa diferença entre intenção e realidade é central em Kubernetes.

Você não quer um operador humano contando Pods o dia inteiro. Quer componentes do sistema observando recursos e agindo quando o estado real se afasta do estado declarado.

Esse comportamento é chamado de reconciliação.

Controllers e reconciliação

Um controller observa recursos e tenta mover o estado atual em direção ao estado desejado. Ele não precisa compreender o negócio da aplicação; precisa compreender o contrato do recurso que controla.

Essa separação transforma operação em loops contínuos de verificação e ajuste.

Em vez de depender de uma sequência imperativa como “crie processo A, reinicie se morrer, mova se a máquina cair, duplique quando faltar capacidade”, você declara uma intenção e deixa o controller reagir quando a realidade se afasta dela.

Isso não torna o sistema mágico. Se a imagem não existe, a configuração está errada, não há capacidade no cluster ou a aplicação inicia mas funciona mal, a reconciliação pode continuar tentando sem corrigir a causa. Controllers preservam intenção operacional; eles não substituem diagnóstico.

Por isso o modelo depende de observabilidade. É preciso saber não apenas que recursos existem, mas se estão prontos, saudáveis e entregando o comportamento esperado.

ReplicaSet: manter a quantidade desejada

ReplicaSet é um controller focado em garantir que uma quantidade especificada de Pods correspondentes esteja em execução.

Se você declara três réplicas e uma desaparece, o ReplicaSet tenta restaurar o conjunto. Se muda a intenção para cinco, novas unidades podem ser criadas. Se reduz para duas, o conjunto é ajustado para aquele novo estado desejado.

O valor do ReplicaSet está nessa garantia de quantidade e seleção de Pods, não em oferecer sozinho toda a experiência de atualização de uma aplicação.

Na prática, para aplicações comuns você geralmente não cria ReplicaSets diretamente. Eles costumam ser administrados por Deployments, que adicionam uma camada de rollout e revisão sobre esse mecanismo.

Deployment
   ↓ gerencia evolução da aplicação
ReplicaSet
   ↓ mantém quantidade desejada
Pods
   ↓ executam containers

Deployment: declarar e evoluir uma aplicação stateless

Deployment é a abstração que normalmente representa uma aplicação stateless que precisa manter réplicas e evoluir entre versões de forma declarativa.

Em vez de você pensar “estes são os três Pods atuais”, o Deployment descreve algo mais próximo de:

quero esta versão da aplicação
com este template de Pod
mantendo esta quantidade de réplicas
sob esta estratégia de atualização

Quando o template muda — por exemplo, porque a imagem da aplicação passou da versão v1 para v2 — o Deployment cria uma nova revisão e coordena a transição entre o conjunto anterior e o novo.

Por baixo dessa operação, ReplicaSets diferentes podem representar revisões distintas do workload. O Deployment gerencia essa evolução para que a equipe não precise manipular cada conjunto manualmente.

Essa distinção ajuda a entender por que Deployment não significa simplesmente “deploy”. O objeto é um controller específico do Kubernetes para workloads declarativos; o processo de deploy, como vimos no artigo sobre o que é deploy, envolve uma responsabilidade mais ampla sobre artefato, configuração, validação, tráfego e recuperação.

O que acontece quando um Pod falha

Suponha que um Deployment mantenha três réplicas.

Uma delas deixa de existir. O ReplicaSet observa que há duas, embora o estado desejado continue sendo três. Ele cria outra unidade compatível com o template.

O novo Pod não precisa ter o mesmo nome, o mesmo IP ou a mesma história da instância anterior. O que importa é restaurar o conjunto desejado.

Essa substituição explica várias decisões de arquitetura:

  • arquivos importantes não devem depender do filesystem efêmero do Pod;
  • consumidores não deveriam depender do IP permanente de uma instância;
  • inicialização precisa ser automatizada;
  • configuração deve estar disponível para uma nova réplica sem intervenção manual;
  • a aplicação precisa tolerar que uma instância desapareça e outra assuma seu lugar.

Kubernetes funciona melhor quando o workload foi desenhado para ser recriado. Quanto mais conhecimento secreto estiver preso a uma instância específica, mais difícil é aproveitar o modelo de reconciliação.

Como rollout entra no modelo sem virar tutorial

Quando um Deployment muda, Kubernetes não precisa destruir todas as réplicas antigas e só depois criar as novas. O controller pode coordenar a substituição progressiva do conjunto, mantendo a aplicação dentro das regras declaradas para aquela atualização.

A ideia importante não é decorar parâmetros de rollout agora. É perceber que atualização também é uma diferença entre estado desejado e estado observado.

Antes:

estado desejado → versão A
estado observado → versão A

Depois da mudança:

estado desejado → versão B
estado observado → parte A + parte B
                 ↓
          reconciliação gradual
                 ↓
estado observado → versão B

Essa transição pode ser acompanhada e, quando necessário, uma revisão anterior pode voltar a ser desejada. Mas o sucesso técnico do rollout não garante que a aplicação esteja saudável para o usuário.

Um Deployment pode concluir sua atualização e ainda haver erros de negócio, latência alta, dependência externa quebrada ou regressão que só aparece sob carga real. Por isso, rollout precisa ser conectado a probes, métricas, logs, traces e critérios de negócio — assuntos que aprofundaremos no conteúdo operacional do 2B.

Pod, container e servidor não são a mesma coisa

Três confusões aparecem com frequência.

“Um Pod é um container.” Não necessariamente. Um Pod é a unidade Kubernetes que pode agrupar um ou mais containers que precisam compartilhar contexto e ciclo de vida.

“Um Pod é uma VM pequena.” Também não. A expectativa operacional é diferente. Pods são descartáveis e substituíveis; você não deveria tratá-los como máquinas nas quais entra para aplicar correções permanentes manualmente.

“Um Deployment é um servidor da aplicação.” Não. Deployment é um objeto controlador que descreve como um workload stateless deve existir e evoluir. As instâncias concretas são Pods, normalmente mantidos por ReplicaSets gerenciados pelo Deployment.

Uma forma melhor de pensar é:

container = processo empacotado
Pod       = unidade de execução do Kubernetes
ReplicaSet = quantidade desejada de Pods equivalentes
Deployment = evolução declarativa desse conjunto

Por que criar Pods diretamente costuma ser a abstração errada

Kubernetes permite criar um Pod diretamente, mas isso raramente é o que você quer para uma aplicação que deve continuar disponível. Um Pod isolado não carrega, sozinho, a intenção de quantas réplicas devem existir nem o histórico de evolução de uma versão para outra.

Se esse Pod desaparece, não existe automaticamente um controlador declarando que outro equivalente precisa ocupar seu lugar. A plataforma conhece o objeto que você criou, mas não recebeu uma política superior dizendo como aquele workload deve ser mantido ao longo do tempo.

Por isso, workloads duradouros normalmente são expressos por controllers apropriados. Para aplicações stateless, Deployment é a escolha comum porque combina template, réplicas e evolução declarativa. Outros tipos de workload, como StatefulSet, DaemonSet, Job e CronJob, existem para necessidades diferentes e serão assunto de aprofundamentos posteriores.

A regra mental é simples: se você está cuidando manualmente da sobrevivência de um Pod específico, provavelmente está trabalhando abaixo da abstração que Kubernetes quer oferecer.

O modelo mental que vale guardar

Se você esquecer os nomes por um momento, a arquitetura fica simples:

  1. existe uma intenção sobre como a aplicação deve rodar;
  2. essa intenção é expressa em recursos declarativos;
  3. controllers observam o que realmente existe;
  4. quando há diferença, eles tentam reconciliar;
  5. Pods concretos podem nascer e desaparecer durante esse processo;
  6. o sistema preserva o estado desejado do conjunto, não a identidade eterna de cada instância.

Esse modelo é mais importante do que memorizar um manifesto. Ele explica por que Kubernetes consegue substituir workloads, manter réplicas e coordenar revisões sem exigir que a equipe gerencie cada processo individualmente.

Também explica por que alguns sistemas se adaptam melhor ao Kubernetes do que outros. Uma aplicação que depende de sessão local, configuração manual e arquivos presos a uma instância específica precisa resolver esses acoplamentos antes de esperar que a plataforma forneça resiliência automaticamente.

Próximo passo: Services e networking

Agora surge um novo problema.

Se Pods podem ser substituídos e seus endereços podem mudar, como uma aplicação encontra outra de forma estável?

Uma API não deveria precisar descobrir o IP atual de cada Pod de worker ou backend manualmente. O frontend não deveria ser reconfigurado a cada nova réplica. E consumidores externos precisam de um ponto previsível para chegar ao serviço certo.

É aí que entram Services, descoberta e networking no Kubernetes.

No próximo conteúdo, vamos partir dessa instabilidade natural dos Pods para entender por que Kubernetes cria uma abstração de serviço sobre workloads efêmeros — novamente começando pelo problema antes da sintaxe.

Publicado em