Skip to content

Vanilla (Kind)

Kind (Kubernetes in Docker) runs upstream Kubernetes clusters using Docker containers as nodes. It is fast (30–60 s), Docker-only, and uses standard kind.yaml files with no vendor lock-in. For common workflows and use cases, see Use Cases.

Create your first Vanilla cluster in under 60 seconds.

  • Docker Desktop or Docker Engine installed and running
  • docker ps command works
Terminal window
ksail cluster init \
--name my-cluster \
--distribution Vanilla \
--control-planes 1 \
--workers 2

This creates:

  • ksail.yaml — KSail configuration
  • kind.yaml — Kind-specific cluster configuration
Terminal window
ksail cluster create
Terminal window
ksail cluster info
kubectl get nodes
Terminal window
# Delete cluster and all resources
ksail cluster delete

The ksail.yaml file controls your cluster:

# yaml-language-server: $schema=https://raw.githubusercontent.com/devantler-tech/ksail/main/schemas/ksail-config.schema.json
apiVersion: ksail.io/v1alpha1
kind: Cluster
spec:
cluster:
distribution: Vanilla
distributionConfig: kind.yaml

Customize Kind behavior in kind.yaml:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
# Port mapping for accessing services
extraPortMappings:
- containerPort: 80
hostPort: 8080
protocol: TCP
- role: worker
- role: worker
# Containerd configuration
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"]
endpoint = ["http://localhost:5000"]

Enable LoadBalancer services with Cloud Provider KIND:

ksail.yaml
apiVersion: ksail.io/v1alpha1
kind: Cluster
spec:
cluster:
distribution: Vanilla
loadBalancer: Enabled

When enabled, KSail installs Cloud Provider KIND, which creates cpk-* Docker containers as LoadBalancer proxies and assigns external IPs. See LoadBalancer Configuration for details.

Configure registry mirrors to avoid rate limits. KSail enables docker.io, ghcr.io, quay.io, and registry.k8s.io mirrors by default. Override with --mirror-registry flags:

Terminal window
ksail cluster init --name my-cluster --distribution Vanilla \
--mirror-registry 'docker.io=https://registry-1.docker.io' \
--mirror-registry 'ghcr.io=https://ghcr.io' \
--mirror-registry 'quay.io=https://quay.io' \
--mirror-registry 'registry.k8s.io=https://registry.k8s.io'

KSail injects containerd registry configuration into all Kind nodes.

Symptom: ksail cluster create fails with Docker errors.

Terminal window
docker ps # Verify Docker is running
df -h # Check disk space
docker system prune -f
ksail cluster create

Symptom: kubectl get nodes shows NotReady status.

Terminal window
kubectl describe node <node-name>
kubectl get pods -n kube-system | grep cilium
kubectl rollout restart daemonset/cilium -n kube-system

Symptom: LoadBalancer service never gets EXTERNAL-IP.

Terminal window
kubectl get pods -A | grep cloud-provider-kind
cat ksail.yaml | grep -A2 loadBalancer
ksail cluster update

Symptom: address already in use error during cluster creation.

Terminal window
kind get clusters
kind delete cluster --name <conflicting-cluster>

Symptom: Cluster creation fails with resource errors.

Terminal window
ksail cluster init --name my-cluster --distribution Vanilla --control-planes 1 --workers 0
# WARNING: removes ALL unused images and volumes — can affect other Docker projects
docker system prune -a --volumes

Create production-like topologies:

Terminal window
ksail cluster init \
--name multi-node \
--distribution Vanilla \
--control-planes 3 \
--workers 5

Kind determines the Kubernetes version via the node image tag. To use a specific version, configure the node image in your kind.yaml:

kind.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
image: kindest/node:v1.31.0
- role: worker
image: kindest/node:v1.31.0

Supported versions: Check Kind release notes for image availability.

Override default CNI:

Terminal window
ksail cluster init --name my-cluster --distribution Vanilla --cni Calico

Available CNI options: Default, Cilium, Calico.

Expose services on host ports:

kind.yaml
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30080 # NodePort service
hostPort: 8080
protocol: TCP

Access services at http://localhost:8080.

Enable persistent storage:

Terminal window
ksail cluster init --name my-cluster --distribution Vanilla --csi Enabled

KSail generates a standard kind.yaml in your project directory (created by ksail cluster init). You can use the Kind CLI directly with that file—configurations are portable and there is no vendor lock-in. KSail can also interact with any Kind cluster accessible via your kubeconfig.

Terminal window
# Run from the directory containing the generated kind.yaml
kind create cluster --config kind.yaml
kind export kubeconfig --name my-cluster