Pods: a menor unidade do Kubernetes

1. O que é um Pod? Conceitos Fundamentais

No ecossistema Kubernetes, o Pod é a menor unidade computacional que pode ser criada e gerenciada. Enquanto o Docker lida com containers individuais, o Kubernetes abstrai essa complexidade através dos Pods. Um Pod pode conter um ou mais containers que compartilham o mesmo ambiente de execução.

Pense no Pod como um "wrapper" ou cápsula que envolve um ou mais containers. Dentro de um Pod, todos os containers compartilham:
- Network namespace: mesmo endereço IP e porta
- Volumes: podem montar os mesmos volumes
- Hostname: compartilham o mesmo hostname

Essa arquitetura permite que containers dentro do mesmo Pod se comuniquem via localhost, eliminando a necessidade de descoberta de serviços para comunicação interna.

# Analogia visual de um Pod
+------------------------------------------+
|                 POD                       |
|  +------------------+  +----------------+ |
|  | Container 1      |  | Container 2    | |
|  | (App Principal)  |  | (Sidecar)      | |
|  | IP: 10.1.0.5     |  | IP: 10.1.0.5   | |
|  | Porta: 8080      |  | Porta: 9090    | |
|  +------------------+  +----------------+ |
|  | Volume Compartilhado (/var/log)       | |
|  +----------------------------------------+ |
+------------------------------------------+

2. Ciclo de Vida de um Pod

O Kubernetes gerencia o ciclo de vida dos Pods através de estados bem definidos:

Estados do Pod:
- Pending: Pod aceito pelo cluster, mas ainda não executando
- Running: Pod vinculado a um nó e containers em execução
- Succeeded: Containers finalizaram com sucesso (exit 0)
- Failed: Containers finalizaram com erro
- Unknown: Estado desconhecido (falha de comunicação)

As políticas de restart definem o comportamento após falha:
- Always: reinicia sempre (padrão para Deployments)
- OnFailure: reinicia apenas se houve erro
- Never: não reinicia automaticamente

# Exemplo de transição de estados
kubectl run nginx --image=nginx
# Estado: Pending -> ContainerCreating -> Running

3. Criando e Gerenciando Pods com Kubectl

Comandos Imperativos (linha de comando)

# Criar Pod diretamente
kubectl run meu-pod --image=nginx --restart=Never

# Listar Pods
kubectl get pods
kubectl get pods -o wide

# Detalhes do Pod
kubectl describe pod meu-pod

# Deletar Pod
kubectl delete pod meu-pod

Comandos Declarativos (manifestos YAML)

# manifesto-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: meu-nginx
  labels:
    app: nginx
    ambiente: producao
spec:
  containers:
  - name: nginx-container
    image: nginx:1.25
    ports:
    - containerPort: 80
# Aplicar manifesto
kubectl apply -f manifesto-pod.yaml

# Diferença principal:
# Imperativo: "faça isso agora" (kubectl run)
# Declarativo: "este é o estado desejado" (kubectl apply)

4. Pods com Múltiplos Containers e Sidecars

O padrão sidecar é uma das arquiteturas mais poderosas do Kubernetes. Consiste em adicionar containers auxiliares ao mesmo Pod para estender funcionalidades.

# pod-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-com-sidecar
spec:
  volumes:
  - name: logs-volume
    emptyDir: {}
  containers:
  - name: app-principal
    image: nginx:1.25
    volumeMounts:
    - name: logs-volume
      mountPath: /var/log/nginx
  - name: coletor-logs
    image: busybox
    command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
    volumeMounts:
    - name: logs-volume
      mountPath: /var/log/nginx

Casos de uso comuns para sidecars:
- Coleta de logs (como no exemplo acima)
- Proxy reverso (Envoy, Istio)
- Sincronização de arquivos (Git sync)
- Monitoramento e métricas

5. Recursos e Limites de Pods

Definir recursos adequadamente é crucial para o agendamento eficiente e estabilidade do cluster.

# pod-com-recursos.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-com-limites
spec:
  containers:
  - name: app
    image: nginx:1.25
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

Classes de QoS (Quality of Service):

# Guaranteed: requests == limits para todos os recursos
# Burstable: requests < limits (pelo menos um recurso)
# BestEffort: sem requests nem limits definidos

# Exemplo de QoS Guaranteed
resources:
  requests:
    memory: "128Mi"
    cpu: "500m"
  limits:
    memory: "128Mi"
    cpu: "500m"

# Exemplo de QoS BestEffort
# (sem requests nem limits)

6. Probes de Saúde: Liveness, Readiness e Startup

As probes garantem que o Kubernetes monitore e gerencie a saúde das aplicações automaticamente.

# pod-com-probes.yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-com-probes
spec:
  containers:
  - name: app
    image: nginx:1.25
    livenessProbe:
      httpGet:
        path: /healthz
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 5
    readinessProbe:
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 10
    startupProbe:
      httpGet:
        path: /startup
        port: 80
      failureThreshold: 30
      periodSeconds: 10

Diferenças entre as probes:
- Liveness: indica se o container precisa ser reiniciado (falha = restart)
- Readiness: indica se o container pode receber tráfego (falha = remove do Service)
- Startup: para aplicações lentas na inicialização (desativa liveness durante startup)

7. Volumes e Armazenamento em Pods

Volumes permitem persistir dados e compartilhar informações entre containers do mesmo Pod.

# pod-com-volumes.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-volumes
spec:
  volumes:
  - name: dados-efemeros
    emptyDir: {}
  - name: dados-persistentes
    persistentVolumeClaim:
      claimName: meu-pvc
  containers:
  - name: app-escritor
    image: busybox
    command: ["sh", "-c", "echo 'dados' > /dados/arquivo.txt; sleep 3600"]
    volumeMounts:
    - name: dados-efemeros
      mountPath: /dados
  - name: app-leitor
    image: busybox
    command: ["sh", "-c", "cat /dados/arquivo.txt; sleep 3600"]
    volumeMounts:
    - name: dados-efemeros
      mountPath: /dados

Tipos de volumes comuns:
- emptyDir: volume efêmero, criado com o Pod
- hostPath: diretório do nó hospedeiro
- persistentVolumeClaim: armazenamento persistente gerenciado pelo cluster
- configMap e secret: dados de configuração

8. Boas Práticas e Troubleshooting

Boas Práticas

# EVITE criar Pods diretamente em produção
# Prefira controladores como Deployment, StatefulSet ou DaemonSet

# Correto: kubectl create deployment nginx --image=nginx
# Incorreto: kubectl run nginx --image=nginx --restart=Never

# Sempre defina recursos (requests/limits) para evitar starvation
# Use labels para organização e seleção

Comandos de Debug Essenciais

# Logs do container
kubectl logs meu-pod
kubectl logs meu-pod -c meu-container
kubectl logs --tail=50 meu-pod

# Executar comando dentro do Pod
kubectl exec -it meu-pod -- /bin/bash
kubectl exec -it meu-pod -c meu-container -- sh

# Port forwarding (acesso local)
kubectl port-forward pod/meu-pod 8080:80

# Eventos do Pod
kubectl describe pod meu-pod
kubectl get events --field-selector involvedObject.name=meu-pod

Troubleshooting Rápido

# Verificar por que o Pod não está rodando
kubectl get pods --all-namespaces | grep Pending
kubectl describe pod meu-pod | grep -A5 Events

# Verificar logs de erro
kubectl logs meu-pod --previous  # logs da última execução

# Verificar estado do nó
kubectl get nodes
kubectl describe node nome-do-no

Referências