Skaffold for Kubernetes Development Workflow
Skaffold automates the build-push-deploy cycle for Kubernetes applications, enabling continuous development with hot reload, multi-stage pipelines, and seamless CI/CD integration. This guide covers installing Skaffold on Linux, configuring build and deploy pipelines, using profiles for different environments, and integrating with Helm.
Prerequisites
- Docker or a container runtime installed
kubectlconfigured with a Kubernetes cluster- A Kubernetes cluster (local: kind, Minikube, or Docker Desktop)
- A container registry (Docker Hub, GCR, ECR, or a local registry)
Install 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/
# Verify installation
skaffold version
# macOS
brew install skaffold
Initialize a Skaffold Project
# From your project root (must have a Dockerfile and Kubernetes manifests)
skaffold init
# Skaffold detects Dockerfiles, Helm charts, Kustomize dirs and prompts:
# [1] Dockerfile
# Which builders would you like to create kubernetes resources from?
# > Dockerfile (myapp/Dockerfile)
# Enter a valid Kubernetes namespace: default
# This creates skaffold.yaml in the project root
A generated skaffold.yaml looks like:
apiVersion: skaffold/v4beta6
kind: Config
metadata:
name: my-app
build:
artifacts:
- image: my-org/web-app
context: .
docker:
dockerfile: Dockerfile
deploy:
kubectl:
manifests:
- k8s/*.yaml
Configure Build Pipelines
Docker build (default):
# skaffold.yaml
apiVersion: skaffold/v4beta6
kind: Config
build:
artifacts:
- image: my-org/web-app
context: .
docker:
dockerfile: Dockerfile
target: production # Multi-stage build target
buildArgs:
NODE_ENV: production
- image: my-org/worker
context: ./worker
docker:
dockerfile: Dockerfile
local:
push: false # Don't push when using local cluster
useBuildkit: true
Kaniko build (for CI environments without Docker daemon):
build:
artifacts:
- image: my-org/web-app
kaniko:
dockerfile: Dockerfile
buildArgs:
VERSION: "1.0.0"
cluster:
namespace: kaniko
pullSecretPath: /tmp/kaniko-secret.json
ko build (for Go projects — no Dockerfile needed):
build:
artifacts:
- image: my-org/go-app
ko:
fromImage: gcr.io/distroless/static-debian11
main: ./cmd/server
env:
- GOOS=linux
- GOARCH=amd64
Buildpacks (auto-detect language and build):
build:
artifacts:
- image: my-org/app
buildpacks:
builder: gcr.io/buildpacks/builder:v1
Deploy with Helm or Kustomize
Deploy with kubectl:
deploy:
kubectl:
manifests:
- k8s/base/*.yaml
- k8s/overlays/development/*.yaml
defaultNamespace: development
Deploy with Helm:
deploy:
helm:
releases:
- name: web-app
chartPath: helm/web-app
namespace: development
createNamespace: true
valuesFiles:
- helm/values.yaml
- helm/values-dev.yaml
setValues:
image.repository: my-org/web-app
image.pullPolicy: IfNotPresent
upgradeOnChange: true
Deploy with Kustomize:
deploy:
kustomize:
paths:
- k8s/overlays/development
File Sync and Hot Reload
Skaffold can sync files directly into running containers without a rebuild:
build:
artifacts:
- image: my-org/web-app
context: .
docker:
dockerfile: Dockerfile
sync:
# Infer sync from .dockerignore (fastest)
infer:
- "**/*.js"
- "**/*.css"
- "**/*.html"
# Manual sync: local path -> container path
manual:
- src: "src/**/*.py"
dest: /app/src/
Development mode with auto-rebuild:
# Start the development loop
skaffold dev
# Skaffold will:
# 1. Build all artifacts
# 2. Deploy to the cluster
# 3. Watch for file changes
# 4. Re-build and re-deploy on changes (or sync files if configured)
# 5. Stream logs from all pods
# 6. Clean up on Ctrl+C
# Port-forward automatically
skaffold dev --port-forward
# Tail logs while developing
skaffold dev --tail
Skaffold Profiles
Profiles let you customize Skaffold behavior per environment:
# skaffold.yaml
apiVersion: skaffold/v4beta6
kind: Config
build:
artifacts:
- image: my-org/web-app
docker:
dockerfile: Dockerfile
deploy:
kubectl:
manifests:
- k8s/base/*.yaml
# Profile for CI (use Kaniko, push to registry)
profiles:
- name: ci
build:
artifacts:
- image: my-org/web-app
kaniko:
dockerfile: Dockerfile
cluster:
namespace: kaniko
deploy:
kubectl:
manifests:
- k8s/overlays/staging/*.yaml
# Profile for production deployment
- name: production
build:
artifacts:
- image: my-org/web-app
docker:
dockerfile: Dockerfile
target: production
tagPolicy:
gitCommit: {} # Tag with git commit SHA
deploy:
helm:
releases:
- name: web-app
chartPath: helm/web-app
valuesFiles:
- helm/values-prod.yaml
# Run with a specific profile
skaffold dev --profile=ci
skaffold run --profile=production
# Activate multiple profiles
skaffold run -p ci -p feature-flag-x
CI/CD Integration
GitHub Actions:
# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Skaffold
run: |
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
chmod +x skaffold && sudo mv skaffold /usr/local/bin/
- name: Configure Docker
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Configure kubectl
run: echo "${{ secrets.KUBECONFIG }}" | base64 -d > /tmp/kubeconfig
- name: Deploy with Skaffold
env:
KUBECONFIG: /tmp/kubeconfig
run: skaffold run --profile=ci --tag=${{ github.sha }}
One-shot build and push (no deploy):
# Build and push images only
skaffold build --push --tag=$(git rev-parse --short HEAD)
# Render manifests to stdout (useful for GitOps)
skaffold render --profile=production --output=rendered.yaml
kubectl apply -f rendered.yaml
Troubleshooting
Image build fails:
# Enable verbose output
skaffold dev -v debug
# Test the Docker build directly
docker build -t my-org/web-app:test .
# Check that Docker daemon is running
docker info
Pods not starting after deploy:
# Check pod status
kubectl get pods -n development
# Skaffold streams logs automatically in dev mode
# For run mode:
kubectl logs -l app=web-app -n development --tail=50
File sync not working:
# Verify sync config in skaffold.yaml
skaffold dev -v debug 2>&1 | grep -i "sync"
# File sync requires the container to be running and the path to exist
# Check the container filesystem
kubectl exec -it <pod-name> -- ls /app/src/
Port forwarding fails:
# List available services for port-forwarding
kubectl get services -n development
# Manual port forward as a workaround
kubectl port-forward svc/web-app 8080:80 -n development
Conclusion
Skaffold dramatically reduces the friction of Kubernetes development by automating the build-deploy loop and providing file sync for rapid iteration. Its profile system handles the full lifecycle from local development through CI and production deployment, with support for Docker, Kaniko, Buildpacks, Helm, and Kustomize. Integrating Skaffold into your CI/CD pipeline ensures developers and automation use the same deployment tooling.


