Skip to content
← Back to Work
Cloud Native · Automation

k8s-cluster-bootstrap

  • Provisioning
  • Bare-metal
  • Automation

Summary

An open-source tool that automates node configuration, component installation, and cluster joining for on-premises Kubernetes. I separated the common installation procedure from environment-specific options so each node can initialize a master or join as a worker with one command.

Role
Developer, Maintainer (installation automation design and development, compatibility improvements)
Stack
Bash, Kubernetes, kubeadm, containerd, Docker, Calico
Outcome
Per-node installation automation, unified master and worker setup, open-source release
Run the bootstrap once per node. Preflight, runtime and version-pinned Kubernetes components are common. The master runs kubeadm init and optional Calico deployment; workers retrieve the master’s join token over SSH and rsync, then run kubeadm join. Without a role option, only common components are installed.
k8s-cluster-bootstrap Pipeline

Problem

More Nodes Meant Repeating the Same Setup

Building an on-premises Kubernetes cluster required configuring swap, the kernel, and networking on every node, then installing the container runtime and Kubernetes components. Even after initializing the master and deploying the CNI, I still had to pass a join command to each worker.

Adding nodes repeated this procedure, and manual setup led to missing or inconsistent settings. The installation sequence and its conditions needed to become a repeatable procedure rather than something a person had to remember each time.

Design Direction

One Common Procedure with Environment-Specific Options

I grouped operating-system configuration and runtime installation into a common Bash procedure. Values that vary by environment, including the Kubernetes version, runtime, master address, and Pod network range, became command-line options. The same flow could then be reused with different values without editing the installation commands.

After common setup, the flow branches by node role. A master proceeds through cluster initialization and network configuration; a worker joins the existing cluster. Each node runs one command with its role and installation options.

Automation

Connecting OS Configuration, Installation, and Cluster Joining

I connected preparation through the final configuration step so package installation and node joining did not require separate manual procedures. The recording below shows a real run on Ubuntu 22.04 with containerd and Kubernetes 1.31.0, completing master initialization and Calico deployment.

k8s-cluster-bootstrap Demo

The script disables swap and UFW and applies the kernel modules and sysctl settings required for containers and networking. It saves these settings to persist across reboots, then installs the selected runtime and Kubernetes components.

On the master, kubeadm initializes the cluster and generates kubeconfig and a join command. Calico defaults to VXLAN for use in cloud and on-premises environments, with IPIP available for suitable networks. Workers retrieve the join command from the master over SSH and execute it, automating the command transfer previously repeated for each added node.

Compatibility Improvements

Handling Version and Dependency Differences as Support Expanded

Combining the steps did not guarantee that the same commands would work in every environment. Inferring a deb package revision from the Kubernetes version caused installations to fail when the repository used a different revision. I changed the script to query available versions with apt-cache madison and install kubelet, kubeadm, and kubectl at the same version. Package holds then prevent updates from changing the Kubernetes version unintentionally.

The Docker option builds cri-dockerd from source to connect it to Kubernetes. Hard-coding its Go version would require changing the script whenever the external project changed, so the script reads the required version from go.mod and prepares that toolchain. Installation requirements thus come from the actual package and project metadata.

I also added checks for role-specific options, addresses, the runtime, and supported versions. A VERSIONLIST beside the script takes precedence; otherwise it is fetched from GitHub. If the list cannot be loaded, installation does not begin. If the requested package version is unavailable at the package-query stage, the script reports the error and stops.

Results

From Repeated Commands to a Reusable Installation Tool

I combined node configuration, runtime installation, master initialization, and worker joining in one tool and released it under Apache-2.0. The supported OS range is Ubuntu 18.04–26.04, and the maintained list contains 169 Kubernetes versions from 1.24.15 to 1.36.4. I have published 28 releases addressing installation problems and environment differences.

The project began with reducing repetitive setup, but expanding support also required handling changes in package repositories and build tools. I separated the common procedure from environment-specific values, queried external dependency metadata, and stopped execution when required conditions were not met. It developed from the convenience of one command per node into a tool for reusing the same installation flow across different environments.