Kind is a tool which can be used for running local multi node Kubernetes clusters. Kind was primarily designed for testing Kubernetes itself and associated extensions, but may be used for local development or CI. With the Kind, you can spin up a multi node Kubernetes cluster in couple of minutes, perform your work and then wind it down. And nobody need to worry about the Bill! Starting with kind 0.11.0, Rootless Docker and Rootless Podman can be used as the node provider of kind. Its not running kubernetes in rootless mode as some component of kubernetes stack cannot run rootless yet, however it is certainly a step in that direction.
Pre-requisites to run rootless Kind
Note that while ability to run rootless containers was always present in the Podman, it is only with the recent version of Docker that it moved to rootless stack. And you can use either Podman or Docker, depending on the container engine you are familiar with.
- Docker: 20.10 or later
- Podman: 3.0 or later
- cgroup v2 should be enabled on the linux host. cgroup v2 is enabled by default on Fedora 31 or RHEL 8.
On other distros, cgroup v2 can be typically enabled by adding GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=1"
to /etc/default/grub
and running sudo update-grub
. In more recent versions of distributions, this functionality should be enabled by default. However, check instruction specific to your distribution.
For the purpose of this blog post, we are using Fedora 33, which has cgroup v2 enabled by default:
[cloud_user@217fabcd221c ~]$ cat /etc/*-release Fedora release 33 (Thirty Three) NAME=Fedora VERSION="33 (Cloud Edition)" ID=fedora VERSION_ID=33 VERSION_CODENAME="" PLATFORM_ID="platform:f33" PRETTY_NAME="Fedora 33 (Cloud Edition)" ... ...
Also, depending on the host configuration, the following steps might be needed:
- Create
/etc/systemd/system/user@.service.d/delegate.conf
with the following content, and then runsudo systemctl daemon-reload
:
[Service] Delegate=yes
[cloud_user@217fabcd221c ~]$ sudo mkdir /etc/systemd/system/user@.service.d [cloud_user@217fabcd221c ~]$ sudo touch /etc/systemd/system/user@.service.d/delegate.conf [cloud_user@217fabcd221c ~]$ sudo vi /etc/systemd/system/user@.service.d/delegate.conf [cloud_user@217fabcd221c ~]$ sudo cat /etc/systemd/system/user@.service.d/delegate.conf [Service] Delegate=yes
- Create
/etc/modules-load.d/iptables.conf
with the following content:
iptables_nat ip6tables_nat
[cloud_user@217fabcd221c ~]$ sudo vi /etc/modules-load.d/iptables.conf [cloud_user@217fabcd221c ~]$ cat vi /etc/modules-load.d/iptables.conf cat: vi: No such file or directory iptables_nat ip6tables_nat
Install and setup Kind
You can review the official installation instructions here. Check for kind releases here to identify latest release version. We can also use below steps to grab and install Kind:
# download the latest version of kind [cloud_user@217fabcd221c kind]$ curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.10.0/kind-linux-amd64 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 98 100 98 0 0 265 0 --:--:-- --:--:-- --:--:-- 265 100 624 100 624 0 0 976 0 --:--:-- --:--:-- --:--:-- 9313 100 7277k 100 7277k 0 0 2429k 0 0:00:02 0:00:02 --:--:-- 3852k # assign execute permissions to binary [cloud_user@217fabcd221c kind]$ chmod +x ./kind # move binary to /usr/local/bin or add to $PATH [cloud_user@217fabcd221c kind]$ sudo mv ./kind /usr/local/bin # verify kind is working [cloud_user@217fabcd221c kind]$ kind version kind v0.10.0 go1.15.7 linux/amd64
Install Rootless Docker 20.10+
The instructions would depend in terms of pre-requisites and setup depending on the underlying linux distribution of choice. For detailed instructions, refer to official docs. TL;DR We can install Docker in rootless mode by grabbing and running script at https://get.docker.com/rootless:
[cloud_user@217fabcd221c kind]$ curl -fsSL https://get.docker.com/rootless | sh # Installing stable version 20.10.5 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 65.9M 100 65.9M 0 0 107M 0 --:--:-- --:--:-- --:--:-- 107M % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 19.0M 100 19.0M 0 0 100M 0 --:--:-- --:--:-- --:--:-- 100M + PATH=/home/cloud_user/bin:/home/cloud_user/.local/bin:/home/cloud_user/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin + /home/cloud_user/bin/dockerd-rootless-setuptool.sh install [INFO] Creating /home/cloud_user/.config/systemd/user/docker.service [INFO] starting systemd service docker.service + systemctl --user start docker.service + sleep 3 + systemctl --user --no-pager --full status docker.service ● docker.service - Docker Application Container Engine (Rootless) Loaded: loaded (/home/cloud_user/.config/systemd/user/docker.service; disabled; vendor preset: disabled) Active: active (running) since Tue 2021-04-06 18:48:09 UTC; 3s ago Docs: https://docs.docker.com/engine/security/rootless/ Main PID: 1727 (rootlesskit) Tasks: 38 Memory: 26.4M CPU: 413ms CGroup: /user.slice/user-1001.slice/user@1001.service/docker.service ├─1727 rootlesskit --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /home/cloud_user/bin/dockerd-rootless.sh ├─1740 /proc/self/exe --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback ... ... + systemctl --user enable docker.service Created symlink /home/cloud_user/.config/systemd/user/default.target.wants/docker.service → /home/cloud_user/.config/systemd/user/docker.service. [INFO] Installed docker.service successfully. [INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service` [INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger cloud_user` [INFO] Make sure the following environment variables are set (or add them to ~/.bashrc): export PATH=/home/cloud_user/bin:$PATH export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
As instructed in the last few lines, set the environmental variables:
[cloud_user@217fabcd221c ~]$ echo "export PATH=/home/cloud_user/bin:$PATH" >> ~/.bashrc [cloud_user@217fabcd221c ~]$ echo "export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock" >> ~/.bashrc
Verify docker is working with docker info
:
[cloud_user@217fabcd221c ~]$ docker info Client: Context: default Debug Mode: false Server: Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 20.10.5 Storage Driver: fuse-overlayfs Logging Driver: json-file Cgroup Driver: systemd Cgroup Version: 2 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc Default Runtime: runc Init Binary: docker-init containerd version: 269548fa27e0089a8b8278fc4fc781d7f65a939b runc version: 12644e614e25b05da6fd08a38ffa0cfe1903fdec init version: de40ad0 Security Options: seccomp Profile: default rootless cgroupns Kernel Version: 5.10.22-200.fc33.x86_64 Operating System: Fedora 33 (Cloud Edition) OSType: linux Architecture: x86_64 CPUs: 2 Total Memory: 7.687GiB Name: 217fabcd221c.mylabserver.com ID: MLMY:JY3Z:3MEK:EBXY:AVNR:XU73:S7V2:OMYO:HBMQ:JDUQ:AH5Y:JBDM Docker Root Dir: /home/cloud_user/.local/share/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false Product License: Community Engine WARNING: No cpu cfs quota support WARNING: No cpu cfs period support WARNING: No cpu shares support WARNING: No cpuset support WARNING: Support for cgroup v2 is experimental WARNING: No io.weight support WARNING: No io.weight (per device) support WARNING: No io.max (rbps) support WARNING: No io.max (wbps) support WARNING: No io.max (riops) support WARNING: No io.max (wiops) support WARNING: bridge-nf-call-iptables is disabled WARNING: bridge-nf-call-ip6tables is disabled
We can see that docker engine is automatically configured to use cgroups v2 by viewing property Cgroup Version: 2
and WARNING: Support for cgroup v2 is experimental
in above output. If cgroups v2 is configured on your host OS, you do not need to do any special steps to enable it for docker engine. Same goes with Podman.
Firewall Changes for Fedora 33
For some reason, I kept getting error related to kind cluster nodes not being able to reach each other. Fortunately, its documented in the list of known issues in kind. I was able to work around this by changing the FirewallBackend
in the /etc/firewalld/firewalld.conf
file from nftables
to iptables
and restarting firewalld:
[cloud_user@217fabcd221c docker]$ sudo sed -i 's/FirewallBackend=.*/FirewallBackend=iptables/' "/etc/firewalld/firewalld.conf" [sudo] password for cloud_user: [cloud_user@217fabcd221c docker]$ [cloud_user@217fabcd221c docker]$ systemctl restart firewalld ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ==== Authentication is required to restart 'firewalld.service'. Authenticating as: cloud_user Password: ==== AUTHENTICATION COMPLETE ====
Create Kubernetes Cluster with Kind and Rootless Docker
Creating an cluster in kind is as simple as running kind create cluster
.
As we mentioned above, that certain components of Kubernetes stack cannot be run in rootless mode yet. So even though we are using docker engine or podman in rootless mode, we cannot run kind in rootless mode. If we try to run kind in rootless mode, we’ll be greeted with an error like below:
[cloud_user@217fabcd221c docker]$ kind create cluster Creating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.20.2) 🖼 ✓ Preparing nodes 📦 ✗ Writing configuration 📜 ERROR: failed to create cluster: failed to generate kubeadm config content: failed to get kubernetes version from node: failed to get file: command "docker exec --privileged kind-control-plane cat /kind/version" failed with error: exit status 1 Command Output: Error response from daemon: Container be1884b745fe628171f7330b50def65e99bf1e69880bb487fc1cdd73fc0a4e83 is not running
However, we can run and launch Kubernetes cluster fine when using kind with sudo privileges:
[cloud_user@217fabcd221c docker]$ sudo kind create cluster enabling experimental podman provider Creating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.20.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 Thanks for using kind! 😊 [cloud_user@217fabcd221c ~]$ sudo kubectl cluster-info --context kind-kind Kubernetes control plane is running at https://127.0.0.1:32769 KubeDNS is running at https://127.0.0.1:32769/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Install Rootless Podman 3.0+
This is an experimental release which is not supported in all linux distributions yet. You can read official instructions here for your distributions here. Once you are done with installation, verify podman is working by using podman version
:
[cloud_user@217fabcd221c ~]$ podman version Version: 3.0.1 API Version: 3.0.0 Go Version: go1.15.8 Built: Fri Feb 19 16:56:17 2021 OS/Arch: linux/amd64
Create Kubernetes Cluster with Kind and Rootless Podman
To instruct kind to use podman, we have to enable property KIND_EXPERIMENTAL_PROVIDER
and set it to podman kind create cluster
:
[cloud_user@217fabcd221c ~]$ export KIND_EXPERIMENTAL_PROVIDER=podman kind create cluster
Again as we mentioned above, that certain components of Kubernetes stack cannot be run in rootless mode yet. So even though we are using docker engine or podman in rootless mode, we cannot run kind in rootless mode. However we can launch cluster fine when running kind with sudo privileges:
[cloud_user@217fabcd221c ~]$ sudo kind create cluster enabling experimental podman provider Creating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.20.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 🙂 [cloud_user@217fabcd221c ~]$ sudo kubectl cluster-info --context kind-kind [sudo] password for cloud_user: Sorry, try again. [sudo] password for cloud_user: Kubernetes control plane is running at https://127.0.0.1:43385 KubeDNS is running at https://127.0.0.1:43385/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. [cloud_user@217fabcd221c ~]$ sudo kubectl get nodes NAME STATUS ROLES AGE VERSION kind-control-plane Ready control-plane,master 4m50s v1.20.2
How do we know if it is indeed using Podman? By looking for below output in the kubectl cluster-info dump
:
[cloud_user@217fabcd221c ~]$ sudo kubectl cluster-info --context kind-kind dump | grep -i podman "providerID": "kind://podman/kind/kind-control-plane"