**Docker isolado:**Arquitetura do Kubernetes
- Muito útil para criar e rodar containers individualmente.
- Escalar manualmente exige iniciar múltiplos containers com comandos repetitivos.
- Dificuldade em monitorar e manter containers distribuídos em várias máquinas.
- Não resolve problemas de alta disponibilidade, orquestração e rede complexa.
Docker Compose:
- Permite definir múltiplos serviços (containers) em um único arquivo YAML.
- Ótimo para desenvolvimento e testes locais.
- Porém, não é ideal para produção porque:
- Não escala automaticamente.
- Não tem balanceamento de carga nativo.
- Não possui tolerância a falhas: se um container cair, ele não se recupera sozinho.
- Não gerencia clusters de múltiplas máquinas.
- Escala: em produção, precisamos de dezenas ou centenas de instâncias rodando. Fazer isso manualmente é impraticável.
- Disponibilidade: aplicações críticas precisam se manter ativas mesmo em falhas. Sem mecanismos automáticos, a queda de um container ou servidor gera indisponibilidade.
- Gerenciamento manual: administrar containers em várias máquinas exige lidar com:
- Rede entre containers distribuídos.
- Balanceamento de tráfego.
- Monitoramento e reinício em caso de falha.
- Atualizações sem downtime (rolling updates).
Esses desafios exigiram uma ferramenta capaz de automatizar e padronizar a execução de containers em larga escala.
-
Google Borg (anos 2000):
- Sistema interno do Google criado para rodar milhões de containers em seus datacenters.
- Fornecia automação, escalabilidade e resiliência muito antes da popularização do Docker.
-
Omega: sucessor do Borg, trazendo ideias mais flexíveis de agendamento e gestão de workloads.
-
2014: engenheiros do Google aproveitaram a experiência desses projetos e lançaram o Kubernetes como open-source.
Kubernetes herdou os conceitos de Borg e Omega, mas os tornou acessíveis à comunidade global, criando o padrão de fato para orquestração de containers.
O Kubernetes (ou K8s) é um sistema de orquestração de containers.
Seu papel é automatizar:
- Implantação (deploy) de containers.
- Escalonamento (scale up/down).
- Recuperação automática em falhas (self-healing).
- Balanceamento de carga.
- Atualizações sem interrupções.
Ele abstrai a complexidade de gerenciar múltiplos containers em múltiplos servidores, oferecendo uma visão unificada do cluster.
Hoje, o Kubernetes é mantido pela Cloud Native Computing Foundation (CNCF) e está presente em praticamente todos os grandes provedores de nuvem (AWS, GCP, Azure).
Crie dois containers usando Docker:
- Um container rodando nginx (porta 8080 → 80).
- Um container rodando httpd (Apache) (porta 8081 → 80).
Após subir os containers, acesse-os pelo navegador ou via curl.
Em seguida, pare manualmente um dos containers e observe o que acontece com o serviço.
Responda:
- O serviço continua disponível?
- O Docker sozinho possui algum mecanismo para reiniciar automaticamente o container?
- Que problema esse comportamento pode causar em um ambiente de produção?
Comandos esperados:
docker run -d --name nginx -p 8080:80 nginx
docker run -d --name apache -p 8081:80 httpdTestes:
- Acessar: http://localhost:8080 → Nginx
- Acessar: http://localhost:8081 → Apache
Parar container:
docker stop nginxRespostas:
- O serviço fica indisponível imediatamente após o container ser parado.
- O Docker não possui mecanismo nativo de orquestração para reiniciar containers falhos de forma inteligente (exceto se configurado com
--restart=always, mas ainda é limitado). - Em produção, se um container cair, o serviço ficaria fora do ar até intervenção manual → falta de resiliência e automação.
Conclusão: O Docker isolado não garante alta disponibilidade.
Crie um arquivo docker-compose.yml que defina:
- Um serviço backend usando
node:18(ou outro app simples). - Um serviço db usando
postgres:15, com usuário e senha definidos via variáveis de ambiente.
Suba os serviços com:
docker-compose up -dResponda:
- O Docker Compose consegue escalar o backend automaticamente caso haja aumento de tráfego?
- O que acontece se o container do banco cair?
- Quais limitações do Docker Compose você identifica para rodar essa aplicação em produção?
docker-compose.yml esperado (exemplo simplificado):
version: '3.9'
services:
backend:
image: node:18
command: ["node", "-e", "require('http').createServer((req,res)=>res.end('Hello')).listen(3000)"]
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: appdb
ports:
- "5432:5432"Execução:
docker-compose up -dRespostas:
- O Docker Compose não escala automaticamente; é preciso rodar manualmente:
docker-compose up --scale backend=3 -d
- Se o container do banco cair, o backend perde conexão até que o container seja reiniciado manualmente.
- Limitações identificadas:
- Não há balanceamento de carga nativo.
- Não há auto-recovery em caso de falhas.
- Não escala dinamicamente com base em métricas.
- Não possui mecanismos de monitoramento integrado.
- Não é ideal para clusters distribuídos em múltiplos hosts.
Conclusão: O Docker Compose é ótimo para desenvolvimento local, mas não atende aos requisitos de produção em larga escala.
O Docker por si só não instala o Kubernetes automaticamente.
O Kubernetes é um orquestrador de containers e precisa de sua própria instalação ou de uma ferramenta que simule um cluster local.
Para usar Kubernetes no seu ambiente, você tem algumas opções:
Alternativa ao Minikube, cria clusters Kubernetes dentro de containers Docker.
Instalação:
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kindCriar cluster:
kind create cluster- K3s → versão leve do Kubernetes, ideal para testes/IoT.
- Kubernetes oficial (kubeadm) → instala em múltiplas máquinas/VMs, recomendado para aprender produção.
Se quiser praticar já em nuvem:
- Google Kubernetes Engine (GKE)
- Amazon EKS
- Azure AKS
- Um cluster é o conjunto de máquinas (físicas ou virtuais) que trabalham em conjunto para executar aplicações em containers.
- Essas máquinas são chamadas de nós (nodes) e podem estar distribuídas em diferentes servidores, datacenters ou nuvens.
- O cluster oferece uma visão unificada: para o desenvolvedor, não importa em qual máquina o container está rodando, apenas que ele está dentro do cluster.
- Isso permite escalabilidade horizontal (mais máquinas adicionadas conforme a demanda cresce).
- O Control Plane é o cérebro do Kubernetes.
- Responsável por gerenciar o estado desejado do cluster, ou seja:
- Quantos Pods devem existir.
- Onde eles devem rodar.
- Como se comunicar entre si.
Principais componentes:
- API Server: ponto central de comunicação (
kubectl→ API Server). - etcd: banco chave-valor que guarda todo o estado do cluster.
- Scheduler: decide em qual Node cada Pod será alocado.
- Controller Manager: mantém o estado desejado (ex.: se 3 Pods caírem, cria 3 novos).
- Os Workers são os nós onde os containers realmente rodam.
Cada Worker possui:
- Kubelet: agente que recebe instruções do Control Plane e garante que os Pods estão rodando como esperado.
- Container Runtime: engine que executa os containers (Docker, containerd, CRI-O, etc.).
- Kube-Proxy: gerencia rede e balanceamento de tráfego entre Pods e Services.
Em resumo: o Control Plane decide o que precisa ser feito e os Workers executam.
- Um Pod é a menor unidade do Kubernetes.
- Pode conter um ou mais containers, que compartilham:
- Rede (mesmo IP e porta).
- Armazenamento (volumes).
Exemplo: um Pod pode ter um container de aplicação (Node.js) e outro de logging/monitoramento (sidecar).
Diferente do Docker isolado, o Kubernetes não gerencia containers individualmente, mas sim Pods.
- Um Deployment é um objeto que gerencia Pods de forma declarativa.
Funcionalidades:
- Criar e manter um número desejado de réplicas (ReplicaSet).
- Substituir Pods antigos por novos em atualizações (rolling updates).
- Garantir alta disponibilidade da aplicação.
Exemplo: você define no Deployment que quer 3 réplicas do Pod Nginx.
Se 1 falhar, o Kubernetes cria outro automaticamente.
- Um Service é a forma de expor Pods na rede de forma estável.
- Como os Pods são criados e destruídos dinamicamente, seus IPs mudam o tempo todo.
- O Service cria um endpoint fixo.
Tipos principais:
- ClusterIP: comunicação interna entre Pods.
- NodePort: expõe a aplicação em uma porta de cada nó do cluster.
- LoadBalancer: integração com balanceadores externos (usado em nuvem).
Exemplo: um Service expõe o Deployment do Nginx em http://node-ip:30000.
- Um Namespace permite dividir logicamente um cluster em múltiplos ambientes isolados.
- Útil para organizar aplicações, equipes ou ambientes (ex.: dev, test, prod).
Permite:
- Gerenciar permissões com mais granularidade (RBAC por namespace).
- Evitar conflitos de nomes entre objetos (Pods, Services, etc.).
- Limitar recursos (CPU/RAM) por namespace.
Exemplo: dois times podem rodar aplicações chamadas frontend, mas em namespaces diferentes (team1/frontend, team2/frontend).
Usando o comando kubectl, crie um Pod simples com a imagem Nginx.
- O Pod deve rodar com o nome
nginx-pode expor a porta 80. - Depois de criado, verifique se o Pod está em execução.
Responda:
- Qual a diferença entre criar um Pod diretamente e criar um Deployment?
- O que acontece se o Pod for excluído manualmente?
Comando para criar Pod:
kubectl run nginx-pod --image=nginx --port=80Verificar status:
kubectl get podsTestar logs ou shell dentro do Pod:
kubectl logs nginx-pod
kubectl exec -it nginx-pod -- curl localhostRespostas:
- Criar um Pod diretamente é útil para testes, mas ele não se recupera automaticamente se falhar. Já o Deployment gerencia Pods por meio de ReplicaSets, garantindo escalabilidade e resiliência.
- Se o Pod for excluído, ele não será recriado automaticamente → é efêmero.
📌 Conclusão: Pods isolados são frágeis, o recomendado em produção é sempre usar um Deployment.
- Crie um namespace chamado
meu-ambiente. - Crie um Deployment chamado
nginx-deploymentcom 3 réplicas da imagemnginx. - Exponha esse Deployment por meio de um Service do tipo
NodePort. - Acesse o Nginx pelo navegador ou via
curl.
Responda:
- Qual a vantagem de rodar em um namespace separado?
- Como o Service ajuda no acesso às réplicas do Deployment?
Criar namespace:
kubectl create namespace meu-ambienteCriar Deployment com 3 réplicas:
kubectl create deployment nginx-deployment --image=nginx --replicas=3 -n meu-ambienteExpor Deployment com NodePort:
kubectl expose deployment nginx-deployment --type=NodePort --port=80 -n meu-ambienteVerificar Service e obter porta:
kubectl get svc -n meu-ambienteSaída esperada (exemplo):
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-deployment NodePort 10.96.12.34 <none> 80:30080/TCP 1m
Habilitar a porta no kube:
kubectl port-forward svc/nginx-deployment 8080:80 -n meu-ambienteTestar acesso via navegador ou curl:
http://localhost:8080Respostas:
- O namespace isola recursos, evitando conflitos de nomes e permitindo aplicar políticas de segurança e quotas específicas.
- O Service age como um balanceador interno, distribuindo requisições entre os 3 Pods do Deployment.
📌 Conclusão: usar Deployment + Service + Namespace é a base da organização e resiliência no Kubernetes.
O Kubernetes possui uma arquitetura distribuída organizada em dois grandes blocos:
- Plano de Controle (Control Plane): responsável por orquestrar, tomar decisões e manter o estado desejado.
- Plano de Execução (Data Plane / Nodes): responsável por executar os containers (via Pods).
- É o ponto central de comunicação no Kubernetes.
- Tudo no Kubernetes é controlado via API, e o kube-apiserver expõe essa interface.
- Ferramentas como
kubectl, dashboards ou aplicações externas falam sempre com o API Server.
Funções principais:
- Validar e processar requisições.
- Salvar o estado desejado no etcd.
- Distribuir instruções para os outros componentes do Control Plane.
➡️ Analogia: é o “balcão de atendimento” do cluster, onde você faz os pedidos.
- É o banco de dados chave-valor distribuído usado pelo Kubernetes.
- Guarda o estado atual e desejado do cluster (todos os objetos: Pods, Deployments, ConfigMaps, etc.).
- Possui alta consistência, usando o algoritmo Raft para consenso.
Funções:
- Armazena toda a configuração.
- Permite recuperar o cluster em caso de falhas.
- Atua como a “memória” do Kubernetes.
➡️ Sem o etcd, o cluster perde a capacidade de lembrar o que deve estar rodando.
- É o gerente automático do Kubernetes.
- Monitora constantemente o estado do cluster (no etcd) e garante que ele esteja conforme o estado desejado.
Funções principais:
- Criar novos Pods quando há menos réplicas do que o especificado.
- Substituir Pods que falharam.
- Gerenciar Jobs, Endpoints, Service Accounts e outros recursos.
Exemplo: você definiu 3 réplicas no Deployment → se 1 Pod cair, o Controller Manager cria outro para manter as 3 ativas.
- Responsável por decidir em qual nó (Worker) cada Pod vai rodar.
Critérios usados na decisão:
- Recursos disponíveis (CPU, memória).
- Restrições de afinidade ou anti-afinidade.
- Políticas de balanceamento de carga.
➡️ O Scheduler não executa o Pod, apenas decide o melhor lugar.
➡️ A execução real é feita pelo Kubelet do nó escolhido.
Analogia: é como um “despachante” que encaminha cada carga para o caminhão certo.
- É um agente que roda em cada nó do cluster.
Funções principais:
- Recebe instruções do API Server (via Control Plane).
- Garante que os Pods definidos estejam de fato rodando no nó.
- Se um container cair, tenta reiniciá-lo.
- Reporta o status dos Pods para o Control Plane.
➡️ É como o “supervisor local” de cada máquina.
- Responsável por gerenciar a rede do cluster.
Funções principais:
- Implementar as regras de rede (iptables ou IPVS).
- Balancear tráfego entre Pods que fazem parte de um mesmo Service.
- Permitir que um Pod em um nó consiga se comunicar com outro Pod em outro nó.
➡️ Em resumo: garante que os Pods consigam conversar entre si e com o mundo externo.
- Control Plane: API Server, etcd, Controller Manager, Scheduler.
- Data Plane (Workers): Kubelet, Kube-Proxy, Container Runtime.
Fluxo simplificado:
- O usuário aplica uma configuração (
kubectl apply). - O API Server registra no etcd.
- O Controller Manager detecta mudanças e pede ao Scheduler a alocação de Pods.
- O Scheduler escolhe o nó.
- O Kubelet executa o Pod no nó.
- O Kube-Proxy garante comunicação em rede.
Utilize os comandos kubectl para verificar o estado dos componentes principais do cluster Kubernetes.
Execute:
kubectl get componentstatus
kubectl cluster-infoObserve os resultados e responda:
- Quais componentes críticos do Control Plane aparecem no status?
- O que o comando
kubectl cluster-infomostra sobre o ambiente? - Qual seria o impacto se o etcd ficasse indisponível?
Comandos esperados:
kubectl get componentstatus
kubectl cluster-infoSaída esperada (exemplo simplificado):
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
Kubernetes control plane is running at https://127.0.0.1:6443
CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Respostas:
- Os principais componentes visíveis são scheduler, controller-manager e etcd (parte do Control Plane).
- O
kubectl cluster-infoexibe informações sobre o API Server e os serviços de DNS do cluster. - Se o etcd parar, o cluster perde a “memória” do estado desejado e estado atual, impossibilitando gerenciar os recursos.
📌 Conclusão: esses comandos permitem verificar rapidamente se o Control Plane está saudável.
- É a menor unidade executável no Kubernetes.
- Representa um ou mais containers que compartilham:
- Rede (mesmo IP e portas).
- Armazenamento (mesmos volumes).
- Container 1: aplicação Node.js.
- Container 2: sidecar para logging ou proxy.
- Pods são efêmeros: podem ser destruídos e recriados a qualquer momento.
- Por isso, não devemos tratá-los como servidores fixos, mas como instâncias transitórias.
- Não criamos Pods diretamente em produção, e sim via controllers como Deployment.
- Objeto que garante que um número específico de réplicas de um Pod esteja sempre em execução.
- Substituir Pods que falham.
- Escalar horizontalmente (aumentar/diminuir réplicas).
Exemplo: se definimos
replicas: 3no ReplicaSet, sempre haverá 3 instâncias ativas do Pod.
- Atualmente, o ReplicaSet é geralmente gerenciado indiretamente por um Deployment.
- É o objeto mais usado no Kubernetes para aplicações stateless.
- Abstrai e gerencia ReplicaSets e Pods.
- Declarar o estado desejado (ex.: 5 réplicas de um Pod).
- Criar e atualizar réplicas.
- Realizar rolling updates (atualizações sem downtime).
- Suporte a rollbacks (reverter para versão anterior).
Exemplo:
kubectl apply -f deployment.yamlO Kubernetes cria Pods, garante o número de réplicas e cuida das atualizações.
- Objeto responsável por expor os Pods de maneira estável na rede.
- Como os Pods são efêmeros e seus IPs mudam, o Service fornece um endereço fixo.
- ClusterIP (padrão): acessível apenas dentro do cluster.
- NodePort: expõe o Service em uma porta específica de cada nó (
http://node-ip:30000). - LoadBalancer: integra com provedores de nuvem para fornecer IP público e balanceamento de carga.
Exemplo:
Um Deployment de Nginx com 3 réplicas pode ser exposto por um Service NodePort em
http://localhost:30080.
- ConfigMap: armazena configurações não sensíveis (strings, variáveis de ambiente, arquivos de config).
- Secret: armazena informações sensíveis (senhas, tokens, certificados).
- Usados para separar código de configuração.
- ConfigMap: URL do banco de dados, nome da aplicação.
- Secret: senha do banco, chave de API, certificado TLS.
🛡️ Boas práticas: Nunca embutir segredos diretamente no Pod ou Deployment.
Sempre usarSecret.
- Containers e Pods são efêmeros: se caírem, os dados desaparecem.
- Volumes permitem associar armazenamento aos Pods.
emptyDir: criado junto com o Pod, descartado ao morrer.hostPath: usa diretório da máquina host.- PersistentVolume (PV) e PersistentVolumeClaim (PVC):
- Armazenamento persistente, independente do ciclo de vida do Pod.
Exemplo:
Um banco de dados rodando no Kubernetes precisa de um PVC para garantir que os dados não sejam perdidos em reinícios.
- Objeto responsável por roteamento HTTP/HTTPS avançado.
- Roteamento baseado em hostnames ou paths (ex.:
/api→ backend,/app→ frontend). - Terminação TLS/HTTPS (certificados).
- Regras centralizadas de entrada para múltiplos Services.
- Requer um Ingress Controller (como NGINX, Traefik, HAProxy).
https://app.minhaempresa.com→ encaminha tráfego para o Service frontend.https://api.minhaempresa.com→ encaminha tráfego para o Service backend.
| Objeto | Função |
|---|---|
| Pod | Unidade mínima (containers agrupados). |
| ReplicaSet | Garante número fixo de réplicas de Pods. |
| Deployment | Gerencia Pods/ReplicaSets com atualizações automáticas. |
| Service | Expõe Pods de forma estável (rede). |
| ConfigMap/Secret | Gerenciamento de configuração e credenciais. |
| Volumes/PVC | Armazenamento persistente. |
| Ingress | Roteamento HTTP/HTTPS externo para múltiplos Services. |
Crie um Deployment chamado nginx-deployment no namespace default.
- Ele deve ter 2 réplicas de Pods usando a imagem
nginx:latest. - Exponha esse Deployment usando um Service do tipo
ClusterIPna porta 80.
Verifique:
- Quantos Pods foram criados?
- O Service tem um ClusterIP fixo?
- Se um Pod for deletado manualmente, o que acontece?
Criar Deployment:
kubectl create deployment nginx-deployment --image=nginx:latest --replicas=2Expor Deployment com Service ClusterIP:
kubectl expose deployment nginx-deployment --type=ClusterIP --port=80 --target-port=80Verificar recursos criados:
kubectl get deployments
kubectl get pods
kubectl get svcRespostas:
- Foram criados 2 Pods pelo Deployment.
- O Service possui um ClusterIP interno e estável dentro do cluster.
- Se um Pod for deletado manualmente, o Deployment cria outro automaticamente → self-healing via ReplicaSet.
📌 Conclusão: Deployment + Service garantem escalabilidade e disponibilidade.
-
Crie um ConfigMap chamado
app-configcom a variável:
APP_MODE=production -
Crie um Secret chamado
db-secretcom a chave:
DB_PASSWORD=kubepass123 -
Crie um Pod chamado
app-podque:- Usa a imagem busybox.
- Exporta as variáveis de ambiente a partir do ConfigMap e do Secret.
- Executa o comando
envpara exibir as variáveis.
Responda:
- Qual a diferença entre ConfigMap e Secret?
- Por que não é recomendável armazenar credenciais em ConfigMaps?
Criar ConfigMap:
kubectl create configmap app-config --from-literal=APP_MODE=productionCriar Secret:
kubectl create secret generic db-secret --from-literal=DB_PASSWORD=kubepass123Pod YAML (app-pod.yaml):
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "env && sleep 3600"]
env:
- name: APP_MODE
valueFrom:
configMapKeyRef:
name: app-config
key: APP_MODE
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PASSWORDAplicar Pod:
kubectl apply -f app-pod.yamlVerificar variáveis:
kubectl logs app-podRespostas:
- ConfigMap: guarda configurações não sensíveis (ex.: URLs, modos de execução).
- Secret: armazena dados sensíveis (senhas, tokens, certificados).
- Não é recomendável usar ConfigMap para credenciais porque ele não oferece proteção extra (apenas texto puro), enquanto Secrets podem ser criptografados em repouso no cluster.
📌 Conclusão: ConfigMap e Secret ajudam a separar código de configuração, mas cada um tem um uso específico.
O Pod é a menor unidade executável no Kubernetes.
Nele definimos o container (imagem, portas, recursos).
Exemplo: subir um servidor Nginx em um Pod:
apiVersion: v1
kind: Pod
metadata:
name: meu-pod
spec:
containers:
- name: nginx-container
image: nginx:1.23
ports:
- containerPort: 80📌 Esse Pod já roda a aplicação, mas não é suficiente para produção (se ele cair, não se recupera).
O Deployment cria e gerencia múltiplas réplicas do Pod.
Garante alta disponibilidade e suporte a atualizações automáticas.
apiVersion: apps/v1
kind: Deployment
metadata:
name: meu-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:1.23
ports:
- containerPort: 80📌 Agora temos 3 réplicas do Pod rodando. Se uma falhar, o Kubernetes cria outra automaticamente.
Os Pods são efêmeros e mudam de IP constantemente.
Um Service fornece um ponto fixo de acesso.
Podemos escolher o tipo: ClusterIP, NodePort, LoadBalancer.
apiVersion: v1
kind: Service
metadata:
name: meu-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort📌 Agora conseguimos acessar o Nginx externamente, via porta exposta no Node.
O Deployment permite atualizar a versão da imagem sem downtime.
Kubernetes substitui Pods antigos por novos, um por vez (rolling update).
spec:
containers:
- name: nginx-container
image: nginx:1.25 # versão nova📌 Se algo der errado, podemos usar rollback para voltar à versão anterior.
Containers e Pods são efêmeros: ao reiniciar, os dados se perdem.
Usamos PersistentVolume (PV) + PersistentVolumeClaim (PVC) para armazenamento persistente.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: meu-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: pod-com-volume
spec:
containers:
- name: app
image: mysql:8
volumeMounts:
- mountPath: "/var/lib/mysql"
name: dados
volumes:
- name: dados
persistentVolumeClaim:
claimName: meu-pvc📌 Agora os dados do banco persistem mesmo que o Pod seja destruído.
- ConfigMap: armazena configs não sensíveis (ex.: URL de API).
- Secret: armazena configs sensíveis (ex.: senha do banco).
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
API_URL: "https://api.meuservico.com"
---
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
DB_PASSWORD: bXlzZW5oYTEyMw== # base64
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 2
template:
spec:
containers:
- name: app
image: minha-app:1.0
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: DB_PASSWORD📌 Assim separamos código da configuração, deixando a aplicação mais flexível e segura.
- Criamos o Pod.
- Escalamos com Deployment.
- Expomos com Service.
- Atualizamos com Rolling Update.
- Persistimos dados com Volumes/PVC.
- Configuramos com ConfigMap/Secret.
👉 Resultado: uma aplicação escalável, resiliente, segura e pronta para produção.
Crie um Deployment chamado nginx-deploy com 2 réplicas da imagem nginx:1.23.
- Exponha esse Deployment como um Service NodePort na porta
30080. - Realize um rolling update para atualizar a imagem do Nginx para
1.25.
Responda:
- O que acontece com os Pods durante o rolling update?
- Como verificar se a atualização foi concluída com sucesso?
Criar Deployment:
kubectl create deployment nginx-deploy --image=nginx:1.23 --replicas=2Expor como Service NodePort:
kubectl expose deployment nginx-deploy --type=NodePort --port=80 --target-port=80 --name=nginx-serviceEditar Deployment para rolling update:
kubectl set image deployment/nginx-deploy nginx=nginx:1.25Verificar status:
kubectl rollout status deployment/nginx-deployRespostas:
- Durante o rolling update, o Kubernetes cria Pods novos com a nova imagem e vai removendo os antigos gradualmente → sem downtime.
- O comando
kubectl rollout statusmostra se a atualização foi concluída, ekubectl get podsconfirma se os Pods usam a nova versão da imagem.
📌 Conclusão: Deployments + rolling updates permitem atualizar aplicações em produção sem interrupções.
- Crie um PersistentVolumeClaim (PVC) de 1Gi chamado
meu-pvc. - Crie um Deployment chamado
app-deploycom 1 réplica usando a imagemnginx. - Monte o PVC no diretório
/usr/share/nginx/html. - Monte também um ConfigMap chamado
app-configcontendo a chave:
Esse arquivo deve substituir a página padrão do Nginx.index.html = <h1>Aplicação rodando com PVC e ConfigMap!</h1>
Responda:
- O que acontece se o Pod for destruído e recriado?
- Por que separar código (imagem) de configuração (ConfigMap)?
Criar PVC (pvc.yaml):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: meu-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gikubectl apply -f pvc.yamlCriar ConfigMap:
kubectl create configmap app-config --from-literal=index.html="<h1>Aplicação rodando com PVC e ConfigMap!</h1>"Deployment (app-deploy.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deploy
spec:
replicas: 1
selector:
matchLabels:
app: minha-app
template:
metadata:
labels:
app: minha-app
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: dados
mountPath: /usr/share/nginx/html
- name: pagina
mountPath: /usr/share/nginx/html/index.html
subPath: index.html
volumes:
- name: dados
persistentVolumeClaim:
claimName: meu-pvc
- name: pagina
configMap:
name: app-config
items:
- key: index.html
path: index.htmlkubectl apply -f app-deploy.yamlTestar aplicação:
kubectl port-forward svc/app-deploy 8080:80
curl http://localhost:8080Respostas:
- O PVC garante que os dados persistem mesmo que o Pod seja destruído. Assim, o conteúdo não se perde.
- Separar código da configuração permite flexibilidade (ex.: mudar mensagens, endpoints, variáveis) sem precisar reconstruir a imagem da aplicação.
📌 Conclusão: PVC + ConfigMap permitem aplicações resilientes, persistentes e configuráveis no Kubernetes.
Problema:
- Os Pods no Kubernetes são efêmeros (criados e destruídos dinamicamente).
- Cada vez que um Pod é recriado, ele recebe um novo IP.
- Isso inviabiliza depender de IPs fixos para comunicação.
Solução: Service Discovery
- O Kubernetes implementa um mecanismo nativo de descoberta de serviços.
- Quando criamos um Service, ele recebe um nome DNS estável dentro do cluster.
- Qualquer Pod pode chamar outro usando esse nome, sem se preocupar com IPs que mudam.
📌 Exemplo:
- Deployment com 3 Pods da aplicação backend.
- Criamos um Service chamado
backend-service. - Outro Pod pode acessar via
http://backend-service:8080, independentemente de qual Pod atenda a requisição.
- Quando um Service aponta para múltiplos Pods, ele também age como load balancer interno.
- O tráfego é distribuído entre as réplicas, geralmente por Round Robin (cada Pod recebe parte das requisições).
Vantagens:
- Escalabilidade: basta aumentar as réplicas no Deployment, o Service distribui automaticamente.
- Resiliência: se um Pod falhar, o tráfego é redirecionado para os outros.
📌 Exemplo:
- Temos 5 Pods de Nginx atrás de um Service ClusterIP.
- Cada requisição feita para
nginx-serviceé encaminhada para um Pod diferente.
- Service resolve comunicação interna, mas e para expor aplicações ao mundo externo?
- NodePort: expõe via porta no nó (limitado, pouco prático).
- LoadBalancer: integra com nuvens públicas (gera custo e depende do provedor).
- Ingress: solução mais flexível e avançada.
Ingress é um recurso que define regras de roteamento HTTP/HTTPS.
Ele permite:
- Roteamento baseado em hostname (
api.minhaempresa.com→ backend,app.minhaempresa.com→ frontend). - Roteamento baseado em path (
/api→ backend,/app→ frontend). - Terminação TLS (HTTPS com certificados).
- Regras centralizadas em um único ponto.
➡️ Para funcionar, precisamos instalar um Ingress Controller (ex.: Nginx Ingress Controller, Traefik, HAProxy).
📌 Exemplo de regra Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: meu-ingress
spec:
rules:
- host: app.minhaempresa.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
- host: api.minhaempresa.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 8080- O Kubernetes integra nativamente com um serviço de DNS interno chamado CoreDNS.
- Ele resolve os nomes de Services para IPs, permitindo que a comunicação seja feita por nomes estáveis.
Funcionamento:
-
Quando criamos um Service chamado
backendno namespaceprod, o CoreDNS gera um endereço como:
backend.prod.svc.cluster.local -
Esse DNS é resolvido automaticamente para o cluster IP do Service.
Benefícios:
- Facilita comunicação interna entre aplicações.
- Não há necessidade de descobrir IPs manualmente.
- Garante portabilidade: workloads podem ser movidos entre clusters sem mudar a lógica de rede.
📌 Exemplo prático:
Um Pod no namespace prod pode acessar o backend com:
curl http://backend.prod.svc.cluster.local:8080- Service Discovery: permite encontrar serviços por nome, sem depender de IPs.
- Balanceamento interno: distribui tráfego entre réplicas de Pods automaticamente.
- Ingress Controller: expõe aplicações externamente com regras HTTP/HTTPS.
- CoreDNS: resolve nomes de serviços para IPs internos no cluster.
Crie dois Deployments:
frontend-deploycom a imagem nginx, 1 réplica.backend-deploycom a imagem hashicorp/http-echo que responde"Hello Backend".
Exponha os dois Deployments como Services ClusterIP (frontend-svc e backend-svc).
Entre no Pod do frontend e faça uma chamada HTTP para o backend usando o nome do Service (backend-svc).
Responda:
- Como o frontend consegue resolver o nome
backend-svcsem conhecer o IP? - O que aconteceria se o Pod do backend fosse recriado com outro IP?
Criar frontend:
kubectl create deployment frontend-deploy --image=nginx
kubectl expose deployment frontend-deploy --port=80 --name=frontend-svcCriar backend (responde via http-echo):
kubectl create deployment backend-deploy --image=hashicorp/http-echo -- -text="Hello Backend"
kubectl expose deployment backend-deploy --port=5678 --name=backend-svcEntrar no Pod frontend e testar comunicação:
kubectl exec -it $(kubectl get pod -l app=frontend-deploy -o jsonpath='{.items[0].metadata.name}') -- sh
# Dentro do Pod
apt update && apt install -y curl # se necessário
curl http://backend-svc:5678Respostas:
- O Kubernetes usa o CoreDNS, que converte automaticamente o nome do Service (
backend-svc) em seu ClusterIP. - Mesmo que o Pod do backend seja recriado com outro IP, o Service continua válido, pois atua como uma camada estável de abstração.
📌 Conclusão: o Service Discovery via DNS garante comunicação confiável entre Pods.
- Instale o Ingress Controller NGINX no cluster.
- Crie dois Deployments e Services:
app-deployexposto comoapp-svc(porta 80).api-deployexposto comoapi-svc(porta 80).
- Configure um Ingress para:
- Roteamento de requisições
/app→app-svc. - Roteamento de requisições
/api→api-svc.
- Roteamento de requisições
- Teste acessando os endpoints.
Responda:
- O que o Ingress resolve que um Service NodePort não resolve?
- Por que ele é importante em produção?
Instalar NGINX Ingress Controller (Helm, minikube ou manifestos):
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yamlCriar app e api:
kubectl create deployment app-deploy --image=nginx
kubectl expose deployment app-deploy --port=80 --name=app-svc
kubectl create deployment api-deploy --image=hashicorp/http-echo -- --text="Hello API"
kubectl expose deployment api-deploy --port=5678 --target-port=5678 --name=api-svcIngress YAML (meu-ingress.yaml):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: meu-ingress
spec:
rules:
- http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: app-svc
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 5678kubectl apply -f meu-ingress.yamlTestar Ingress (minikube):
minikube tunnel &
curl http://localhost/app
curl http://localhost/apiRespostas:
- O Ingress permite um único ponto de entrada HTTP/HTTPS, com roteamento inteligente por path/host. Já o NodePort expõe apenas portas estáticas.
- Em produção, o Ingress é fundamental porque permite balanceamento, TLS/HTTPS, roteamento avançado e integração com domínios reais.
📌 Conclusão: o Ingress Controller é a porta de entrada oficial para aplicações web no Kubernetes.
O HPA (Horizontal Pod Autoscaler) é responsável por ajustar automaticamente o número de réplicas de um Deployment, ReplicaSet ou StatefulSet.
Ele toma decisões com base em métricas como:
- Uso de CPU.
- Uso de memória.
- Métricas customizadas (ex.: fila de mensagens, requisições por segundo).
Como funciona:
- O HPA monitora métricas em tempo real (via Metrics Server ou Prometheus).
- Se a carga aumentar além do limite configurado, cria novas réplicas.
- Se a carga cair, reduz o número de réplicas.
Exemplo (YAML):
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: hpa-exemplo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: meu-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70📌 Nesse exemplo:
- O HPA garante entre 2 e 10 réplicas.
- Se o uso médio de CPU ultrapassar 70%, ele cria novos Pods.
No Kubernetes, as Probes são verificações automáticas para avaliar a saúde dos containers.
✅ Liveness Probe
- Verifica se o container ainda está vivo.
- Se falhar, o Kubernetes mata o container e recria o Pod.
- Útil para casos em que a aplicação trava ou entra em estado inconsistente.
✅ Readiness Probe
- Verifica se o container está pronto para receber tráfego.
- Se falhar, o Pod não entra no balanceador de carga.
- Evita que usuários recebam erros enquanto a aplicação inicializa.
Exemplo (YAML):
apiVersion: v1
kind: Pod
metadata:
name: pod-com-probes
spec:
containers:
- name: app
image: minha-app:1.0
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5📌 Nesse exemplo:
- O Liveness Probe checa
/healthz→ se falhar, o container é reiniciado. - O Readiness Probe checa
/ready→ só depois de passar, o Pod recebe tráfego.
O Kubernetes tem a capacidade de auto-recuperação.
Isso significa que, se um Pod ou nó falhar, ele automaticamente tenta corrigir o problema sem intervenção humana.
Mecanismos:
- Se um Pod cai → o Controller recria outro baseado no Deployment/ReplicaSet.
- Se um nó falha → os Pods daquele nó são reagendados em outros nós disponíveis.
- Se um container trava → o Liveness Probe detecta e força um restart.
➡️ Resultado: a aplicação se mantém disponível mesmo diante de falhas inevitáveis em hardware, rede ou software.
📌 Exemplo real:
- Um Deployment de 5 réplicas.
- Se 2 Pods caírem, o Kubernetes imediatamente cria 2 novos em outros nós.
- Para o usuário final, a aplicação continua disponível, pois o Service redireciona tráfego apenas para Pods saudáveis.
- Horizontal Pod Autoscaler (HPA): garante escalabilidade automática com base em métricas.
- Liveness Probe: reinicia containers não responsivos.
- Readiness Probe: só libera tráfego para Pods prontos.
- Self-healing: substitui Pods ou nós falhos automaticamente, garantindo resiliência.
Crie um Deployment chamado app-deploy com 1 réplica da imagem nginx.
Adicione probes para verificar a saúde do container:
- Liveness Probe: checar
/na porta 80 a cada 10s. - Readiness Probe: checar
/na porta 80 após 5s de delay.
Verifique:
- O que acontece se o container não responder ao Liveness Probe?
- O que acontece se falhar no Readiness Probe?
Deployment com probes (app-deploy.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deploy
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5Aplicar e verificar:
kubectl apply -f app-deploy.yaml
kubectl describe pod <nome-do-pod>Respostas:
- Se o Liveness Probe falhar, o Kubernetes mata e recria o container.
- Se o Readiness Probe falhar, o Pod fica fora do Service (não recebe tráfego), mas não é destruído.
📌 Conclusão: Liveness = está vivo?, Readiness = está pronto?
- Crie um Deployment chamado
api-deploycom 2 réplicas usando a imagemk8s.gcr.io/hpa-example. - Exponha-o como um Service ClusterIP na porta 80.
- Configure um Horizontal Pod Autoscaler (HPA) que:
- Mantenha entre 2 e 5 réplicas.
- Escale quando o uso de CPU médio ultrapassar 50%.
- Gere carga de teste no serviço para forçar o autoscaling.
Responda:
- O que acontece com o número de Pods quando a carga aumenta?
- E quando a carga diminui?
Criar Deployment e Service:
kubectl create deployment api-deploy --image=k8s.gcr.io/hpa-example --replicas=2
kubectl expose deployment api-deploy --port=80 --name=api-svcCriar HPA:
kubectl autoscale deployment api-deploy --cpu-percent=50 --min=2 --max=5Gerar carga (testar com busybox):
kubectl run -i --tty load-generator --image=busybox --restart=Never -- /bin/sh
# Dentro do pod busybox:
while true; do wget -q -O- http://api-svc; doneVerificar HPA:
kubectl get hpa
kubectl get pods -wRespostas:
- Quando a carga aumenta e a CPU passa de 50%, o HPA cria novos Pods até o limite de 5.
- Quando a carga diminui, o HPA reduz as réplicas de volta até o mínimo configurado (2).
📌 Conclusão: o HPA garante escalabilidade automática e o Kubernetes mantém resiliência com self-healing.
O Kubernetes é dinâmico e distribuído: Pods são criados, destruídos e movidos automaticamente.
Precisamos de visibilidade em tempo real sobre:
- Estado do cluster (nodes, pods, serviços).
- Uso de recursos (CPU, memória, disco, rede).
- Métricas customizadas de aplicações.
➡️ Sem monitoramento → difícil detectar gargalos, incidentes e prever capacidade.
📌 Prometheus + Grafana se tornaram o padrão de fato para monitoramento cloud-native.
Prometheus é um sistema de monitoramento e alertas baseado em métricas numéricas.
Arquitetura principal:
- Prometheus Server: coleta métricas via pull (
/metrics). - Exporters: expõem métricas (ex.: node-exporter, kube-state-metrics).
- Time-Series Database (TSDB): armazena métricas como séries temporais.
- Alertmanager: dispara alertas (e-mail, Slack, PagerDuty).
Exemplo de métrica coletada:
http_requests_total{method="GET", handler="/api"} 1527
- Nome:
http_requests_total - Labels:
method,handler - Valor: 1527 (requisições GET na rota
/api)
Configuração básica de scrape:
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true📌 Assim o Prometheus descobre automaticamente Pods que expõem métricas via anotação.
Grafana é uma ferramenta de visualização e análise de métricas.
Permite criar dashboards dinâmicos a partir dos dados coletados pelo Prometheus (ou outras fontes).
Recursos principais:
- Gráficos interativos (linhas, barras, gauges, heatmaps).
- Filtros por labels (namespace, app, node, status).
- Alertas visuais integrados.
- Templates de dashboards prontos (Kubernetes, Nginx, MySQL, etc.).
Exemplo de consulta em PromQL:
rate(container_cpu_usage_seconds_total{namespace="prod", pod=~"api.*"}[5m])
➡️ Calcula a taxa de uso de CPU para Pods que começam com api no namespace prod.
- Aplicações e componentes expõem métricas via
/metrics. - Prometheus coleta periodicamente essas métricas.
- Alertmanager dispara alertas com base em condições definidas.
- Grafana consome os dados do Prometheus e mostra em dashboards interativos.
📊 Diagrama simplificado:
[Apps / Pods / Nodes] --> [Prometheus Server] --> [Grafana]
|
[Alertmanager]
- kube-state-metrics: expõe métricas sobre o estado de objetos do Kubernetes.
- node-exporter: expõe métricas de hardware e sistema operacional.
- cAdvisor (kubelet): expõe métricas de containers.
- Prometheus Operator: facilita deploy e gestão via CRDs.
Instalar o Prometheus com Helm:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack➡️ Isso instala:
- Prometheus
- Grafana
- kube-state-metrics
- node-exporter
Acessar Grafana:
kubectl port-forward svc/prometheus-grafana 3000:80Depois abra em: http://localhost:3000
Usuário: admin, senha obtida no Secret do Helm.
- Alertas inteligentes: CPU/Memória alta, Pods em CrashLoopBackOff, falhas em Deployments.
- Dashboards úteis: saúde do cluster, tráfego de rede, métricas de aplicações.
- Retenção de métricas: cuidado com armazenamento (Prometheus consome muito disco).
- Segurança: proteja a UI do Grafana com autenticação forte e, se possível, OIDC.
- Prometheus: coleta, armazena e gera alertas.
- Grafana: visualiza e analisa métricas.
No Kubernetes:
- Prometheus coleta métricas de Pods, Nodes e Services.
- Grafana mostra a saúde do cluster e aplicações.
- Alertmanager notifica em caso de problemas.
👉 Resultado: observabilidade completa com métricas, alertas e dashboards.
Instale o Prometheus + Grafana no cluster usando o Helm Chart kube-prometheus-stack.
Após a instalação, verifique:
- Os Pods criados no namespace (prometheus, grafana, alertmanager, etc.).
- O acesso ao Grafana via
kubectl port-forward. - Faça login no Grafana (usuário
admin, senha do Secret).
Responda:
- Quais dashboards prontos já estão disponíveis?
- Como acessar métricas coletadas do cluster (ex.: CPU/memória dos Pods)?
Adicionar repositório Helm e instalar:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitor prometheus-community/kube-prometheus-stack -n monitoring --create-namespaceVerificar recursos criados:
kubectl get pods -n monitoring
kubectl get svc -n monitoringAcessar Grafana:
kubectl port-forward svc/monitor-grafana -n monitoring 3000:80Acessar em: http://localhost:3000
Obter senha do Grafana:
kubectl get secret monitor-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 --decodeRespostas:
- Dashboards prontos incluem Cluster Health, Nodes, Pods, Kubernetes API Server, etcd, etc.
- As métricas do cluster podem ser acessadas no Prometheus (
kubectl port-forward svc/monitor-kube-prometheus-prometheus 9090:9090) e visualizadas no Grafana em gráficos de uso de CPU, memória e rede por Pod/namespace.
📌 Conclusão: Prometheus coleta métricas e Grafana fornece dashboards de visualização poderosos.
- Crie um Deployment chamado
app-metricscom a imagem nginx. - Configure o Pod com uma anotação para que o Prometheus faça o scrape de métricas:
prometheus.io/scrape: "true" prometheus.io/port: "80"
- No Grafana, crie um dashboard personalizado que exiba:
- Número de requisições HTTP feitas ao
app-metrics. - Consumo de CPU/memória desse Deployment.
- Número de requisições HTTP feitas ao
Responda:
- Como o Prometheus descobre os Pods que precisam ser monitorados?
- Qual vantagem de ter dashboards customizados por aplicação?
Deployment com anotação (app-metrics.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-metrics
labels:
app: app-metrics
spec:
replicas: 1
selector:
matchLabels:
app: app-metrics
template:
metadata:
labels:
app: app-metrics
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "80"
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80kubectl apply -f app-metrics.yamlCriar Dashboard no Grafana:
- Ir em Dashboards → New → Import/Build Custom.
- Criar gráficos com consultas PromQL, por exemplo:
CPU Usage:
rate(container_cpu_usage_seconds_total{pod=~"app-metrics.*"}[2m])
Memory Usage:
container_memory_usage_bytes{pod=~"app-metrics.*"}
Respostas:
- O Prometheus usa service discovery e as anotações nos Pods/Services para saber quais endpoints
/metricsdeve coletar. - Dashboards customizados permitem que cada equipe acompanhe métricas específicas da sua aplicação (ex.: requisições HTTP, filas de mensagens), indo além da visão geral do cluster.
📌 Conclusão: com Prometheus + Grafana, é possível ter observabilidade completa, tanto do cluster quanto de aplicações específicas.
| Aspecto | Docker Compose 🐳 | Kubernetes ☸️ |
|---|---|---|
| Objetivo | Orquestração simples em um host (local/dev) | Orquestração distribuída em clusters |
| Escopo | Desenvolvimento, prototipagem, testes locais | Produção em escala, clusters distribuídos |
| Rede | Rede interna simples entre containers | Rede complexa, DNS interno, Ingress, Service Discovery |
| Escalabilidade | Manual (alterar docker-compose.yml) |
Automática (HPA, escalonamento dinâmico) |
| Resiliência | Se um container cair, precisa reiniciar manualmente | Self-healing: recria Pods automaticamente |
| Atualizações | Sem suporte nativo a rolling updates | Rolling updates e rollbacks nativos |
| Complexidade | Baixa (um arquivo, poucos comandos) | Alta (diversos objetos, YAMLs, operadores) |
| Monitoramento | Básico, com ferramentas externas | Integrado com Prometheus/Grafana, probes, métricas |
| Uso típico | Times pequenos, POCs, dev local | Produção em larga escala, microserviços, cloud-native |
📌 Resumo:
- Docker Compose → ótimo para desenvolvimento local e projetos pequenos.
- Kubernetes → essencial para ambientes distribuídos, resilientes e escaláveis.
✅ Quando faz sentido usar Kubernetes
- Múltiplos serviços que precisam de escalabilidade horizontal.
- Necessidade de alta disponibilidade.
- Ambientes multi-cloud ou híbridos.
- Times com expertise em DevOps/SRE.
- Casos de microserviços com dependências complexas.
- Necessidade de observabilidade integrada.
❌ Quando não faz sentido usar Kubernetes
- Projetos pequenos ou MVPs de rápida entrega.
- Quando 1 servidor/VM é suficiente.
- Times sem experiência em infraestrutura.
- Situações onde simplicidade > escalabilidade.
- Casos onde serverless resolve melhor (ex.: AWS Lambda).
📌 Muitas startups começam com Docker Compose + serviços gerenciados e só migram para Kubernetes quando a complexidade aumenta.
Ambientes pequenos (startup, POC, times reduzidos):
- Kubernetes pode ser overkill.
- Curva de aprendizado alta.
- Alternativas: Docker Compose, Swarm, PaaS (Heroku, Render, Fly.io).
Ambientes médios:
- Kubernetes começa a fazer sentido com resiliência e automação.
- Clusters menores em nuvem podem equilibrar complexidade x benefício.
Ambientes grandes (enterprise, SaaS em escala):
- Kubernetes é praticamente indispensável.
- Oferece autoescala, tolerância a falhas, observabilidade, multi-tenant.
- Benefícios superam a complexidade.
📌 Equação mental:
- Menos de 3 serviços, poucas réplicas, tráfego baixo → Docker Compose é suficiente.
- Muitos serviços, equipes grandes, SLA alto → Kubernetes é o padrão.
- Tornou-se o padrão da indústria para aplicações cloud-native.
- Suportado nativamente por todos os principais provedores de nuvem: EKS, GKE, AKS.
- Fator chave: portabilidade → mesma aplicação roda em qualquer cluster.
Base para o ecossistema CNCF:
- Service Mesh: Istio, Linkerd.
- Observabilidade: Prometheus, Grafana, Loki, Jaeger.
- CI/CD cloud-native: ArgoCD, Tekton.
- Segurança: OPA, Kyverno, Falco.
📌 Em 2025, Kubernetes é considerado commodity: tão essencial quanto Linux ou redes para DevOps/SRE.
- Docker Compose vs Kubernetes: Compose é simples e prático; Kubernetes é poderoso, mas complexo.
- Quando usar: Kubernetes brilha em sistemas distribuídos, mas é exagero para MVPs simples.
- Complexidade vs benefício: quanto maior o sistema e equipe, maior o ganho do Kubernetes.
- Padrão de fato: Kubernetes é a fundação da arquitetura cloud-native moderna.