Setting up a production-ready Kubernetes cluster from scratch is one of the most important skills for any Kubernetes administrator. Whether you’re preparing for the CKA certification or building infrastructure for your organization, understanding the complete cluster installation process with kubeadm is essential. This comprehensive guide walks you through every step, from system preparation to cluster verification.
What is kubeadm?
kubeadm is the official Kubernetes tool for bootstrapping a minimum viable Kubernetes cluster that conforms to best practices. It’s designed to be a simple way to set up a secure cluster in a user-friendly manner. Unlike managed Kubernetes services (like GKE or EKS), kubeadm gives you complete control over your cluster configuration and is the recommended method for on-premises deployments.
Why Use kubeadm?
- Best Practices Built-in: Implements Kubernetes security and operational best practices by default
- Certification Standard: Required knowledge for CKA (Certified Kubernetes Administrator) exam
- Production Ready: Suitable for production environments when properly configured
- Flexible: Works across different infrastructure providers and operating systems
- Community Supported: Actively maintained by the Kubernetes community
Prerequisites and System Requirements
Before diving into the installation, ensure your environment meets these requirements. These are not arbitrary—they’re based on Kubernetes’ actual resource needs and architectural constraints.
Hardware Requirements
Minimum specifications for each node:
- 2 or more CPUs - Kubernetes control plane components are CPU-intensive
- 2GB RAM minimum (4GB recommended for control plane nodes)
- 20GB disk space - For OS, Kubernetes binaries, and container images
- Network connectivity between all nodes (public or private network)
Network Requirements
Each node must have:
- Unique hostname - No duplicate names in the cluster
- Unique MAC address - Network interface identification
- Unique product_uuid - Hardware identification
- Network ports open - Required Kubernetes ports must be accessible
Required ports:
- Control Plane: 6443 (API server), 2379-2380 (etcd), 10250 (kubelet), 10259 (scheduler), 10257 (controller-manager)
- Worker Nodes: 10250 (kubelet), 30000-32767 (NodePort services)
Software Requirements
- Linux OS (Ubuntu 20.04+, Debian 10+, CentOS 7+, or RHEL 7+)
- Container runtime (containerd, CRI-O, or Docker)
- Swap must be disabled - Kubernetes requires this for performance reasons
- Root or sudo access - Required for installation
Step 1: Prepare All Nodes
These steps must be performed on all nodes in your cluster (both control plane and worker nodes). This ensures a consistent environment across your cluster.
Disable Swap
Kubernetes requires swap to be disabled because swap can interfere with pod memory limits and Kubernetes’ resource management. When swap is enabled, it becomes difficult for Kubernetes to accurately track and limit memory usage.
# Disable swap immediately
sudo swapoff -a
# Disable swap permanently (survives reboots)
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# Verify swap is off (should show 0)
free -h
Load Required Kernel Modules
Kubernetes networking and container runtime require specific Linux kernel modules. The overlay module is needed for OverlayFS (efficient container filesystem), and br_netfilter enables transparent masquerading and facilitates VxLAN traffic for communication between Kubernetes pods.
# Create configuration file for modules to load at boot
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
# Load modules immediately
sudo modprobe overlay
sudo modprobe br_netfilter
# Verify modules are loaded
lsmod | grep br_netfilter
lsmod | grep overlay
Configure Kernel Parameters
These sysctl settings are essential for Kubernetes networking to function correctly:
- net.bridge.bridge-nf-call-iptables: Enables iptables to see bridged IPv4 traffic
- net.bridge.bridge-nf-call-ip6tables: Enables iptables to see bridged IPv6 traffic
- net.ipv4.ip_forward: Allows the Linux kernel to forward packets (routing)
# Create sysctl configuration
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 params without reboot
sudo sysctl --system
# Verify settings
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
Step 2: Install Container Runtime (containerd)
Kubernetes doesn’t run containers directly—it needs a container runtime. containerd is the recommended choice because it’s lightweight, performant, and has graduated from CNCF. It’s also what Docker uses under the hood!
Why containerd?
- Industry Standard: Default runtime in many Kubernetes distributions
- Lightweight: Fewer resources than full Docker installation
- CRI Compatible: Native Container Runtime Interface support
- Production Ready: Powers Docker and is battle-tested
Install containerd
# Update package index
sudo apt-get update
# Install containerd
sudo apt-get install -y containerd
# Verify installation
containerd --version
Configure containerd for Kubernetes
The default containerd configuration doesn’t enable systemd cgroup driver, which Kubernetes recommends for better system stability and resource management.
# Create containerd configuration directory
sudo mkdir -p /etc/containerd
# Generate default configuration
containerd config default | sudo tee /etc/containerd/config.toml
# Enable systemd cgroup driver (recommended by Kubernetes)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# Restart containerd to apply changes
sudo systemctl restart containerd
# Enable containerd to start on boot
sudo systemctl enable containerd
# Verify containerd is running
sudo systemctl status containerd
Pro Tip: The systemd cgroup driver is crucial for system stability. It ensures containerd and kubelet use the same cgroup driver, preventing resource management conflicts.
Step 3: Install kubeadm, kubelet, and kubectl
Now we’ll install the three essential Kubernetes components. Each serves a specific purpose:
- kubeadm: Tool for bootstrapping and managing the cluster
- kubelet: The “node agent” that runs on every node and manages containers
- kubectl: Command-line tool for interacting with the cluster
Add Kubernetes Package Repository
Google maintains the official Kubernetes package repository. We need to add it to our system’s package manager.
# Install prerequisite packages
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
# Download and add the Kubernetes GPG key (for package verification)
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# Add Kubernetes repository to apt sources
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
Install Kubernetes Components
# Update package index with new repository
sudo apt-get update
# Install kubelet, kubeadm, and kubectl
sudo apt-get install -y kubelet kubeadm kubectl
# Prevent automatic updates (important for cluster stability)
sudo apt-mark hold kubelet kubeadm kubectl
# Verify installations
kubeadm version
kubelet --version
kubectl version --client
Important: We use apt-mark hold to prevent automatic updates. Kubernetes components must be upgraded carefully in a specific order to avoid cluster downtime.
Step 4: Initialize the Control Plane
This is the most crucial step! The control plane is the brain of your Kubernetes cluster, hosting the API server, scheduler, controller manager, and etcd database. This step should only be run on your designated control plane node.
Understanding the Init Command
The --pod-network-cidr flag specifies the IP range for pod networking. We’re using 10.244.0.0/16 which is compatible with Flannel CNI, but you can adjust this based on your chosen network plugin:
- Flannel: 10.244.0.0/16
- Calico: 192.168.0.0/16 (or can work without this flag)
- Weave: 10.32.0.0/12
# Initialize the control plane (run ONLY on control plane node)
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
# The command will take 2-5 minutes and will output:
# - Pre-flight checks
# - Certificate generation
# - Control plane component startup
# - Join command for worker nodes (SAVE THIS!)
Critical: Save the kubeadm join command from the output! You’ll need it to add worker nodes. It looks like:
kubeadm join <control-plane-ip>:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
Configure kubectl Access
To interact with your cluster, you need to set up the kubeconfig file. This file contains cluster connection details and authentication credentials.
# Create .kube directory in your home folder
mkdir -p $HOME/.kube
# Copy the admin configuration file
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# Change ownership to your user
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# Verify cluster access
kubectl cluster-info
kubectl get nodes
At this point, your control plane node will show as NotReady because we haven’t installed a network plugin yet—that’s normal!
Step 5: Install Container Network Interface (CNI)
Kubernetes doesn’t come with networking built-in—you need to install a CNI plugin to enable pod-to-pod communication across nodes. Think of it as the “nervous system” of your cluster.
Popular CNI Options
| CNI Plugin | Best For | Network Policy | Performance |
|---|---|---|---|
| Calico | Production, network policies | Yes | Excellent |
| Flannel | Simple setups, learning | No | Good |
| Weave | Easy setup, encryption | Yes | Good |
| Cilium | Advanced features, eBPF | Yes | Excellent |
For this guide, we’ll use Calico because it’s production-ready, supports network policies, and is commonly used in CKA exams.
Install Calico
# Download and apply Calico manifest
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
# Wait for Calico pods to be ready (this may take 1-2 minutes)
kubectl wait --for=condition=ready pod -l k8s-app=calico-node -n kube-system --timeout=300s
# Verify Calico installation
kubectl get pods -n kube-system -l k8s-app=calico-node
Verify Network Setup
After installing Calico, your control plane node should transition from NotReady to Ready:
# Check node status (should show Ready)
kubectl get nodes
# Verify all kube-system pods are running
kubectl get pods -n kube-system
# Check Calico components specifically
kubectl get pods -n kube-system | grep calico
Troubleshooting Tip: If nodes remain NotReady, check Calico pod logs:
kubectl logs -n kube-system -l k8s-app=calico-node
Step 6: Join Worker Nodes to the Cluster
Now that your control plane is ready, it’s time to add worker nodes. Worker nodes are where your actual application workloads will run.
Joining Worker Nodes
On each worker node, run the kubeadm join command you saved from the control plane initialization:
# On EACH worker node
sudo kubeadm join <control-plane-ip>:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
# Expected output:
# [preflight] Running pre-flight checks
# [kubelet-start] Starting the kubelet
# This node has joined the cluster
If You Lost the Join Command
Don’t worry! You can regenerate the join command from the control plane:
# On control plane node
kubeadm token create --print-join-command
This generates a new token and prints the complete join command.
Verify Worker Nodes
From the control plane node, verify that worker nodes have joined successfully:
# Check all nodes (should show Ready status)
kubectl get nodes
# Get detailed node information
kubectl get nodes -o wide
# Check node resources
kubectl top nodes # (requires metrics-server)
Step 7: Verify Your Cluster
Congratulations! Your cluster is now operational. Let’s perform a comprehensive verification.
Check Cluster Components
# Verify all nodes are Ready
kubectl get nodes
# Check all system pods are Running
kubectl get pods -n kube-system
# Verify cluster info
kubectl cluster-info
# Check component health
kubectl get componentstatuses # (deprecated but still useful)
Deploy a Test Application
Let’s deploy a simple application to verify everything works end-to-end:
# Create a test deployment
kubectl create deployment nginx --image=nginx:latest --replicas=3
# Expose the deployment
kubectl expose deployment nginx --port=80 --type=NodePort
# Check the deployment
kubectl get deployments
kubectl get pods
kubectl get services
# Get the NodePort
kubectl get svc nginx
# Test the service (replace with your node IP and NodePort)
curl http://<node-ip>:<nodeport>
Verify Pod Networking
# Check pod IPs
kubectl get pods -o wide
# Test pod-to-pod communication
kubectl run test-pod --image=busybox --rm -it --restart=Never -- wget -O- http://<pod-ip>
Common Issues and Troubleshooting
Even experienced administrators encounter issues during cluster setup. Here are the most common problems and their solutions:
Nodes Stuck in NotReady State
Symptoms: Nodes show NotReady status after joining
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# node1 NotReady control-plane 5m v1.29.0
Solutions:
- Check CNI Installation
kubectl get pods -n kube-system | grep -E 'calico|flannel|weave'
- Verify Kubelet Status
sudo systemctl status kubelet
sudo journalctl -xeu kubelet # Check logs
- Check Network Configuration
sudo sysctl net.bridge.bridge-nf-call-iptables
Kubelet Failing to Start
Symptoms: Kubelet service keeps restarting
sudo systemctl status kubelet
# Active: activating (auto-restart)
Solutions:
- Verify Container Runtime
sudo systemctl status containerd
crictl ps # Test container runtime
- Check Swap is Disabled
free -h # Swap should show 0
- Review Kubelet Logs
sudo journalctl -xeu kubelet --no-pager | tail -50
API Server Not Responding
Symptoms: kubectl commands fail with connection errors
kubectl get nodes
# The connection to the server <ip>:6443 was refused
Solutions:
- Check API Server Pod
sudo crictl ps | grep kube-apiserver
- Verify Certificates
sudo kubeadm certs check-expiration
- Check Firewall Rules
sudo ufw status # Ensure port 6443 is open
Pod Network Issues
Symptoms: Pods can’t communicate across nodes
Solutions:
- Verify CNI Plugin
kubectl get pods -n kube-system -o wide
- Check IP Forwarding
cat /proc/sys/net/ipv4/ip_forward # Should be 1
- Test Pod Connectivity
kubectl run test --image=busybox --rm -it -- ping <pod-ip>
Best Practices for Production Clusters
Setting up a basic cluster is just the beginning. Here are essential practices for production readiness:
1. High Availability (HA) Setup
For production, use multiple control plane nodes:
- Minimum 3 control plane nodes (odd numbers for etcd quorum)
- Load balancer in front of API servers
- External etcd cluster (optional, for better isolation)
2. Security Hardening
# Enable audit logging
# Configure in /etc/kubernetes/manifests/kube-apiserver.yaml
# Use RBAC policies
kubectl create clusterrolebinding secure-cluster --clusterrole=view --group=developers
# Enable Pod Security Standards
# Configure PodSecurity admission controller
3. Backup and Disaster Recovery
# Backup etcd regularly
ETCDCTL_API=3 etcdctl snapshot save snapshot.db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
4. Monitoring and Observability
Install essential monitoring tools:
- Metrics Server - Resource metrics
- Prometheus - Monitoring and alerting
- Grafana - Visualization
- Loki - Log aggregation
5. Cluster Upgrades
Always follow the upgrade order:
- Upgrade kubeadm on control plane
- Upgrade control plane components
- Upgrade kubelet and kubectl on control plane
- Upgrade worker nodes one by one
# Example upgrade process
sudo apt-mark unhold kubeadm
sudo apt-get update && sudo apt-get install -y kubeadm=1.29.x-00
sudo apt-mark hold kubeadm
sudo kubeadm upgrade apply v1.29.x
Essential Post-Installation Steps
Install Metrics Server
For resource monitoring and HPA (Horizontal Pod Autoscaler):
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Set Up Ingress Controller
For HTTP/HTTPS routing to services:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
Configure Storage Classes
For dynamic volume provisioning:
# Example: Local path provisioner for testing
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
CKA Exam Tips
Cluster installation is a critical topic in the CKA certification. Here’s what you need to master:
Key Skills Tested
- ✅ Initialize control plane with kubeadm
- ✅ Configure kubectl for cluster access
- ✅ Install and configure CNI plugins
- ✅ Join worker nodes to cluster
- ✅ Troubleshoot cluster component failures
- ✅ Verify cluster and component health
Time Management
- Cluster setup typically takes 10-15 minutes
- Practice until you can do it in under 10 minutes
- Know troubleshooting commands by heart
- Bookmark official Kubernetes documentation
Common Exam Scenarios
- Complete cluster setup from scratch
- Add worker node to existing cluster
- Troubleshoot failing kubelets or nodes
- Upgrade cluster components
- Backup and restore etcd
Practice and Certification Preparation
Ready to master Kubernetes cluster administration? The best way to learn is through hands-on practice in a real environment.
Practice Resources
- Sailor.sh CKA Simulator - Realistic exam environment with unlimited practice
- Kubernetes Playground - Free practice clusters with no setup required
- CKA Mock Exams - Full-length practice tests
Why Practice Matters
Setting up clusters from scratch requires muscle memory. You need to:
- Type commands confidently without reference
- Troubleshoot issues quickly under time pressure
- Understand what each command does and why
- Know where to find information in the docs
Conclusion
Congratulations! You’ve successfully set up a Kubernetes cluster using kubeadm. This is a fundamental skill that forms the foundation of Kubernetes administration. You now understand:
- ✅ System prerequisites and preparation
- ✅ Container runtime installation and configuration
- ✅ Control plane initialization
- ✅ Network plugin deployment
- ✅ Worker node management
- ✅ Cluster verification and troubleshooting
Next Steps
Continue your Kubernetes journey:
- Deploy applications - Practice with Deployments, Services, and Ingress
- Learn storage - PersistentVolumes, StatefulSets, and storage classes
- Master networking - NetworkPolicies, DNS, and service discovery
- Implement security - RBAC, Pod Security, and secrets management
- Study backup/restore - etcd snapshots and disaster recovery
Ready to Test Your Skills?
Practice cluster installation in a risk-free environment. Our CKA practice labs provide unlimited cluster setups with instant feedback and detailed explanations. Perfect for exam preparation or skill building.
Happy clustering! 🚀