Local Kubernetes cheatsheet.

kind (Kubernetes in Docker)

brew install kind

kind create cluster
kind create cluster --name dev --image kindest/node:v1.30.0
kind get clusters
kind delete cluster --name dev

With config:

# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
    extraPortMappings:
      - { containerPort: 80, hostPort: 80 }
      - { containerPort: 443, hostPort: 443 }
  - role: worker
  - role: worker
kind create cluster --config kind-config.yaml

Load image into kind

docker build -t myapp:dev .
kind load docker-image myapp:dev --name dev

Or use imagePullPolicy: Never to use locally built.

k3d (k3s in Docker)

brew install k3d

k3d cluster create dev --agents 2 -p "80:80@loadbalancer" -p "443:443@loadbalancer"
k3d cluster delete dev

k3d image import myapp:dev -c dev

Lighter than kind; bundles Traefik + LoadBalancer.

minikube

brew install minikube
minikube start
minikube start --driver=docker --cpus=4 --memory=8g
minikube tunnel                 # exposes LoadBalancer locally
minikube addons enable ingress
minikube image load myapp:dev

More features (addons), heavier.

k3s (single-node Linux)

curl -sfL https://get.k3s.io | sh -
sudo cat /etc/rancher/k3s/k3s.yaml > ~/.kube/config

For lightweight server / edge use.

microk8s (Ubuntu)

sudo snap install microk8s --classic
microk8s status --wait-ready
microk8s enable dashboard dns ingress

Tilt (dev loop)

brew install tilt-dev/tap/tilt
# Tiltfile
docker_build('myreg/web', '.', dockerfile='Dockerfile.dev')
k8s_yaml('manifests/web.yaml')
k8s_resource('web', port_forwards='3000:3000')
tilt up

Auto-rebuilds image + redeploys on file change. Lives in browser dashboard.

Skaffold (alternative)

skaffold init
skaffold dev
# skaffold.yaml
apiVersion: skaffold/v4beta11
kind: Config
build:
  artifacts: [{ image: myreg/web, context: . }]
deploy:
  kubectl: { manifests: ["manifests/*.yaml"] }

DevSpace, Garden, Telepresence

Other dev workflow tools. Pick whichever fits.

Locally test ingress

# /etc/hosts
127.0.0.1 myapp.local

kind with port mappings + ingress controller → curl myapp.local works.

Local registry

docker run -d --restart=always -p 5000:5000 --name registry registry:2

# Configure kind to use local registry
# See https://kind.sigs.k8s.io/docs/user/local-registry/

Push to localhost:5000 and reference in pod yaml.

Resources

Local clusters need RAM + CPU:

  • kind: 2-4 GB minimum.
  • k3d: 1-2 GB.
  • minikube: 4-8 GB.

Allocate accordingly in Docker Desktop/Colima.

Persistence across restarts

kind clusters survive Docker restarts. To clean: kind delete cluster.

minikube: VM-based, persists.

Cross-platform images

For Apple Silicon: ensure CNI / kube components support arm64. Modern kind/k3d/minikube do.

Connecting host → cluster

kubectl port-forward svc/web 8080:80
kubectl proxy                       # API access at localhost:8001

Connecting cluster → host

host.docker.internal           # Docker Desktop
host.lima.internal             # Lima / OrbStack
host.k3d.internal              # k3d default

Multi-node testing

# kind config with 3 workers
nodes:
  - { role: control-plane }
  - { role: worker }
  - { role: worker }
  - { role: worker }

Test pod anti-affinity, topology, etc.

Common mistakes

  • Heavy K8s + heavy Docker Desktop → laptop melts.
  • Forgetting to load image → ImagePullBackOff.
  • Wrong context → kubectl modifies remote cluster.
  • LoadBalancer without kind: cloud-provider-kind or k3d’s built-in.
  • Not deleting clusters → wasted resources.

Read this next

If you want my Tilt + kind dev setup, it’s at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .