CKA — Kubeadm Cluster Setup Lab

2 minute read

Lab Overview

Build a complete Kubernetes cluster from scratch using kubeadm, covering prerequisites, control plane initialization, worker node joining, and CNI installation.

Prerequisites: Three VMs or cloud instances running Ubuntu 22.04 with at least 2 CPU and 2 GB RAM each.


Task 1: Prepare All Nodes

Run on all three nodes (control plane + 2 workers):

# Disable swap
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

# Load kernel modules
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter

# Set sysctl params
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

# Install containerd
sudo apt-get update && sudo apt-get install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd && sudo systemctl enable containerd

# Install kubeadm, kubelet, kubectl
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key \
  | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
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
sudo apt-get update
sudo apt-get install -y kubelet=1.30.0-1.1 kubeadm=1.30.0-1.1 kubectl=1.30.0-1.1
sudo apt-mark hold kubelet kubeadm kubectl

Task 2: Initialize the Control Plane

On the control plane node:

sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --kubernetes-version=v1.30.0

# Configure kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Save the kubeadm join command from the output.


Task 3: Install Calico CNI

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml

# Wait for the node to become Ready
kubectl get nodes -w

Task 4: Join Worker Nodes

On each worker node, run the join command:

sudo kubeadm join <control-plane-ip>:6443 \
  --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash>

Task 5: Verify the Cluster

Back on the control plane:

# All nodes should be Ready
kubectl get nodes -o wide

# All system pods should be Running
kubectl get pods -n kube-system

# Test with a deployment
kubectl create deployment web --image=nginx --replicas=3
kubectl get pods -o wide
# Pods should be distributed across nodes

# Clean up
kubectl delete deployment web

Practice Questions

Q1: What CIDR should you pass to kubeadm init if you plan to use Flannel?

Show Answer
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

Flannel uses 10.244.0.0/16 by default. Calico uses 192.168.0.0/16.


Q2: A worker node needs to join the cluster but the token has expired. How do you generate a new join command?

Show Answer

On the control plane node:

kubeadm token create --print-join-command

Tokens expire after 24 hours by default.


Q3: After kubeadm init, the control plane node shows NotReady. What is the most likely cause?

Show Answer

No CNI plugin has been installed. Without a CNI plugin, nodes remain NotReady and CoreDNS Pods stay in Pending.

Fix:

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml

Q4: Why is it critical to set SystemdCgroup = true in containerd config?

Show Answer

Kubernetes kubelet uses systemd as its cgroup driver by default. If containerd uses cgroupfs instead, there will be a cgroup driver mismatch causing kubelet to fail to start Pods properly.

In /etc/containerd/config.toml:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true

Restart containerd after the change:

sudo systemctl restart containerd

Q5: Write the command to completely reset a kubeadm-managed node.

Show Answer
# Reset kubeadm
sudo kubeadm reset

# Clean up CNI configuration
sudo rm -rf /etc/cni/net.d

# Remove kubeconfig
rm -rf $HOME/.kube

# Flush iptables rules
sudo iptables -F && sudo iptables -t nat -F && sudo iptables -t mangle -F && sudo iptables -X

Kubeadm Cluster Setup ← Next: Cluster Upgrades →

Updated: