Initial design

This document covers some of the initial design for kind.

NOTE: Some of this is out of date relative to what is currently implemented. This mostly exists for historical purposes, the the original proposal covers some more details.

Going forward the design principles may be more relevant.

Overview 🔗︎

kind or kubernetes in docker is a suite of tooling for local Kubernetes “clusters” where each “node” is a Docker container. kind is targeted at testing Kubernetes.

kind is divided into go packages implementing most of the functionality, a command line for users, and a “node” base image. The intent is that the kind suite of packages should eventually be importable and reusable by other tools (e.g. kubetest) while the CLI provides a quick way to use and debug these packages.

For the original proposal by Q-Lee see the kubernetes-sig-testing post (NOTE: this document is shared with kubernetes-sig-testing).

In short kind targets local clusters for testing purposes. While not all testing can be performed without “real” clusters in “the cloud” with provider enabled CCMs, enough can that we want something that:

In practice kind looks something like this:

Clusters 🔗︎

Clusters are managed by logic in pkg/cluster, which the kind cli wraps.

Each “cluster” is identified by an internal but well-known docker object label key, with the cluster name / ID as the value on each “node” container.

We initially offload this type of state into the containers and Docker. Similarly the container names are automatically managed by kind, though we will select over labels instead of names because these are less brittle and are properly namespaced. Doing this also avoids us needing to manage anything on the host filesystem, but should not degrade usage.

The KUBECONFIG will be bind-mounted to a temp directory, with the tooling capable of detecting this from the containers and providing helpers to use it.

Images 🔗︎

To run Kubernetes in a container, we first need suitable container image(s). A single standard base layer is used, containing basic utilities like systemd, certificates, mount, etc.

Installing Kubernetes etc. is performed on top of this image, and may be cached in pre-built images. We expect to provide images with releases already installed for use in integrating against Kubernetes.

For more see node-image.md.

Cluster Lifecycle 🔗︎

Cluster Creation 🔗︎

Each “node” runs as a docker container. Each container initially boots to a pseudo “paused” state, with the entrypoint waiting for SIGUSR1. This allows us to manipulate and inspect the container with docker exec ... and other tools prior to starting systemd and all of the components.

This setup includes fixing mounts and pre-loading saved docker images.

Once the nodes are sufficiently prepared, we signal the entrypoint to actually “boot” the node.

We then wait for the Docker service to be ready on the node before running kubeadm to initialize the node.

Once kubeadm has booted, we export the KUBECONFIG, then apply an overlay network.

At this point users can test Kubernetes by using the exported kubeconfig.

Cluster Deletion 🔗︎

All “node” containers in the cluster are tagged with docker labels identifying the cluster by the chosen cluster name (default is “kind”), to delete a cluster we can simply list and delete containers with this label.