1.4 Initializing Clusters with Kubeadm
Key Takeaways
- kubeadm is the standard Kubernetes bootstrapping CLI that automates certificate generation, static pod manifest creation, kubeconfig files, and node registration.
- For the common kubeadm path, disable swap or explicitly configure kubelet swap support, load networking modules required by the chosen CNI, enable IPv4 forwarding, and keep kubelet and runtime cgroup drivers aligned.
- The kubeadm init execution runs through sequential phases: preflight, certs, kubeconfig, kubelet-start, control-plane, etcd, upload-config, upload-certs, mark-control-plane, bootstrap-token, and addon.
- A freshly initialized control plane node remains in the NotReady state until a Container Network Interface (CNI) plugin (e.g., Calico or Flannel) is deployed.
- Worker nodes join the cluster via kubeadm join using a bootstrap token and a SHA-256 discovery token CA certificate hash.
1.4 Initializing Clusters with Kubeadm
kubeadm is the official Kubernetes project tool designed to establish a minimum viable, secure, best-practice Kubernetes cluster with full lifecycle management capabilities. Rather than manually generating dozens of X.509 certificates, configuring complex systemd unit files, and writing static pod manifests from scratch (the "Kubernetes The Hard Way" approach), kubeadm standardizes the bootstrap process into two fundamental commands:
kubeadm init: Bootstraps the primary control plane node.kubeadm join: Attaches additional control plane or worker nodes to an existing cluster.
1. Host Operating System & Node Prerequisites
Before running kubeadm, every host machine (control plane and worker) must satisfy strict OS and networking prerequisites.
+-----------------------------------------------------------------------------+
| NODE PRE-BOOTSTRAP CHECKLIST |
| |
| 1. DISABLE LINUX SWAP MEMORY |
| $ swapoff -a |
| $ sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab |
| |
| 2. LOAD KERNEL OVERLAY & BRIDGE MODULES |
| $ modprobe overlay |
| $ modprobe br_netfilter |
| |
| 3. CONFIGURE SYSCTL BRIDGING & IP FORWARDING |
| net.bridge.bridge-nf-call-iptables = 1 |
| net.bridge.bridge-nf-call-ip6tables = 1 |
| net.ipv4.ip_forward = 1 |
| $ sysctl --system |
| |
| 4. CONFIGURE CONTAINER RUNTIME CGROUP DRIVER |
| containerd config default -> SystemdCgroup = true |
| $ systemctl restart containerd |
+-----------------------------------------------------------------------------+
Step-by-Step Prerequisite Configuration:
# 1. Use the default kubeadm path: disable swap. Kubernetes v1.35 can also use swap when kubelet is deliberately configured with failSwapOn: false and an appropriate memorySwap policy:
sudo swapoff -a
sudo cp /etc/fstab /etc/fstab.pre-kubeadm
sudo sed -i '/[[:space:]]swap[[:space:]]/ s/^/#/' /etc/fstab
# 2. Persist Kernel Modules Required for CNI Bridging:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 3. Apply Sysctl Parameters for Packet Filtering:
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
sudo sysctl --system
# 4. Configure containerd with systemd Cgroup Driver:
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
[!IMPORTANT] Cgroup Driver Matching: The container runtime and kubelet must use compatible cgroup drivers. The
systemddriver is recommended on systemd-based hosts, and kubeadm defaults kubelet to it. Configure containerd consistently; a mismatch can prevent kubelet from managing containers correctly.
2. The kubeadm init Multi-Phase Bootstrap Pipeline
When kubeadm init is executed, it runs through a strictly orchestrated sequence of internal bootstrap phases:
preflight: Validates kernel parameters, CPU cores (minimum 2), RAM (minimum 2GB), swap status, port availability (6443, 2379, 2380, 10250, 10259, 10257), and CRI socket connectivity.certs: Generates self-signed Certificate Authorities (CAs) and certificates for all components inside/etc/kubernetes/pki(ca.crt,apiserver.crt,apiserver-kubelet-client.crt,front-proxy-ca.crt,etcd/ca.crt).kubeconfig: Generates administrative and internal kubeconfig files in/etc/kubernetes/(admin.conf,kubelet.conf,controller-manager.conf,scheduler.conf).kubelet-start: Writes the initial/var/lib/kubelet/config.yamland environment file/var/lib/kubelet/kubeadm-flags.env, then starts the localkubeletdaemon via systemd.control-plane: Generates static pod manifests in/etc/kubernetes/manifests/forkube-apiserver,kube-controller-manager, andkube-scheduler.etcd: Generates the static pod manifest for the local stackedetcdinstance.upload-config: Uploads thekubeadm-configandkubelet-configConfigMaps into thekube-systemnamespace for future reference.upload-certs: If--upload-certsis specified, encrypts control plane certificates and uploads them to a Secret inkube-systemwith a 2-hour decryption key.mark-control-plane: Labels the node as a control plane (node-role.kubernetes.io/control-plane:NoSchedule) to prevent regular workloads from scheduling on it.bootstrap-token: Creates a token inkube-systemused by worker nodes to authenticate during join.addon: Deployskube-proxy(as a DaemonSet) andCoreDNS(as a Deployment) intokube-system.
3. Initializing the Primary Master Node
To initialize the first control plane node with standard pod CIDR networking:
sudo kubeadm init \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=192.168.1.10 \
--cri-socket=unix:///run/containerd/containerd.sock
Setting Up kubectl Access for the User:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
4. Deploying the Container Network Interface (CNI)
Upon initialization, running kubectl get nodes shows the node in a NotReady status. This is because no pod network interface has been configured.
# Use the task-provided or current vendor-supported manifest for the chosen CNI.
kubectl apply -f <cni-manifest-or-operator-resource>
# Watch reconciliation instead of assuming a fixed delay.
kubectl get pods -n kube-system -w
kubectl get nodes
The node becomes Ready only after the selected CNI is installed and healthy. Installation commands and compatible versions differ among Calico, Flannel, and Cilium, so follow the supplied task or the current provider documentation.
5. Joining Worker Nodes (kubeadm join)
To attach worker nodes to the cluster, execute the printed join command on each worker:
sudo kubeadm join 192.168.1.10:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:8f4c2e6b7a9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f
Regenerating Tokens and Hashes:
If the 24-hour join token has expired, generate a new join command from the control plane:
# Generate new token with full join command:
sudo kubeadm token create --print-join-command
# Or manually calculate the CA cert hash:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
An administrator initializes a single-node control plane using kubeadm init --pod-network-cidr=10.244.0.0/16. When running kubectl get nodes, the node reports status NotReady, and CoreDNS pods remain in the Pending state. What is the cause and required resolution?
A worker node fails to join the Kubernetes cluster during kubeadm join, throwing a bootstrap token validation error because the original token expired after 24 hours. Which command should be executed on the control plane to generate a new token and print the complete join command?
For a common bridge-and-iptables CNI setup, which Linux settings enable bridged packet inspection and IPv4 forwarding?