Skip to main content
πŸŽ“ Claude Code Masterclass Learn AI-assisted development on Udemy β€” plus the companion book on Leanpub & Amazon. Start Learning
Install Kubernetes on Rocky Linux 9
Platform Engineering

Install Kubernetes on Rocky Linux 9 (Step-by-Step 2026)

Complete guide to install Kubernetes on Rocky Linux 9 with kubeadm in 2026. Prerequisites, containerd, kubeadm, cluster init, CNI, worker join, and.

LB
Luca Berton
Β· 1 min read

Complete guide to install Kubernetes on Rocky Linux 9 using kubeadm. These steps also work on AlmaLinux 9 and CentOS Stream 9.

Requirements

  • 2+ CPU cores, 2 GB+ RAM per node
  • Rocky Linux 9 (minimal install)
  • Root or sudo access
  • Unique hostname, MAC, and product_uuid on each node
  • Full network connectivity between nodes

Step 1: System prerequisites (all nodes)

Disable swap, load kernel modules, and configure sysctl:

# Disable swap permanently
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

# Load required kernel modules
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter

# Set required sysctl parameters
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

# Set SELinux to permissive (required for kubelet)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

# Open firewall ports (control plane)
sudo firewall-cmd --permanent --add-port=6443/tcp    # API server
sudo firewall-cmd --permanent --add-port=2379-2380/tcp # etcd
sudo firewall-cmd --permanent --add-port=10250/tcp    # kubelet
sudo firewall-cmd --permanent --add-port=10259/tcp    # scheduler
sudo firewall-cmd --permanent --add-port=10257/tcp    # controller-manager
sudo firewall-cmd --reload

# Open firewall ports (worker nodes)
sudo firewall-cmd --permanent --add-port=10250/tcp    # kubelet
sudo firewall-cmd --permanent --add-port=10256/tcp    # kube-proxy
sudo firewall-cmd --permanent --add-port=30000-32767/tcp # NodePort
sudo firewall-cmd --reload

Step 2: Install containerd (all nodes)

# Add Docker repo (for containerd.io package)
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# Install containerd
sudo dnf install -y containerd.io

# Generate default config
sudo containerd config default | sudo tee /etc/containerd/config.toml

# Enable SystemdCgroup (critical for Kubernetes)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

# Start and enable
sudo systemctl restart containerd
sudo systemctl enable containerd

# Verify
sudo systemctl status containerd

Step 3: Install kubeadm, kubelet, kubectl (all nodes)

# Add Kubernetes repository
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.31/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.31/rpm/repodata/repomd.xml.key
EOF

# Install
sudo dnf install -y kubelet kubeadm kubectl

# Enable kubelet (it will wait for kubeadm init)
sudo systemctl enable --now kubelet

Step 4: Initialize the control plane (control plane only)

# Initialize with pod CIDR for Flannel
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

# Set up kubeconfig
mkdir -p $HOME/.kube
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# Verify the API server is running
kubectl get nodes
# NAME     STATUS     ROLES           AGE   VERSION
# master   NotReady   control-plane   30s   v1.31.x

The node shows NotReady until a CNI plugin is installed.

Step 5: Install a CNI plugin (control plane)

Option A: Flannel (simple)

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

Option B: Cilium (advanced, eBPF-based)

# Install Cilium CLI
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
curl -L --fail https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz | sudo tar xz -C /usr/local/bin

# Install Cilium
cilium install

# Verify
cilium status --wait

After CNI installation:

kubectl get nodes
# NAME     STATUS   ROLES           AGE   VERSION
# master   Ready    control-plane   2m    v1.31.x

Step 6: Join worker nodes

On the control plane, get the join command:

kubeadm token create --print-join-command

On each worker node (after completing Steps 1-3):

# Paste the join command from above
sudo kubeadm join 192.168.1.100:6443 --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash>

Verify from the control plane:

kubectl get nodes
# NAME      STATUS   ROLES           AGE   VERSION
# master    Ready    control-plane   5m    v1.31.x
# worker1   Ready    <none>          1m    v1.31.x
# worker2   Ready    <none>          1m    v1.31.x

Step 7: Post-install verification

# All system pods should be Running
kubectl get pods -n kube-system

# Deploy a test application
kubectl create deployment nginx --image=nginx:alpine --replicas=3
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get svc nginx
# Access via http://<node-ip>:<nodeport>

# Clean up test
kubectl delete deployment nginx
kubectl delete svc nginx

Production hardening

For production clusters, also configure:

# Enable audit logging
# Add to /etc/kubernetes/manifests/kube-apiserver.yaml:
# --audit-log-path=/var/log/kubernetes/audit.log
# --audit-policy-file=/etc/kubernetes/audit-policy.yaml

# Set up etcd backup
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-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

# Install metrics-server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

Troubleshooting

kubelet not starting:

sudo journalctl -xeu kubelet
# Common: containerd not running or SystemdCgroup not enabled

Node stays NotReady:

kubectl describe node <name>
# Check for CNI not installed or network plugin errors

kubeadm init fails with preflight errors:

# Reset and retry
sudo kubeadm reset -f
sudo rm -rf /etc/cni/net.d
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

Free 30-min AI & Cloud consultation

Book Now