Execute kubectl run nginx --image=nginx:1.27 e o Kubernetes cria exatamente um Pod chamado nginx. Apague-o com kubectl delete pod nginx e ele some de vez — ninguém percebe, ninguém o substitui. Um Pod é a menor unidade implantável no Kubernetes: um ou mais containers que compartilham um namespace de rede e um conjunto de volumes, agendados juntos em um único Node.

Esse Pod isolado é um beco sem saída em produção. Se o container dentro dele travar, o kubelet o reinicia no mesmo lugar. Se o Node reiniciar, ou alguém apagar o Pod, nada o recria. Nada guarda a memória de que ele deveria existir.

O que um Deployment adiciona a um Pod

Um Deployment é um objeto do Kubernetes que define quantas cópias de um Pod devem existir e como implantar mudanças nelas. Você para de gerenciar Pods diretamente e passa a descrever o estado desejado; um loop de controle se encarrega de tornar esse estado real. É o mesmo modelo de reconciliação por trás de tudo o mais no Kubernetes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web-app
          image: nginx:1.27
          ports:
            - containerPort: 80
1
2
kubectl apply -f web-app-deployment.yaml
kubectl get pods
1
2
3
4
NAME                       READY   STATUS    RESTARTS   AGE
web-app-7d9f8c7b86-4kxqz   1/1     Running   0          8s
web-app-7d9f8c7b86-9wj2p   1/1     Running   0          8s
web-app-7d9f8c7b86-x2p6t   1/1     Running   0          8s

Três Pods, não um, e nenhum se chama web-app. Esse padrão de nomenclatura (web-app-7d9f8c7b86-4kxqz) é o primeiro sinal de que algo mais está gerenciando esses Pods.

replicas: 3 é a mesma instrução que você dá com docker compose up --scale web=3 no Docker Compose. A diferença é que aqui um controller continua garantindo esse número muito depois de o comando terminar.

Como um Deployment realmente cria os Pods: o ReplicaSet no meio

Um Deployment não cria Pods diretamente. Ele cria um ReplicaSet, e é o ReplicaSet que cria os Pods. Você pode ver a cadeia inteira:

1
2
3
kubectl get deployment web-app
kubectl get replicaset -l app=web-app
kubectl get pods -l app=web-app
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
web-app   3/3     3            3           2m

NAME                 DESIRED   CURRENT   READY   AGE
web-app-7d9f8c7b86   3         3         3       2m

NAME                       READY   STATUS    RESTARTS   AGE
web-app-7d9f8c7b86-4kxqz   1/1     Running   0          2m
web-app-7d9f8c7b86-9wj2p   1/1     Running   0          2m
web-app-7d9f8c7b86-x2p6t   1/1     Running   0          2m

O nome do ReplicaSet é o nome do Deployment mais um hash do template do Pod (7d9f8c7b86); o nome de cada Pod é o nome do ReplicaSet mais um sufixo aleatório. kubectl describe pod web-app-7d9f8c7b86-4kxqz mostra a relação diretamente, no campo Controlled By: ReplicaSet/web-app-7d9f8c7b86.

Apague um desses Pods e a contagem cai para 2. Em segundos aparece um substituto. É o ReplicaSet notando a falta e criando um novo Pod a partir do mesmo template, não o Deployment agindo diretamente. O ReplicaSet é quem vigia. O Deployment existe para a única coisa que um ReplicaSet não consegue fazer sozinho: substituir um template de Pod de forma gradual em vez de tudo de uma vez.

O que um rollout faz aos ReplicaSets

Troque a imagem e aplique:

1
2
kubectl set image deployment/web-app web-app=nginx:1.27.1
kubectl rollout status deployment/web-app
1
2
3
Waiting for deployment "web-app" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "web-app" rollout to finish: 2 out of 3 new replicas have been updated...
deployment "web-app" successfully rolled out

Por trás dessa linha de status, o Deployment criou um segundo ReplicaSet para o novo template de Pod e o escalou para cima enquanto reduzia o antigo. Com a estratégia padrão RollingUpdate em 3 réplicas, isso resulta em um Pod de cada vez:

1
kubectl get replicaset -l app=web-app
1
2
3
NAME                 DESIRED   CURRENT   READY   AGE
web-app-7d9f8c7b86   0         0         0       6m
web-app-6b8f6d9c4d   3         3         3       40s

O ReplicaSet antigo não é apagado. Ele fica em zero réplicas, mantendo o template de Pod anterior como registro. É isso que torna o rollback rápido:

1
kubectl rollout undo deployment/web-app

O Kubernetes escala o ReplicaSet antigo de volta para cima e reduz o novo — sem reconstrução, sem novo pull de uma imagem antiga se ela ainda estiver em cache no Node. kubectl rollout history deployment/web-app --revision=1 ainda mostra exatamente qual imagem essa revisão executava.

Quando um Pod nu é a escolha certa

Um Pod nu não é um erro em todo contexto, só na maioria deles:

  1. Um container de diagnóstico descartável que você vai apagar em cinco minutos: kubectl run debug --image=busybox -it --rm -- sh.
  2. Um Job ou CronJob, que cria Pods através do seu próprio controller porque o trabalho precisa chegar ao fim em vez de continuar rodando.
  3. Inspecionar ou estudar a spec do Pod em si, antes de envolvê-la em algo que a gerencie.

Tudo que precisa continuar rodando após um crash, uma falha de Node ou uma atualização passa por um Deployment. Ou por um StatefulSet, para Pods que precisam de identidade estável e armazenamento próprio — um problema diferente, e um objeto diferente. Escreva o manifesto do Deployment por padrão e só desça para um Pod nu nos três casos acima.

Pod, ReplicaSet e Deployment lado a lado

PodReplicaSetDeployment
O que gerenciaContainersPodsReplicaSets
Substitui uma instância apagadaNãoSimSim, via seu ReplicaSet
Escala para N réplicasNãoSimSim
Rolling updatesNãoNãoSim
Rollback para uma versão anteriorNãoNãoSim
Você cria diretamenteRaramenteQuase nuncaNormalmente

Verifique se os seus próprios Pods têm um Deployment por trás

Execute isso contra o que já existe no seu cluster:

1
kubectl get deployment,replicaset,pod -l app=<seu-label>

Se só voltarem linhas de Pod, esses são Pods nus. É a lacuna a fechar antes que o próximo drain de Node derrube o app junto com eles.

Artigos relacionados