KIND – Kubernetes in Docker

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.