Setup kubernetes cluster with qemu on Ubuntu
I am Tech enthusiastic from India. Learning and sharing about DevOps journey.
References:
Create Vms with qemu
Step 1: Open QEMU GUI
Launch the QEMU GUI tool, such as
virt-manager.Ensure the
libvirtdservice is running on your host:bashsudo systemctl status libvirtd
Step 2: Create the Master Node VM
Open
virt-managerand click "Create a new virtual machine".Select Installation Source:
Choose Local install media (ISO image).
Browse and select the Ubuntu 24.04.2 Server ISO file.
Configure CPU and Memory:
- Allocate 4 vCPUs and 4 GB RAM.
Disk Configuration:
- Create a new 20 GB disk for the VM.
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.
- Select "Bridge connection" and choose the bridge interface (e.g.,
Finalize:
Name the VM as
master-nodeand 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
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
Install the required tools on your host machine:bash
sudo apt install bridge-utils net-toolsCreate a bridge interface (
br0):Open the network configuration file:bash
sudo nano /etc/netplan/01-netcfg.yamlAdd the following configuration:YAML
network: version: 2 ethernets: enp0s3: dhcp4: no bridges: br0: dhcp4: yes interfaces: - enp0s3Replace
enp0s3with your active network interface (useip ato identify it).
Apply the changes:bash
sudo netplan applyVerify the bridge is created:bash
ip aYou should see the
br0interface with an IP address.
Step 5: Connect VMs to Bridge Network
In
virt-manager, edit the NIC settings for both VMs (Master and Worker nodes).Ensure the NIC is set to use the Bridge connection (br0).
Restart the VMs to apply the changes.
Step 6: Validate VM and Network Configuration
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.
SSH into the VMs from the host to verify connectivity:bash
ssh user@<master_node_ip> ssh user@<worker_node_ip>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
SSH into the Master server
Disable Swap using the below commands
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
- 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
- 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
- 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
- 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
- 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
- Configure
crictlto work withcontainerd
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.
- 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
- 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