Cheatsheet Kubernetes
Orquestração de contentores para deploy, escala e gestão automatizada
Kubernetes
Cluster e Contexto
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
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: 8080livenessProbe 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: 80Um 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
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.25spec.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: RecreateRollingUpdate 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.0minReadySeconds 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
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: 80Um 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: 3600sessionAffinity: 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: ClusterIPO 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 -Adescribe 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: 9090Um 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: 8080NetworkPolicy 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
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.0imagePullSecrets 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.0data 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-configconfigMapKeyRef 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-credssecretKeyRef 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: trueMontar 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: trueMontar 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
PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dados-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standardUm 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/dataO 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: 256MiemptyDir 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/dataUm 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: DirectoryOrCreatehostPath 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
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: 16GiResourceQuota 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: webO 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: ContainerLimitRange 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: webtopologySpreadConstraints 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: 75autoscaling/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/hostnamepodAntiAffinity 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
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: 80Ingress 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.0ServiceAccount 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: 10GiStatefulSet é 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: 80tls 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: NeverUm 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: 5432policyTypes: 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: OnFailureCronJob 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: restrictedLabels 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:latestUm 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
Estrutura básica
apiVersion: v1
kind: Pod
metadata:
name: meu-pod
labels:
app: web
annotations:
team: backend
spec:
containers:
- name: app
image: nginxTodo 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.hostIPenv 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
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).