Como usar o Skaffold para desenvolvimento local com Kubernetes

1. O que é o Skaffold e por que ele é essencial para o desenvolvimento local em Kubernetes

1.1. Visão geral do Skaffold

Skaffold é uma ferramenta open-source criada pelo Google que automatiza o fluxo de trabalho de desenvolvimento para aplicações Kubernetes. Ela gerencia todo o ciclo: build da imagem, push para registry, deploy no cluster e monitoramento contínuo de mudanças. O Skaffold elimina a necessidade de comandos manuais repetitivos, permitindo que desenvolvedores foquem no código.

1.2. Problemas resolvidos

No desenvolvimento local com Kubernetes, os principais gargalos são:
- Rebuild manual: a cada alteração, o desenvolvedor precisa executar docker build, docker push e kubectl apply manualmente.
- Redeploy lento: mesmo pequenas mudanças exigem rebuild completo da imagem.
- Inconsistência entre ambientes: diferenças entre configurações locais e de produção geram bugs difíceis de rastrear.

O Skaffold resolve isso com um loop automatizado que detecta alterações no código-fonte e dispara rebuilds e redeploys instantâneos.

1.3. Comparação com alternativas

Ferramenta Foco principal Caso ideal
Skaffold CI/CD local completo Times que precisam de build + deploy + debug integrados
Kompose Conversão Docker Compose → K8s Migração rápida de Docker Compose
Telepresence Proxy de tráfego remoto Debug de serviços em cluster remoto
Tilt Visualização de deployments Times que preferem UI interativa

O Skaffold se destaca por ser independente de IDE, suportar múltiplos builders e deployers, e ter integração nativa com pipelines CI/CD.

2. Instalação e configuração inicial do Skaffold

2.1. Pré-requisitos

Antes de instalar o Skaffold, certifique-se de ter:
- Docker instalado e rodando
- kubectl configurado com acesso a um cluster (minikube, kind ou Docker Desktop)
- Cluster Kubernetes local (exemplo: minikube start)

2.2. Instalação via gerenciadores de pacotes

# macOS (Homebrew)
brew install skaffold

# Windows (Chocolatey)
choco install skaffold

# Linux (script oficial)
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
sudo install skaffold /usr/local/bin/

Verifique a instalação:

skaffold version

2.3. Primeiro projeto: estrutura de diretórios e arquivo skaffold.yaml

Crie a seguinte estrutura de projeto:

meu-app/
├── skaffold.yaml
├── Dockerfile
├── k8s/
│   └── deployment.yaml
└── src/
    └── app.py

Arquivo skaffold.yaml básico:

apiVersion: skaffold/v4beta7
kind: Config
build:
  artifacts:
    - image: meu-app-dev
      docker:
        dockerfile: Dockerfile
deploy:
  kubectl:
    manifests:
      - k8s/deployment.yaml

Com isso, um simples skaffold dev já inicia o loop de desenvolvimento.

3. Modos de desenvolvimento: skaffold dev e skaffold run

3.1. skaffold dev: loop contínuo

O comando principal para desenvolvimento local:

skaffold dev --tail --port-forward
  • --tail: exibe logs em tempo real de todos os pods
  • --port-forward: mapeia portas dos serviços para localhost automaticamente

O Skaffold monitora o diretório do projeto. Ao detectar alterações, ele:
1. Reconstrói a imagem
2. Faz push (se necessário)
3. Atualiza o deployment no cluster

3.2. skaffold run: execução única

Para testes rápidos ou integração com pipelines:

skaffold run

Útil quando você quer apenas um deploy rápido sem manter o processo em background.

3.3. Diferenças práticas

Característica skaffold dev skaffold run
Watch automático Sim Não
Logs em tempo real Sim (com --tail) Apenas durante execução
Port forwarding Sim (com --port-forward) Não
Uso típico Desenvolvimento local CI/CD, testes únicos

4. Configuração avançada do skaffold.yaml

4.1. Seções principais

apiVersion: skaffold/v4beta7
kind: Config
build:
  artifacts:
    - image: app-backend
      docker:
        dockerfile: Dockerfile
      sync:
        manual:
          - src: 'src/**/*.py'
            dest: /app
deploy:
  helm:
    releases:
      - name: app-backend
        chartPath: charts/app-backend
        namespace: dev
        createNamespace: true
portForward:
  - resourceType: service
    resourceName: app-backend
    port: 8080
    localPort: 3000
test:
  - image: app-backend
    structureTests:
      - test/*.yaml

4.2. Estratégias de build

# Usando Buildpacks (sem Dockerfile)
build:
  artifacts:
    - image: app-java
      buildpacks:
        builder: gcr.io/buildpacks/builder:v1

# Usando Jib para Java
build:
  artifacts:
    - image: app-java
      jib:
        project: meu-projeto

4.3. Deployers suportados

# Kustomize
deploy:
  kustomize:
    paths: ["k8s/overlays/dev"]

# Helm
deploy:
  helm:
    releases:
      - name: app
        chartPath: ./chart
        valuesFiles: ["./values-dev.yaml"]

5. Hot reload e sincronização de arquivos com file sync

5.1. Configuração de sync

O sync evita rebuild completo ao copiar arquivos modificados diretamente para o container:

build:
  artifacts:
    - image: app-node
      sync:
        manual:
          - src: 'src/**/*.js'
            dest: /app/src
          - src: 'public/**/*'
            dest: /app/public

5.2. Modos de sync

  • Manual: você especifica padrões de arquivo e destinos
  • Infer: Skaffold tenta adivinhar baseado no Dockerfile (nem sempre preciso)
  • Customizado: combina regras manuais com inferência

5.3. Limitações e melhores práticas

Use sync para:
- Arquivos estáticos (HTML, CSS, JS)
- Código interpretado (Python, Node.js sem build step)

Evite sync para:
- Alterações que exigem rebuild (dependências, Dockerfile)
- Linguagens compiladas (Go, Rust, Java sem hot reload)

6. Debugging e testes integrados com Skaffold

6.1. Debug automático

skaffold debug

Isso habilita ports de debug para IDEs:
- VS Code: configure launch.json com "type": "node" e porta 9229
- IntelliJ: Remote JVM Debug na porta 5005

6.2. Execução de testes

test:
  - image: app-backend
    structureTests:
      - tests/*.yaml

Exemplo de teste estrutural:

schemaVersion: 2.0.0
commandTests:
  - name: "Python version"
    command: ["python", "--version"]
    expectedOutput: ["Python 3.9.*"]

6.3. Profiles para ambientes

profiles:
  - name: staging
    patches:
      - op: replace
        path: /deploy/kubectl/manifests
        value:
          - k8s/staging/deployment.yaml
  - name: debug
    activation:
      - env: DEBUG_MODE=true
    patches:
      - op: add
        path: /build/artifacts/0/sync
        value:
          manual:
            - src: 'src/**/*.py'
              dest: /app

Uso: skaffold dev -p staging

7. Integração com pipelines CI/CD e multi-cluster

7.1. Skaffold em GitHub Actions

# .github/workflows/deploy.yml
name: Deploy
on: [push]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: google-github-actions/setup-gcloud@v1
      - run: skaffold run --default-repo=gcr.io/${{ secrets.PROJECT_ID }}

7.2. Uso de skaffold render

Gera manifests sem fazer deploy:

skaffold render --output rendered.yaml

Útil para:
- Revisão de código
- Armazenamento de manifests versionados
- Deploy manual controlado

7.3. Estratégias para multi-cluster

# skaffold.yaml com profiles por cluster
profiles:
  - name: dev-cluster
    patches:
      - op: replace
        path: /deploy/kubectl/defaultNamespace
        value: dev
  - name: staging-cluster
    patches:
      - op: replace
        path: /deploy/kubectl/defaultNamespace
        value: staging
      - op: replace
        path: /build/artifacts/0/image
        value: gcr.io/project/app:staging

Uso: skaffold dev -p dev-cluster --kube-context=minikube

8. Troubleshooting, boas práticas e próximos passos

8.1. Erros comuns

Problema Solução
Porta ocupada Use --port-forward com portas diferentes ou mate processos anteriores
Build falha Verifique Dockerfile e dependências; use skaffold build para testar isoladamente
Permissão de cluster Execute kubectl cluster-info para verificar conectividade
Sync não funciona Confirme que os padrões de arquivo estão corretos e o container suporta hot reload

8.2. Boas práticas

  1. Versionamento: mantenha skaffold.yaml no repositório Git
  2. .dockerignore: inclua para evitar cache desnecessário
  3. Cache de build: use --cache-artifacts para acelerar rebuilds
  4. Logs estruturados: configure --tail com filtros para evitar ruído
  5. Cleanup: use skaffold delete para remover recursos ao finalizar

8.3. Recursos complementares

  • Plugins: Skaffold suporta hooks customizados com lifecycleHooks
  • Comunidade: Fórum oficial e GitHub Discussions
  • Evolução para produção: use skaffold run em pipelines com --default-repo e perfis separados

Referências