Kubernetes has become the de facto standard for container orchestration, and RHEL 8 provides a stable, enterprise-grade foundation for running production Kubernetes clusters. In this tutorial you will walk through a complete kubeadm-based installation on RHEL 8, from preparing the host operating system through initialising the control-plane node and connecting worker nodes via a Flannel CNI overlay network. All commands are executed as root or with sudo unless otherwise stated. By the end you will have a functional single-node cluster ready to accept workloads.

Prerequisites

  • A RHEL 8 server (or VM) with at least 2 vCPUs and 2 GB RAM
  • A valid RHEL subscription or access to a compatible repository (CentOS Stream 8, AlmaLinux 8, Rocky Linux 8)
  • Root or sudo access
  • A static IP address and a resolvable hostname
  • Outbound internet access to reach container and package repositories

Step 1 — Disable Swap

Kubernetes requires swap to be disabled on all nodes. Disable it immediately and remove it from /etc/fstab so it does not re-enable on reboot.

swapoff -a
sed -i '/sswaps/d' /etc/fstab
free -h   # Swap line should show 0B

Step 2 — Configure SELinux and Required Kernel Parameters

Set SELinux to permissive mode for the current session and persist the change. Also enable bridge traffic filtering so iptables can see bridged traffic inside containers.

setenforce 0
sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config

cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

cat <<EOF | 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

sysctl --system

Step 3 — Open Firewall Ports

If firewalld is running, open the ports required by the Kubernetes control plane and worker components.

# Control-plane ports
firewall-cmd --permanent --add-port=6443/tcp      # API server
firewall-cmd --permanent --add-port=2379-2380/tcp # etcd
firewall-cmd --permanent --add-port=10250/tcp     # Kubelet
firewall-cmd --permanent --add-port=10251/tcp     # kube-scheduler
firewall-cmd --permanent --add-port=10252/tcp     # kube-controller-manager

# Flannel overlay
firewall-cmd --permanent --add-port=8472/udp

firewall-cmd --reload

Step 4 — Install containerd and Add the Kubernetes Repository

Kubernetes needs a CRI-compliant container runtime. Install containerd from the Docker repository, then add the official Kubernetes yum repository.

dnf config-manager --add-repo 
  https://download.docker.com/linux/centos/docker-ce.repo
dnf install -y containerd.io
containerd config default | tee /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' 
  /etc/containerd/config.toml
systemctl enable --now containerd

cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

Step 5 — Install kubelet, kubeadm, and kubectl

Install the three core Kubernetes tools and enable the kubelet service so it starts automatically after cluster initialisation.

dnf install -y kubelet kubeadm kubectl 
  --disableexcludes=kubernetes
systemctl enable --now kubelet

Step 6 — Initialise the Control Plane and Install a CNI Plugin

Use kubeadm init to bootstrap the control plane. After the command succeeds, configure kubectl access and deploy the Flannel CNI so pods can communicate across nodes.

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

# Configure kubectl for the current user
mkdir -p $HOME/.kube
cp /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

# Deploy Flannel CNI
kubectl apply -f 
  https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

# Allow scheduling on the control-plane node (single-node lab only)
kubectl taint nodes --all node-role.kubernetes.io/control-plane-

# Verify the node is Ready
kubectl get nodes

Conclusion

You have successfully installed a Kubernetes cluster on RHEL 8 using kubeadm. The cluster is bootstrapped with containerd as the container runtime, iptables bridge filtering enabled, swap disabled, and Flannel providing pod-to-pod networking. The node should report a Ready status within a minute or two of deploying the CNI plugin. From here you can join worker nodes by running the kubeadm join command that was printed at the end of kubeadm init, or start deploying workloads on this single-node setup.

Next steps: Deploy an application to Kubernetes on RHEL 8, Install Helm on RHEL 8, and Configure Kubernetes Persistent Volumes on RHEL 8.