Kubernetes do Zero ao Profissional: 100 Exemplos com kubectl, Manifestos, Helm e GitOps
O Kubernetes executa contêineres em um conjunto de máquinas chamado cluster. Ele reinicia contêineres que falham, distribui-os entre os nós, publica novas versões sem interromper o serviço e os escala conforme a carga. Este artigo leva você do primeiro Pod até uma configuração pensada para produção, em 100 exemplos. Você vai aprender o kubectl e os contextos, Pods, Deployments e atualizações graduais, Services e Ingress, ConfigMaps e Secrets, armazenamento persistente, Jobs e CronJobs, StatefulSets e DaemonSets, escalonamento automático, requests de recursos e sondas, agendamento, RBAC e segurança de Pods, Helm e Kustomize, observabilidade e depuração, além de GitOps e backups. Nota de transparência: nenhum cluster Kubernetes nem o kubectl estavam instalados no computador usado para preparar este artigo, então nenhum dos 100 exemplos foi executado aqui. Os manifestos seguem a API atual do Kubernetes, mas aplique cada um em um cluster de teste antes de confiar nele.
O que você precisa
Docker Desktop com o Kubernetes integrado, ou kind ou minikube para um cluster local de prática, além do kubectl e do Helm. Conhecimentos básicos de contêineres ajudam; o artigo de Docker desta série é um bom começo. Alguns exemplos usam um provedor de nuvem, como o Azure Kubernetes Service, e um controlador de ingress. Use nomes de host de exemplo como shop.example.com e senhas de exemplo como <strong-password>, e nunca cole credenciais reais em manifestos ou comandos.
Como usar um exemplo
Os exemplos em bash usam kubectl, Helm e Kustomize. Os exemplos em YAML são salvos em um arquivo .yaml e aplicados com kubectl apply -f, usando o nome de arquivo indicado no texto. Os exemplos em Python usam o cliente oficial do Kubernetes para Python.
Tópico 1: Primeiros passos com o Kubernetes
O Kubernetes é um laço de controle. Você descreve o estado desejado em YAML, e o cluster continua trabalhando até que a realidade corresponda à descrição. Conheça as partes de um cluster, o cliente kubectl, os contextos e os namespaces.
Plano de controle e nós
O plano de controle guarda o estado desejado e toma decisões, e os nós de trabalho executam seus contêineres. Você se comunica com o cluster pelo servidor de API, e o kubectl é o cliente padrão que envia suas requisições.
Contextos e namespaces
Um contexto guarda qual cluster, usuário e namespace os seus comandos usam. Verifique com kubectl config current-context antes de alterar qualquer coisa, para nunca remover recursos do cluster errado.
Manifestos e mudança declarativa
Um manifesto tem apiVersion, kind, metadata e spec. O kubectl apply compara o seu arquivo com o cluster e altera apenas o que difere, o que torna as mudanças repetíveis e fáceis de revisar no Git.
Ilustrações
Exemplo 1: Verificar o cliente e o cluster
Confirme que o kubectl consegue falar com o cluster.
kubectl version --client
kubectl cluster-info
kubectl get nodes -o wide
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 2: Criar um cluster de prática com kind
Um cluster local no seu computador para aprender.
kind create cluster --name learn
kubectl config current-context
kubectl get nodes
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 3: Trocar de contexto
Escolha em qual cluster os comandos atuam.
kubectl config get-contexts
kubectl config use-context kind-learn
kubectl config view --minify --output "jsonpath={.current-context}"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 4: Criar um namespace
Separe equipes e aplicações dentro de um único cluster.
kubectl create namespace shop
kubectl config set-context --current --namespace=shop
kubectl get pods
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 5: Ler um manifesto
Os quatro campos de nível superior de todo objeto.
apiVersion: v1
kind: Namespace
metadata:
name: shop
labels:
team: platform
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 6: Aplicar um manifesto
Faça mudanças declarativas com kubectl apply.
kubectl apply -f namespace.yaml
kubectl get namespace shop --show-labels
kubectl describe namespace shop
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 2: Pods: a menor unidade
Um Pod é um ou mais contêineres que compartilham endereço de rede e armazenamento. A maioria dos Pods executa um contêiner, mas um Pod também pode conter auxiliares que precisam rodar ao lado da aplicação principal.
O que é um Pod
Todos os contêineres de um Pod compartilham o mesmo endereço IP e se comunicam pelo localhost. Os Pods são temporários: quando um morre, o cluster cria outro com novo nome e novo endereço, por isso não dependa do endereço de um Pod.
Contêineres init e sidecar
Os contêineres init rodam até terminar antes de os contêineres principais iniciarem, o que é útil para esperar um banco de dados. Os contêineres sidecar rodam ao lado do principal para registrar logs, fazer proxy ou sincronizar arquivos, e compartilham seus volumes.
Logs, eventos e exec
O kubectl logs mostra a saída, o kubectl describe mostra eventos como erros ao baixar a imagem e falhas de agendamento, e o kubectl exec abre um shell. Leia primeiro o describe, porque ele explica a maioria das falhas na inicialização.
Exemplo 7: Executar um Pod rapidamente
Um comando imperativo, apenas para testes rápidos.
kubectl run hello --image=nginx:1.27 --port=80
kubectl get pod hello -o wide
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 8: Um Pod declarativo
A menor unidade que você implanta.
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27
ports:
- containerPort: 80
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 9: Ler logs e eventos
Descubra o que aconteceu com um Pod.
kubectl logs web
kubectl logs web --previous
kubectl get events --sort-by=.lastTimestamp
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 10: Executar comandos dentro de um Pod
Depure por dentro.
kubectl exec -it web -- sh
kubectl exec web -- nginx -v
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 11: Port-forward para um Pod
Acesse um Pod pelo seu computador para testar.
kubectl port-forward pod/web 8080:80
curl http://localhost:8080
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 12: Dois contêineres compartilham um volume
O padrão sidecar.
apiVersion: v1
kind: Pod
metadata:
name: sidecar-demo
spec:
volumes:
- name: logs
emptyDir: {}
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "while true; do date >> /logs/app.log; sleep 5; done"]
volumeMounts:
- name: logs
mountPath: /logs
- name: log-reader
image: busybox:1.36
command: ["sh", "-c", "tail -F /logs/app.log"]
volumeMounts:
- name: logs
mountPath: /logs
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 13: Um contêiner init espera
Execute etapas de preparação antes de a aplicação iniciar.
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command: ["sh", "-c", "until nslookup db; do sleep 2; done"]
containers:
- name: app
image: nginx:1.27
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 14: Excluir Pods de teste
Limpe os objetos que não são mais necessários.
kubectl delete pod hello web sidecar-demo init-demo --ignore-not-found
kubectl get pods
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 3: Deployments e atualizações graduais
Você raramente cria Pods diretamente. Um Deployment gerencia um ReplicaSet, que mantém o número solicitado de Pods em execução, e faz atualizações graduais para que as novas versões substituam as antigas aos poucos.
Réplicas e seletores
O campo replicas define quantos Pods você quer. O seletor precisa corresponder aos rótulos dos Pods, para que o Deployment saiba quais Pods lhe pertencem. Uma divergência é rejeitada na criação.
Estratégia de atualização gradual
maxSurge define quantos Pods extras podem existir durante a atualização, e maxUnavailable define quantos podem faltar. Definir maxUnavailable como 0 mantém a capacidade total durante a publicação.
Histórico de rollout e rollback
Cada mudança cria um novo ReplicaSet e um número de revisão. O kubectl rollout undo volta para a versão anterior, e o kubectl rollout history lista as revisões para que você escolha uma específica.
Exemplo 15: Um Deployment mantém réplicas em execução
Atualizações graduais gerenciadas para você.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27
ports:
- containerPort: 80
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 16: Criar e acompanhar um Deployment
Verifique o status do rollout.
kubectl apply -f deployment.yaml
kubectl rollout status deployment/web
kubectl get deploy,rs,pods -l app=web
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 17: Escalar manualmente
Altere o número de réplicas.
kubectl scale deployment web --replicas=5
kubectl get pods -l app=web -o wide
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 18: Lançar uma nova imagem
Atualize a versão da aplicação.
kubectl set image deployment/web web=nginx:1.27.2
kubectl rollout status deployment/web
kubectl rollout history deployment/web
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 19: Reverter um lançamento ruim
Desfaça um rollout que deu errado.
kubectl rollout undo deployment/web
kubectl rollout undo deployment/web --to-revision=1
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 20: Controlar a atualização gradual
maxSurge e maxUnavailable.
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 21: Pausar e retomar um rollout
Agrupe várias mudanças juntas.
kubectl rollout pause deployment/web
kubectl set resources deployment/web -c web --limits=memory=256Mi
kubectl rollout resume deployment/web
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 22: Uma sonda de prontidão
O tráfego espera até a aplicação estar pronta.
containers:
- name: web
image: nginx:1.27
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 3
periodSeconds: 5
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 4: Services e redes
Os Pods surgem e desaparecem, então os clientes precisam de um nome e um endereço estáveis. Um Service seleciona Pods por rótulo e lhes dá um IP virtual e um nome DNS que não muda.
Tipos de Service
O ClusterIP só é acessível dentro do cluster. O NodePort abre uma porta em cada nó. O LoadBalancer pede ao provedor de nuvem um balanceador de carga externo. Escolha o tipo mais simples que atenda à necessidade.
DNS e endpoints
Cada Service recebe um nome DNS como web-svc.shop.svc.cluster.local, e dentro do mesmo namespace o nome curto funciona. O kubectl get endpoints mostra os endereços dos Pods por trás do Service, e é a primeira coisa a verificar quando um Service não responde.
Services headless
Com clusterIP definido como None, o DNS devolve os endereços dos Pods individuais em vez de um IP virtual. Bancos de dados e sistemas em cluster usam isso para que os clientes conversem com membros específicos.
Exemplo 23: Um Service ClusterIP
Um endereço estável dentro do cluster.
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: ClusterIP
selector:
app: web
ports:
- port: 80
targetPort: 80
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 24: Expor com kubectl
Um jeito rápido de criar um Service.
kubectl expose deployment web --port=80 --target-port=80 --name=web-svc
kubectl get svc web-svc
kubectl get endpoints web-svc
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 25: Chamar um Service a partir de um Pod temporário
Teste o DNS dentro do cluster.
kubectl run tmp-client --rm -it --image=busybox:1.36 --restart=Never -- wget -qO- http://web-svc
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 26: Um Service NodePort
Abre uma porta em cada nó.
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 80
nodePort: 30080
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 27: Um Service LoadBalancer
Um balanceador de carga da nuvem para acesso público.
apiVersion: v1
kind: Service
metadata:
name: web-public
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "false"
spec:
type: LoadBalancer
selector:
app: web
ports:
- port: 80
targetPort: 80
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 28: Encontrar o endereço externo
Leia o endereço atribuído pela nuvem.
kubectl get svc web-public -o jsonpath="{.status.loadBalancer.ingress[0].ip}"
kubectl get svc web-public -w
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 29: Uma porta nomeada
Use nomes de porta para trocar números com segurança.
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api
ports:
- name: http
port: 8000
targetPort: http
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 30: Um Service headless
Obtenha os endereços de cada Pod.
apiVersion: v1
kind: Service
metadata:
name: db-headless
spec:
clusterIP: None
selector:
app: db
ports:
- port: 5432
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 5: Configuração com ConfigMaps e Secrets
Mantenha a configuração fora da imagem. Os ConfigMaps guardam configurações comuns, e os Secrets guardam valores sensíveis. Ambos podem virar variáveis de ambiente ou arquivos dentro do Pod, então você altera configurações sem reconstruir a imagem.
ConfigMaps
Um ConfigMap guarda pares chave-valor ou arquivos inteiros. Use envFrom para carregar cada chave como variável de ambiente, ou monte o ConfigMap como diretório quando a aplicação lê um arquivo.
Secrets
Um Secret guarda valores codificados em base64. Base64 é codificação, não criptografia. Por isso, ative a criptografia em repouso no cluster, limite quem lê Secrets com RBAC e monte-os como arquivos sempre que possível.
Recarregando alterações
As variáveis de ambiente são lidas apenas na inicialização, então um ConfigMap alterado exige um novo rollout. Arquivos montados são atualizados com atraso, mas a aplicação precisa lê-los novamente. Planeje o recarregamento sempre que mudar a configuração.
Exemplo 31: Um ConfigMap a partir de valores literais
Guarde configurações que não são secretas.
kubectl create configmap app-config --from-literal=LOG_LEVEL=info --from-literal=FEATURE_X=on
kubectl get configmap app-config -o yaml
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 32: Um manifesto de ConfigMap
Configurações escritas em YAML.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: info
FEATURE_X: "on"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 33: ConfigMap como variáveis de ambiente
Carregue todas as chaves com envFrom.
containers:
- name: api
image: sample-api:1.4.2
envFrom:
- configMapRef:
name: app-config
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 34: Montar um ConfigMap como arquivos
Arquivos de configuração dentro do contêiner.
containers:
- name: web
image: nginx:1.27
volumeMounts:
- name: site-config
mountPath: /etc/nginx/conf.d
readOnly: true
volumes:
- name: site-config
configMap:
name: nginx-conf
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 35: Criar um Secret
Guarde uma senha sem gravá-la em um arquivo.
kubectl create secret generic db-secret --from-literal=DB_PASSWORD='<strong-password>'
kubectl get secret db-secret -o jsonpath="{.type}"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 36: Um manifesto de Secret
stringData permite escrever texto simples.
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
stringData:
DB_PASSWORD: <strong-password>
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 37: Ler o valor de um Secret
Verifique o valor decodificado e mantenha-o em sigilo.
kubectl get secret db-secret -o jsonpath="{.data.DB_PASSWORD}" | base64 --decode; echo
# Do not print secrets in shared logs or screenshots.
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 38: Montar um Secret como arquivos
Arquivos de credenciais somente leitura.
containers:
- name: api
image: sample-api:1.4.2
volumeMounts:
- name: db-creds
mountPath: /var/run/secrets/db
readOnly: true
volumes:
- name: db-creds
secret:
secretName: db-secret
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 6: Armazenamento persistente
Os contêineres perdem seus arquivos ao reiniciar. Um PersistentVolumeClaim pede armazenamento que sobrevive ao Pod, e um StorageClass diz ao cluster como criar esse armazenamento.
PV, PVC e StorageClass
Um PersistentVolume é o armazenamento em si, um PersistentVolumeClaim é o pedido por ele, e um StorageClass define como os volumes são criados sob demanda. A maioria dos clusters oferece um StorageClass padrão, então o claim costuma precisar apenas do tamanho.
Modos de acesso
ReadWriteOnce monta o volume em um nó por vez, o que serve para a maioria dos bancos de dados. ReadWriteMany permite que vários nós gravem, mas só alguns tipos de armazenamento suportam isso. Escolha o modo que o seu armazenamento oferece.
Política de reclaim
Delete remove o armazenamento quando o claim é excluído, e Retain mantém os dados para recuperação manual. Use Retain para dados que precisam sobreviver a uma exclusão acidental, e faça backup dos dados importantes em qualquer caso.
Exemplo 39: Um PersistentVolumeClaim
Peça armazenamento ao cluster.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 40: Um Pod que usa o claim
Os dados sobrevivem a reinícios do Pod.
apiVersion: v1
kind: Pod
metadata:
name: writer
spec:
containers:
- name: writer
image: busybox:1.36
command: ["sh", "-c", "echo hello >> /data/out.txt; sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 41: Verificar o armazenamento vinculado
Leia o status do claim e do volume.
kubectl get pvc data-pvc
kubectl get pv
kubectl describe pvc data-pvc
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 42: Escolher uma StorageClass
Escolha o tipo de disco.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: fast-pvc
spec:
storageClassName: managed-premium
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 43: Listar StorageClasses
Encontre a classe padrão.
kubectl get storageclass
kubectl get storageclass -o custom-columns=NAME:.metadata.name,DEFAULT:.metadata.annotations."storageclass\.kubernetes\.io/is-default-class"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 44: Expandir um claim
Aumente o armazenamento quando a classe permitir.
kubectl patch pvc data-pvc -p '{"spec":{"resources":{"requests":{"storage":"2Gi"}}}}'
kubectl get pvc data-pvc
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 45: Política de reclaim
Mantenha os dados depois que o claim for excluído.
apiVersion: v1
kind: PersistentVolume
metadata:
name: archive-pv
spec:
capacity:
storage: 5Gi
accessModes: ["ReadWriteOnce"]
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /srv/archive
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 46: Limitar o armazenamento efêmero
Interrompa arquivos temporários que crescem sem controle.
containers:
- name: worker
image: busybox:1.36
resources:
limits:
ephemeral-storage: 1Gi
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 7: Ingress e roteamento de tráfego
Um Ingress expõe rotas HTTP e HTTPS de fora do cluster para os Services. Ele roteia por nome de host e caminho, e termina o TLS, então um único endereço público pode atender várias aplicações.
Ingress e o controlador
Um recurso Ingress não faz nada sozinho. Um controlador de ingress, como o ingress-nginx, lê os objetos Ingress e configura o proxy. Instale um controlador por cluster e defina ingressClassName em cada Ingress.
Certificados TLS
A seção tls aponta para um Secret que contém o certificado e a chave. O cert-manager pode solicitar e renovar certificados automaticamente, então você não precisa acompanhar a validade manualmente.
Roteamento por caminho e host
As regras comparam nome de host e prefixo de caminho, e vence o caminho mais específico. Assim, /api pode ir para a API enquanto / vai para o site. Mantenha as rotas simples para que a tabela de roteamento seja fácil de revisar.
Exemplo 47: Ingress por nome de host
Roteamento HTTP para Services.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 48: Ingress com TLS
HTTPS usando um certificado guardado em um Secret.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-tls
spec:
ingressClassName: nginx
tls:
- hosts: [shop.example.com]
secretName: shop-tls
rules:
- host: shop.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 49: Instalar um ingress controller
Instale o controlador com o Helm.
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress ingress-nginx/ingress-nginx --namespace ingress --create-namespace
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 50: Rotear pelo caminho
Envie /api e / para Services diferentes.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop-routes
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 8000
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 51: Anotações de Ingress para uploads
Aumente o limite de tamanho de upload e o tempo limite de um site.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: upload-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
spec:
ingressClassName: nginx
rules:
- host: upload.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: uploader
port:
number: 80
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 52: Um ClusterIssuer do cert-manager
Peça certificados ao Let's Encrypt automaticamente.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
ingressClassName: nginx
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 53: Pedir um certificado pelo Ingress
Use uma anotação para o TLS ser gerenciado para você.
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts: [shop.example.com]
secretName: shop-tls
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 54: NetworkPolicy para a API
Somente a camada web pode alcançar a API.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow-web
spec:
podSelector:
matchLabels:
app: api
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels:
app: web
ports:
- port: 8000
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 8: Jobs e CronJobs
Nem toda carga de trabalho roda para sempre. Um Job executa uma tarefa até ela dar certo, e um CronJob inicia Jobs em um agendamento, como uma tabela cron que roda dentro do cluster.
Jobs e conclusões
Um Job cria Pods até que o número de conclusões solicitado tenha sucesso. O backoffLimit limita as tentativas. Use restartPolicy como Never ou OnFailure, porque Always não é permitido em Jobs.
Trabalho paralelo
O parallelism define quantos Pods rodam ao mesmo tempo, e o completions define quantas execuções bem-sucedidas são necessárias. Esse padrão processa um lote de itens com vários workers.
CronJobs e histórico
Um CronJob usa a sintaxe cron no agendamento. O concurrencyPolicy Forbid impede execuções sobrepostas, e os limites de histórico removem Jobs antigos para manter o cluster organizado.
Exemplo 55: Um Job roda até terminar
Tarefas pontuais, como migrações de banco de dados.
apiVersion: batch/v1
kind: Job
metadata:
name: db-migrate
spec:
backoffLimit: 2
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: sample-api:1.4.2
command: ["python", "manage.py", "migrate"]
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 56: Executar um Job e esperar
Aguarde a conclusão da tarefa e depois leia os logs.
kubectl apply -f job.yaml
kubectl wait --for=condition=complete job/db-migrate --timeout=120s
kubectl logs job/db-migrate
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 57: Um Job paralelo
Processe muitos itens com vários workers.
apiVersion: batch/v1
kind: Job
metadata:
name: thumbnails
spec:
completions: 10
parallelism: 3
template:
spec:
restartPolicy: OnFailure
containers:
- name: worker
image: thumbnailer:2.0
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 58: Um CronJob agendado
Gere um relatório todas as noites às 02:00.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "0 2 * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: report
image: reporter:1.1
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 59: Inspecionar e disparar CronJobs
Veja execuções anteriores e inicie uma manualmente.
kubectl get cronjob nightly-report
kubectl get jobs --sort-by=.metadata.creationTimestamp
kubectl create job --from=cronjob/nightly-report manual-report-1
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 60: Limites de histórico de Jobs
Evite que Jobs concluídos se acumulem.
spec:
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
startingDeadlineSeconds: 300
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 9: StatefulSets e DaemonSets
Algumas cargas precisam de identidade estável ou de um Pod por nó. Um StatefulSet dá aos Pods nomes ordenados e armazenamento próprio, e um DaemonSet executa uma cópia de um Pod em cada nó que atende ao critério.
Identidade do StatefulSet
Os Pods são nomeados name-0, name-1 e assim por diante, e cada um mantém o seu próprio claim criado a partir de volumeClaimTemplates. O nome permanece com o Pod ao reiniciar, o que serve para bancos de dados e brokers de mensagens.
Operações ordenadas
Por padrão, um StatefulSet inicia e para os Pods em ordem. Atualizações com partition permitem alterar primeiro os Pods de número mais alto, o que oferece um canário controlado para um sistema com estado.
DaemonSets
Um DaemonSet mantém um Pod em cada nó, o que serve para coletores de log, agentes de monitoramento e plugins de rede. O nodeSelector ou as tolerations o restringem a nós específicos.
Exemplo 61: Um StatefulSet
Nomes e armazenamento estáveis para bancos de dados.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis
replicas: 3
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 62: Verificar um StatefulSet
Nomes ordinais e um claim por Pod.
kubectl get statefulset redis
kubectl get pods -l app=redis
kubectl get pvc
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 63: Um DaemonSet
Um Pod em cada nó, para agentes.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-agent
spec:
selector:
matchLabels:
app: node-agent
template:
metadata:
labels:
app: node-agent
spec:
containers:
- name: agent
image: busybox:1.36
command: ["sh", "-c", "sleep 3600"]
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 64: Um DaemonSet em nós rotulados
Use nodeSelector para escolher os nós.
spec:
template:
spec:
nodeSelector:
workload: edge
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 65: Partição de um StatefulSet
Atualize primeiro apenas alguns Pods.
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 2
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 66: Escalar um StatefulSet com cuidado
Verifique os claims depois de reduzir.
kubectl get statefulset redis -o jsonpath="{.spec.replicas}"; echo
kubectl scale statefulset redis --replicas=2
kubectl get pvc -l app=redis
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 10: Escalonamento automático
A carga muda ao longo do dia. O escalonamento automático adiciona Pods quando a demanda sobe e os remove quando ela cai, então você paga pelo que usa e os usuários continuam recebendo respostas rápidas.
Horizontal Pod Autoscaler
O HPA compara uma métrica, como o uso médio de CPU, com um alvo e altera o número de réplicas. Ele precisa do metrics server e de requests de CPU nos Pods, porque o uso é medido em relação ao request.
Comportamento do escalonamento
O campo behavior controla a velocidade com que o HPA aumenta e reduz as réplicas. Uma janela de estabilização na redução evita oscilações rápidas depois de um pico curto.
Escalonamento orientado a eventos
O KEDA escala com base em sinais externos, como o tamanho de uma fila ou o atraso de mensagens, e pode reduzir até zero quando não há trabalho. Use-o para workers que consomem filas.
Exemplo 67: Uso de recursos em tempo real
O kubectl top precisa do metrics server.
kubectl top nodes
kubectl top pods -l app=web
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 68: Escalonamento automático por CPU
Adicione Pods quando a carga média estiver alta.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 69: Criar um HPA pela linha de comando
Escalone automaticamente e acompanhe a reação.
kubectl autoscale deployment web --min=2 --max=10 --cpu-percent=70
kubectl get hpa web -w
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 70: Escalonamento automático por memória
Use mais de uma métrica.
spec:
metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 71: Limitar a velocidade de redução do HPA
Evite oscilações com uma janela de estabilização.
spec:
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 60
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 72: Escalonamento orientado a eventos
Escale um worker pelo tamanho da fila com KEDA.
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: worker-scaler
spec:
scaleTargetRef:
name: worker
minReplicaCount: 0
maxReplicaCount: 20
triggers:
- type: rabbitmq
metadata:
queueName: orders
mode: QueueLength
value: "50"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 11: Recursos, sondas e agendamento
Informe ao Kubernetes quanta CPU e memória cada contêiner precisa, e como saber se ele está saudável. O agendador usa os requests para posicionar os Pods, e as sondas decidem quando reiniciar ou quando enviar tráfego.
Requests e limits
Um request é o que o agendador reserva para o contêiner. Um limit é o máximo que ele pode usar. Memória acima do limit faz o contêiner ser encerrado, e CPU acima do limit é limitada. Defina os dois com base no uso medido.
Sondas
A liveness probe reinicia um contêiner travado. A readiness probe remove o contêiner dos endpoints do Service enquanto ele não está pronto. A startup probe adia as outras sondas para aplicações que demoram a iniciar.
Distribuição e interrupções
As restrições de distribuição por topologia colocam as réplicas em nós ou zonas diferentes. O PodDisruptionBudget limita quantos Pods ações voluntárias, como o drain, podem remover ao mesmo tempo.
Exemplo 73: requests e limits
Como o escalonador e o kernel os usam.
containers:
- name: api
image: sample-api:1.4.2
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 512Mi
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 74: Uma sonda de liveness
Reinicie um contêiner travado.
livenessProbe:
httpGet:
path: /healthz
port: 8000
initialDelaySeconds: 10
periodSeconds: 15
failureThreshold: 3
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 75: Uma sonda de startup
Dê tempo para uma aplicação lenta iniciar.
startupProbe:
httpGet:
path: /healthz
port: 8000
failureThreshold: 30
periodSeconds: 10
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 76: Um PodDisruptionBudget
Mantenha réplicas suficientes durante a manutenção.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: web
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 77: Espalhar réplicas entre nós
Evite colocar todas as réplicas em uma única máquina.
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: web
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 78: Um PriorityClass
Mantenha Pods importantes agendados quando o cluster lotar.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: business-critical
value: 100000
globalDefault: false
description: "Keep these Pods running when the cluster is full."
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 12: Segurança: RBAC e segurança de Pods
O privilégio mínimo se aplica a pessoas e a aplicações. O RBAC decide quem pode fazer o quê, e as configurações de segurança do Pod limitam o que um contêiner pode fazer no nó.
ServiceAccounts, Roles e vínculos
Um ServiceAccount é a identidade de um Pod. Um Role lista os verbos permitidos sobre recursos em um namespace, e um RoleBinding o associa. Conceda apenas os verbos que a aplicação precisa, e evite o cluster-admin para aplicações.
Verificando acessos
O kubectl auth can-i testa uma permissão, opcionalmente como outro usuário ou ServiceAccount. Execute-o na etapa de revisão para que um erro apareça antes da implantação, e não depois de um incidente.
Segurança de Pods
Rótulos de namespace aplicam os Pod Security Standards, como o restricted, que bloqueia contêineres root e escalonamento de privilégios. Combine-os com um securityContext que remove capacidades e define o sistema de arquivos raiz como somente leitura.
Exemplo 79: Um ServiceAccount
Uma identidade para os Pods, com o token desativado.
apiVersion: v1
kind: ServiceAccount
metadata:
name: api-sa
automountServiceAccountToken: false
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 80: Um Role com privilégio mínimo
Ler ConfigMaps em um único namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: read-config
namespace: shop
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 81: Um RoleBinding
Vincule o role ao ServiceAccount.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: api-read-config
namespace: shop
subjects:
- kind: ServiceAccount
name: api-sa
namespace: shop
roleRef:
kind: Role
name: read-config
apiGroup: rbac.authorization.k8s.io
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 82: Verificar permissões com auth can-i
Valide o RBAC antes de implantar.
kubectl auth can-i list configmaps --as=system:serviceaccount:shop:api-sa -n shop
kubectl auth can-i delete pods --as=system:serviceaccount:shop:api-sa -n shop
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 83: Padrões de segurança de Pods
Aplique o perfil restricted em um namespace.
kubectl label namespace shop pod-security.kubernetes.io/enforce=restricted
kubectl label namespace shop pod-security.kubernetes.io/warn=restricted
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 84: Um contexto de segurança reforçado
Não root, somente leitura, sem capacidades extras.
securityContext:
runAsNonRoot: true
runAsUser: 10001
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefault
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 13: Helm e Kustomize
Aplicações reais têm muitos manifestos e vários ambientes. O Helm os empacota como charts com values, e o Kustomize mantém uma base e aplica pequenos overlays para cada ambiente.
Charts e releases do Helm
Um chart é um pacote de templates com valores padrão. Um release é uma instalação. Instale, atualize e reverta com o helm, e use --atomic para que uma atualização que falha seja revertida automaticamente.
Values por ambiente
Mantenha um arquivo de values por ambiente e passe-o com -f. Confira a saída renderizada com helm template antes de instalar, para saber exatamente o que vai chegar ao cluster.
Overlays do Kustomize
O Kustomize combina uma base com overlays que alteram réplicas, imagens ou rótulos sem templates. O kubectl apply -k aplica o resultado, e o kubectl diff mostra a mudança antes.
Exemplo 85: Instalar uma aplicação com Helm
Use um chart de um repositório.
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install shop-cache bitnami/redis --namespace shop --set architecture=standalone
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 86: Renderizar e verificar um chart
Visualize o YAML e valide-o no servidor.
helm template shop-web ./chart --values values-prod.yaml > rendered.yaml
kubectl apply --dry-run=server -f rendered.yaml
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 87: Um arquivo de values do Helm
Configurações de um ambiente.
replicaCount: 3
image:
repository: registry.example.com/team/web
tag: "1.4.2"
resources:
limits:
memory: 512Mi
ingress:
enabled: true
host: shop.example.com
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 88: Atualizar e reverter com Helm
Atualizações atômicas que se desfazem em caso de falha.
helm upgrade shop-web ./chart -n shop -f values-prod.yaml --atomic --wait
helm history shop-web -n shop
helm rollback shop-web 1 -n shop
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 89: Um overlay do Kustomize
Diferenças de ambiente sem templates.
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
replicas:
- name: web
count: 5
images:
- name: web
newTag: "1.4.2"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 90: Aplicar um overlay do Kustomize
Veja o diff primeiro e depois aplique.
kubectl kustomize overlays/prod | kubectl diff -f -
kubectl apply -k overlays/prod
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 14: Observabilidade e depuração
Quando um Pod se comporta mal, as respostas estão no seu status, nos eventos, nos logs e nas métricas. Uma rotina calma e ordenada encontra a maioria das falhas rapidamente, e os mesmos sinais alimentam painéis e alertas.
Status, eventos e describe
O kubectl get pod mostra a fase e a contagem de reinícios. O kubectl describe lista eventos como ImagePullBackOff, CrashLoopBackOff ou FailedScheduling, e explica por que o Pod está parado.
Logs de vários Pods
Selecione Pods por rótulo com kubectl logs -l e use --prefix para ver qual Pod escreveu cada linha. Use --previous para ler os logs de um contêiner que travou e reiniciou.
Contêineres de depuração efêmeros
O kubectl debug anexa um contêiner temporário a um Pod em execução, para que você use ferramentas que não estão na imagem da aplicação, sem reiniciar a aplicação.
Exemplo 91: Logs de vários Pods
Selecione Pods por rótulo.
kubectl logs -l app=web --all-containers --prefix --tail=20
kubectl logs -l app=web -f --max-log-requests=10
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 92: Por que um Pod não inicia
Leia a saída do describe e o estado do contêiner.
kubectl describe pod web-6d4cf56db6-abcde
kubectl get pod web-6d4cf56db6-abcde -o jsonpath="{.status.containerStatuses[0].state}"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 93: Um contêiner de depuração efêmero
Depure um Pod em execução sem reiniciá-lo.
kubectl debug -it web-6d4cf56db6-abcde --image=busybox:1.36 --target=web -- sh
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 94: Eventos e pressão no nó
Encontre problemas de capacidade e de despejo.
kubectl get events -A --sort-by=.lastTimestamp | tail -20
kubectl describe node worker-1 | grep -A5 "Conditions"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Tópico 15: Operação em produção e GitOps
Produção significa publicações repetíveis, manutenção segura e recuperação. O GitOps mantém o cluster alinhado a um repositório Git, e os backups protegem os objetos e os dados que não podem ser recriados.
GitOps
Uma ferramenta de GitOps, como o Argo CD, observa um repositório e aplica seus manifestos ao cluster. Cada mudança passa por um pull request, e o selfHeal reverte alterações manuais que se desviam do Git.
Manutenção sem interrupção
O kubectl drain move os Pods para fora de um nó antes de você atualizá-lo, e o PodDisruptionBudget mantém réplicas suficientes em execução. Execute kubectl uncordon quando o nó estiver pronto de novo.
Backups e recuperação
O Velero faz backup dos objetos do cluster e dos volumes persistentes em armazenamento de objetos. Teste a restauração em um cluster separado, porque um backup que nunca foi restaurado não está comprovado.
Exemplo 95: GitOps com Argo CD
Mantenha o cluster sincronizado com um repositório Git.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: shop
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/shop-deploy
targetRevision: main
path: overlays/prod
destination:
server: https://kubernetes.default.svc
namespace: shop
syncPolicy:
automated:
prune: true
selfHeal: true
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 96: Um Deployment de produção
Sondas, limites e um rollout seguro juntos.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
labels:
app: api
spec:
replicas: 3
revisionHistoryLimit: 5
selector:
matchLabels:
app: api
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.example.com/team/api:1.4.2
ports:
- containerPort: 8000
resources:
requests: {cpu: 250m, memory: 256Mi}
limits: {memory: 512Mi}
readinessProbe:
httpGet: {path: /ready, port: 8000}
livenessProbe:
httpGet: {path: /healthz, port: 8000}
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 97: Backup com Velero
Salve objetos e volumes do cluster no armazenamento.
velero install --provider azure --plugins velero/velero-plugin-for-microsoft-azure:v1.10.0 --bucket k8s-backups
velero backup create shop-daily --include-namespaces shop
velero backup describe shop-daily
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 98: Drenar e liberar um nó
Manutenção sem interromper os Pods.
kubectl cordon worker-1
kubectl drain worker-1 --ignore-daemonsets --delete-emptydir-data
kubectl uncordon worker-1
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 99: Verificar réplicas com Python
Use o cliente oficial do Kubernetes.
from kubernetes import client, config
config.load_kube_config()
apps = client.AppsV1Api()
for d in apps.list_namespaced_deployment("shop").items:
ready = d.status.ready_replicas or 0
print(d.metadata.name, f"{ready}/{d.spec.replicas}")
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Exemplo 100: Um script de checklist de lançamento
Interrompa o lançamento se uma verificação falhar.
#!/usr/bin/env bash
set -euo pipefail
NS="$1"
kubectl -n "$NS" rollout status deployment --timeout=180s
kubectl -n "$NS" get pdb
kubectl -n "$NS" auth can-i --list --as=system:serviceaccount:"$NS":default | grep -q "\*" && { echo "default account has wildcard rights"; exit 1; }
kubectl -n "$NS" get pods -o jsonpath="{range .items[*]}{.metadata.name}{' runAsRoot='}{.spec.securityContext.runAsNonRoot}{'\n'}{end}"
echo "release checks passed for namespace $NS"
*Este exemplo não foi executado aqui, porque nenhum cluster Kubernetes nem o kubectl estavam instalados no computador que preparou este artigo.*
Laboratório: implantar, expor e lançar uma pequena aplicação web
Reúna o artigo em um único cluster de prática: um Deployment com sondas e limites, um Service, um Ingress, um ConfigMap e um Secret, uma atualização gradual com rollback e uma checagem antes do lançamento.
1. Crie um cluster de prática com kind, depois crie o namespace shop e defina-o como padrão.
2. Aplique um Deployment com três réplicas, requests e limits de recursos, uma readiness probe e uma liveness probe.
3. Adicione um Service ClusterIP, verifique os endpoints e chame-o a partir de um Pod temporário.
4. Crie um ConfigMap para as configurações e um Secret para uma senha de exemplo, e monte os dois nos Pods.
5. Publique uma nova versão da imagem, acompanhe o rollout e desfaça com kubectl rollout undo.
6. Adicione um Ingress para shop.example.com e restrinja a API com uma NetworkPolicy.
7. Execute a checklist de lançamento do exemplo 100 no namespace e pare se alguma verificação falhar.
Próximos passos
Depois do laboratório, pratique em um cluster gerenciado em uma assinatura de sandbox, aprenda charts Helm para as suas próprias aplicações e configure o GitOps para que cada mudança seja revisada no Git. Guarde os exemplos em um repositório e execute-os de novo ao atualizar o cluster, porque as APIs do Kubernetes mudam entre versões.
Resumo
O Kubernetes mantém seus contêineres em execução, distribui-os entre os nós, os atualiza sem interromper o serviço e os escala conforme a demanda. Você aprendeu o kubectl e os contextos, Pods, Deployments e rollbacks, Services e Ingress, configuração e segredos, armazenamento, Jobs e CronJobs, StatefulSets e DaemonSets, escalonamento automático, requests de recursos e sondas, RBAC e segurança de Pods, Helm e Kustomize, depuração, e GitOps com backups para produção.