Sooner or later, everyone learning Kubernetes asks the same question: how do you install a Kubernetes server? In this post we compare the different installation methods and then build a Kubernetes cluster step by step on Ubuntu with kubeadm, the most common method. If you're not sure what Kubernetes is yet, we suggest reading our What is Kubernetes post first.
Kubernetes Installation Methods
There isn't just one way to install Kubernetes. Depending on your needs and experience, there are different tools:
| Method | Difficulty | Key trait | Good for |
|---|---|---|---|
| kubeadm | Medium | Official tool, installs "vanilla" Kubernetes | People who want to learn Kubernetes in depth, production |
| k3s | Easy | Lightweight distribution, one-command install | Small servers, testing, edge |
| RKE2 | Medium | Security-focused, Rancher-friendly | Enterprise environments, Rancher users |
| MicroK8s | Easy | Installed as a snap, extended with add-ons | Development environments |
| Managed Kubernetes | Easy | The provider runs the control plane | Large, critical workloads with the budget for it |
| Ready-made Kubernetes Server | Very easy | Delivered with Kubernetes installed | People who want to start right away |
We cover kubeadm here because it's the official method, and you actually learn Kubernetes' moving parts while installing it.
Hardware Requirements
| Role | Minimum | Recommended |
|---|---|---|
| Control plane | 2 CPU, 2 GB RAM | 4 CPU, 8 GB RAM, NVMe disk |
| Worker | 1–2 CPU, 2 GB RAM | Depends on your workload; usually 4+ CPU, 8+ GB RAM |
| Single node (all-in-one) | 2 CPU, 4 GB RAM | 4 CPU, 8–16 GB RAM |
All servers need network access to each other, each needs a unique hostname, and swap must be off.
Single Node or Multi-Node?
| Single node | Multi-node | High availability (HA) | |
|---|---|---|---|
| Servers | 1 | 1 control plane + 2+ workers | 3 control planes + 2+ workers |
| If a server fails | Everything stops | If a worker fails pods move; if the control plane fails management stops | The cluster keeps running |
| Good for | Learning, testing, staging | Small to mid production | Critical production |
Ports You Need to Open
| Port | Where | What for |
|---|---|---|
| 6443 | Control plane | Kubernetes API server (kubectl connects here) |
| 2379–2380 | Control plane | etcd database |
| 10250 | All nodes | kubelet API |
| 10257 / 10259 | Control plane | controller-manager / scheduler |
| 30000–32767 | All nodes | NodePort services |
Your network plugin also uses its own ports (e.g. UDP 8472 for Flannel). Make sure your firewall allows traffic between nodes.
Installing Kubernetes with kubeadm (Ubuntu 24.04)
Run steps 1–4 on all servers (control plane and workers), and steps 5–7 only on the control plane.
1. Prep: hostname and swap
By default the kubelet won't run with swap on, so we turn it off:
sudo hostnamectl set-hostname k8s-cp-1 # give each server a different name
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab # keep it off after reboots
2. Kernel modules and network settings
We enable the modules and settings needed to route traffic between pods properly:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
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
3. Container runtime: containerd
Kubernetes needs a runtime to run containers. We install containerd and set its cgroup driver to systemd; skip this and the kubelet keeps restarting:
sudo apt-get update
sudo apt-get install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
4. kubeadm, kubelet and kubectl
We install the packages from the official Kubernetes repository. The version number is part of the repository URL; check the current stable version on kubernetes.io before installing and set K8S_VERSION accordingly:
K8S_VERSION=v1.34 # check kubernetes.io for the current version
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/${K8S_VERSION}/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:/${K8S_VERSION}/deb/ /" \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl # stop the packages from auto-updating
5. Initialize the cluster (control plane only)
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
When it finishes, a kubeadm join ... command is printed. You'll need it to add workers, so save it somewhere.
6. Install a network plugin (CNI)
Pods need a network plugin to talk to each other. We use Flannel because it's simple and lightweight (Calico and Cilium are also very popular):
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
kubectl get nodes # should show STATUS: Ready within a few minutes
7. Single node only: allow pods on the control plane
By default, application pods aren't scheduled on the control plane. On a single-server setup you need to remove that restriction:
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
8. Add worker nodes
# on the worker, run the command from the kubeadm init output:
sudo kubeadm join 10.0.0.10:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:<hash>
# lost it? generate it again on the control plane:
kubeadm token create --print-join-command
9. Test it
If everything looks good, let's deploy a simple nginx app and reach it from outside:
kubectl create deployment web --image=nginx
kubectl expose deployment web --port=80 --type=NodePort
kubectl get svc web # note the 30000-32767 port in the PORT(S) column
If you see the nginx welcome page at http://SERVER_IP:NODEPORT in your browser, your cluster is ready. For more on the commands, see our kubectl commands post.
What to Do After Installation
- Ingress controller: To route traffic to services by domain (e.g. ingress-nginx), plus cert-manager for certificates.
- Persistent storage: A StorageClass for apps like databases (local-path-provisioner is a simple start for a single node).
- metrics-server: For
kubectl topand autoscaling. - Backups: Back up etcd regularly; use tools like Velero for application data.
- Upgrades: Keep up with version upgrades via kubeadm and don't skip more than one minor version.
A Faster Way: k3s
If all these steps feel like alot, k3s, a lightweight Kubernetes distribution, installs with a single command and is a great option for small servers:
curl -sfL https://get.k3s.io | sh -
sudo k3s kubectl get nodes
Common Problems
| Symptom | Likely cause | Fix |
|---|---|---|
Node stuck in NotReady | No network plugin (CNI) installed | Do step 6 and check its pods are running |
| kubelet keeps restarting | Swap is on or the cgroup driver doesn't match | Check steps 1 and 3 (SystemdCgroup = true) |
kubeadm join fails | The token expired (24 hours by default) | kubeadm token create --print-join-command |
Pods stay Pending | Taint not removed on a single node, or not enough resources | Step 7; check the reason with kubectl describe pod |
| Worker can't reach the control plane | Port 6443 is closed | Check your firewall rules |
If You'd Rather Skip All This
If your goal is running apps on Kubernetes rather than installing it, you can skip every one of these steps. VECDC Kubernetes Server packages are delivered with Kubernetes installed; they start at $6/month and thanks to automated setup your kubeconfig is ready in about 5 minutes. If you want to do your own install, our NVMe-backed virtual servers are a perfect fit for this guide.
If you need a multi-node, highly available, production-ready cluster, our Kubernetes consulting team supports you from design to setup, and we also offer Rancher consulting for managing multiple clusters from one panel.
Frequently Asked Questions
How many servers do I need to install Kubernetes?
For learning and testing a single server is enough; the control plane and worker run on the same machine. For production, 1 control plane and at least 2 workers is typical, and 3 control planes are recommended for high availability.
Should I use kubeadm or k3s?
If you want to learn Kubernetes in depth and do a standard install, go with kubeadm; if you want a quick, lightweight install on small servers, k3s is a better fit. Both provide the standard Kubernetes API.
How long does it take to install Kubernetes?
With some preparation, a single-node kubeadm install usually takes 20–40 minutes. With k3s it takes a few minutes, and with a ready-made Kubernetes Server you get a usable cluster in about 5 minutes.
Why do I need to turn off swap for Kubernetes?
To keep resource management predictable, the kubelet refuses to run with swap on by default. Newer versions have added swap support, but turning swap off is still recommended for standard installs.
In Short
Installing Kubernetes looks complicated at first, but the steps are clear: prep the servers, install containerd, initialize the cluster with kubeadm, add a network plugin and join the workers. Once you've installed it yourself, you understand how Kubernetes works much better. If you get stuck during the install, drop us a message, were happy to help.