Create Kubernetes Cluster with CRI-O on Rocky Linux 9.1

Overview

As a container orchestration, Kubernetes help anyone who needs to deploy a container service in a declarative way. Kubernetes will manage and maintain every resource to meet the state needed by the developer. Developer simply defined the desired state by JSON or YAML file and sends it to Kubernetes API. In this article, I will guide you to deploy a Kubernetes cluster with CRI-O as container runtime on RHEL-based OS, Rocky Linux 9.1.

Installation

Pre-requisites

We need 1 node for the control-plane node and at least 1 node or more nodes for the worker node with the specifications:

  • Control-plane node:

    • 2 core or more processor

    • 2 GB or more memory

    • Rocky Linux 9

  • Worker node:

    • 4 core or more processor

    • 8 GB or more memory

    • Rocky Linux 9

Steps

Master Node

  1. Configure firewall on every node

    You need to set firewall rules on the node(s) to open several inbound ports or connections between the Kubernetes cluster node based on Kubernetes Documentation.

     firewall-cmd --permanent --new-zone=kubernetes-master
     firewall-cmd --permanent --zone=kubernetes-master --add-service=ssh
     firewall-cmd --permanent --zone=kubernetes-master --add-port={6443,2379,2380,10250,10259,10257}/tcp
     firewall-cmd --reload
     firewall-cmd --permanent --zone=kubernetes-master --change-interface=enp1s0
     firewall-cmd --set-default-zone=kubernetes-master
    
  2. Setup CRI-O

    CRI-O repository will be added to YUM depending Kubernetes version want to be installed by specifying the VERSION environment variable.

     export VERSION=1.26
     export OS=CentOS_8_Stream
     curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo
     yum install cri-o -y
     systemctl enable --now crio
    
  3. Setup kubeadm, kubelet, and kubectl

    Kubernetes’ repository will be added to YUM and install kubelet, kubectl and kubeadm following the version of Kubernetes want to installed. See Kubernetes Releases.

     cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
     [kubernetes]
     name=Kubernetes
     baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
     enabled=1
     gpgcheck=1
     gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
     exclude=kubelet kubeadm kubectl
     EOF
     # Set SELinux in permissive mode (effectively disabling it)
     sudo setenforce 0
     sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
     yum install kubelet-1.26.5 kubectl-1.26.5 kubeadm-1.26.5 --disableexcludes=kubernetes
    
  4. Configure prerequisites

     cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
     overlay
     br_netfilter
     EOF
    
     modprobe overlay
     modprobe br_netfilter
    
     # sysctl params required by setup, params persist across reboots
     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
    
     # Apply sysctl params without reboot
     sysctl --system
    
  5. Create kubeadm’s and InitConfiguration and ClusterConfiguration file for master node

     vim kubeadm-worker-conf.yaml
    
     apiVersion: kubeadm.k8s.io/v1beta3
     kind: InitConfiguration
     nodeRegistration:
      name: "master-node0"
      criSocket: "/var/run/crio/crio.sock"
     ---
     apiVersion: kubeadm.k8s.io/v1beta3
     kind: ClusterConfiguration
     networking:
      serviceSubnet: "10.10.0.0/16"
      podSubnet: "10.10.10.0/24"
      dnsDomain: "jesaya.lab"
     kubernetesVersion: "v1.26.5"
     controlPlaneEndpoint: "[control-plane-ip]:6443"
     clusterName: "[cluster-name]"
    
  6. Initialize Kubeadm

     systemctl enable kubelet.service
     kubeadm init --config kubeadm-cluster-conf.yaml
    
  7. Check the Kubernetes has been initilized

     mkdir -p $HOME/.kube
     cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
     chown $(id -u):$(id -g) $HOME/.kube/config
     kubectl get node
    

Worker node(s)

  1. Configure firewall on every node

    You need to set firewall rules on the node(s) to open several inbound ports or connections between the Kubernetes cluster node based on Kubernetes Documentation.

     firewall-cmd --permanent --new-zone=kubernetes-worker
     firewall-cmd --permanent --zone=kubernetes-worker --add-service=ssh 
     firewall-cmd --permanent --zone=kubernetes-worker --add-port={10250,30000-32767}/tcp
     firewall-cmd --reload
     firewall-cmd --permanent --zone=kubernetes-worker --change-interface=enp1s0
     firewall-cmd --set-default-zone=kubernetes-worker
    
  2. Setup CRI-O

    CRI-O repository will be added to YUM depending Kubernetes version want to be installed by specifying the VERSION environment variable.

     export VERSION=1.26
     export OS=CentOS_8_Stream
     curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo
     yum install cri-o -y
     systemctl enable --now crio
    
  3. Setup kubeadm, kubelet, and kubectl

    Kubernetes’ repository will be added to YUM and install kubelet, kubectl and kubeadm following the version of Kubernetes want to installed. See Kubernetes Releases.

     cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
     [kubernetes]
     name=Kubernetes
     baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
     enabled=1
     gpgcheck=1
     gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
     exclude=kubelet kubeadm kubectl
     EOF
     # Set SELinux in permissive mode (effectively disabling it)
     sudo setenforce 0
     sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
     yum install kubelet-1.26.5 kubeadm-1.26.5 --disableexcludes=kubernetes
    
  4. Configure prerequisites needed on node

     cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
     overlay
     br_netfilter
     EOF
    
     modprobe overlay
     modprobe br_netfilter
    
     # sysctl params required by setup, params persist across reboots
     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
    
     # Apply sysctl params without reboot
     sysctl --system
    
  5. Create kubeadm’s JoinConfiguration file for worker node

     vim kubeadm-worker-conf.yaml
    
     apiVersion: kubeadm.k8s.io/v1beta3
     kind: JoinConfiguration
     nodeRegistration:
      name: "worker-node0"
      criSocket: "/var/run/crio/crio.sock"
     discovery: 
       bootstrapToken: 
         token: "[bootstrap-token]"
         apiServerEndpoint: "[control-plane-ip]:6443"
         caCertHashes: 
         - "[CA-cert-Hash]"
    
  6. Joining worker node

     systemctl enable kubelet.service
     kubeadm join --config kubeadm-worker-conf.yaml