Skaffold is a command-line tool from Google that automates the build, push, and deploy cycle for Kubernetes applications, giving developers a hot-reload inner loop without writing bespoke shell scripts. On RHEL 8 with a local Kubernetes cluster such as k3s, Skaffold detects file changes, rebuilds the affected container image, and rolls out the updated deployment in seconds, making the local development experience feel nearly as fast as running code directly on the host. This tutorial covers installing Skaffold, writing a skaffold.yaml manifest, using skaffold dev for iterative development, running a one-shot deployment with skaffold run, and tearing down resources with skaffold delete.

Prerequisites

  • RHEL 8 server with Docker or Podman installed and a local Kubernetes cluster (k3s recommended)
  • kubectl configured and pointing at your local cluster
  • A sample application with a Dockerfile and Kubernetes manifests in a k8s/ directory
  • Outbound internet access to download the Skaffold binary from storage.googleapis.com

Step 1 — Install k3s and Skaffold

Install k3s as a lightweight single-node Kubernetes cluster on RHEL 8, then download the Skaffold binary and place it on your PATH.

# Install k3s (disables traefik to keep resource usage low)
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable=traefik" sh -

# Copy kubeconfig for the current user
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
export KUBECONFIG=~/.kube/config

# Verify cluster is ready
kubectl get nodes

# Install Skaffold
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
sudo install skaffold /usr/local/bin/
skaffold version

Step 2 — Prepare a Sample Application

Create a minimal Python Flask application with a Dockerfile and Kubernetes deployment manifest so Skaffold has something to build and deploy.

mkdir -p ~/skaffold-demo/k8s && cd ~/skaffold-demo

# Minimal Flask app
cat > app.py < requirements.txt < Dockerfile < k8s/deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flask-demo
  template:
    metadata:
      labels:
        app: flask-demo
    spec:
      containers:
        - name: flask-demo
          image: flask-demo
          ports:
            - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: flask-demo
spec:
  type: NodePort
  selector:
    app: flask-demo
  ports:
    - port: 5000
      targetPort: 5000
      nodePort: 30500
EOF

Step 3 — Write the skaffold.yaml Configuration

The skaffold.yaml file declares how to build the image and how to deploy the manifests. The local build mode pushes directly into the k3s containerd registry, skipping a separate registry.

cat > skaffold.yaml <<'EOF'
apiVersion: skaffold/v4beta11
kind: Config
metadata:
  name: flask-demo

build:
  artifacts:
    - image: flask-demo
      docker:
        dockerfile: Dockerfile
  local:
    push: false
    useBuildkit: true

deploy:
  kubectl:
    manifests:
      - k8s/*.yaml

# Optional: port-forward for easy local access
portForward:
  - resourceType: service
    resourceName: flask-demo
    port: 5000
    localPort: 5000

# File sync: update Python files in the running container without a full rebuild
#sync:
#  manual:
#    - src: "app.py"
#      dest: /app
EOF

# Validate the configuration
skaffold diagnose

Step 4 — Run skaffold dev for Hot-Reload Development

skaffold dev watches your source tree for changes. When you save a file, Skaffold rebuilds the image and rolls out a new deployment automatically, streaming logs to your terminal.

# Start the development loop (Ctrl+C stops and cleans up resources)
skaffold dev --port-forward

# In another terminal, test the running service
curl http://localhost:5000

# Now edit app.py and save — Skaffold will detect the change:
sed -i 's/Hello from Skaffold/Hello UPDATED from Skaffold/' app.py

# Watch Skaffold rebuild and redeploy automatically in the first terminal
# Then verify the updated response:
curl http://localhost:5000

# Use --trigger=manual to rebuild only when you press Enter
skaffold dev --trigger=manual

Step 5 — One-Shot Deploy with skaffold run

skaffold run performs a single build-and-deploy cycle without watching for changes. It is suited for CI pipelines or staging deployments where you want Skaffold to exit after completion.

# Build and deploy once (does not watch for changes)
skaffold run --port-forward

# Check deployment status
kubectl get pods
kubectl get service flask-demo

# Test the deployed service
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}')
curl http://$NODE_IP:30500

# Run with a specific image tag (useful in CI to stamp the Git commit SHA)
skaffold run --tag=$(git rev-parse --short HEAD)

# Build only — skip deployment (useful for image caching in CI)
skaffold build

# Deploy only — skip build (use a pre-built image)
skaffold deploy --images flask-demo=docker.io/youruser/flask-demo:abc1234

Step 6 — Clean Up with skaffold delete

skaffold delete removes all Kubernetes resources that were deployed by Skaffold, leaving the cluster clean without requiring manual kubectl delete commands.

# Delete all resources deployed by the current skaffold.yaml
skaffold delete

# Verify resources are removed
kubectl get deployments
kubectl get services | grep flask-demo

# Useful Skaffold profile flags for environment-specific configs:
# Define profiles in skaffold.yaml to override build/deploy settings per environment
cat >> skaffold.yaml <<'EOF'

profiles:
  - name: production
    build:
      local:
        push: true
    deploy:
      kubectl:
        manifests:
          - k8s/*.yaml
          - k8s/prod/*.yaml
EOF

# Run with a specific profile
skaffold run --profile=production

# Check Skaffold's understanding of the full resolved config
skaffold diagnose --yaml

Conclusion

You have installed Skaffold on RHEL 8 alongside a k3s cluster, written a skaffold.yaml that builds a Docker image and deploys it with kubectl, and experienced the hot-reload inner loop with skaffold dev. The combination of skaffold run for CI pipelines and profiles for environment-specific overrides makes Skaffold a versatile tool that spans local development all the way to production delivery. Using a local k3s cluster dramatically reduces iteration time by eliminating round-trips to a remote registry and cluster.

Next steps: Using Skaffold File Sync to Avoid Full Rebuilds on RHEL 8, Integrating Skaffold into a Tekton CI Pipeline, and Managing Multiple Microservices with Skaffold Modules.