🧭 How To Setup Kubernetes Cluster Using Kubeadm — Step-by-Step Guide (2025)

This guide provides a comprehensive, step-by-step walkthrough on setting up a Kubernetes cluster using Kubeadm. It covers everything from preparing the nodes and installing the necessary components like Containerd, Kubeadm, Kubelet, and Kubectl, to initializing the control plane, joining worker nodes, and verifying the cluster setup. This guide is designed for both beginners and DevOps professionals who want to gain a deeper understanding of Kubernetes and its underlying infrastructure.

🚀 Introduction

Setting up a Kubernetes cluster from scratch might sound intimidating — but with Kubeadm, it becomes clean, predictable, and repeatable.

Unlike managed services like EKS, GKE, or AKS, Kubeadm gives you full control over your cluster’s infrastructure. You get to learn how Kubernetes works under the hood — the control plane, networking, certificates, and more.

In this tutorial, we’ll go step by step to build your own Kubernetes cluster using Kubeadm on Ubuntu 22.04.

By the end, you’ll have a fully working multi-node cluster ready for workloads — exactly like you’d run in a real-world DevOps setup. ⚙️

🧩 Prerequisites

Before we start, make sure you have:

We’ll use these hostnames for clarity:

  • master-node → Control plane
  • worker-node1 → Worker node
  • worker-node2 → (optional)

⚙️ Step 1: Prepare All Nodes

Login to each node (master and workers) and run the following setup commands.

1.1 Update System

sudo apt update && sudo apt upgrade -y

1.2 Disable Swap

Kubernetes requires swap to be disabled.

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

1.3 Enable Required Kernel Modules

sudo modprobe overlay
sudo modprobe br_netfilter

1.4 Apply Network Settings

cat <<EOF | sudo tee /etc/sysctl.d/kubernetes.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sudo sysctl --system

🐋 Step 2: Install Container Runtime (Containerd)

Kubernetes needs a container runtime.

We’ll use containerd, the most recommended one (used by Docker and Kubernetes itself).

2.1 Install Dependencies

sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

2.2 Install Containerd

sudo apt install -y containerd

2.3 Configure Containerd

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null

Edit the config to use systemd as cgroup driver:

sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

Restart and enable containerd:

sudo systemctl restart containerd
sudo systemctl enable containerd

🧱 Step 3: Install Kubeadm, Kubelet, and Kubectl

Kubeadm will bootstrap your cluster, kubelet runs on all nodes, and kubectl is the CLI to manage it.

sudo apt update
sudo apt install -y apt-transport-https curl
sudo curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes.gpg
echo "deb https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

Check versions:

kubeadm version
kubectl version --client

🧠 Step 4: Initialize the Control Plane (Master Node)

Run this only on the master node:

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

Tip:

The --pod-network-cidr flag depends on which network plugin (CNI) you plan to install.

  • For Flannel → use 10.244.0.0/16
  • For Calico → use 192.168.0.0/16

When initialization finishes, you’ll see a join command like this:

kubeadm join 10.0.0.1:6443 --token abcd12.efgh34ijkl56 --discovery-token-ca-cert-hash sha256:xxxx...

Save this — you’ll need it for worker nodes.

4.1 Configure kubectl Access

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

Now verify:

kubectl get nodes

You’ll see the master node in NotReady state — that’s because the CNI isn’t installed yet.

🌐 Step 5: Install a Pod Network Add-on (CNI)

Let’s use Flannel (simple and beginner-friendly).

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

Wait a minute, then check:

kubectl get pods -n kube-system
kubectl get nodes

Your master node should now be in Ready state. ✅

🧩 Step 6: Join Worker Nodes

Run this on each worker node, replacing the join command you got earlier:

sudo kubeadm join 10.0.0.1:6443 --token abcd12.efgh34ijkl56 --discovery-token-ca-cert-hash sha256:xxxx...

If you lost the token, create a new one:

sudo kubeadm token create --print-join-command

🧾 Step 7: Verify Your Cluster

On the master node:

kubectl get nodes

Output example:

NAME           STATUS   ROLES           AGE   VERSION
master-node    Ready    control-plane   10m   v1.30.0
worker-node1   Ready    <none>          5m    v1.30.0

You now have a fully functional Kubernetes cluster! 🎉

🧰 Step 8: Deploy a Sample Application

Let’s verify the setup with an NGINX deployment:

kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pods,svc

Access via any worker node IP and the assigned NodePort.

🔐 Step 9: (Optional) Enable Cluster Access for Other Users

If you need to share access with teammates:

kubectl config view --flatten > cluster-config.yaml

They can use this kubeconfig file with restricted RBAC permissions.

🛠️ Troubleshooting Tips

IssueSolution
Node not joiningCheck network/firewall between nodes
Pod stuck in PendingVerify CNI (Flannel/Calico) is running
kubelet not startingRecheck containerd config and systemd cgroups
DNS not resolvingRestart coredns and check kube-proxy logs

🏁 Conclusion

And that’s it! You’ve successfully created a Kubernetes cluster using Kubeadm — the most powerful way to understand how Kubernetes actually works.

With this setup, you can:

  • Practice real-world cluster administration
  • Deploy monitoring (Prometheus/Grafana)
  • Configure Ingress controllers
  • Experiment with scaling, RBAC, and security policies

When you’re ready, you can even turn this into a highly available (HA) cluster by adding more control planes and etcd nodes.

🔖 Key Takeaways

  • Kubeadm simplifies the setup but doesn’t abstract Kubernetes internals — you learn the real deal.
  • Containerd is now the standard runtime for most clusters.
  • CNI (Flannel, Calico) defines how pods communicate — choose wisely for production.
  • Always disable swap and configure systemd cgroups.
  • For production, enable audit logs, certificates, and backup automation.

Leave a Comment