DevOps & CI/CD

Pods, Deployments e ReplicaSets em Kubernetes na Prática

16 min de leitura

Pods, Deployments e ReplicaSets em Kubernetes na Prática

Entendendo a Arquitetura de Containers no Kubernetes Antes de mergulharmos em Pods, Deployments e ReplicaSets, é fundamental entender que Kubernetes não trabalha diretamente com containers Docker. Em vez disso, ele abstrai a complexidade através de objetos que gerenciam containers em escala. O Kubernetes foi projetado para orquestrar containers, garantir alta disponibilidade, balanceamento de carga e escalabilidade automática. Esses três componentes (Pods, Deployments e ReplicaSets) são os pilares dessa orquestração e trabalham em conjunto de forma hierárquica. A beleza do Kubernetes está justamente em camadas de abstração que facilitam o trabalho do desenvolvedor e do operador. Você não precisa pensar em máquinas individuais ou em como replicar manualmente um container quando ele falha. O Kubernetes faz isso por você, e compreender como funciona essa orquestração é a chave para dominar a plataforma. Pods: O Menor Recurso Computável do Kubernetes O que é um Pod? Um Pod é a menor unidade de deployment no Kubernetes. Diferente do que muitos iniciantes pensam, um

<h2>Entendendo a Arquitetura de Containers no Kubernetes</h2>

<p>Antes de mergulharmos em Pods, Deployments e ReplicaSets, é fundamental entender que Kubernetes não trabalha diretamente com containers Docker. Em vez disso, ele abstrai a complexidade através de objetos que gerenciam containers em escala. O Kubernetes foi projetado para orquestrar containers, garantir alta disponibilidade, balanceamento de carga e escalabilidade automática. Esses três componentes (Pods, Deployments e ReplicaSets) são os pilares dessa orquestração e trabalham em conjunto de forma hierárquica.</p>

<p>A beleza do Kubernetes está justamente em camadas de abstração que facilitam o trabalho do desenvolvedor e do operador. Você não precisa pensar em máquinas individuais ou em como replicar manualmente um container quando ele falha. O Kubernetes faz isso por você, e compreender como funciona essa orquestração é a chave para dominar a plataforma.</p>

<h2>Pods: O Menor Recurso Computável do Kubernetes</h2>

<h3>O que é um Pod?</h3>

<p>Um Pod é a menor unidade de deployment no Kubernetes. Diferente do que muitos iniciantes pensam, um Pod não é um container — é um wrapper ao redor de um ou mais containers que compartilham recursos de rede e armazenamento. Na maioria dos casos, você terá um container por Pod, mas existem cenários onde múltiplos containers em um mesmo Pod faz sentido (padrão sidecar, por exemplo).</p>

<p>Todos os containers dentro de um Pod compartilham o mesmo namespace de rede, o que significa que eles têm o mesmo endereço IP e podem se comunicar via localhost usando portas diferentes. Além disso, podem compartilhar volumes de armazenamento, facilitando a troca de dados. Um Pod é efêmero — quando ele morre, desaparece. Você nunca deve criar Pods manualmente em produção; sempre os gerencie através de controllers como Deployments e ReplicaSets.</p>

<h3>Criando um Pod Simples</h3>

<p>Vejamos um exemplo prático de um Pod rodando uma aplicação Nginx:</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Pod

metadata:

name: nginx-pod

namespace: default

labels:

app: web

spec:

containers:

  • name: nginx

image: nginx:1.21

ports:

  • containerPort: 80

resources:

requests:

memory: &quot;64Mi&quot;

cpu: &quot;250m&quot;

limits:

memory: &quot;128Mi&quot;

cpu: &quot;500m&quot;</code></pre>

<p>Para criar esse Pod no seu cluster, você salvaria esse arquivo como <code>nginx-pod.yaml</code> e executaria:</p>

<pre><code class="language-bash">kubectl apply -f nginx-pod.yaml</code></pre>

<p>Para verificar se o Pod foi criado com sucesso:</p>

<pre><code class="language-bash">kubectl get pods

kubectl describe pod nginx-pod</code></pre>

<h3>Um Pod com Múltiplos Containers (Padrão Sidecar)</h3>

<p>Às vezes, você pode precisar de um container auxiliar que trabalhe junto com o principal. Neste exemplo, temos uma aplicação que precisa fazer logging centralizado:</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Pod

metadata:

name: app-with-sidecar

spec:

containers:

  • name: app

image: nginx:latest

ports:

  • containerPort: 80

volumeMounts:

  • name: shared-logs

mountPath: /var/log/nginx

  • name: log-collector

image: busybox:latest

command: [&#039;sh&#039;, &#039;-c&#039;, &#039;tail -f /var/log/nginx/access.log&#039;]

volumeMounts:

  • name: shared-logs

mountPath: /var/log/nginx

volumes:

  • name: shared-logs

emptyDir: {}</code></pre>

<p>Nesse padrão, o container <code>log-collector</code> monitora logs gerados pelo Nginx, ambos compartilhando o volume <code>shared-logs</code>. Essa é uma forma elegante de separar responsabilidades sem criar overhead de comunicação por rede.</p>

<h2>ReplicaSets: Garantindo Disponibilidade</h2>

<h3>Introdução aos ReplicaSets</h3>

<p>Um ReplicaSet é um controller que garante que um número específico de réplicas de um Pod estejam sempre rodando. Se um Pod falha, o ReplicaSet automaticamente cria um novo para manter o número desejado. Isso garante alta disponibilidade e tolerância a falhas. Um ReplicaSet utiliza um seletor de labels para identificar quais Pods ele gerencia, tornando a gestão dinâmica e flexível.</p>

<p>Embora você possa usar ReplicaSets diretamente, a maioria das aplicações modernas usam Deployments, que são um nível a mais de abstração sobre ReplicaSets e fornecem atualizações controladas (rolling updates). Porém, entender ReplicaSets é essencial para compreender como o Kubernetes mantém suas aplicações funcionando.</p>

<h3>Criando um ReplicaSet</h3>

<p>Aqui está um ReplicaSet prático que mantém 3 réplicas de um servidor web:</p>

<pre><code class="language-yaml">apiVersion: apps/v1

kind: ReplicaSet

metadata:

name: nginx-replicaset

namespace: default

spec:

replicas: 3

selector:

matchLabels:

app: web-server

template:

metadata:

labels:

app: web-server

spec:

containers:

  • name: nginx

image: nginx:1.21

ports:

  • containerPort: 80

resources:

requests:

memory: &quot;64Mi&quot;

cpu: &quot;250m&quot;

limits:

memory: &quot;128Mi&quot;

cpu: &quot;500m&quot;</code></pre>

<p>Aplicando esse ReplicaSet:</p>

<pre><code class="language-bash">kubectl apply -f nginx-replicaset.yaml</code></pre>

<p>Verificando o status:</p>

<pre><code class="language-bash">kubectl get replicasets

kubectl get pods -l app=web-server</code></pre>

<p>Você verá 3 Pods sendo gerenciados automaticamente. Se você deletar um Pod manualmente:</p>

<pre><code class="language-bash">kubectl delete pod &lt;nome-do-pod&gt;</code></pre>

<p>O ReplicaSet imediatamente criará um novo Pod para manter as 3 réplicas ativas.</p>

<h3>Escalando um ReplicaSet</h3>

<p>Uma das grandes vantagens é a escalabilidade dinâmica. Para aumentar para 5 réplicas:</p>

<pre><code class="language-bash">kubectl scale replicaset nginx-replicaset --replicas=5</code></pre>

<p>Ou edite o arquivo YAML diretamente e reaplique:</p>

<pre><code class="language-bash">kubectl edit replicaset nginx-replicaset</code></pre>

<p>Mude o campo <code>replicas</code> para 5 e salve. O Kubernetes ajustará automaticamente.</p>

<h2>Deployments: Orquestração Inteligente e Atualizações</h2>

<h3>O Poder dos Deployments</h3>

<p>Um Deployment é a abstração mais alta e mais usada no Kubernetes. Ele gerencia um ReplicaSet, que por sua vez gerencia os Pods. A grande vantagem é que Deployments facilitam atualizações de aplicações de forma segura e controlada. Você pode fazer rolling updates, onde as novas versões são implantadas gradualmente enquanto as antigas continuam servindo tráfego. Se algo der errado, você pode fazer rollback instantaneamente.</p>

<p>Deployments também fornecem histórico de revisões, permitindo voltar para qualquer versão anterior da sua aplicação. Além disso, garantem que o número desejado de réplicas esteja sempre disponível, mesmo durante atualizações. Na prática, 99% do tempo você usará Deployments em vez de ReplicaSets diretamente.</p>

<h3>Criando seu Primeiro Deployment</h3>

<p>Vejamos um Deployment funcional com uma aplicação real:</p>

<pre><code class="language-yaml">apiVersion: apps/v1

kind: Deployment

metadata:

name: app-deployment

namespace: default

labels:

app: myapp

spec:

replicas: 3

strategy:

type: RollingUpdate

rollingUpdate:

maxSurge: 1

maxUnavailable: 1

selector:

matchLabels:

app: myapp

template:

metadata:

labels:

app: myapp

version: v1

spec:

containers:

  • name: myapp

image: nginx:1.21

ports:

  • containerPort: 80

name: http

env:

  • name: ENVIRONMENT

value: &quot;production&quot;

livenessProbe:

httpGet:

path: /

port: 80

initialDelaySeconds: 10

periodSeconds: 10

readinessProbe:

httpGet:

path: /

port: 80

initialDelaySeconds: 5

periodSeconds: 5

resources:

requests:

memory: &quot;64Mi&quot;

cpu: &quot;250m&quot;

limits:

memory: &quot;128Mi&quot;

cpu: &quot;500m&quot;</code></pre>

<p>Criando o Deployment:</p>

<pre><code class="language-bash">kubectl apply -f app-deployment.yaml</code></pre>

<p>Verificando o status:</p>

<pre><code class="language-bash">kubectl get deployments

kubectl get replicasets

kubectl get pods</code></pre>

<p>Você verá a hierarquia: 1 Deployment gerenciando 1 ReplicaSet que gerencia 3 Pods.</p>

<h3>Rolling Update: Atualizando sua Aplicação</h3>

<p>Agora vem a magia. Você quer atualizar a imagem do Nginx para a versão 1.22. Em vez de derrubar tudo e reiniciar, o Kubernetes faz isso graciosamente:</p>

<pre><code class="language-bash">kubectl set image deployment/app-deployment myapp=nginx:1.22 --record</code></pre>

<p>O comando <code>--record</code> registra essa mudança no histórico de revisões. Observe o que acontece:</p>

<pre><code class="language-bash">kubectl rollout status deployment/app-deployment</code></pre>

<p>Você verá os Pods sendo atualizados gradualmente. Nunca há downtime. Se você quiser ver mais detalhes:</p>

<pre><code class="language-bash">kubectl describe deployment app-deployment</code></pre>

<h3>Rollback: Voltando para a Versão Anterior</h3>

<p>Se algo deu errado com a versão 1.22, você pode voltar instantaneamente:</p>

<pre><code class="language-bash">kubectl rollout undo deployment/app-deployment</code></pre>

<p>Para ver o histórico de revisões:</p>

<pre><code class="language-bash">kubectl rollout history deployment/app-deployment</code></pre>

<p>Para voltar para uma revisão específica:</p>

<pre><code class="language-bash">kubectl rollout undo deployment/app-deployment --to-revision=1</code></pre>

<h3>Configurando a Estratégia de Atualização</h3>

<p>No exemplo anterior, usamos <code>RollingUpdate</code> com <code>maxSurge: 1</code> e <code>maxUnavailable: 1</code>. Isso significa: crie no máximo 1 Pod novo além das 3 replicas, e mantenha no máximo 1 Pod indisponível. Você pode ajustar isso conforme sua necessidade:</p>

<pre><code class="language-yaml">strategy:

type: RollingUpdate

rollingUpdate:

maxSurge: 2 # até 2 Pods além do desejado

maxUnavailable: 0 # nunca deixe Pods indisponíveis</code></pre>

<p>Ou use a estratégia Recreate para ambientes de teste:</p>

<pre><code class="language-yaml">strategy:

type: Recreate</code></pre>

<p>Isso derruba todos os Pods antigos e cria novos, causando downtime breve mas garantindo que apenas uma versão rode de cada vez.</p>

<h2>Probes e Healthchecks: Mantendo sua Aplicação Saudável</h2>

<h3>Liveness e Readiness Probes</h3>

<p>Para que o Kubernetes gerencie adequadamente seus Pods, você precisa dizer a ele quando um Pod está saudável e pronto para receber tráfego. Existem dois tipos principais de probes:</p>

<p><strong>Liveness Probe</strong>: Detecta quando um Pod travou e precisa ser reiniciado. Se a probe falhar, o Kubernetes derruba o Pod e cria um novo.</p>

<p><strong>Readiness Probe</strong>: Determina se um Pod está pronto para receber tráfego. Pods não prontos são temporariamente removidos do load balancer.</p>

<p>Aqui está um exemplo completo com ambas as probes:</p>

<pre><code class="language-yaml">apiVersion: apps/v1

kind: Deployment

metadata:

name: health-check-app

spec:

replicas: 2

selector:

matchLabels:

app: api

template:

metadata:

labels:

app: api

spec:

containers:

  • name: api

image: node:16

command: [&quot;node&quot;, &quot;app.js&quot;]

ports:

  • containerPort: 3000

livenessProbe:

httpGet:

path: /health

port: 3000

initialDelaySeconds: 30

periodSeconds: 10

timeoutSeconds: 5

failureThreshold: 3

readinessProbe:

httpGet:

path: /ready

port: 3000

initialDelaySeconds: 5

periodSeconds: 5

timeoutSeconds: 3

failureThreshold: 2</code></pre>

<p>Neste exemplo, a aplicação Node.js precisa responder com sucesso no endpoint <code>/health</code> a cada 10 segundos. Se falhar 3 vezes consecutivas, o Pod é reiniciado. Além disso, <code>/ready</code> indica se a aplicação está inicializada e pronta para receber requisições.</p>

<h2>Casos de Uso Práticos: Quando Usar Cada Um</h2>

<h3>Pods Isolados: Raramente em Produção</h3>

<p>Você criaria um Pod diretamente apenas em cenários de teste, debug ou em jobs únicos que não precisam de replicação. Na maioria das vezes, evite. O exemplo que mostramos no início foi apenas para fins educacionais.</p>

<h3>ReplicaSets: Quando Você Quer Controle Fino</h3>

<p>Use ReplicaSets quando precisar apenas de replicação simples, sem atualizações controladas. Cenários raros em produção, pois Deployments cobrem 99% dos casos. Você poderia usar ReplicaSets se tiver uma aplicação stateful que não pode ter rolling updates complexas, mas mesmo assim, considere usar StatefulSets (que é outro tópico).</p>

<h3>Deployments: A Escolha Padrão</h3>

<p>Para 99% das aplicações, use Deployments. Eles fornecem replicação, high availability, rolling updates, rollback automático e histórico. Quer fazer deploy de uma nova versão? Deployments. Quer escalar sua aplicação? Deployments. Quer garantir que sempre haja 3 instâncias rodando? Deployments.</p>

<p>Aqui está um exemplo realista completo que você poderia usar em produção:</p>

<pre><code class="language-yaml">apiVersion: apps/v1

kind: Deployment

metadata:

name: production-api

namespace: production

labels:

app: api

environment: prod

spec:

replicas: 3

strategy:

type: RollingUpdate

rollingUpdate:

maxSurge: 1

maxUnavailable: 0

selector:

matchLabels:

app: api

template:

metadata:

labels:

app: api

environment: prod

spec:

affinity:

podAntiAffinity:

preferredDuringSchedulingIgnoredDuringExecution:

  • weight: 100

podAffinityTerm:

labelSelector:

matchExpressions:

  • key: app

operator: In

values:

  • api

topologyKey: kubernetes.io/hostname

containers:

  • name: api

image: myregistry.azurecr.io/myapp:v1.2.3

imagePullPolicy: Always

ports:

  • containerPort: 8080

name: http

env:

  • name: LOG_LEVEL

value: &quot;info&quot;

  • name: DATABASE_URL

valueFrom:

secretKeyRef:

name: db-credentials

key: connection-string

livenessProbe:

httpGet:

path: /api/health

port: 8080

initialDelaySeconds: 30

periodSeconds: 10

failureThreshold: 3

readinessProbe:

httpGet:

path: /api/ready

port: 8080

initialDelaySeconds: 10

periodSeconds: 5

failureThreshold: 2

resources:

requests:

memory: &quot;256Mi&quot;

cpu: &quot;500m&quot;

limits:

memory: &quot;512Mi&quot;

cpu: &quot;1000m&quot;

securityContext:

runAsNonRoot: true

runAsUser: 1000

allowPrivilegeEscalation: false</code></pre>

<p>Neste exemplo, note que:</p>

<ul>

<li>Usamos <code>affinity</code> para distribuir os Pods em diferentes nós</li>

<li>Injetamos secrets (credenciais de banco de dados) de forma segura</li>

<li>Definimos limites de recursos para evitar que a aplicação consuma todos os recursos do nó</li>

<li>Configuramos probes apropriadas para detectar falhas rapidamente</li>

<li>Usamos imagens de um registry privado com <code>imagePullPolicy: Always</code></li>

</ul>

<h2>Debugging e Monitoramento</h2>

<h3>Comandos Essenciais</h3>

<p>Quando algo dá errado, você precisa saber como investigar. Aqui estão os comandos mais úteis:</p>

<pre><code class="language-bash"># Ver logs da aplicação

kubectl logs &lt;nome-do-pod&gt;

kubectl logs deployment/app-deployment -c container-name

Acompanhar logs em tempo real

kubectl logs -f pod/app-deployment-xxxxx

Execar comando dentro do container

kubectl exec -it &lt;nome-do-pod&gt; -- /bin/bash

Ver eventos do cluster

kubectl describe pod &lt;nome-do-pod&gt;

kubectl describe deployment app-deployment

Verificar por quais nós os Pods estão distribuídos

kubectl get pods -o wide

Debug completo de um Deployment

kubectl get all -l app=myapp</code></pre>

<h2>Conclusão</h2>

<p>Dominar Pods, ReplicaSets e Deployments é fundamental para trabalhar efetivamente com Kubernetes. A chave é entender a hierarquia: Deployments gerenciam ReplicaSets, que gerenciam Pods, que contêm containers. Na prática, você quase nunca criará Pods ou ReplicaSets manualmente em produção — use sempre Deployments, que fornecem atualizações seguras, rollback automático e escalabilidade sem downtime. Por fim, sempre configure liveness e readiness probes para permitir que o Kubernetes gerencie sua aplicação de forma inteligente, detectando e recuperando-se automaticamente de falhas.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://kubernetes.io/docs/concepts/workloads/pods/" target="_blank" rel="noopener noreferrer">Kubernetes Official Documentation - Pods</a></li>

<li><a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" target="_blank" rel="noopener noreferrer">Kubernetes Official Documentation - Deployments</a></li>

<li><a href="https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/" target="_blank" rel="noopener noreferrer">Kubernetes Official Documentation - ReplicaSets</a></li>

<li><a href="https://www.manning.com/books/kubernetes-in-action-second-edition" target="_blank" rel="noopener noreferrer">Kubernetes in Action - 2nd Edition</a></li>

<li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/" target="_blank" rel="noopener noreferrer">Healthchecks and Probes - Official Documentation</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em DevOps & CI/CD

AWS Fundamentos para DevOps: IAM, VPC, EC2 e S3 na Prática: Do Básico ao Avançado
AWS Fundamentos para DevOps: IAM, VPC, EC2 e S3 na Prática: Do Básico ao Avançado

IAM: Controle de Acesso e Identidade na AWS O Identity and Access Management...

O que Todo Dev Deve Saber sobre ArgoCD: GitOps Contínuo para Kubernetes na Prática
O que Todo Dev Deve Saber sobre ArgoCD: GitOps Contínuo para Kubernetes na Prática

O que é ArgoCD e Por que GitOps? ArgoCD é uma ferramenta declarativa de entre...

Crossplane: Infraestrutura como Código dentro do Kubernetes na Prática
Crossplane: Infraestrutura como Código dentro do Kubernetes na Prática

O que é Crossplane e por que você deve aprender Crossplane é um framework ope...