TR/EN
Blog

How to Install a Kubernetes Server: Step-by-Step Guide with kubeadm

Published: · 12 min read

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:

MethodDifficultyKey traitGood for
kubeadmMediumOfficial tool, installs "vanilla" KubernetesPeople who want to learn Kubernetes in depth, production
k3sEasyLightweight distribution, one-command installSmall servers, testing, edge
RKE2MediumSecurity-focused, Rancher-friendlyEnterprise environments, Rancher users
MicroK8sEasyInstalled as a snap, extended with add-onsDevelopment environments
Managed KubernetesEasyThe provider runs the control planeLarge, critical workloads with the budget for it
Ready-made Kubernetes ServerVery easyDelivered with Kubernetes installedPeople 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

RoleMinimumRecommended
Control plane2 CPU, 2 GB RAM4 CPU, 8 GB RAM, NVMe disk
Worker1–2 CPU, 2 GB RAMDepends on your workload; usually 4+ CPU, 8+ GB RAM
Single node (all-in-one)2 CPU, 4 GB RAM4 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 nodeMulti-nodeHigh availability (HA)
Servers11 control plane + 2+ workers3 control planes + 2+ workers
If a server failsEverything stopsIf a worker fails pods move; if the control plane fails management stopsThe cluster keeps running
Good forLearning, testing, stagingSmall to mid productionCritical production

Ports You Need to Open

PortWhereWhat for
6443Control planeKubernetes API server (kubectl connects here)
2379–2380Control planeetcd database
10250All nodeskubelet API
10257 / 10259Control planecontroller-manager / scheduler
30000–32767All nodesNodePort 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 top and 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

SymptomLikely causeFix
Node stuck in NotReadyNo network plugin (CNI) installedDo step 6 and check its pods are running
kubelet keeps restartingSwap is on or the cgroup driver doesn't matchCheck steps 1 and 3 (SystemdCgroup = true)
kubeadm join failsThe token expired (24 hours by default)kubeadm token create --print-join-command
Pods stay PendingTaint not removed on a single node, or not enough resourcesStep 7; check the reason with kubectl describe pod
Worker can't reach the control planePort 6443 is closedCheck 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.

Your Virtual Server, Ready in 5 Minutes

NVMe virtual servers with dedicated resources start at $6/month.

See Packages →