Hello! Welcome to your fourth lesson.
In our last session, we demystified the Kubernetes API and learned how to define cluster resources using YAML manifests. You now understand the declarative model—defining the what (spec) and letting Kubernetes handle the how.
Today, we move from theory to practice. This lesson is the first step in building a Kubernetes cluster from the ground up using kubeadm. Our goal is to prepare the virtual machines (or physical servers) that will become our cluster nodes. By the end of this lesson, you will have configured all the necessary prerequisites and installed the core Kubernetes packages: kubeadm, kubelet, and kubectl. Since you're comfortable with Linux system administration, we'll move through the command-line steps methodically, focusing on why each step is necessary for a stable cluster.
These steps must be performed on every machine you intend to add to your cluster, whether it will be a control-plane node or a worker node.
Step 1: Understanding and Configuring Node Prerequisites
Before installing any Kubernetes packages, we need to ensure our nodes meet the baseline requirements. The official Kubernetes documentation is the definitive source for these prerequisites.
Let's start by reviewing the official requirements for a kubeadm installation. This document lists the hardware, software, and network prerequisites.
Read the section titled 'Before you begin'. Pay special attention to the subsections on 'Check required ports' and 'Swap configuration'. We will implement these configurations next.
From the documentation, there are several key requirements. We'll focus on the three that require active configuration on a standard Linux installation (like Ubuntu Server).
A. Disable Swap
Kubernetes is designed to be the single source of truth for resource management on a node. The kubelet needs to control exactly how much CPU and memory is available to Pods. Swap memory on disk introduces unpredictability in performance and complicates resource accounting. Therefore, kubeadm will fail to initialize a cluster if it detects that swap is enabled.
You must disable swap on all nodes.
# Disable swap immediately
sudo swapoff -a
# Comment out the swap line in /etc/fstab to make the change persistent across reboots
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
This is a critical pre-flight check for kubeadm and a common point of failure for beginners.
B. Enable Kernel Modules and Bridged Traffic
For Pods on different nodes to communicate, packets need to be correctly routed through the node's network stack. Kubernetes networking plugins (CNIs) rely on the Linux kernel's ability to pass bridged traffic to iptables for processing. We need to explicitly load the necessary kernel modules and configure sysctl settings to enable this.
How To Setup Kubernetes Cluster Using Kubeadm
The following article provides a clear set of commands to configure the necessary kernel parameters. It's a great example of a practical walkthrough.
Review the commands in 'Step 1: Enable iptables Bridged Traffic on all the Nodes'. These commands ensure the overlay and br_netfilter modules are loaded and that the necessary sysctl parameters are set to allow IP forwarding and iptables bridging.
Here are the commands to execute on all nodes:
# Load required kernel modules
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# Configure sysctl parameters for Kubernetes networking
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# Apply sysctl parameters without a reboot
sudo sysctl --system
Step 2: Install and Configure a Container Runtime
Kubernetes itself doesn't run containers. It delegates that task to a container runtime that complies with the Container Runtime Interface (CRI) standard. While you are familiar with Docker, since Kubernetes v1.24, the direct integration (dockershim) was removed. The recommended approach is to use a CRI-compliant runtime like containerd directly. Your experience with Docker is still highly relevant, as containerd is the underlying runtime used by Docker itself.
Let's watch a video that demonstrates the installation and configuration of containerd.
How to Install Kubernetes with Kubeadm (2025 Update) | Full Cluster Setup Walkthrough
This video provides a concise walkthrough of installing containerd and, crucially, configuring its cgroup driver.
Watch the segment from 00:55 to 02:31. Focus on two parts: the installation of the containerd package and the modification of its configuration file.
The most critical part of this step is ensuring the container runtime and the kubelet use the same cgroup driver. Cgroups are a Linux kernel feature for limiting and isolating the resource usage of a process group. A mismatch here will prevent the kubelet from starting correctly. The modern standard is the systemd cgroup driver.
Here's how to install containerd and configure it:
# 1. Install containerd
sudo apt-get update
sudo apt-get install -y containerd
# 2. Create a default configuration file
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
# 3. Set the cgroup driver to systemd
# This command uses sed to find and replace the `SystemdCgroup` setting.
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# 4. Restart containerd to apply the changes
sudo systemctl restart containerd
Step 3: Install Kubernetes Packages
With the prerequisites and container runtime in place, we can now install the three essential Kubernetes tools on every node:
kubelet: The agent that runs on each node and communicates with the control plane. It's responsible for managing the lifecycle of Pods on its node.kubeadm: The command-line tool used to bootstrap a cluster, join nodes, and manage upgrades.kubectl: The command-line tool you will use to interact with your cluster's API server.
We will follow the official installation guide to add the new Kubernetes package repositories (pkgs.k8s.io).
The official documentation provides the most current and reliable method for setting up the Kubernetes apt repository and installing the packages. Following these instructions ensures you're aligned with best practices.
Follow the steps under the 'Debian-based distributions' tab. The process involves installing dependencies, downloading the GPG key, adding the repository, and finally installing and holding the packages.
Here is the consolidated sequence of commands based on the official documentation:
# 1. Update apt and install prerequisite packages
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
# 2. Download the public signing key for the Kubernetes package repositories
# The directory /etc/apt/keyrings might not exist by default, so we create it.
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 3. Add the Kubernetes apt repository
# This example is for Kubernetes v1.30. For a different version, change v1.30 in the URL.
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
# 4. Update apt package index and install kubelet, kubeadm, and kubectl
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
# 5. Pin the versions to prevent unwanted upgrades
sudo apt-mark hold kubelet kubeadm kubectl
The apt-mark hold command is particularly important. Kubernetes cluster upgrades are a deliberate process that must be managed carefully. Holding the packages prevents the system's package manager from automatically upgrading a component, which could cause version-skew issues and destabilize your cluster.
Test your understanding!
After following all the steps in this lesson, you run systemctl status kubelet and notice that the kubelet service is running but repeatedly crashing and restarting. You haven't initialized the cluster with kubeadm yet. Is this expected behavior? Why or why not?
Show answer
Yes, this is expected behavior. The kubelet service starts upon installation, but it doesn't know what to do. It's in a "crash loop" waiting for instructions, which it will receive from kubeadm during the cluster initialization process. It needs a kubeconfig file to communicate with the API server, which doesn't exist yet. This behavior will stop once the node is successfully joined to a cluster.
Conclusion
Excellent work. You have now completed the foundational setup for every node in our future cluster. While it seems like a lot of command-line work, understanding each step is vital for troubleshooting and for your CKA exam preparation, where you'll be expected to work efficiently in a terminal.
Let's summarize the key preparations you performed on each node:
- System Configuration: You disabled swap memory to ensure predictable resource management by the
kubelet. - Kernel Configuration: You enabled the
overlayandbr_netfiltermodules and configuredsysctlto allow container network traffic to be processed correctly. - Container Runtime: You installed
containerdand critically configured it to use thesystemdcgroup driver, ensuring compatibility with thekubelet. - Kubernetes Tooling: You installed
kubelet,kubeadm, andkubectlfrom the official Kubernetes package repositories and placed a hold on them to prevent automatic upgrades.
Your nodes are now primed and ready. In our next lesson, we will use kubeadm init on one of these nodes to bootstrap the control plane, bringing your Kubernetes cluster to life. We will then install a Pod network add-on, which is essential for cluster networking.