MakeStack
Back to Feed

Start Kubernetes installation on Ubuntu 26.04 server

Prepare Ubuntu 26.04 Server for Kubernetes v1.36 with containerd, kubeadm, kubelet, kubectl, and the first control-plane initialization.

Starting point#

This guide starts after the Ubuntu 26.04 Server installation guide. At this point the server should boot cleanly, have SSH access available, and use a storage layout that leaves enough room for Kubernetes runtime data under /var.

Read the Ubuntu 26.04 Server installation guide

Use this guide first if the server operating system is not installed yet.

Do not install Kubernetes packages before the node passes basic operating system, hostname, kernel, and container runtime checks.

Kubernetes node preparation rule

Swap and system updates#

Start by checking swap. Kubernetes expects swap to be disabled unless the cluster is explicitly configured for swap-aware behavior. For a standard kubeadm-style setup, this command should print nothing.

Examplesh
swapon --show
expected-output.txttext
# Expected result: no output

Update package metadata and apply available upgrades before adding Kubernetes or container runtime repositories. This reduces avoidable package conflicts later.

Examplesh
sudo apt update && \
sudo apt full-upgrade -y

Base utilities#

Install a small base toolset for downloading repositories, editing configuration, inspecting the node, and troubleshooting networking during cluster setup.

Examplesh
sudo apt install -y \
  curl \
  wget \
  vim \
  git \
  htop \
  ca-certificates \
  gnupg \
  lsb-release \
  apt-transport-https \
  software-properties-common \
  net-tools \
  unzip

Hardware checks#

Before changing kernel and container runtime configuration, confirm that the node has the expected CPU capabilities, memory, and CPU topology. These checks are especially useful when the node is a virtual machine.

Virtualization support#

Examplesh
egrep -c '(vmx|svm)' /proc/cpuinfo

A value greater than 0 means CPU virtualization flags are exposed to the operating system. This matters when the Kubernetes node itself will run nested virtualization workloads or when you are validating VM host settings.

Memory and CPU#

Examplesh
free -h
Examplesh
lscpu

Hostname configuration#

Use a stable hostname before joining the node to a cluster. Renaming a node after Kubernetes components are installed is possible, but it creates unnecessary cleanup work.

Check hostname#

Examplesh
hostnamectl

Change hostname if needed#

Examplesh
sudo hostnamectl set-hostname yourhostname

Add hostname to /etc/hosts#

Examplesh
sudo nano /etc/hosts
/etc/hoststext
127.0.1.1 yourhostname

Kernel modules for Kubernetes#

Kubernetes networking relies on Linux bridge filtering and overlay support. Configure the required modules so they load on boot, then load them immediately for the current session.

Examplesh
sudo nano /etc/modules-load.d/k8s.conf
/etc/modules-load.d/k8s.conftext
overlay
br_netfilter
Examplesh
sudo modprobe overlay && \
sudo modprobe br_netfilter

Checks#

Examplesh
lsmod | grep overlay && \
lsmod | grep br_netfilter

sysctl for Kubernetes#

Enable bridge packet visibility for iptables and IPv4 forwarding. Without these settings, pod networking and service routing can fail in ways that are hard to diagnose later.

Examplesh
sudo nano /etc/sysctl.d/k8s.conf
/etc/sysctl.d/k8s.conftext
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
Examplesh
sudo sysctl --system

Check IPv4 forwarding#

Examplesh
sysctl net.ipv4.ip_forward
expected-output.txttext
net.ipv4.ip_forward = 1

Docker repository and containerd#

containerd is the container runtime used by the Kubernetes node. Add Docker's Ubuntu repository first, then install the packaged containerd runtime from that repository.

Add Docker repository#

Examplesh
sudo install -m 0755 -d /etc/apt/keyrings
Examplesh
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Examplesh
echo \
  "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo $VERSION_CODENAME) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Install containerd#

Examplesh
sudo apt update && \
sudo apt install -y containerd.io
Examplesh
containerd --version

containerd SystemdCgroup#

Configure containerd to use systemd cgroups for the Kubernetes runtime. This keeps the kubelet and container runtime aligned with the cgroup manager used by the operating system.

Examplesh
sudo mkdir -p /etc/containerd/conf.d && \
sudo nano /etc/containerd/conf.d/k8s.toml
/etc/containerd/conf.d/k8s.tomltoml
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc]
runtime_type = 'io.containerd.runc.v2'

[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
SystemdCgroup = true

Restart and check containerd#

Examplesh
sudo systemctl restart containerd
Examplesh
sudo systemctl status containerd --no-pager
Examplesh
sudo journalctl -u containerd -n 50 --no-pager

At this point the node has the base operating system checks, kernel networking settings, and container runtime configuration needed before adding the Kubernetes package repository.

Kubernetes v1.36 packages#

This article targets Kubernetes v1.36. Keeping the repository URL, installed tools, and held package versions aligned around one Kubernetes minor version makes the setup easier to reproduce and prevents accidental upgrades while the cluster is being configured.

Add kubernetes keyring#

Examplesh
sudo mkdir -p /etc/apt/keyrings && \
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | \
  sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

Add Kubernetes repository#

Examplesh
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /' | \
sudo tee /etc/apt/sources.list.d/kubernetes.list && \
sudo apt update

Install Kubernetes tools#

Install kubelet, kubeadm, and kubectl together. kubelet runs on the node, kubeadm bootstraps the cluster, and kubectl is the command-line client used to inspect and manage the cluster.

Examplesh
sudo apt install -y \
  kubelet \
  kubeadm \
  kubectl

Hold package versions#

Hold the Kubernetes packages after installation. Cluster upgrades should be planned and executed deliberately, not pulled in by a normal system upgrade.

Examplesh
sudo apt-mark hold kubelet kubeadm kubectl

Check the installed tools#

Examplesh
kubeadm version && \
kubectl version --client

Pull Kubernetes images#

Before initializing the control plane, pull the Kubernetes images that kubeadm needs. This is a useful checkpoint because image pull problems are easier to diagnose before kubeadm starts writing cluster state.

Examplesh
sudo kubeadm config images pull

Initialize the control plane#

Initialize the first control-plane node with kubeadm. The pod CIDR below is commonly used with Flannel. If a different CNI plugin will be installed later, use the pod network CIDR required by that plugin instead.

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

A successful initialization prints a clear confirmation message near the end of the output.

expected-kubeadm-output.txttext
Your Kubernetes control-plane has initialized successfully!

Keep the kubeadm output. It contains the kubeconfig setup commands and, later, the join command for worker nodes.

kubeadm initialization note

Configure kubectl access#

After kubeadm finishes, configure kubectl for the current user. kubeadm prints these commands in the output; the standard local-admin setup usually looks like this.

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

First cluster check#

Check the node after configuring kubectl. At this stage the control-plane node usually appears, but it is not ready yet because a pod network add-on has not been installed.

Examplesh
kubectl get nodes
expected-node-state.txttext
STATUS
NotReady

The NotReady status is normal here. The next article installs Cilium as the CNI, verifies that the node becomes Ready, and adds the first cluster checks.

Continue with Cilium networking

Install the Cilium CLI, Gateway API CRDs, Cilium networking, single-node scheduling, a test workload, and metrics-server.