Skaffold: Flujo de Desarrollo Kubernetes Automatizado

Skaffold automatiza el ciclo build-push-deploy para el desarrollo de aplicaciones en Kubernetes, detectando cambios en el código y actualizando el clúster en tiempo real. Esta guía explica cómo configurar Skaffold en Linux para sincronización de archivos, hot reload, pipelines de construcción, estrategias de despliegue y la integración con CI/CD.

Requisitos Previos

  • Docker instalado y en ejecución
  • kubectl configurado con acceso a un clúster (local con kind/minikube o remoto)
  • Conocimientos básicos de Kubernetes y Docker
# Verificar Docker
docker version

# Verificar kubectl
kubectl cluster-info

Instalación de Skaffold

# Linux (amd64)
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
chmod +x skaffold
sudo mv skaffold /usr/local/bin/

# Verificar la instalación
skaffold version

# Completado automático de comandos para bash
skaffold completion bash >> ~/.bashrc
source ~/.bashrc

Configuración Básica

Skaffold se configura mediante el archivo skaffold.yaml en la raíz del proyecto:

# Inicializar Skaffold en un proyecto existente (detecta Dockerfile y manifiestos)
skaffold init

# O crear manualmente el archivo de configuración
cat << 'EOF' > skaffold.yaml
apiVersion: skaffold/v4beta8
kind: Config
metadata:
  name: mi-aplicacion

# Configuración de construcción de imágenes
build:
  artifacts:
    - image: mi-aplicacion
      context: .
      docker:
        dockerfile: Dockerfile
  # Construir localmente sin subir al registro
  local:
    push: false
    useBuildkit: true

# Configuración del despliegue
manifests:
  rawYaml:
    - k8s/deployment.yaml
    - k8s/service.yaml

deploy:
  kubectl: {}
EOF

Estructura de proyecto recomendada:

mi-aplicacion/
├── skaffold.yaml
├── Dockerfile
├── src/
│   └── app.py
└── k8s/
    ├── deployment.yaml
    └── service.yaml

Modos de Sincronización y Hot Reload

La sincronización de archivos evita reconstruir la imagen completa en cada cambio:

# skaffold.yaml con sincronización de archivos
build:
  artifacts:
    - image: mi-app-python
      context: .
      sync:
        # Sincronización manual: copia archivos directamente al contenedor
        manual:
          - src: 'src/**/*.py'
            dest: /app/src
          - src: 'templates/**/*.html'
            dest: /app/templates
        # Sincronización inferida: Skaffold detecta el método automáticamente
        infer:
          - '**/*.js'
          - '**/*.css'

Para aplicaciones con hot reload nativo (por ejemplo, Node.js con nodemon):

# Configuración para Node.js con nodemon
build:
  artifacts:
    - image: mi-app-node
      context: .
      docker:
        dockerfile: Dockerfile.dev
      sync:
        infer:
          - '**/*.js'
          - 'package.json'
# Dockerfile.dev - Usa nodemon para hot reload
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
# nodemon reinicia la app al detectar cambios
CMD ["npx", "nodemon", "--watch", "src", "src/index.js"]

Pipelines de Construcción

Skaffold soporta múltiples backends de construcción:

# Construcción con Kaniko (en el clúster, sin Docker local)
build:
  artifacts:
    - image: registry.empresa.com/mi-app
      kaniko:
        cache:
          repo: registry.empresa.com/cache
  cluster:
    pullSecretName: regcred
    namespace: kaniko

---
# Construcción con Buildpacks (sin Dockerfile)
build:
  artifacts:
    - image: mi-app-buildpack
      buildpacks:
        builder: gcr.io/buildpacks/builder:latest
        dependencies:
          paths:
            - src/
            - package.json

---
# Construcción multi-etapa paralela
build:
  artifacts:
    - image: frontend
      context: frontend/
    - image: backend
      context: backend/
    - image: worker
      context: worker/
  # Construir todas las imágenes en paralelo
  local:
    concurrency: 0

Estrategias de Despliegue

# Despliegue con Helm
manifests:
  helm:
    releases:
      - name: mi-app
        chartPath: helm/mi-app
        valuesFiles:
          - helm/values-dev.yaml
        setValues:
          image.tag: ""  # Skaffold gestiona el tag automáticamente
        recreatePods: false

deploy:
  helm: {}
# Despliegue con Kustomize
manifests:
  kustomize:
    paths:
      - k8s/overlays/desarrollo

deploy:
  kubectl:
    defaultNamespace: desarrollo
# Verificar el despliegue con health checks
deploy:
  kubectl:
    defaultNamespace: default
  statusCheck: true
  statusCheckDeadlineSeconds: 120
  tolerateFailuresUntilDeadline: true

Perfiles de Skaffold

Los perfiles permiten tener configuraciones diferentes para desarrollo, staging y CI:

# skaffold.yaml con múltiples perfiles
apiVersion: skaffold/v4beta8
kind: Config
metadata:
  name: mi-aplicacion

# Configuración base
build:
  artifacts:
    - image: mi-app
      context: .

manifests:
  kustomize:
    paths:
      - k8s/base

# Perfil de desarrollo local
profiles:
  - name: dev
    activation:
      - command: dev  # Se activa automáticamente con skaffold dev
    build:
      local:
        push: false
    manifests:
      kustomize:
        paths:
          - k8s/overlays/desarrollo

  # Perfil de staging con imagen en registry
  - name: staging
    build:
      artifacts:
        - image: registry.empresa.com/mi-app
    manifests:
      kustomize:
        paths:
          - k8s/overlays/staging

  # Perfil de CI/CD sin watch
  - name: ci
    build:
      local:
        push: true
        useBuildkit: true
    manifests:
      kustomize:
        paths:
          - k8s/overlays/produccion

Usar los perfiles:

# Desarrollo con hot reload (perfil dev activado automáticamente)
skaffold dev --profile dev

# Despliegue en staging
skaffold run --profile staging

# Pipeline de CI
skaffold run --profile ci --tag $(git rev-parse --short HEAD)

# Limpiar recursos después del desarrollo
skaffold delete --profile dev

Integración con CI/CD

# Ejemplo de pipeline en GitLab CI
cat << 'EOF' > .gitlab-ci.yml
stages:
  - build
  - deploy

variables:
  SKAFFOLD_DEFAULT_REPO: registry.gitlab.com/mi-org/mi-app

build-y-deploy-staging:
  stage: deploy
  image: gcr.io/k8s-skaffold/skaffold:latest
  script:
    # Configurar acceso al clúster de staging
    - kubectl config set-cluster staging --server=$K8S_STAGING_SERVER
    - kubectl config set-credentials ci --token=$K8S_TOKEN
    - kubectl config set-context staging --cluster=staging --user=ci
    - kubectl config use-context staging
    # Construir y desplegar con el perfil de staging
    - skaffold run --profile staging --tag ${CI_COMMIT_SHORT_SHA}
  only:
    - develop

deploy-produccion:
  stage: deploy
  script:
    - skaffold run --profile ci --tag ${CI_COMMIT_TAG}
  only:
    - tags
EOF
# Comandos útiles de Skaffold
# Iniciar en modo desarrollo con logs en tiempo real
skaffold dev --verbosity info

# Ver el estado del pipeline
skaffold run --dry-run

# Depurar con puertos de debug abiertos
skaffold debug

# Ver diagnósticos del entorno
skaffold diagnose

Solución de Problemas

# Ver logs detallados
skaffold dev --verbosity debug 2>&1 | head -100

# Forzar reconstrucción sin cache
skaffold dev --no-prune --cache-artifacts=false

# Verificar que las imágenes se construyen correctamente
skaffold build --dry-run

# Errores de contexto Docker: verificar el contexto actual
kubectl config current-context

# Ver los manifiestos que Skaffold generaría sin aplicarlos
skaffold render

# Problemas de sincronización de archivos
skaffold dev --verbosity debug 2>&1 | grep -i sync

Error "image not found" después del build:

# Verificar que la imagen se construyó correctamente
docker images | grep mi-app

# Si usas un registro remoto, verificar credenciales
docker login registry.empresa.com
kubectl create secret docker-registry regcred \
  --docker-server=registry.empresa.com \
  --docker-username=usuario \
  --docker-password=contraseña

Conclusión

Skaffold elimina la fricción del desarrollo en Kubernetes automatizando completamente el ciclo de construcción y despliegue, permitiendo a los desarrolladores centrarse en el código en lugar de en los comandos de Docker y kubectl. La combinación de perfiles para diferentes entornos y la integración nativa con Helm, Kustomize y sistemas de CI/CD convierte a Skaffold en una herramienta imprescindible para cualquier equipo que trabaje con Kubernetes a diario.