K8s em Exemplos: Pods

Um Pod é a unidade atômica de agendamento no Kubernetes. Ele envolve um ou mais containers que compartilham rede e armazenamento. Containers em um Pod se comunicam via localhost e compartilham o mesmo endereço IP, faixa de portas e volumes.

pod.yaml

Pods usam a API core v1. O kind informa ao Kubernetes qual recurso criar.

apiVersion: v1
kind: Pod

O name identifica unicamente o Pod dentro de seu namespace. Labels permitem seleção e agrupamento.

metadata:
  name: my-app
  labels:
    app: my-app

O array spec.containers define os containers. Cada um precisa de um nome e imagem.

spec:
  containers:
    - name: app
      image: nginx:alpine

Declare as portas do container. containerPort é principalmente documentação, mas Services podem referenciar portas nomeadas e ferramentas como Istio usam esses metadados.

      ports:
        - containerPort: 80
terminal

Estados do ciclo de vida do Pod: Pending (aguardando agendamento ou pull de imagem), Running (pelo menos um container rodando), Succeeded (todos containers terminaram com sucesso), Failed (container terminou com erro).

$ kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
my-app   0/1     Pending   0          0s
my-app   0/1     Pending   0          1s
my-app   0/1     ContainerCreating   0   2s
my-app   1/1     Running   0          5s
terminal

Razões comuns para Pending incluem CPU/memória insuficiente, nenhum node compatível (affinity/taints), ou problemas no pull de imagem. Verifique os Events para detalhes.

$ kubectl describe pod my-app | grep -A5 Events
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  10s   default-scheduler  Successfully assigned
  Normal  Pulled     8s    kubelet            Container image pulled
  Normal  Started    7s    kubelet            Started container app
terminal

Pods são efêmeros. Quando um Pod morre, ele se foi para sempre - novos Pods recebem novos IPs e identidades. Use esses comandos para debugar Pods em execução.

$ kubectl logs my-app
2024/01/15 10:30:00 [notice] nginx started
2024/01/15 10:30:00 [notice] ready to accept connections
terminal

Execute comandos dentro de um container em execução. Use -c container-name para Pods multi-container.

$ kubectl exec -it my-app -- sh
/ # hostname
my-app
/ # cat /etc/nginx/nginx.conf
terminal

Crie um Pod temporário de debug. A flag —rm o deleta quando você sai.

$ kubectl run debug --image=alpine --rm -it -- sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- http://my-app:80
<!DOCTYPE html>
<html>
multi-container-pod.yaml

O Kubernetes cria um container “pause” que mantém o namespace de rede. Containers de app se juntam a este namespace, compartilhando o mesmo IP e usando localhost.

apiVersion: v1
kind: Pod
metadata:
  name: web-metrics
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - containerPort: 80

Pods multi-container são para workloads fortemente acoplados. Padrões comuns: sidecar (logging, proxies), ambassador (proxy para serviços externos), adapter (transforma saída).

    - name: metrics
      image: prom/node-exporter
      ports:
        - containerPort: 9100
sidecar-pod.yaml

O padrão sidecar usa um volume compartilhado. A aplicação principal escreve logs, e o container sidecar os envia.

apiVersion: v1
kind: Pod
metadata:
  name: app-with-sidecar
spec:
  containers:
    - name: app
      image: my-app:v1
      ports:
        - containerPort: 8080
      volumeMounts:
        - name: logs
          mountPath: /var/log/app

O sidecar lê do mesmo volume e encaminha logs para sua infraestrutura de logging.

    - name: log-shipper
      image: fluent-bit:latest
      volumeMounts:
        - name: logs
          mountPath: /var/log/app

emptyDir cria um diretório temporário que é compartilhado entre containers e deletado quando o Pod termina.

  volumes:
    - name: logs
      emptyDir: {}
pod-resources.yaml

Requests e limits de recursos controlam alocação de CPU/memória. Sem limits, um Pod pode consumir todos os recursos do node.

apiVersion: v1
kind: Pod
metadata:
  name: app-with-resources
spec:
  containers:
    - name: app
      image: my-app:v1

requests são recursos garantidos usados para agendamento. limits são o máximo permitido. CPU é em millicores (100m = 0.1 cores).

      resources:
        requests:
          memory: "128Mi"
          cpu: "100m"
        limits:
          memory: "256Mi"
          cpu: "500m"
terminal

O deploy do Pod é atômico - ou todos os containers iniciam com sucesso, ou o Pod falha. Veja o spec completo do Pod com -o yaml.

$ kubectl get pod my-app -o yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: default
status:
  phase: Running
  podIP: 10.244.1.5
  conditions:
    - type: Ready
      status: "True"
terminal

Todo Pod recebe um IP único interno ao cluster. Pods podem se comunicar diretamente com qualquer outro Pod usando seu IP - sem NAT necessário.

$ kubectl get pod my-app -o wide
NAME     READY   STATUS    IP           NODE
my-app   1/1     Running   10.244.1.5   worker-1
terminal

Esta é a base do modelo de rede flat do Kubernetes. Todos os Pods podem alcançar uns aos outros diretamente por IP.

$ kubectl exec debug -- wget -qO- 10.244.1.5:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
terminal

Veja logs de uma instância anterior do container. Útil quando um container crashou e reiniciou.

$ kubectl logs my-app --previous
2024/01/15 10:29:00 [error] out of memory
2024/01/15 10:29:00 [notice] nginx shutting down

Índice | GitHub | Use as setas do teclado para navegar |