When exploring ways to study Kubernetes on my local computer, I came across a tool called KIND
which is the short for Kubernetes IN Docker. It seemed perfect for testing Kubernetes locally without spending money on cloud providers or purchasing additional hardware. In this post I’ll share my experiences with KIND, including how I set it up, deployed an Ingress controller and a few applications.
TL;DR: KIND is a tool for running Kubernetes clusters locally using Docker. This post covers installation, cluster creation, troubleshooting PATH issues, and deploying an NGINX ingress controller with example services.
What is kind?
According to its documentation page:
kind is a tool for running local Kubernetes clusters using Docker container “nodes”.
kind was primarily designed for testing Kubernetes itself, but may be used for local development or CI.
Note that KIND is not Generally Available (GA) therefore, it’s not intended for production workloads. This is also described at it’s 1.0-Roadmap document as one of it’s non-goals.
So, what are the use cases for kind? I’ll list some that I can think of:
- Local development: allow developers to have a local Kubernetes cluster
- Testing: how cool is to have the option to test your deployments locally?
- Continuous Integration (CI): just don’t test your deployment locally, have it automated as part of your CI pipeline!
- Self Study: do you want to study Kubernetes and don’t break the bank? Maybe kind is what you were looking for
Installation and cluster creation
Before installing KIND, you’ll need to make sure you already have:
- go 1.16+
- docker, podman or nerdctl installed
The installation is pretty easy, just type the command below in your terminal:
$ go install sigs.k8s.io/kind@v0.25.0 && kind create cluster
However, the kind create
command didn’t work for me and I got the error zsh: command not found: kind
.
I saw the packages being downloaded but ~/go/bin
was not added to my PATH, so I manually added it to my .zshrc
file:
# kind
export PATH="/Users/jpmota/go/bin:$PATH"
Now I’m able to create the cluster:
$ kind create cluster
Creating cluster "kind" ...
✓ Ensuring node image (kindest/node:v1.31.2) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:
kubectl cluster-info --context kind-kind
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
Cool, there’s a kind-control-plane
container already running:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6b5006a91a14 kindest/node:v1.31.2 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes 127.0.0.1:56522->6443/tcp kind-control-plane
It also generated a kubectl
configuration:
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
docker-desktop docker-desktop docker-desktop
* kind-kind kind-kind kind-kind
Alternative: create KIND cluster with extra port mappings
Let’s say you want your cluster to have different port mappings, for such you can create a configuration file and use it during the cluster creation:
Configuration file:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 31437 # Port inside the cluster
hostPort: 8080 # Port exposed on localhost
protocol: TCP
- containerPort: 31438
hostPort: 8443
protocol: TCP
Create cluster with config file:
kind create cluster --config=kind-cluster-with-extra-port-mappings.yaml
Install NGINX Ingress Controller and create a deployment
Let’s play a little bit with our kind cluster. I’m going to install the Nginx ingress controller and create a deployment consisting of 2 pods and its respective services. Then, let’s create an ingress rule to route traffic to each service based on the pathPrefix
:
Deploy NGINX Ingress controller:
$ kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml
With the ingress controller created, let’s create the pods, services and create the ingress rule to route the traffic:
kind: Pod
apiVersion: v1
metadata:
name: foo-app
labels:
app: foo
spec:
containers:
- command:
- /agnhost
- serve-hostname
- --http=true
- --port=8080
image: registry.k8s.io/e2e-test-images/agnhost:2.39
name: foo-app
---
kind: Service
apiVersion: v1
metadata:
name: foo-service
spec:
selector:
app: foo
ports:
# Default port used by the image
- port: 8080
---
kind: Pod
apiVersion: v1
metadata:
name: bar-app
labels:
app: bar
spec:
containers:
- command:
- /agnhost
- serve-hostname
- --http=true
- --port=8080
image: registry.k8s.io/e2e-test-images/agnhost:2.39
name: bar-app
---
kind: Service
apiVersion: v1
metadata:
name: bar-service
spec:
selector:
app: bar
ports:
# Default port used by the image
- port: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- http:
paths:
- pathType: Prefix
path: /foo
backend:
service:
name: foo-service
port:
number: 8080
- pathType: Prefix
path: /bar
backend:
service:
name: bar-service
port:
number: 8080
Now test the ingress:
$ curl localhost/foo
foo-app
$ curl localhost/bar
bar-app
To keep this post concise, I plan to share additional posts in the future about other tests I’ve tried with KIND. I’m thinking about deploying the Gateway API, comparing it with the NGINX Ingress Controller and also deploying some Helm charts.
KIND is great for those looking to try Kubernetes locally. With its lightweight setup and flexibility, it makes testing, learning, or even incorporating into CI pipelines much easier. I hope this post helps you get started.