# kind create cluster: Ephemeral Clusters in CI

> kind create cluster spins up a Kubernetes cluster in Docker for tests. Reference for --name, --config, --image, --wait, and the Docker errors in CI.

Source: https://latchkey.dev/learn/command-reference/kind-create-cluster  
Updated: 2026-06-30

kind create cluster runs a full Kubernetes cluster inside Docker containers, ready in under a minute for ephemeral CI testing.

kind (Kubernetes IN Docker) gives a real API server and nodes as containers, perfect for integration tests that need an actual cluster and tear down clean.

## What it does

kind create cluster boots a control plane (and optional worker nodes) as Docker containers, writes a kubeconfig context named `kind-<name>`, and waits for the API server. A `--config` file defines node count, port mappings, and feature gates.

## Common usage

```Terminal
kind create cluster --name ci
kind create cluster --name ci --config kind.yaml --wait 120s
kind create cluster --image kindest/node:v1.29.2
kubectl cluster-info --context kind-ci
```

## Options

| Flag | What it does |
| --- | --- |
| --name | Cluster name (context becomes kind-<name>) |
| --config | Cluster config YAML (nodes, ports, gates) |
| --image | Node image, pinning the Kubernetes version |
| --wait | Wait up to a duration for the control plane |
| --kubeconfig | Write kubeconfig to a specific path |
| --retain | Keep containers on failure for debugging |

## In CI

Pin `--image kindest/node:vX.Y.Z` so the Kubernetes version is reproducible. Add `--wait 120s` so the next step does not race the API server. On GitHub-hosted runners Docker is already present; create the cluster, run tests, then `kind delete cluster --name ci`.

## Common errors in CI

`ERROR: failed to create cluster: ... Cannot connect to the Docker daemon` means Docker is not running or the socket is unavailable. `failed to create cluster: node(s) already exist for a cluster with the name "ci"` means a leftover cluster; delete it first. `failed to init node with kubeadm ... timed out` on small runners is usually too little memory; reduce nodes or raise resources.

## Using this in CI

A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.

```Terminal
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods

# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info

# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes
```

> Always set `--request-timeout` in CI. Without it an unreachable API server hangs until the job times out, which turns a thirty-second failure into a twenty-minute one.

## FAQ

### kind create cluster: Ephemeral Clusters in CI?

kind (Kubernetes IN Docker) gives a real API server and nodes as containers, perfect for integration tests that need an actual cluster and tear down clean.

### What it does?

kind create cluster boots a control plane (and optional worker nodes) as Docker containers, writes a kubeconfig context named kind-<name>, and waits for the API server. A --config file defines node count, port mappings, and feature gates.

### In CI?

Pin --image kindest/node:vX.Y.Z so the Kubernetes version is reproducible. Add --wait 120s so the next step does not race the API server. On GitHub-hosted runners Docker is already present; create the cluster, run tests, then kind delete cluster --name ci.

### Common errors in CI?

ERROR: failed to create cluster: ... Cannot connect to the Docker daemon means Docker is not running or the socket is unavailable. failed to create cluster: node(s) already exist for a cluster with the name "ci" means a leftover cluster; delete it first. failed to init node with kubeadm ...

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
