kind – Kubernetes IN Docker

Watch out! This tutorial is over 5 years old. Please keep this in mind as some code snippets provided may no longer work or need modification to work on current systems.
Tutorial Difficulty Level    

Kubernetes (commonly shortened to “k8s”) is an open-source container-orchestration system for automating application deployment, scaling, and management. It was originally designed by Google, and is now maintained by the Cloud Native Computing Foundation. It aims to provide a “platform for automating deployment, scaling, and operations of application containers across clusters of hosts”. It works with a range of container tools, including Docker.

Computer Services have now added the ability to run local Kubernetes clusters to the Docker Host (with Dockly) VM image on XOA. This facility is powered by kind (Kubernetes IN Docker) which in turn is powered by the GO Programming Language. Kind was born out of the necessity for a lightweight local Kubernetes setup that could be used for testing and conformance.

With kind included, creating a cluster is now as simple as typing:

kind create cluster


To delete your cluster use:

kind delete cluster

How awesome is that?!

So kind is basically a tool that allows you to spin up Kubernetes clusters locally, using containers as ‘nodes’. The images it uses are full base images containing everything required to run Kubernetes control plane and worker nodes. Systemd, Docker, kubelet, the works! This does mean the images can be a little heavy (~1.5GB) but it’s still a great way to run Kubernetes locally in a multi-node configuration without having the overhead of running multiple virtual machines.

Okay, so here is what you need to know….

Creating a Cluster

Creating a Kubernetes cluster is as simple as kind create cluster.

This will bootstrap a Kubernetes cluster using a pre-built node image – you can find it on docker hub kindest/node. If you desire to build the node image yourself see the building image section below. To specify another image use the --image flag.

By default, the cluster will be given the name kind. Use the --name flag to assign the cluster a different context name.

If you want the create cluster command to block until the control plane reaches a ready status, you can use the --wait flag and specify a timeout. To use --wait you must specify the units of the time to wait. For example, to wait for 30 seconds, do --wait 30s, for 5 minutes do --wait 5m, etc.

Interacting With Your Cluster

After creating a cluster, you can use kubectl to interact with it by using the configuration file generated by kind.

By default, the cluster access configuration is stored in ${HOME}/.kube/config if $KUBECONFIG environment variable is not set.

If $KUBECONFIG environment variable is set, then it is used as a list of paths (normal path delimiting rules for your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list.

You can use the --kubeconfig flag when creating the cluster, then only that file is loaded. The flag may only be set once and no merging takes place.

To see all the clusters you have created, you can use the get clusters command.

For example, let’s say you create two clusters:

kind create cluster # Default cluster context name is `kind` .
...
kind create cluster --name kind-2

When you list your kind clusters, you will see something like the following:

kind get clusters
kind
kind-2

In order to interact with a specific cluster, you only need to specify the cluster name as a context in kubectl:

kubectl cluster-info --context kind-kind 
kubectl cluster-info --context kind-2

Deleting a Cluster

If you created a cluster with kind create cluster then deleting is equally simple:

kind delete cluster

If the flag --name is not specified, kind will use the default cluster context name kind and delete that cluster.

Loading an Image Into Your Cluster

Docker images can be loaded into your cluster nodes with: kind load docker-image my-custom-image

Note: If using a named cluster you will need to specify the name of the cluster you wish to load the image into: kind load docker-image my-custom-image --name kind-2

Additionally, image archives can be loaded with: kind load image-archive /my-image-archive.tar

This allows a workflow like:

docker build -t my-custom-image:unique-tag ./my-image-dir 
kind load docker-image my-custom-image:unique-tag 
kubectl apply -f my-manifest-using-my-image:unique-tag

Note: The Kubernetes default pull policy is IfNotPresent unless the image tag is :latest in which case the default policy is Always.

IfNotPresent causes the Kubelet to skip pulling an image if it already exists. If you want those images loaded into node to work as expected, please:

  • don’t use a :latest tag

and / or:

  • specify imagePullPolicy: IfNotPresent or imagePullPolicy: Never on your container(s).

See Kubernetes imagePullPolicy for more information.

See also: Using kind with Private Registries.

Configuring Your kind Cluster

When creating your kind cluster, via create cluster, you can use a configuration file to run specific commands before or after systemd or kubeadm run. For a sample kind configuration file see kind-example-config. To specify a configuration file when creating a cluster, use the --config flag:

kind create cluster --config kind-example-config.yaml

Exporting Cluster Logs

kind has the ability to export all kind related logs for you to explore. To export all logs from the default cluster (context name kind):

kind export logs
Exported logs to: /tmp/396758314

Like all other commands, if you want to perform the action on a cluster with a different context name use the --name flag.

As you can see, kind placed all the logs for the cluster kind in a temporary directory. If you want to specify a location then simply add the path to the directory after the command:

kind export logs ./somedir
Exported logs to: ./somedir

The structure of the logs will look more or less like this:

.
├── docker-info.txt
└── kind-control-plane/
    ├── containers
    ├── docker.log
    ├── inspect.json
    ├── journal.log
    ├── kubelet.log
    ├── kubernetes-version.txt
    └── pods/

The logs contain information about the Docker host, the containers running kind, the Kubernetes cluster itself, etc.