Kubernetes para Quem Já Trabalha com Docker

setembro 1, 2026 · 11 min de leitura · Luiz Seabra

Kubernetes para Quem Já Trabalha com Docker

Introdução

Se você domina docker run, docker compose e já imaginou escalar seus serviços sem tocar em scripts de supervisord, chegou o momento certo. Kubernetes (ou K8s) é a evolução natural do Docker para ambientes produtivos: orquestação declarativa, self-healing e scaling automático. No entanto, muitos dos conceitos são novos. Este artigo traduz sua experiência com Docker para o universo Kubernetes, com YAMLs completos, explicações de control plane e laboratórios práticos. Ao final, você será capaz de:
– Compreender a diferença entre Docker (executar) e Kubernetes (declarar).
– Instalar um cluster single-node usando kind ou minikube.
– Criar Deployments, Services, Ingress, ConfigMap, Secret e PVC.
– Diagnóstico de problemas comuns com kubectl.
– Entender a segurança e boas práticas de produção.

O que você vai aprender

  • Arquitetura do cluster Kubernetes.
  • Workload Resources: Pod, Deployment, Service, Ingress.
  • Config Management: ConfigMap e Secret.
  • Persistência: PersistentVolume e StorageClass.
  • Diagnóstico e troubleshooting com kubectl.

Pré-requisitos

  • Docker instalado e funcionando (não será necessário docker run, apenas como backend).
  • Conexão à internet para baixar imagens do kind ou minikube.
  • Conhecimento básico de Linux e YAML.

Conceitos fundamentais

Conceito Definição Relação com Docker
Pod Unidade mínima de execução – um ou containers co-locados. Um Pod é um wrapper ao redor de um ou mais containers.
Deployment Declarativo: desejo N réplicas, atualizações em rolling update. Substitui docker run -d + restart: always.
Service Abstraction de rede – ClusterIP, NodePort, LoadBalancer. Equivalente a expor porta via docker -p, mas sem IP fixo.
Ingress Roteamento HTTP baseado em host/path para Services. Substitui proxy reverso (NGINX) manual.
Namespace Isolamento lógico – múltiplos ambientes em um cluster. Não existe equivalente direto no Docker.
ConfigMap/Secret Variáveis de ambiente e arquivos de configuração. Substituem -e VAR=value ou volume de arquivos.
PVC/StorageClass Persistência de dados independente do Pod. Similar a volume bind mount, mas com provisionamento automático.
Control Plane Componentes que gerenciam o estado desejado. Nenhum equivalente – k8s faz o trabalho de orquestrador.

O que Kubernetes resolve (e o que NÃO resolve)

Resolve:
– Escalabilidade automática de réplicas.
– Self-healing (recria Pods mortos).
– Rolling updates sem downtime.
– Balanceamento de carga interno/externo.
– Gerenciamento de creden­sias e configurações.

NÃO resolve:
– Orquestração de hosts (precisa de cluster).
– Configuração de rede avançada (CNI ainda é plugin).
– Builds de imagens (use docker build ou CI/CD).

Diferenças para Docker

Aspecto Docker Kubernetes
Modelo Imperativo (execute este container) Declarativo (o estado desejado é este YAML)
Escopo Um host Múltiplos hosts (cluster)
Escalabilidade Manual (docker-compose scale) ou script Automática (replicas: 3)
Atualização docker stop && docker run kubectl rollout restart com novo YAML
Degradação Falha total se processo morre restartPolicy: Always no Pod

Preparação do ambiente

  1. Verificar versão do Docker – docker --version ≥ 24.x.
  2. Instalar kind – usado para criar clusters locais rápidos.
  3. Configurar kubectl – CLI oficial para comunicação com o cluster.
  4. Criar namespace de testes – dev, staging e prod.

Tutorial passo a passo

1. Instalar o cluster local com Kind

Objetivo: Criar um cluster Kubernetes em containers Docker.

# Instalar kind (v0.20.0)
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-$(uname)-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

# Criar cluster com 2 nodes (1 control-plane, 1 worker)
cat <<EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
EOF
kind create cluster --name dev-cluster --config kind-config.yaml
# Verificar
kubectl cluster-info --context kind-dev-cluster

Explicação: kind usa containers Docker como nodes. O control-plane roda dentro de um pod; o worker também. O kubeconfig é ajustado automaticamente.
Resultado esperado: kubectl get nodes retorna 2 nós com status Ready.

2. Instalar o Ingress Controller (NGINX)

Objetivo: Habilitar rotas HTTP externas.

# Usar helm para instalar
curl -fsSL -o /tmp/helm https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 /tmp/helm
/tmp/helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace --set controller.publishService.enabled=true
# Aguardar pods prontos
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=90s

Explicação: O Helm simplifica a instalação. O controller deixa de ouvir na porta 80/443 do node.
Resultado esperado: kubectl get svc -n ingress-nginx mostra ingress-nginx-controller com EXTERNAL-IP = localhost.

3. Criar um Deployment básico

Objetivo: Implantar 2 réplicas de um app Nginx customizado.

# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: nginx
          image: nginx:1.25-alpine
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "250m"
              memory: "256Mi"
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: web-app-svc
spec:
  type: NodePort
  selector:
    app: web-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080
kubectl apply -f app-deployment.yaml
kubectl get pods -l app=web-app

Explicação: Deployment gere 2 pods. Service tipo NodePort expõe na porta 30080 de cada node.
Resultado esperado: Pods com READY=1/1, Service escutando em 30080.

4. Configurar ConfigMap e Secret

Objetivo: Passar variáveis e credenciais de forma segura.

# app-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: web-config
data:
  ENVIRONMENT: "production"
  LOG_LEVEL: "info"
---
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
stringData:
  username: "admin"
  password: "SuperSecret123"
kubectl apply -f app-config.yaml
# Montar como env
kubectl set env deployment/web-app --from=configmap/web-config --from=secret=db-credentials

Explicação: ConfigMap para valores não sensíveis, Secret (stringData base64) para credenciais. Ambos podem ser injetados como env ou arquivos via volume.
Resultado esperado: kubectl exec <pod> -- env | grep ENVIRONMENT exibe production.

5. Criar PVC e StorageClass

Objetivo: Persistir dados do container.

# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: webapp-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
# Usar storageClass local do kind
kubectl apply -f pvc.yaml
# Verificar PVC bound
kubectl get pvc

Explicação: accessModes: ReadWriteOnce permite escrita pelo pod. O kind cria um local-path StorageClass automaticamente.
Resultado esperado: PVC com status Bound a um PV.

6. Criar Ingress com roteamento

Objetivo: Acessar a aplicação via hostname.

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: dev.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-app-svc
                port:
                  number: 80
# Adicionar ao /etc/hosts
echo "127.0.0.1 dev.local" | sudo tee -a /etc/hosts
kubectl apply -f ingress.yaml
# Testar
curl -H "Host: dev.local" http://localhost

Explicação: O Ingress roteia requisições com Host: dev.local para o Service web-app-svc.
Resultado esperado: Resposta HTTP 200 com conteúdo do Nginx padrão.

7. Simular Rolling Update e rollback

Objetivo: Atualizar a imagem sem downtime.

# Atualizar
kubectl set image deployment/web-app nginx=nginx:1.25.3
# Ver rollout status
kubectl rollout status deployment/web-app
# Se necessário, rollback
kubectl rollout undo deployment/web-app

Explicação: Kubernetes mantém 25% das réplicas antigas durante o update, garantindo disponibilidade.
Resultado esperado: Histórico de revisões visível em kubectl rollout history.

Laboratório

Cenário: Deploy de um app customizado com ConfigMap, Secret, PVC e Ingress sobre cluster Kind.

Passos do laboratório

  1. Crie o cluster kind create cluster --name lab --config kind-config.yaml.
  2. Clone o repositório de exemplo:
git clone https://github.com/bittux/lab-kubernetes-demo.git
cd lab-kubernetes-demo
  1. Ajuste o ConfigMap para variação de host:
# host-vars.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  SITE_NAME: "Meu Laboratório K8s"
  VERSION: "1.0.0"
  1. Aplique todos os recursos:
kubectl create namespace lab
kubectl apply -n lab -f k8s/
  1. Valide:
kubectl get all -n lab
kubectl describe ingress -n lab
  1. Acesse via http://localhost com Host lab.local.

# Troubleshooting: problemas comuns e como resolver

Sintoma 1 – ImagePullBackOff

  • Possível causa: Nome da imagem errado, tag não existe ou registro não autenticado.
  • Diagnóstico: kubectl describe pod <pod> → “Failed to pull image”.
  • Solução: Verifique a tag (docker pull nginx:1.25-alpine); crie docker-registry Secret e referencie em imagePullSecrets.
  • Prevenção: Use tags estáveis como nginx:v1.25 e teste localmente antes de subir ao cluster.

Sintoma 2 – CrashLoopBackOff

  • Possível causa: Falha no início do container (erro de configuração, falta de permissões).
  • Diagnóstico: kubectl logs <pod>; kubectl describe pod <pod>.
  • Solução: Corrija o comando de entrada (command ou entrypoint), ajuste permissões de arquivo (chmod), adicione securityContext.
  • Prevenção: Use restartPolicy: Never em Jobs de migração, adicione postStart liveness probe.

Sintoma 3 – Pending Pod (scheduling de resources)

  • Possível causa: Nenhum node disponível com recursos suficientes.
  • Diagnóstico: kubectl describe pod <pod> → evento “0/1 nodes are available: 1 Insufficient cpu.”`.
  • Solução: Reduza requests, adicione node ao cluster (kind create cluster --name extended --nodes 3).
  • Prevenção: Monitore uso de recursos com kubectl top nodes e ajuste requests/limits em conjunto.

Sintoma 4 – ContainerCreating (volume provisioning)

  • Possível causa: Provisionador de storage não está disponível ou StorageClass errado.
  • Diagnóstico: kubectl describe pvc <pvc>.
  • Solução: Use StorageClass correto (local-path no Kind) ou configure driver CSI adequado.
  • Prevenção: Verifique se o provisionador está rodando (kubectl get pods -n kube-system).

Sintoma 5 – Readiness probe failing

  • Possível causa: Probe apontando para porta ou path errado.
  • Diagnóstico: kubectl describe pod <pod> → “Readiness probe failed”.
  • Solução: Ajuste initialDelaySeconds e periodSeconds; verifique se a aplicação responde ao path /healthz.
  • Prevenção: Adicione endpoint de saúde na aplicação e teste localmente.

# Segurança

  • RBAC: Atribua papéis mínimos (Role, RoleBinding). Evite cluster-admin em produção.
  • Namespaces: Isolar ambientes (dev, staging, prod) impede vazamento de credenciais.
  • Secrets: Não armazene no Git. Use sealed-secrets ou externas (AWS Secrets Manager).
  • Network Policies: Defina NetworkPolicy para restringir tráfego entre Pods.
  • Images: Use imagens oficiais ou construa via CI com scan de vulnerabilidades (Trivy, Grype).
  • Resource Limits: Defina requests e limits para evitar que um Pod monopolize recursos.

# Boas práticas

  • Nunca crie Pods soltos em produção – sempre use Deployment, StatefulSet ou DaemonSet.
  • Versione manifests – use Git com kustomize ou helm para ambientes.
  • Labels e Anotações – padronize labels (app, tier, environment) para facilitar busca.
  • Health Checks – sempre adicione livenessProbe e readinessProbe.
  • Horizontal Pod Autoscaler (HPA) – configure baseado em CPU ou métricas custom metrics-server.
  • Rolling Update – ajuste maxSurge: 25%, maxUnavailable: 25% conforme SLA.
  • Service Discovery – use ClusterIP para comunicação interna; LoadBalancer apenas quando preciso (custo de nuvem).

Comparação de ferramentas

Ferramenta Uso Vantagem Desvantagem
Docker Compose Ambiente local, desenvolvimento Simples, rápido Não escala, sem HA
Kind Testes locais, CI Rápido, Docker-based Não produzido, sem rede real
Minikube Desenvolvimento Plugins (ingress, dashboard) Mais lento que Kind
k3s Edge/IoT, produção leve Tudo em um binário Menos recursos avançados
Kops / EKS / GKE / AKS Produção em nuvem Gerenciado, HA Custo, lock-in de provedor

Conclusão

Kubernetes não substitui Docker – ele o orquestra. Com o conhecimento de Docker, você entende containers, imagens e rede. Em Kubernetes, essas ideias se transformam em Pods, Deployments e Services. Ao seguir os passos acima, você tem um laboratório funcional para experimentar upgrades, rollbacks e novas funcionalidades. Em produção, combine k8s com CI/CD (GitHub Actions, ArgoCD) e ferramentas de observação (Prometheus, Grafana) – como veremos no artigo 10 monitoramento zabbix prometheus grafana.

Perguntas frequentes

Q: Posso usar Docker Compose para migrar para Kubernetes?
A: Sim, com kompose – converte docker-compose.yml para manifests K8s. Não é perfeito, mas acelera o onboarding.

Q: Qual a diferença entre Deployment e StatefulSet?
A: Deployment para apps stateless; StatefulSet para stateful (banco, redis). Garante identidade de Pod e ordenação.

Q: Como backup o cluster Kubernetes?
A: Otimize etcd com etcdctl para clusters management plane. Para workloads, use velero (backup de recursos e PV).

Próximo passo

Agora que você domina Kubernetes Para Quem Ja Trabalha Com Docker, o próximo passo lógico da nossa trilha de aprendizado é continuar desenvolvendo suas habilidades.

→ Continue: Ansible na Prática

Artigos relacionados

Estes artigos complementam o conteúdo apresentado:

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Rolar para cima