DevTools

Cheatsheet Kubernetes

Orquestração de contentores para deploy, escala e gestão automatizada

Voltar às linguagens
Kubernetes
114 cards encontrados
Categorias:
Versões:

Cluster e Contexto


12 cards
Info do cluster
kubectl cluster-info
kubectl cluster-info dump

kubectl get nodes
kubectl get nodes -o wide
kubectl top nodes

kubectl version --short

cluster-info mostra o endereço do API server e serviços. get nodes lista os nós do cluster com estado (Ready, NotReady). top nodes mostra uso de CPU/memória (requer metrics-server).

Estado dos nodes
kubectl get nodes -o wide
kubectl describe node worker-1

kubectl get nodes --show-labels
kubectl get nodes -l kubernetes.io/os=linux

kubectl cordon worker-1
kubectl uncordon worker-1

describe node mostra capacidade, condições e pods agendados. cordon marca o nó como indisponível para novos pods (manutenção). uncordon reverte. Labels como kubernetes.io/os permitem filtrar nós.

Labels e Selectors
kubectl get pods -l app=web
kubectl get pods -l 'env in (prod,staging)'
kubectl get pods -l app=web,tier=frontend

kubectl label pod meu-pod tier=frontend
kubectl label pod meu-pod tier-
kubectl get pods --show-labels

Labels são pares chave/valor que identificam recursos. -l filtra por selector. label pod tier=frontend adiciona; tier- remove. --show-labels mostra todas as labels de cada recurso.

Namespaces
kubectl get namespaces
kubectl get ns

kubectl create namespace dev
kubectl create namespace staging

kubectl get pods -n dev
kubectl get pods --all-namespaces
kubectl get pods -A

Namespaces isolam recursos logicamente dentro do mesmo cluster. -n ou --namespace especifica o namespace alvo. -A ou --all-namespaces lista recursos de todos os namespaces.

Drenar um node
kubectl drain worker-1 \
  --ignore-daemonsets \
  --delete-emptydir-data

kubectl drain worker-1 --force

kubectl uncordon worker-1

drain evacua um nó: termina pods gracefully e impede novos agendamentos. --ignore-daemonsets é necessário porque DaemonSets não podem ser evacuados. Após manutenção, uncordon reativa o nó.

Annotations
kubectl annotate pod meu-pod \
  description="Pod de teste"

kubectl annotate pod meu-pod description-

kubectl get pod meu-pod -o jsonpath=\
  '{.metadata.annotations}'

Annotations guardam metadados não-identificadores (descrições, URLs, contactos). Ao contrário das labels, não são usadas para seleção. annotate chave- remove a annotation.

Contextos e kubeconfig
kubectl config get-contexts
kubectl config current-context

kubectl config use-context prod-cluster
kubectl config set-context --current \
  --namespace=dev

kubectl config view

Um context combina cluster + utilizador + namespace. use-context troca de cluster/ambiente. set-context --current --namespace define o namespace padrão do contexto atual. O ficheiro ~/.kube/config guarda tudo.

Componentes do sistema
kubectl get componentstatuses
kubectl get pods -n kube-system

kubectl get pods -n kube-system -l \
  k8s-app=kube-dns

kubectl logs -n kube-system \
  -l k8s-app=kube-dns

O namespace kube-system contém os componentes core: API server, etcd, scheduler, controller-manager e CoreDNS. Verificar estes pods é o primeiro passo ao diagnosticar problemas do cluster.

Apagar recursos
kubectl delete pod meu-pod
kubectl delete pods --all -n dev
kubectl delete deployment web

kubectl delete -f manifest.yaml
kubectl delete pods -l app=legacy

kubectl delete pod meu-pod \
  --grace-period=0 --force

delete remove recursos por nome, label (-l) ou ficheiro (-f). --grace-period=0 --force força a remoção imediata (útil para pods presos em Terminating). Cuidado com --all.

Explorar a API
kubectl api-resources
kubectl api-resources --namespaced=true
kubectl api-versions

kubectl explain pod
kubectl explain pod.spec.containers
kubectl explain deployment.spec --recursive

api-resources lista todos os tipos de recurso disponíveis com os seus shortnames. explain mostra a documentação de um campo diretamente no terminal — útil para explorar a estrutura de qualquer objeto sem sair do CLI.

Output formatado
kubectl get pods -o wide
kubectl get pods -o yaml
kubectl get pods -o json

kubectl get pod meu-pod -o jsonpath=\
  '{.status.podIP}'

kubectl get pods -o custom-columns=\
  NAME:.metadata.name,STATUS:.status.phase

-o controla o formato de saída: wide (mais colunas), yaml, json. jsonpath extrai campos específicos. custom-columns cria tabelas personalizadas com os campos que quiser.

Dry-run e gerar YAML
kubectl run nginx --image=nginx \
  --dry-run=client -o yaml > pod.yaml

kubectl create deployment web \
  --image=nginx --replicas=3 \
  --dry-run=client -o yaml > deploy.yaml

kubectl apply -f pod.yaml --dry-run=server

--dry-run=client simula sem criar e -o yaml gera o manifesto — ideal para criar templates. --dry-run=server valida contra o API server sem persistir. Poupa tempo e evita erros de sintaxe YAML.

Pods


12 cards
Listar pods
kubectl get pods
kubectl get pods -o wide
kubectl get pods -A
kubectl get pods -w

kubectl get pods --field-selector \
  status.phase=Running

kubectl get pods --sort-by=.status.startTime

get pods lista pods do namespace atual. -w (watch) atualiza em tempo real. --field-selector filtra por campos como status.phase. -o wide adiciona IP e nó de cada pod.

Executar comandos
kubectl exec -it meu-pod -- sh
kubectl exec -it meu-pod -- bash

kubectl exec meu-pod -- ls /app
kubectl exec meu-pod -- cat /etc/config/app.yaml

kubectl exec -it meu-pod -c sidecar -- sh

exec corre comandos dentro de um contentor em execução. -it dá terminal interativo. Tudo após -- é o comando. -c seleciona o contentor em pods com múltiplos. Essencial para inspecionar o interior de pods.

Multi-container pods
spec:
  containers:
  - name: app
    image: myapp:1.0
  - name: sidecar
    image: fluentd:latest
  initContainers:
  - name: init-db
    image: busybox
    command: ['sh', '-c', 'sleep 5']

Um pod pode ter vários contentores que partilham rede e volumes. initContainers correm sequencialmente antes dos principais (setup, migrações). Padrões comuns: sidecar (logging, proxy) e ambassador (proxy de rede).

Criar pod imperativo
kubectl run nginx --image=nginx
kubectl run app --image=myapp:1.0 \
  --port=8080

kubectl run test --image=busybox \
  --rm -it -- sh

kubectl run debug --image=nicolaka/netshoot \
  --rm -it -- bash

run cria um pod diretamente. --rm -it cria um pod efémero com terminal interativo que se apaga ao sair — perfeito para debug. --port expõe a porta do contentor (não cria Service).

Port-forward
kubectl port-forward meu-pod 8080:80
kubectl port-forward svc/web 8080:80
kubectl port-forward deployment/web 8080:80

kubectl port-forward meu-pod 8080:80 \
  --address=0.0.0.0

port-forward cria um túnel local para um pod, Service ou Deployment. 8080:80 mapeia porta local 8080 para porta 80 do pod. Ideal para testar sem criar Service. --address=0.0.0.0 permite acesso externo.

Probes (health checks)
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 5
readinessProbe:
  httpGet:
    path: /ready
    port: 8080

livenessProbe reinicia o contentor se falhar (app presa). readinessProbe remove o pod do Service se não estiver pronto (ainda a arrancar). Tipos: httpGet, tcpSocket, exec. initialDelaySeconds dá tempo ao arranque.

Criar pod declarativo
apiVersion: v1
kind: Pod
metadata:
  name: meu-pod
  labels:
    app: web
spec:
  containers:
  - name: app
    image: nginx:1.25
    ports:
    - containerPort: 80

Um Pod é a menor unidade agendável. spec.containers define os contentores (pode ter vários). containerPort é informativo — a exposição real faz-se via Service. Aplique com kubectl apply -f pod.yaml.

Descrever pod
kubectl describe pod meu-pod

kubectl get pod meu-pod -o yaml
kubectl get events --field-selector \
  involvedObject.name=meu-pod

describe mostra detalhes completos: spec, estado, condições e Events no final. Os eventos revelam erros de agendamento, pull de imagem ou probes falhados. É o primeiro comando para diagnosticar um pod com problemas.

Copiar ficheiros
kubectl cp meu-pod:/app/log.txt ./log.txt
kubectl cp ./config.yaml meu-pod:/etc/config/

kubectl cp meu-pod:/data ./backup \
  -c sidecar

cp copia ficheiros entre o sistema local e um pod (como docker cp). Formato: pod:/caminho para remoto. -c especifica o contentor. Útil para extrair logs, configs ou injectar ficheiros de debug.

Logs
kubectl logs meu-pod
kubectl logs -f meu-pod
kubectl logs meu-pod --tail=100
kubectl logs meu-pod --since=1h

kubectl logs meu-pod -c sidecar
kubectl logs meu-pod --previous

logs mostra a saída do contentor. -f segue em tempo real (como tail -f). -c especifica o contentor em pods multi-container. --previous mostra logs do contentor anterior (após crash/restart).

Estados do pod
Pending     # aguarda agendamento/pull
Running     # em execução
Succeeded   # terminou com sucesso
Failed      # terminou com erro
Unknown     # estado indeterminado

CrashLoopBackOff  # reinicia em loop
ImagePullBackOff  # falha ao puxar imagem

Pending indica falta de recursos ou imagem a descargar. CrashLoopBackOff significa que o contentor termina repetidamente. ImagePullBackOff indica erro de imagem (nome errado, registry privado, sem credenciais).

Apagar pods
kubectl delete pod meu-pod
kubectl delete pods --all
kubectl delete pods -l app=legacy

kubectl delete pod meu-pod \
  --grace-period=0 --force

kubectl delete pod meu-pod --wait=false

Pods geridos por Deployments são recriados automaticamente ao serem apagados. --grace-period=0 --force força remoção imediata (pods presos). --wait=false não espera pela terminação. Para parar de vez, apague o Deployment.

Deployments e Rollouts


12 cards
Criar deployment
kubectl create deployment web \
  --image=nginx --replicas=3

kubectl apply -f deployment.yaml

kubectl get deployments
kubectl get rs

Um Deployment gere ReplicaSets que mantêm o número desejado de pods. create deployment é imperativo; apply -f é declarativo (preferido). get rs mostra os ReplicaSets criados.

Pausar e retomar rollout
kubectl rollout pause deployment/web
kubectl set image deployment/web \
  nginx=nginx:1.26
kubectl set resources deployment/web \
  --limits=cpu=500m,memory=256Mi
kubectl rollout resume deployment/web

pause congela o rollout para aplicar múltiplas alterações de uma vez. Ao resume, o Kubernetes faz um único rollout com todas as mudanças — evita múltiplos rollouts intermédios e reduz downtime.

Restart de deployment
kubectl rollout restart deployment/web

kubectl rollout status deployment/web

rollout restart reinicia todos os pods de forma controlada (rolling update) sem mudar a imagem. Útil após atualizar um ConfigMap ou Secret montado, ou para limpar estado em memória dos contentores.

Manifesto de Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.25

spec.selector.matchLabels deve corresponder às template.metadata.labels — o Deployment usa isso para saber quais pods gerir. template é o template de pod que o ReplicaSet replica.

Estratégia RollingUpdate
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

spec:
  strategy:
    type: Recreate

RollingUpdate substitui pods gradualmente (padrão). maxSurge = pods extra durante o update; maxUnavailable: 0 garante zero-downtime. Recreate termina todos antes de criar novos (há downtime).

Revision history limit
spec:
  revisionHistoryLimit: 5
  progressDeadlineSeconds: 300

revisionHistoryLimit controla quantas revisões antigas guardar (padrão: 10). progressDeadlineSeconds define o timeout para o rollout ser considerado falhado se não progredir. Ajuste conforme a velocidade dos seus deploys.

Atualizar imagem
kubectl set image deployment/web \
  nginx=nginx:1.26

kubectl apply -f deployment.yaml

kubectl rollout status deployment/web
kubectl rollout status deployment/web \
  --timeout=60s

set image atualiza a imagem de um contentor sem editar YAML. O formato é contentor=nova-imagem. rollout status acompanha o progresso da atualização até todos os pods estarem prontos.

ReplicaSet
kubectl get rs
kubectl get rs -l app=web
kubectl describe rs web-abc123

kubectl scale rs web-abc123 --replicas=5
kubectl delete rs web-abc123

O ReplicaSet garante que N pods com as labels certas estão sempre a correr. É criado automaticamente pelo Deployment. Raramente se cria diretamente — use sempre Deployment para ter rollouts e histórico.

MinReadySeconds
spec:
  minReadySeconds: 10
  template:
    spec:
      containers:
      - name: app
        image: myapp:1.0

minReadySeconds define quanto tempo um pod deve estar Ready antes de ser considerado disponível. Evita que o rollout avance demasiado rápido se a app demora a estabilizar após o readiness probe passar.

Rollback
kubectl rollout history deployment/web
kubectl rollout history deployment/web \
  --revision=2

kubectl rollout undo deployment/web
kubectl rollout undo deployment/web \
  --to-revision=2

rollout undo reverte para a revisão anterior. --to-revision=N reverte para uma revisão específica. rollout history lista as revisões. Por padrão, o Kubernetes guarda 10 revisões (revisionHistoryLimit).

Escalar deployment
kubectl scale deployment web --replicas=5
kubectl scale deployment web --replicas=0

kubectl get deployment web -o jsonpath=\
  '{.spec.replicas}'

scale ajusta o número de réplicas imediatamente. --replicas=0 pausa a app sem apagar o Deployment (todos os pods terminam). Útil para ambientes de staging que não precisam de estar sempre ativos.

Inspecionar deployment
kubectl get deployment web -o yaml
kubectl describe deployment web

kubectl get deployment web -o jsonpath=\
  '{.status.readyReplicas}'

kubectl get deployment web -o jsonpath=\
  '{.status.conditions[*].type}'

describe mostra réplicas, condições e eventos. status.readyReplicas indica quantos pods estão prontos. conditions revela Available, Progressing e ReplicaFailure para diagnóstico rápido.

Services e Networking


12 cards
Tipos de Service
ClusterIP     # interno (padrão)
NodePort      # porta em cada node
LoadBalancer  # LB externo (cloud)
ExternalName  # CNAME DNS

kubectl get svc
kubectl get svc -o wide

ClusterIP expõe só dentro do cluster (padrão). NodePort abre uma porta (30000-32767) em todos os nós. LoadBalancer provisiona um balanceador externo (AWS, GCP, Azure). ExternalName faz CNAME para um DNS externo.

DNS interno
# Formato:
# <svc>.<namespace>.svc.cluster.local

curl http://web.default.svc.cluster.local
nslookup web.default

# Mesmo namespace:
curl http://web

Cada Service recebe um registo DNS: <nome>.<namespace>.svc.cluster.local. Dentro do mesmo namespace, basta o nome (http://web). O CoreDNS no kube-system resolve estes nomes automaticamente.

Service sem selector
apiVersion: v1
kind: Service
metadata:
  name: db-externo
spec:
  ports:
  - port: 5432
---
apiVersion: v1
kind: Endpoints
metadata:
  name: db-externo
subsets:
- addresses:
  - ip: 10.0.0.50
  ports:
  - port: 5432

Um Service sem selector não cria Endpoints automaticamente. Pode criar Endpoints manuais apontando para IPs externos — útil para bases de dados fora do cluster, mantendo o mesmo padrão de DNS interno.

Criar Service imperativo
kubectl expose deployment web \
  --port=80 --target-port=8080

kubectl expose deployment web \
  --port=80 --type=NodePort

kubectl expose pod meu-pod --port=8080

expose cria um Service a partir de um Deployment ou Pod. --port é a porta do Service; --target-port é a porta do contentor. O selector é herdado automaticamente das labels do recurso exposto.

Headless Service
spec:
  clusterIP: None
  selector:
    app: web
  ports:
  - port: 80

Um Headless Service (clusterIP: None) não tem IP virtual. O DNS retorna diretamente os IPs dos pods. Usado com StatefulSets para dar DNS estável a cada pod (pod-0.svc.ns) ou para service discovery manual.

Session affinity
spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 3600

sessionAffinity: ClientIP encaminha pedidos do mesmo IP sempre para o mesmo pod (sticky sessions). Padrão é None (round-robin). Útil para apps com estado em memória, mas prefira stateless + cache externo.

Manifesto de Service
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: ClusterIP

O selector do Service deve corresponder às labels dos pods alvo. port é a porta do Service; targetPort é a porta do contentor. O Service distribui tráfego pelos pods que matcham o selector (load balancing interno).

Endpoints
kubectl get endpoints web
kubectl describe endpoints web

kubectl get endpointslice

Endpoints lista os IPs dos pods que o Service está a encaminhar. Se estiver vazio, o selector não matcha nenhum pod ou os pods não estão Ready. EndpointSlice é a versão escalável para clusters grandes.

Inspecionar Services
kubectl get svc -o wide
kubectl describe svc web

kubectl get svc web -o jsonpath=\
  '{.spec.clusterIP}'

kubectl get svc -A

describe svc mostra selector, portas, endpoints e tipo. clusterIP é o IP virtual interno. Se os Endpoints estiverem vazios, verifique se as labels dos pods correspondem ao selector do Service.

NodePort
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080

kubectl get svc web -o jsonpath=\
  '{.spec.ports[0].nodePort}'

NodePort expõe o Service numa porta fixa (30000-32767) de todos os nós. Acessível via IP-do-node:nodePort. Se nodePort não for especificado, o Kubernetes atribui automaticamente. Bom para dev/teste.

Multi-port Service
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  - name: metrics
    port: 9090
    targetPort: 9090

Um Service pode expor múltiplas portas. Cada porta precisa de um name quando há mais de uma. Útil para expor a app (80) e métricas (9090) no mesmo Service. O Ingress referencia pelo nome da porta.

NetworkPolicy básica
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-web
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - port: 8080

NetworkPolicy controla tráfego entre pods (firewall L3/L4). podSelector define os pods afetados. ingress.from especifica quem pode comunicar. Requer um CNI que suporte NetworkPolicy (Calico, Cilium).

ConfigMaps e Secrets


12 cards
Criar ConfigMap
kubectl create configmap app-config \
  --from-file=config.yaml

kubectl create configmap vars \
  --from-literal=ENV=prod \
  --from-literal=DEBUG=false

kubectl get configmaps

ConfigMap armazena configuração não-sensível em pares chave/valor. --from-file carrega ficheiros; --from-literal define valores inline. Cada chave fica disponível como variável de ambiente ou ficheiro montado.

Criar Secret
kubectl create secret generic db-pass \
  --from-literal=password=s3cret

kubectl create secret docker-registry \
  regcred --docker-server=registry.io \
  --docker-user=admin --docker-password=pass

kubectl get secrets

Secret guarda dados sensíveis (passwords, tokens, chaves). Valores são codificados em base64 (não encriptados por padrão). docker-registry cria credenciais para registries privados. Ative encriptação etcd em produção.

ImagePullSecrets
spec:
  imagePullSecrets:
  - name: regcred
  containers:
  - name: app
    image: registry.io/myapp:1.0

imagePullSecrets fornece credenciais para puxar imagens de registries privados. Crie com kubectl create secret docker-registry. Pode configurar no ServiceAccount para aplicar a todos os pods do namespace.

Manifesto de ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  ENV: "production"
  LOG_LEVEL: "info"
  app.properties: |
    server.port=8080
    server.host=0.0.0.0

data aceita pares chave/valor simples ou ficheiros completos (com | para multi-linha). Chaves com ponto (ex.: app.properties) são tratadas como nomes de ficheiro quando montadas como volume.

Manifesto de Secret
apiVersion: v1
kind: Secret
metadata:
  name: db-creds
type: Opaque
stringData:
  username: admin
  password: s3cret

# ou com base64:
data:
  password: czNjcmV0

stringData aceita valores em texto simples (o Kubernetes codifica). data exige valores já em base64. type: Opaque é o padrão; tipos especiais: kubernetes.io/tls, kubernetes.io/dockerconfigjson.

Editar ConfigMap/Secret
kubectl edit configmap app-config
kubectl edit secret db-creds

kubectl create configmap vars \
  --from-literal=ENV=staging \
  --dry-run=client -o yaml | kubectl apply -f -

edit abre o editor para modificar diretamente. O padrão --dry-run=client -o yaml | kubectl apply -f - recria o recurso com novos valores (útil em CI/CD). Volumes montados atualizam; env vars requerem restart do pod.

ConfigMap como env
env:
- name: ENV
  valueFrom:
    configMapKeyRef:
      name: app-config
      key: ENV

envFrom:
- configMapRef:
    name: app-config

configMapKeyRef injeta uma chave específica como variável. envFrom.configMapRef injeta todas as chaves do ConfigMap como variáveis de ambiente (nome da chave = nome da variável). Mais simples para configs com muitas chaves.

Secret como env
env:
- name: DB_PASS
  valueFrom:
    secretKeyRef:
      name: db-creds
      key: password

envFrom:
- secretRef:
    name: db-creds

secretKeyRef injeta uma chave do Secret como variável. envFrom.secretRef injeta todas as chaves. O valor é descodificado automaticamente. A app vê texto simples — o base64 é só transporte/armazenamento.

ConfigMap vs Secret
# ConfigMap: dados não-sensíveis
# - configs, URLs, flags
# - texto simples no etcd

# Secret: dados sensíveis
# - passwords, tokens, chaves
# - base64 no etcd (ative encriptação)

kubectl get cm app-config -o yaml
kubectl get secret db-creds -o yaml

Use ConfigMap para configuração não-sensível e Secret para credenciais. Ambos têm limite de 1 MiB. Secrets são base64 (não encriptados por padrão) — ative EncryptionConfiguration no etcd em produção.

ConfigMap como volume
volumes:
- name: config-vol
  configMap:
    name: app-config
volumeMounts:
- name: config-vol
  mountPath: /etc/config
  readOnly: true

Montar um ConfigMap como volume cria um ficheiro por chave em mountPath. Atualizações no ConfigMap propagam-se automaticamente (com delay). readOnly: true evita escrita acidental.

Secret como volume
volumes:
- name: secret-vol
  secret:
    secretName: db-creds
    defaultMode: 0400
volumeMounts:
- name: secret-vol
  mountPath: /etc/secrets
  readOnly: true

Montar um Secret como volume cria ficheiros com permissões restritas. defaultMode: 0400 garante leitura só pelo owner. Atualizações propagam-se automaticamente. Prefira volumes a env vars para secrets grandes.

Immutable ConfigMap/Secret
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
immutable: true
data:
  ENV: "production"

immutable: true impede alterações após criação (melhora performance do cluster — o kubelet não faz watch). Para atualizar, apague e recrie. Ideal para configs versionadas que mudam via novo Deployment.

Storage e Volumes


10 cards
PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dados-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard

Um PVC solicita armazenamento ao cluster. accessModes: ReadWriteOnce (1 nó), ReadOnlyMany (vários nós, leitura), ReadWriteMany (vários nós, escrita). O StorageClass define o provisionador.

Ver volumes e classes
kubectl get pv
kubectl get pvc
kubectl get storageclass
kubectl get sc

kubectl describe pvc dados-pvc
kubectl get pvc -o wide

get pv mostra volumes do cluster (globais). get pvc mostra claims por namespace. Estados: Bound (ligado), Pending (à espera). describe pvc revela eventos de provisionamento e erros de bind.

Expandir volume
kubectl edit pvc dados-pvc
# Alterar: storage: 10Gi -> 20Gi

kubectl get pvc dados-pvc

A expansão requer allowVolumeExpansion: true no StorageClass. Edite o PVC para aumentar o tamanho. Alguns provisionadores expandem online; outros requerem restart do pod. Reduzir não é suportado.

Usar PVC em Pod
volumes:
- name: dados
  persistentVolumeClaim:
    claimName: dados-pvc
containers:
- name: app
  volumeMounts:
  - name: dados
    mountPath: /var/data

O pod referencia o PVC pelo nome em volumes e monta em mountPath. Os dados persistem mesmo que o pod seja apagado ou recriado. O PVC deve estar no mesmo namespace do pod.

emptyDir
volumes:
- name: cache
  emptyDir: {}

- name: shared
  emptyDir:
    medium: Memory
    sizeLimit: 256Mi

emptyDir cria um volume temporário que vive enquanto o pod existir. Ideal para cache partilhado entre contentores do mesmo pod. medium: Memory usa RAM (tmpfs) para performance. Dados perdem-se ao apagar o pod.

Volume subPath
volumeMounts:
- name: config-vol
  mountPath: /etc/app/config.yaml
  subPath: config.yaml
- name: dados
  mountPath: /data/user1
  subPath: user1

subPath monta apenas um ficheiro/subdiretório do volume em vez do volume inteiro. Útil para montar um único ficheiro de um ConfigMap sem substituir o diretório todo. Não atualiza automaticamente com ConfigMaps.

PersistentVolume
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
spec:
  capacity:
    storage: 50Gi
  accessModes:
  - ReadWriteMany
  nfs:
    server: 10.0.0.10
    path: /exports/data

Um PV é o recurso de armazenamento real (NFS, iSCSI, cloud disk). Pode ser provisionado estaticamente (admin cria) ou dinamicamente (via StorageClass). O PVC faz bind a um PV compatível automaticamente.

hostPath
volumes:
- name: logs
  hostPath:
    path: /var/log/app
    type: DirectoryOrCreate

hostPath monta um diretório do nó no pod. O dado persiste no nó mas não migra com o pod. type: DirectoryOrCreate cria se não existir. Use com cautela — acopla o pod a um nó específico (evite em produção).

StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

StorageClass permite provisionamento dinâmico: ao criar um PVC, o PV é criado automaticamente. provisioner define o plugin (cloud, NFS, local). WaitForFirstConsumer atrasa a criação até um pod usar o PVC.

Reclaim policies
# Retain: PV mantém dados após PVC apagar
# Delete: PV e dados são apagados
# Recycle: dados apagados, PV reutilizável

kubectl patch pv pv-nfs -p \
  '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

reclaimPolicy define o que acontece ao PV quando o PVC é apagado. Retain preserva dados (seguro). Delete remove tudo (padrão em cloud). Recycle está deprecated. Configure no StorageClass ou PV.

Escala e Recursos


12 cards
Escalar manualmente
kubectl scale deployment web --replicas=5
kubectl scale deployment web --replicas=0

kubectl get deployment web
kubectl get pods -l app=web

scale ajusta réplicas imediatamente. O ReplicaSet cria ou termina pods para atingir o desejado. --replicas=0 para a app sem apagar o Deployment. Escalar para baixo termina pods (graceful shutdown).

ResourceQuota
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-dev
  namespace: dev
spec:
  hard:
    pods: "20"
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi

ResourceQuota limita o total de recursos por namespace. Impede que uma equipa esgote o cluster. Se a quota for atingida, novos pods são rejeitados. Combine com LimitRange para defaults por pod.

Pod Disruption Budget
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: web

O PDB garante disponibilidade mínima durante disrupções voluntárias (drain, upgrade). minAvailable: 2 garante pelo menos 2 pods ativos. Alternativa: maxUnavailable: 1. Protege contra downtime em manutenções.

HPA (Horizontal Pod Autoscaler)
kubectl autoscale deployment web \
  --min=2 --max=10 --cpu-percent=80

kubectl get hpa
kubectl describe hpa web
kubectl delete hpa web

O HPA ajusta réplicas automaticamente baseado em métricas. --cpu-percent=80 escala quando a média de CPU ultrapassa 80%. Requer metrics-server e requests definidos nos pods para calcular percentagens.

LimitRange
apiVersion: v1
kind: LimitRange
metadata:
  name: defaults
spec:
  limits:
  - default:
      cpu: "500m"
      memory: "256Mi"
    defaultRequest:
      cpu: "100m"
      memory: "64Mi"
    type: Container

LimitRange define defaults de requests/limits para contentores sem valores explícitos. Também pode impor min/max por contentor. Aplicado por namespace. Garante que nenhum pod fica sem limites definidos.

Topology spread
spec:
  topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        app: web

topologySpreadConstraints distribui pods uniformemente por nós, zonas ou regiões. maxSkew: 1 permite diferença máxima de 1 pod entre topologias. DoNotSchedule rejeita se não conseguir distribuir. Garante alta disponibilidade.

HPA declarativo
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 75

autoscaling/v2 suporta múltiplas métricas (CPU, memória, custom). scaleTargetRef aponta para o Deployment. averageUtilization é percentagem do request. O HPA verifica métricas a cada 15-30 segundos.

VPA (Vertical Pod Autoscaler)
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: web-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  updatePolicy:
    updateMode: "Auto"

O VPA ajusta requests/limits automaticamente baseado no uso real. updateMode: Auto reinicia pods com novos valores. Off só recomenda. Não use VPA e HPA por CPU ao mesmo tempo (conflito). Requer instalação extra.

Node affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values: [ssd]

nodeAffinity controla em que nós os pods são agendados. required é obrigatório; preferred é soft (peso). Mais flexível que nodeSelector simples. Use para SSDs, GPUs ou zonas específicas.

Requests e Limits
resources:
  requests:
    cpu: "250m"
    memory: "128Mi"
  limits:
    cpu: "500m"
    memory: "256Mi"

requests = recursos garantidos (usados no agendamento). limits = máximo permitido. CPU em millicores (250m = 0.25 core). Memória: Mi (mebibytes). Exceder o limit de memória causa OOMKilled; CPU é throttled.

Priority e Preemption
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: alta-prioridade
value: 1000000
globalDefault: false
description: "Pods críticos"
---
spec:
  priorityClassName: alta-prioridade

PriorityClass define prioridade numérica. Pods com maior prioridade podem preempt (terminar) pods de menor prioridade para obter recursos. Essencial para workloads críticos em clusters partilhados.

Pod affinity/anti-affinity
spec:
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: web
          topologyKey: kubernetes.io/hostname

podAntiAffinity espalha pods da mesma app por nós diferentes (HA). podAffinity agrupa pods relacionados no mesmo nó (cache local). topologyKey define o domínio: hostname, zona ou região.

Avançado


12 cards
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: app.exemplo.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web
            port:
              number: 80

Ingress encaminha tráfego HTTP/HTTPS externo para Services internos. host define o domínio; path define a rota. Requer um Ingress Controller (nginx, traefik, AWS ALB). Suporta TLS, rewrites e rate limiting.

ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
---
spec:
  serviceAccountName: app-sa
  containers:
  - name: app
    image: myapp:1.0

ServiceAccount dá identidade a pods para comunicar com a API. Cada pod usa o SA default se não especificar. Crie SAs dedicados com RBAC mínimo. O token é montado automaticamente em /var/run/secrets/.

StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres-headless
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: db
        image: postgres:15
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi

StatefulSet é para apps com estado (BDs, filas). Garante: nomes estáveis (postgres-0, postgres-1), DNS individual, storage persistente por pod e ordem de arranque/paragem. Requer Headless Service.

Ingress com TLS
spec:
  tls:
  - hosts:
    - app.exemplo.com
    secretName: tls-secret
  rules:
  - host: app.exemplo.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web
            port:
              number: 80

tls ativa HTTPS no Ingress. secretName referencia um Secret do tipo kubernetes.io/tls com tls.crt e tls.key. Combine com cert-manager para certificados automáticos via Let's Encrypt.

Jobs
apiVersion: batch/v1
kind: Job
metadata:
  name: backup
spec:
  completions: 1
  backoffLimit: 3
  template:
    spec:
      containers:
      - name: backup
        image: busybox
        command: ["sh", "-c", "echo backup done"]
      restartPolicy: Never

Um Job corre uma tarefa até completar. completions = execuções com sucesso necessárias. backoffLimit = tentativas antes de falhar. restartPolicy: Never ou OnFailure (nunca Always). Ideal para migrações e backups.

NetworkPolicy (egress)
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: database
    ports:
    - port: 5432

policyTypes: Egress controla tráfego de saída. Este exemplo só permite ao pod web comunicar com a porta 5432 no namespace database. Sem NetworkPolicy, todo o tráfego é permitido por padrão (zero-trust).

RBAC (Role e RoleBinding)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: leitor
  namespace: dev
rules:
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "watch"]
---
kind: RoleBinding
metadata:
  name: leitor-binding
subjects:
- kind: User
  name: dev
roleRef:
  kind: Role
  name: leitor

Role define permissões (recursos + verbs) num namespace. RoleBinding liga a Role a utilizadores/grupos/ServiceAccounts. ClusterRole/ClusterRoleBinding são globais. Princípio do menor privilégio.

CronJobs
apiVersion: batch/v1
kind: CronJob
metadata:
  name: backup-diario
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  template:
    spec:
      containers:
      - name: backup
        image: busybox
        command: ["sh", "-c", "echo backup"]
      restartPolicy: OnFailure

CronJob cria Jobs num horário (formato cron). concurrencyPolicy: Allow, Forbid (não sobrepõe), Replace (cancela o anterior). successfulJobsHistoryLimit controla quantos Jobs completados guardar.

Pod security standards
metadata:
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Labels de Pod Security Standards no namespace: privileged (sem restrições), baseline (mínimo), restricted (máximo). enforce bloqueia, audit regista, warn avisa. Substitui o deprecated PodSecurityPolicy.

RBAC imperativo
kubectl create role leitor \
  --verb=get,list,watch \
  --resource=pods,services -n dev

kubectl create rolebinding leitor-bind \
  --role=leitor --user=dev -n dev

kubectl auth can-i get pods -n dev
kubectl auth can-i delete pods --as=dev

create role e create rolebinding criam permissões via CLI. auth can-i verifica se uma ação é permitida. --as=dev simula outro utilizador. Essencial para validar permissões antes de dar acesso.

DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-agent
spec:
  selector:
    matchLabels:
      app: log-agent
  template:
    metadata:
      labels:
        app: log-agent
    spec:
      containers:
      - name: fluentd
        image: fluentd:latest

Um DaemonSet corre exatamente 1 pod em cada nó (ou subconjunto via nodeSelector). Quando um nó novo entra, o pod é criado automaticamente. Usado para logging (fluentd), monitoring (prometheus-node-exporter) e networking (CNI).

kubectl debug
kubectl debug meu-pod -it --image=busybox
kubectl debug meu-pod --image=nicolaka/netshoot \
  --target=app

kubectl debug node/worker-1 -it \
  --image=ubuntu

kubectl debug deployment/web \
  --image=curlimages/curl

debug cria um contentor efémero num pod existente (sem restart). --target partilha o namespace de rede do contentor alvo. debug node/ cria um pod privilegiado no nó. Ideal para diagnosticar pods sem ferramentas de debug.

Manifests YAML


12 cards
Estrutura básica
apiVersion: v1
kind: Pod
metadata:
  name: meu-pod
  labels:
    app: web
  annotations:
    team: backend
spec:
  containers:
  - name: app
    image: nginx

Todo manifesto tem 4 campos obrigatórios: apiVersion (versão da API), kind (tipo de recurso), metadata (nome, labels) e spec (estado desejado). metadata.name deve ser único no namespace.

Labels e selectors em manifests
metadata:
  labels:
    app: web
    version: v1
    tier: frontend
spec:
  selector:
    matchLabels:
      app: web
    matchExpressions:
    - key: version
      operator: In
      values: [v1, v2]

matchLabels exige correspondência exata. matchExpressions suporta operadores: In, NotIn, Exists, DoesNotExist. O selector do Deployment é imutável após criação — planeie bem as labels.

Security context
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
  - name: app
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]

securityContext define privilégios: runAsNonRoot impede root, readOnlyRootFilesystem impede escrita, drop: ALL remove capabilities Linux. Essencial para hardening em produção.

Multi-documento YAML
apiVersion: v1
kind: ConfigMap
metadata:
  name: config
data:
  ENV: prod
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  ports:
  - port: 80

--- separa múltiplos recursos num único ficheiro. kubectl apply -f processa todos sequencialmente. Ideal para agrupar recursos relacionados (Deployment + Service + ConfigMap) num só ficheiro versionado.

Environment variables
spec:
  containers:
  - name: app
    env:
    - name: DB_HOST
      value: "postgres.default"
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: NODE_IP
      valueFrom:
        fieldRef:
          fieldPath: status.hostIP

env define variáveis de ambiente. fieldRef injeta metadados do pod (nome, IP, namespace) — chamado Downward API. Útil para logging, service discovery e identificação do pod sem hardcoding.

Tolerations e taints
# Taint no node:
kubectl taint nodes worker-1 gpu=true:NoSchedule

# Toleration no pod:
spec:
  tolerations:
  - key: "gpu"
    operator: "Equal"
    value: "true"
    effect: "NoSchedule"

Taints repelem pods de nós. Tolerations permitem que um pod tolere o taint. Efeitos: NoSchedule (não agenda), PreferNoSchedule (evita), NoExecute (termina). Use para nós dedicados (GPU, maintenance).

Apply vs Create
kubectl apply -f manifest.yaml
kubectl create -f manifest.yaml

kubectl apply -f ./manifests/
kubectl apply -f https://url/manifest.yaml

kubectl diff -f manifest.yaml

apply é declarativo e idempotente: cria ou atualiza (merge). create falha se o recurso já existir. apply -f ./dir/ aplica todos os YAML do diretório. diff mostra o que mudaria sem aplicar.

Commands e args
spec:
  containers:
  - name: app
    command: ["sh", "-c"]
    args: ["echo $ENV && sleep 3600"]
    env:
    - name: ENV
      value: "production"

command substitui o ENTRYPOINT do Dockerfile. args substitui o CMD. Ambos aceitam arrays. Variáveis de ambiente definidas em env são expandidas em args. Essencial para init scripts e debug.

Owner references e GC
kubectl get rs -o yaml | grep ownerReferences -A5

kubectl delete deployment web \
  --cascade=foreground
kubectl delete deployment web \
  --cascade=orphan

ownerReferences ligam recursos (Deployment → ReplicaSet → Pod). Apagar o owner apaga os dependentes (garbage collection). --cascade=orphan remove o owner mas mantém os pods. foreground espera os dependentes serem apagados.

Kustomize
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
namePrefix: prod-
replicas:
- name: web
  count: 5
commonLabels:
  env: production

Kustomize personaliza manifests sem templates. namePrefix, replicas, patches e commonLabels transformam a base. Integrado no kubectl: kubectl apply -k ./overlays/prod/. Alternativa ao Helm.

Lifecycle hooks
lifecycle:
  postStart:
    exec:
      command: ["sh", "-c", "echo ready"]
  preStop:
    exec:
      command: ["sh", "-c", "sleep 10"]

postStart corre após o contentor iniciar (sem garantia de ordem com ENTRYPOINT). preStop corre antes de terminar — ideal para graceful shutdown (deregistar do LB, drenar conexões). O pod espera o preStop completar.

Validar manifests
kubectl apply -f manifest.yaml --dry-run=client
kubectl apply -f manifest.yaml --dry-run=server

kubectl apply -f manifest.yaml --validate=strict

kubeconform -f manifest.yaml
kubeval manifest.yaml

--dry-run=client valida sintaxe localmente. --dry-run=server valida contra o API server (mais completo). --validate=strict rejeita campos desconhecidos. Ferramentas externas: kubeconform, kubeval, datree.

Dicas e Troubleshooting


8 cards
Eventos do cluster
kubectl get events --sort-by=\
  .metadata.creationTimestamp

kubectl get events -n dev --field-selector \
  type=Warning

kubectl get events -A --watch

get events mostra eventos recentes (criação de pods, falhas de pull, OOM). --sort-by ordena cronologicamente. type=Warning filtra só erros. Eventos expiram após ~1 hora — use logging centralizado para histórico.

Backup e restore (etcd)
kubectl get all -A -o yaml > backup-all.yaml

kubectl get deployment,svc,cm,secret \
  -n prod -o yaml > prod-backup.yaml

kubectl apply -f prod-backup.yaml

# etcd snapshot (admin):
ETCDCTL_API=3 etcdctl snapshot save /backup.db

Exporte recursos com -o yaml para backup declarativo. get all não inclui tudo (faltam PVCs, Secrets, Roles). Para backup completo do cluster, faça snapshot do etcd. Ferramentas: Velero, kube-backup.

JSONPath e output custom
kubectl get pods -o jsonpath=\
  '{.items[*].metadata.name}'

kubectl get pods -o jsonpath=\
  '{.items[?(@.status.phase=="Running")].metadata.name}'

kubectl get nodes -o jsonpath=\
  '{range .items[*]}{.metadata.name}{"\t"}{.status.conditions[-1].type}{"\n"}{end}'

jsonpath extrai dados específicos do JSON. .items[*] itera arrays. ?(@.campo=="valor") filtra. range/end cria loops com formatação. Combine com xargs para automação de scripts.

Namespaces como ambientes
kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace prod

kubectl config set-context dev-ctx \
  --cluster=my-cluster --namespace=dev

kubectl get pods -n prod
kubectl top pods -n staging

Use namespaces para isolar ambientes (dev, staging, prod) ou equipas. Combine com ResourceQuota para limitar recursos e NetworkPolicy para isolar tráfego. Contextos com namespace padrão evitam -n constante.

Aliases úteis
alias k='kubectl'
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kgd='kubectl get deployments'
alias kaf='kubectl apply -f'
alias kdp='kubectl describe pod'
alias kl='kubectl logs -f'
alias kex='kubectl exec -it'

# Autocomplete:
source <(kubectl completion bash)
complete -o default -F __start_kubectl k

Aliases aceleram o uso diário do kubectl. completion bash ativa autocomplete de recursos e nomes. Adicione ao .bashrc ou .zshrc. Ferramentas como kubectx e kubens agilizam troca de contexto/namespace.

Boas práticas de produção
# 1. Sempre definir requests/limits
# 2. Usar liveness + readiness probes
# 3. runAsNonRoot: true
# 4. readOnlyRootFilesystem: true
# 5. Imagens com tag específica (não :latest)
# 6. PodDisruptionBudget para HA
# 7. topologySpreadConstraints
# 8. Secrets encriptados (etcd encryption)

Produção exige: requests/limits (evita noisy neighbors), probes (health checks), securityContext restritivo, tags de imagem fixas (reproducibilidade), PDB (disponibilidade em upgrades) e topologySpread (HA).

Debug de pods com problemas
kubectl get pods
kubectl describe pod meu-pod
kubectl logs meu-pod --previous
kubectl exec -it meu-pod -- sh

kubectl get events --field-selector \
  involvedObject.name=meu-pod

kubectl top pod meu-pod

Fluxo de debug: 1) get pods (estado), 2) describe (eventos), 3) logs --previous (crash anterior), 4) exec (interior), 5) top (recursos). CrashLoopBackOff → ver logs; Pending → verificar recursos/nós.

Ferramentas essenciais
# Gestão:
kubectl, kubectx, kubens, k9s

# Debug:
kubectl debug, stern (logs), ktop

# Segurança:
kube-bench, trivy, falco, opa

# Deploy:
helm, kustomize, argocd, flux

# Monitoring:
prometheus, grafana, loki

Ecossistema essencial: k9s (TUI), stern (multi-pod logs), helm (package manager), argocd (GitOps), prometheus+grafana (monitoring), trivy (scan de imagens), kube-bench (CIS benchmarks).