Week 2 - Lab 1: KVM Virtualization Fundamentals
Module: Operating Systems 3 (Virtualisation & Cloud Technologies) Instructor: KT Nshimba Topic: KVM CLI, QEMU, and Low-Level Virtualization Estimated Time: 45 Minutes
Lab Overview
In this lab, you will interact with the "Engine" (KVM/QEMU) directly to understand the low-level mechanics of virtualization. This "under-the-hood" looking is essential before using high-level interfaces like Proxmox VE.
Objectives:
- Part A: Verify hardware virtualization support and prepare virtual disks.
- Part B: Launch a Virtual Machine via CLI, log in, and manage its power state.
- Part C: (Bonus) Permanently install Alpine Linux to the virtual disk.
- Part D: Use
libvirtandvirshto accomplish the same tasks through a management API.
Prerequisites:
- Access to a Linux environment (Ubuntu Desktop/Server, or the Proxmox Shell).
- Internet access (to download the test ISO).
Part A: Verification & Preparation
Before we can run a VM, we must ensure the host is ready and we have storage.
- Verify CPU Support
Check if your processor supports hardware virtualization (VT-x or AMD-V).
lscpu | grep Virtualization
- Record: Which technology did you find? [ ] VT-x [ ] AMD-V
2. Verify Kernel Modules
Ensure the Linux Kernel has the KVM hypervisor modules loaded.
lsmod | grep kvm
-
Record: Is
kvm_intelorkvm_amdloaded? [ ] Yes [ ] NoTroubleshooting: usage if "No" If the modules are not loaded, try to enable them manually: 1. Load the specific driver:
bash sudo modprobe kvm_intel # For Intel CPUs # OR sudo modprobe kvm_amd # For AMD CPUs2. Check dmesg for errors:bash dmesg | grep kvm* If you see "disabled by bios", you must reboot and enable VT-x/AMD-V in your BIOS settings. * If you are running inside a VM (Nested), ensure "Nested Virtualization" is enabled in the host hypervisor.
3. Verify Permissions
Ensure your user can access the /dev/kvm device node.
ls -l /dev/kvm
- Group Name: ________
4. Virtual Disk Configuration
We will now prepare the storage for our Virtual Machine. In this step, we will create the disk image and briefly explore how different formats (QCOW2 vs RAW) behave on the filesystem.
Step 1: Create the Disk
Use qemu-img to create a qcow2 (QEMU Copy On Write) disk. This format is
"Thinly Provisioned", meaning it only uses space as data is written.
qemu-img create -f qcow2 test-disk.qcow2 10G
-
Inspect it:
bash qemu-img info test-disk.qcow2- Record:
- Virtual Size: ________
- Disk Size: ________
- Record:
Step 2: Format Analysis (Concepts)
Virtual disks come in many formats. Let's verify why we chose QCOW2 by converting it to RAW and
comparing the size.
1. Convert Qcow2 to Raw:
bash
qemu-img convert -f qcow2 -O raw test-disk.qcow2 test-disk.img
2. Compare Sizes:
Run ls -lh test-disk.*
**Comparison Table**:
| File | Format | Actual Size on Disk (ls -lh) | Explanation |
| :--- | :--- | :--- | :--- |
| test-disk.qcow2 | QCOW2 | ____________________ | Grows on demand (Thin) |
| test-disk.img | RAW | ____________________ | Pre-allocated (Thick) |
6. Part A Summary: Deployment Readiness
Before proceeding to Part B (launching the VM), confirm you have the following pieces in place. Missing any one of these will cause the launch command to fail.
Deployment Checklist:
- CPU: Hardware virtualization is supported and active.
- Kernel:
kvmandkvm_intel/kvm_amdmodules are loaded. - Permissions: My user has
access to
/dev/kvm. - Storage:
test-disk.qcow2exists and is 10GB in virtual size.
Critical Thinking:
- Why is QCOW2 format preferred over RAW for virtual machines?
[ _________________________________________________________________________ ]- What happens if you try to run QEMU without
-enable-kvm? [ _________________________________________________________________________ ]
Part B: Launching & Logging In
Now we will manually perform the job of a hypervisor management tool. We will download a minimal Operating System, wire up the virtual hardware using QEMU commands, and boot the machine.
1. Download Boot Image (Alpine Linux)
We use Alpine Linux because it is tiny (~60MB) and boots instantly.
wget https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/alpine-virt-3.20.0-x86_64.iso
2. The Launch Command
Execute the following single command to build and boot the VM.
Tip: If you are using a server without a GUI, add -nographic to the end.
qemu-system-x86_64 \
-enable-kvm \
-m 512 \
-drive file=test-disk.qcow2,format=qcow2 \
-cdrom alpine-virt-3.20.0-x86_64.iso \
-boot d
Command Analysis:
qemu-system-x86_64: The main emulator binary.-enable-kvm: CRITICAL. Tells QEMU to use the KVM engine. Without this, it runs in slow software emulation mode.-m 512: Allocates 512 MiB of RAM.-drive ...: Connects ourtest-disk.qcow2file to the virtual IDE controller.-cdrom ...: Inserts the Alpine ISO into the virtual Optical Drive.-boot d: Forces BIOS to boot from the CD-ROM (d) instead of the hard disk (c).
3. Log In to the VM (Live Session)
Note: We are booting into a Live RAM Environment directly from the ISO.
You do not need to install the OS to log in. The test-disk.qcow2 we attached is present but
currently empty.
- The VM will boot and scroll text.
-
At the prompt
localhost login:, type:- User:
root - Password: (None, just press Enter)
- You are now inside the VM! Run
uname -ato see the guest kernel.
- User:
4. Verify Virtual Hardware
Even though we didn't install to the disk, let's prove it is connected.
1. Check Disks:
bash
fdisk -l
2. Record:
* **Device Name**: ____________________ (Likely `/dev/vda`)
* **Size**: ____________________ (Should be 10 GiB)
* **Conclusion**: The disk we created in Part A is successfully "wired" to the VM.
5. Basic Networking Test
By default, QEMU uses SLIRP (User Networking), which acts like a NAT behind the host
process.
1. Check IP:
bash
ip addr show
* **Record IP**: ____________________ (e.g., 10.0.2.15)
-
Test Connectivity:
bash ping -c 3 8.8.8.8- Result: Did it reply? [ ] Yes [ ] No
Critical Thinking:
- Why can't other machines on your network ping your VM by default with SLIRP networking?
[ _________________________________________________________________________ ]
6. Shutdown
To turn off the VM safely:
poweroff
The QEMU window should close (or the process terminate).
Part C: Bonus Challenge - Permanent Installation
For students who want to go further, you can install the OS permanently to the
test-disk.qcow2 file. This means your changes will be saved even after you shutdown.
1. Run the Installer
Start the VM again (using the command from Part B) if it is off. Inside the VM, run the Alpine setup script:
setup-alpine
- Prompts: Follow the interactions.
- Keyboard:
us - Hostname:
alpine-vm - Network:
eth0,dhcp,no - Root Password: Set a password.
- Timezone:
UTC - Mirror:
1(Detect or select a number) - Disk:
vda->sys(Crucial step!) - Erase Disk:
y
- Keyboard:
2. Verify Persistence
- Shutdown the VM (
poweroff). - Boot from Disk: Run the QEMU command again, but REMOVE the
-cdromand-boot dflags.bash qemu-system-x86_64 \ -enable-kvm \ -m 512 \ -drive file=test-disk.qcow2,format=qcow2 - Result: If the VM boots and asks for a login, you have successfully initialized a virtual hard drive!
Part D: Managing VMs with libvirt
In Parts A–C, you used raw qemu-img and qemu-system-x86_64 commands to create storage and launch VMs. While this teaches you what happens "under the hood", production environments rarely work this way.
libvirt is an open-source API and management layer that sits on top of hypervisors like KVM/QEMU. It provides a single, consistent interface (virsh CLI, XML configs, and a daemon) that is used by virtually every major virtualisation platform — including Proxmox VE (Lab 2), OpenStack (Week 8+), and oVirt.
Think of it this way:
- QEMU/KVM = The engine of a car
- libvirt = The dashboard, steering wheel, and pedals
- Proxmox/OpenStack = A full self-driving system built on top of those controls
1. Install libvirt
Install the libvirt daemon, the virsh CLI, and the virt-install provisioning tool:
sudo apt install qemu-kvm libvirt-daemon-system virtinst -y
Verify the service is running:
systemctl status libvirtd
- Record: Is the service
active (running)? [ ] Yes [ ] No
Add your user to the libvirt group so you can manage VMs without sudo:
sudo usermod -aG libvirt $USER
Note: You may need to log out and log back in for the group change to take effect. On the Proxmox shell, you can skip this step as you are already root.
2. Create a Storage Pool and Volume
In Part A, you created a disk with qemu-img create. With libvirt, storage is organised into Pools (directories, LVM groups, NFS mounts, etc.) and Volumes (individual disk images within a pool).
Step 1: Define a Storage Pool
virsh pool-define-as lab-pool dir --target /var/lib/libvirt/images/lab-pool
Step 2: Build, Start, and Auto-start the Pool
virsh pool-build lab-pool
virsh pool-start lab-pool
virsh pool-autostart lab-pool
Step 3: Verify the Pool
virsh pool-list --all
- Record: Is
lab-poollisted with stateactive? [ ] Yes [ ] No
Step 4: Create a Volume (equivalent to qemu-img create -f qcow2)
virsh vol-create-as lab-pool libvirt-test-disk.qcow2 10G --format qcow2
Step 5: Verify the Volume
virsh vol-info libvirt-test-disk.qcow2 --pool lab-pool
- Record:
- Capacity: ____________________ (should be 10 GiB)
- Allocation: ____________________ (should be very small — thin provisioned!)
3. Deploy a VM with virt-install
In Part B, you used a long qemu-system-x86_64 command to wire up all the virtual hardware. The virt-install tool does the same thing but through libvirt, and it automatically generates the XML domain definition that libvirt uses to manage the VM.
First, copy the Alpine ISO to a location libvirt can access:
sudo cp alpine-virt-3.20.0-x86_64.iso /var/lib/libvirt/images/
Now deploy:
virt-install \
--name alpine-libvirt \
--ram 512 \
--vcpus 1 \
--disk vol=lab-pool/libvirt-test-disk.qcow2 \
--cdrom /var/lib/libvirt/images/alpine-virt-3.20.0-x86_64.iso \
--os-variant alpinelinux3.19 \
--graphics none \
--console pty,target_type=serial \
--boot cdrom
Command Analysis (compare with Part B):
--name: Gives the VM a persistent name (libvirt tracks it by name).--ram 512: Same as-m 512in QEMU.--vcpus 1: Allocates 1 virtual CPU.--disk vol=lab-pool/...: References the volume we created in our pool (instead of a raw file path).--cdrom: Same concept as-cdromin QEMU.--os-variant: Helps libvirt optimise settings for the guest OS.--graphics none --console pty: Attaches directly to the serial console (no GUI window).
When the VM boots, log in as root (no password) just like in Part B.
Tip: To detach from the console without shutting down the VM, press
Ctrl+].
4. Manage the VM with virsh
Now use virsh to manage your running VM — no QEMU commands needed.
List running VMs:
virsh list
- Record: Is
alpine-libvirtlisted with staterunning? [ ] Yes [ ] No
Get VM details:
virsh dominfo alpine-libvirt
- Record:
- Max memory: ____________________
- CPU(s): ____________________
- State: ____________________
Reconnect to the console (if you detached earlier):
virsh console alpine-libvirt
Gracefully shut down the VM:
virsh shutdown alpine-libvirt
Start it again:
virsh start alpine-libvirt
Force stop (like pulling the power plug):
virsh destroy alpine-libvirt
Delete the VM definition (clean up when done):
virsh undefine alpine-libvirt
5. Comparison: QEMU CLI vs libvirt
The following table summarises how the raw QEMU commands you used in Parts A–C map to their libvirt equivalents:
| Task | Raw QEMU Command | libvirt / virsh Equivalent |
|---|---|---|
| Create a virtual disk | qemu-img create -f qcow2 disk.qcow2 10G |
virsh vol-create-as pool disk.qcow2 10G --format qcow2 |
| Inspect a disk | qemu-img info disk.qcow2 |
virsh vol-info disk.qcow2 --pool pool |
| Launch a VM | qemu-system-x86_64 -enable-kvm -m 512 ... |
virt-install --name vm --ram 512 ... |
| List running VMs | ps aux | grep qemu |
virsh list |
| Shut down a VM | poweroff (from inside guest) |
virsh shutdown vm-name |
| Force stop a VM | Kill the QEMU process | virsh destroy vm-name |
| Start a stopped VM | Re-run the full QEMU command | virsh start vm-name |
| Get VM info | info in QEMU monitor |
virsh dominfo vm-name |
Critical Thinking:
- Why would a cloud platform like OpenStack use libvirt instead of calling QEMU directly?
[ _________________________________________________________________________ ] - What advantage does a named VM (
virsh start alpine-libvirt) have over re-typing the full QEMU command each time?[ _________________________________________________________________________ ]
Lab Checkpoint
Practical Skills Checklist
- Confirmed CPU supports virtualization
(
lscpu) - Verified KVM kernel modules are loaded
- Created virtual disk using
qemu-imgand analyzed QCOW2 vs RAW - Successfully booted Alpine Linux from ISO
- Logged in as root and explored the VM environment
- Verified network connectivity (ping) from inside VM
- (Bonus) Permanently installed Alpine Linux to the disk
- Installed libvirt and verified
libvirtdservice is running - Created a storage pool and volume using
virsh - Deployed a VM using
virt-install - Managed VM lifecycle (list, console,
shutdown, start, destroy) with
virsh
Theoretical Understanding Checklist
- Explained why QCOW2 is preferred over RAW format
- Understood the purpose of
-enable-kvmflag - Identified the role of SLIRP networking
- Recognized the difference between live boot and permanent installation
- Explained the role of libvirt as an abstraction layer over QEMU/KVM
- Understood the relationship between storage pools, volumes, and disk images
- Compared raw QEMU commands with libvirt/virsh equivalents
Troubleshooting Scenarios
Scenario 1: qemu-system-x86_64 command errors with "Could not access KVM
kernel module"
Solution:
[ _________________________________________________________________________ ]
Scenario 2: VM boots but network ping fails
Possible Causes:
[ _________________________________________________________________________ ]
Lab Reflection
Take a moment to reflect on what you learned:
-
Most Valuable Skill: What CLI command or concept will you use most?
[ _________________________________________________________________________ ] -
Biggest Challenge: What was the hardest part of this lab?
[ _________________________________________________________________________ ] -
Real-World Application: When would you use QEMU/KVM directly instead of Proxmox?
[ _________________________________________________________________________ ] -
Next Steps: What virtualization topic do you want to explore further?
[ _________________________________________________________________________ ]