Skip to main content

Command Palette

Search for a command to run...

Setup kubernetes cluster with qemu on Ubuntu

Published
5 min read
H

I am Tech enthusiastic from India. Learning and sharing about DevOps journey.

References:

qemu installation

Kubernetes Cluster setup

Create Vms with qemu

Step 1: Open QEMU GUI

  1. Launch the QEMU GUI tool, such as virt-manager.

  2. Ensure the libvirtd service is running on your host:bash

     sudo systemctl status libvirtd
    

Step 2: Create the Master Node VM

  1. Open virt-manager and click "Create a new virtual machine".

  2. Select Installation Source:

    • Choose Local install media (ISO image).

    • Browse and select the Ubuntu 24.04.2 Server ISO file.

  3. Configure CPU and Memory:

    • Allocate 4 vCPUs and 4 GB RAM.
  4. Disk Configuration:

    • Create a new 20 GB disk for the VM.
  5. Network Configuration:

    • Select "Bridge connection" and choose the bridge interface (e.g., br0). If no bridge exists, follow the bridge setup steps in Step 4.
  6. Finalize:

    • Name the VM as master-node and proceed with the installation.

    • During the installation, configure the OS according to your requirements (e.g., hostname as master-node, static IP if needed, and SSH server installation).


Step 3: Create the Worker Node VM

  1. Repeat the steps from Step 2 to create a second VM.

    • Name this VM as worker-node.

    • Assign the same configuration:

      • 4 vCPUs, 4 GB RAM, 20 GB disk, and Bridge connection for networking.
    • Proceed with the Ubuntu 24.04.2 installation on this VM.


Step 4: Set Up Bridge Networking on the Host

  1. Install the required tools on your host machine:bash

     sudo apt install bridge-utils net-tools
    
  2. Create a bridge interface (br0):

    • Open the network configuration file:bash

        sudo nano /etc/netplan/01-netcfg.yaml
      
    • Add the following configuration:YAML

        network:
          version: 2
          ethernets:
            enp0s3:
              dhcp4: no
          bridges:
            br0:
              dhcp4: yes
              interfaces:
                - enp0s3
      

      Replace enp0s3 with your active network interface (use ip a to identify it).

  3. Apply the changes:bash

     sudo netplan apply
    
  4. Verify the bridge is created:bash

     ip a
    

    You should see the br0 interface with an IP address.


Step 5: Connect VMs to Bridge Network

  1. In virt-manager, edit the NIC settings for both VMs (Master and Worker nodes).

  2. Ensure the NIC is set to use the Bridge connection (br0).

  3. Restart the VMs to apply the changes.


Step 6: Validate VM and Network Configuration

  1. Boot both VMs and configure their network settings during the Ubuntu installation:

    • Use DHCP or assign Static IPs manually.

    • Ensure that both VMs are on the same subnet.

  2. SSH into the VMs from the host to verify connectivity:bash

     ssh user@<master_node_ip>
     ssh user@<worker_node_ip>
    
  3. Test communication between the two VMs by pinging:bash

     ping <worker_node_ip>  # Run this from the Master VM
    


Kubernetes Cluster Setup

Run the below steps on the Master VM

  1. SSH into the Master server

  2. Disable Swap using the below commands

sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
  1. Forwarding IPv4 and letting iptables see bridged traffic
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo 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
sudo sysctl --system

# Verify that the br_netfilter, overlay modules are loaded by running the following commands:
lsmod | grep br_netfilter
lsmod | grep overlay

# Verify that the net.bridge.bridge-nf-call-iptables, net.bridge.bridge-nf-call-ip6tables, and net.ipv4.ip_forward system variables are set to 1 in your sysctl config by running the following command:
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
  1. Install Container Runtime (containerd)
sudo apt-get update
sudo apt-get install -y containerd

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

# Check that containerd service is up and running
systemctl status containerd
  1. Install runc
curl -LO https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64
sudo install -m 755 runc.amd64 /usr/local/sbin/runc
  1. install cni plugin
curl -LO https://github.com/containernetworking/plugins/releases/download/v1.5.0/cni-plugins-linux-amd64-v1.5.0.tgz
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.5.0.tgz
  1. Install kubeadm, kubelet and kubectl
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/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:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet=1.30.0-1.1 kubeadm=1.30.0-1.1 kubectl=1.30.0-1.1
sudo apt-mark hold kubelet kubeadm kubectl

kubeadm version
kubelet --version
kubectl version --client

Note: The reason we are installing 1.30, so that in one of the later task, we can upgrade the cluster to 1.31

  1. Configure crictl to work with containerd

sudo crictl config runtime-endpoint unix:///var/run/containerd/containerd.sock

initialize control plane

sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address=<your-master-ip> --node-name master
sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address=172.31.89.68 --node-name master

Note: Copy the copy to the notepad that was generated after the init command completion, we will use that later.

  1. Prepare kubeconfig
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
  1. Install calico
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml

curl https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/custom-resources.yaml -O

kubectl apply -f custom-resources.yaml

Perform the below steps on both the worker nodes

  • Perform steps 1-8 on both the nodes

  • Run the command generated in step 9 on the Master node which is similar to below

sudo kubeadm join 172.31.71.210:6443 --token xxxxx --discovery-token-ca-cert-hash sha256:xxx
  • If you forgot to copy the command, you can execute below command on master node to generate the join command again
kubeadm token create --print-join-command