Skip to main content
In this guide we will create a Kubernetes cluster using QEMU.

Video Walkthrough

To see a live demo of this writeup, see the video below:

Requirements

  • Linux
  • a kernel with
    • KVM enabled (/dev/kvm must exist)
    • CONFIG_NET_SCH_NETEM enabled
    • CONFIG_NET_SCH_INGRESS enabled
  • at least CAP_SYS_ADMIN and CAP_NET_ADMIN capabilities
  • QEMU
  • bridge, static and firewall CNI plugins from the standard CNI plugins, and tc-redirect-tap CNI plugin from the awslabs tc-redirect-tap installed to /opt/cni/bin (installed automatically by talosctl)
  • iptables
  • /var/run/netns directory should exist

Installation

How to get QEMU

Install QEMU with your operating system package manager. For example, on Ubuntu for x86:

Install talosctl

You can download talosctl on MacOS and Linux via:
For manual installation and other platforms please see the talosctl installation guide.

Install Talos kernel and initramfs

QEMU provisioner depends on Talos kernel (vmlinuz) and initramfs (initramfs.xz). These files can be downloaded from the Talos release:
For example version $:

Create the Cluster

For the first time, create root state directory as your user so that you can inspect the logs as non-root user:
Create the cluster:
Before the first cluster is created, talosctl will download the CNI bundle for the VM provisioning and install it to ~/.talos/cni directory. Once the above finishes successfully, your talosconfig (~/.talos/config) will be configured to point to the new cluster, and kubeconfig will be downloaded and merged into default kubectl config location (~/.kube/config). Cluster provisioning process can be optimized with registry pull-through caches.

Using the Cluster

Once the cluster is available, you can make use of talosctl and kubectl to interact with the cluster. For example, to view current running containers, run talosctl -n 10.5.0.2 containers for a list of containers in the system namespace, or talosctl -n 10.5.0.2 containers -k for the k8s.io namespace. To view the logs of a container, use talosctl -n 10.5.0.2 logs <container> or talosctl -n 10.5.0.2 logs -k <container>. A bridge interface will be created, and assigned the default IP 10.5.0.1. Each node will be directly accessible on the subnet specified at cluster creation time. A loadbalancer runs on 10.5.0.1 by default, which handles loadbalancing for the Kubernetes APIs. You can see a summary of the cluster state by running:

Cleaning Up

To cleanup, run:
Note: In that case that the host machine is rebooted before destroying the cluster, you may need to manually remove ~/.talos/clusters/talos-default.

Manual Clean Up

The talosctl cluster destroy command depends heavily on the clusters state directory. It contains all related information of the cluster. The PIDs and network associated with the cluster nodes. If you happened to have deleted the state folder by mistake or you would like to cleanup the environment, here are the steps how to do it manually:

Remove VM Launchers

Find the process of talosctl qemu-launch:
To remove the VMs manually, execute:
Example output, where VMs are running with PIDs 157615 and 157617

Stopping VMs

Find the process of qemu-system:
To stop the VMs manually, execute:
Example output, where VMs are running with PIDs 158065 and 158216

Remove load balancer

Find the process of talosctl loadbalancer-launch:
To remove the LB manually, execute:
Example output, where loadbalancer is running with PID 157609

Remove DHCP server

Find the process of talosctl dhcpd-launch:
To remove the LB manually, execute:
Example output, where loadbalancer is running with PID 157609

Remove network

This is more tricky part as if you have already deleted the state folder. If you didn’t then it is written in the state.yaml in the ~/.talos/clusters/<cluster-name> directory.
If you only had one cluster, then it will be the interface with name talos<uuid>
To remove this interface:

Remove state directory

To remove the state directory execute:

Troubleshooting

Logs

Inspect logs directory
Logs are saved under <cluster-name>-<role>-<node-id>.log For example in case of k8s cluster name:
Inspect logs during the installation