--- title: "Cómo usar Skaffold para desarrollar en Kubernetes" description: "Instala Skaffold en Ubuntu 24.04 y automatiza el ciclo build y deploy en Kubernetes con sincronización de archivos, port-forward, perfiles y despliegue en CI." category: "Ingeniería de Plataformas" language: es source: https://cubepath.com/es/docs/ingeniería-de-plataformas/skaffold-flujo-de-desarrollo-kubernetes updated: 2026-09-25 --- # Cómo usar Skaffold para desarrollar en Kubernetes Skaffold es una herramienta de línea de comandos de Google que automatiza el ciclo de construir la imagen, publicarla y desplegarla en Kubernetes cada vez que cambias el código. En este tutorial instalarás Skaffold en Ubuntu 24.04, prepararás una pequeña aplicación Python, la desarrollarás con `skaffold dev` usando sincronización de archivos en caliente y crearás perfiles para desplegar la misma aplicación desde un pipeline de CI/CD. ## Requisitos previos - Ubuntu 24.04 LTS en tu equipo de desarrollo o en un VPS de CubePath, con un usuario no root con `sudo`. - Docker Engine instalado y tu usuario en el grupo `docker` (`docker run hello-world` debe funcionar sin `sudo`). - `kubectl` instalado. - Un clúster de Kubernetes. Para desarrollo local se recomienda kind, que se instala en el paso 1. ## Paso 1: Crear un clúster local con kind Skaffold detecta los clústeres locales (kind, k3d, minikube) y carga en ellos las imágenes directamente, sin necesidad de un registro. Descarga kind desde su página de releases. Consulta la última versión en `https://github.com/kubernetes-sigs/kind/releases` y ajusta la variable si hay una más reciente: ```bash KIND_VERSION=v0.27.0 curl -fsSLo kind "https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-linux-amd64" sudo install -m 0755 kind /usr/local/bin/kind ``` Crea el clúster. kind configura automáticamente el contexto `kind-desarrollo` en `kubectl`: ```bash kind create cluster --name desarrollo kubectl get nodes ``` ```output NAME STATUS ROLES AGE VERSION desarrollo-control-plane Ready control-plane 40s v1.32.2 ``` ## Paso 2: Instalar Skaffold Skaffold se distribuye como un binario estático. Descarga la última versión estable y colócala en `/usr/local/bin`: ```bash curl -fsSLo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 sudo install -m 0755 skaffold /usr/local/bin/skaffold ``` En servidores ARM64 usa `skaffold-linux-arm64` en lugar de `skaffold-linux-amd64`. Comprueba la instalación: ```bash skaffold version ``` ```output v2.16.0 ``` Opcionalmente, activa el autocompletado en Bash: ```bash echo 'source <(skaffold completion bash)' >> ~/.bashrc ``` ## Paso 3: Preparar una aplicación de ejemplo Crea un directorio de proyecto con una aplicación Flask mínima: ```bash mkdir -p ~/hola-skaffold/k8s cd ~/hola-skaffold nano app.py ``` ```python from flask import Flask app = Flask(__name__) @app.route("/") def index(): return "Hola desde Skaffold\n" ``` Crea el `Dockerfile`. El servidor se arranca con `--debug`, que recarga la aplicación cuando un archivo `.py` cambia dentro del contenedor. Esto es lo que aprovechará la sincronización de Skaffold: ```bash nano Dockerfile ``` ```dockerfile FROM python:3.12-slim WORKDIR /app RUN pip install --no-cache-dir flask COPY app.py . CMD ["flask", "--app", "app", "run", "--host", "0.0.0.0", "--port", "8080", "--debug"] ``` > Advertencia: el modo `--debug` de Flask es solo para desarrollo. En producción usa un servidor WSGI como Gunicorn. Crea los manifiestos de Kubernetes. La imagen se llama `hola-skaffold`, sin etiqueta: Skaffold la sustituye por la etiqueta que genera en cada build. ```bash nano k8s/deployment.yaml ``` ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: hola-skaffold spec: replicas: 1 selector: matchLabels: app: hola-skaffold template: metadata: labels: app: hola-skaffold spec: containers: - name: app image: hola-skaffold ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: hola-skaffold spec: selector: app: hola-skaffold ports: - port: 80 targetPort: 8080 ``` ## Paso 4: Crear el archivo skaffold.yaml `skaffold init` puede generar el archivo detectando el `Dockerfile` y los manifiestos, pero es mejor entender cada bloque. Crea `skaffold.yaml` en la raíz del proyecto: ```bash nano skaffold.yaml ``` ```yaml apiVersion: skaffold/v4beta11 kind: Config metadata: name: hola-skaffold build: artifacts: - image: hola-skaffold docker: dockerfile: Dockerfile sync: manual: - src: "*.py" dest: . local: push: false manifests: rawYaml: - k8s/deployment.yaml deploy: kubectl: {} portForward: - resourceType: service resourceName: hola-skaffold port: 80 localPort: 8080 ``` Qué hace cada sección: - `build.artifacts` define la imagen y cómo se construye. `sync.manual` indica que los cambios en archivos `.py` se copian al contenedor en ejecución (en el `WORKDIR`, `/app`) en lugar de reconstruir la imagen. - `build.local.push: false` evita subir la imagen a un registro. Con kind, Skaffold la carga directamente en el clúster. - `manifests` y `deploy` separan qué se renderiza (YAML plano, Kustomize o Helm) de cómo se aplica (`kubectl` o `helm`). - `portForward` redirige `localhost:8080` al Service cuando ejecutas Skaffold con `--port-forward`. > Nota: si tu versión de Skaffold usa un esquema más reciente, ejecuta `skaffold fix --overwrite` para actualizar el `apiVersion` del archivo. Las versiones nuevas siguen aceptando esquemas anteriores. Valida la configuración renderizando los manifiestos sin desplegar nada: ```bash skaffold render --digest-source=tag ``` La salida muestra el Deployment con la imagen ya etiquetada por Skaffold. Por defecto la etiqueta se basa en el commit de Git, así que conviene que el proyecto sea un repositorio (`git init` y un primer commit). ## Paso 5: Desarrollar con skaffold dev `skaffold dev` construye la imagen, la despliega, muestra los logs de los pods y vigila el directorio. Cuando detecta cambios, sincroniza o reconstruye según corresponda. Al pulsar `Ctrl+C` elimina lo que ha desplegado. ```bash skaffold dev --port-forward ``` ```output Generating tags... - hola-skaffold -> hola-skaffold:3f2c1ab Building [hola-skaffold]... Loading images into kind cluster nodes... Starting deploy... - deployment.apps/hola-skaffold created - service/hola-skaffold created Waiting for deployments to stabilize... - deployment/hola-skaffold is ready. Port forwarding service/hola-skaffold in namespace default, remote port 80 -> http://127.0.0.1:8080 Watching for changes... ``` En otra terminal, comprueba la respuesta: ```bash curl http://127.0.0.1:8080 ``` ```output Hola desde Skaffold ``` Ahora edita `app.py` y cambia el texto a `Hola de nuevo`. En la terminal de Skaffold verás `Syncing 1 files for hola-skaffold` en lugar de un build completo, y Flask recargará la aplicación en uno o dos segundos: ```bash curl http://127.0.0.1:8080 ``` ```output Hola de nuevo ``` Si en cambio modificas el `Dockerfile`, Skaffold reconstruye la imagen y vuelve a desplegar, porque ese archivo no está cubierto por la regla de sincronización. ## Paso 6: Añadir perfiles para otros entornos Los perfiles modifican partes de `skaffold.yaml` según el entorno. Añade al final del archivo un perfil `ci` que publica la imagen en un registro y comprueba el estado del despliegue con un límite de tiempo: ```bash nano skaffold.yaml ``` ```yaml profiles: - name: ci build: artifacts: - image: hola-skaffold docker: dockerfile: Dockerfile local: push: true deploy: kubectl: {} statusCheckDeadlineSeconds: 180 ``` Las listas de un perfil sustituyen por completo a las de la configuración principal, por eso el perfil vuelve a declarar el artefacto, esta vez sin `sync`, que no tiene sentido en CI. Comprueba que el perfil se resuelve correctamente: ```bash skaffold diagnose -p ci ``` Un perfil también puede activarse solo con un contexto o un comando concretos mediante `activation`, por ejemplo para usar siempre el perfil `ci` al apuntar al clúster de staging: ```yaml activation: - kubeContext: staging ``` ## Paso 7: Desplegar desde CI/CD En un pipeline no quieres el modo de vigilancia, sino un build y un deploy únicos. Inicia sesión en tu registro y usa `skaffold run` con el perfil `ci`. La opción `--default-repo` antepone el registro al nombre de la imagen y `--tag` fija la etiqueta al commit: ```bash docker login registry.example.com skaffold run -p ci \ --default-repo registry.example.com/your_team \ --tag "$(git rev-parse --short HEAD)" ``` Sustituye `registry.example.com/your_team` por la ruta de tu registro. El clúster de destino es el contexto actual de `kubectl`, así que el job de CI debe tener un kubeconfig con permisos sobre el namespace. Si prefieres separar el build del despliegue (por ejemplo, construir una vez y promocionar la misma imagen entre entornos), Skaffold puede guardar el resultado del build en un archivo y reutilizarlo: ```bash skaffold build -p ci --default-repo registry.example.com/your_team --file-output=build.json skaffold deploy -p ci --build-artifacts=build.json ``` Para borrar lo desplegado por `skaffold run`: ```bash skaffold delete -p ci ``` ## Solución de problemas **`ErrImagePull` o `ImagePullBackOff` en un clúster remoto**: con `push: false` la imagen solo existe en tu Docker local. En clústeres que no son kind, k3d ni minikube necesitas `push: true`, `--default-repo` y, si el registro es privado, un `imagePullSecret`. **Los cambios no se sincronizan**: ejecuta `skaffold dev -v debug` y busca líneas con `sync`. El patrón de `src` es relativo al contexto del artefacto y `dest` es relativo al `WORKDIR` del contenedor. **Build lento o que reutiliza una capa antigua**: desactiva la caché de artefactos de Skaffold con `skaffold dev --cache-artifacts=false`. **Ver la configuración efectiva tras aplicar perfiles**: `skaffold diagnose --yaml-only -p ci` imprime el `skaffold.yaml` resultante. ## Conclusión Has instalado Skaffold, creado un flujo de desarrollo en el que los cambios de código llegan al pod en segundos sin reconstruir la imagen, y un perfil para construir, publicar y desplegar desde CI/CD. Como siguientes pasos, puedes sustituir `rawYaml` por `kustomize` o `helm` para gestionar varios entornos, usar `skaffold debug` para conectar un depurador a los pods, o comparar este flujo con Tilt si trabajas con muchos microservicios a la vez.