Menjalankan satu VM dengan qemu-system-x86_64 mentah masih tertangani: satu baris panjang, satu proses, satu terminal yang tidak boleh tertutup. Masalah mulai terasa ketika VM-nya ada sepuluh, harus menyala otomatis saat boot, dan disknya harus dipindah-pindah antar storage. libvirt lahir untuk pekerjaan itu: sebuah daemon yang menyimpan seluruh definisi VM sebagai berkas XML, menjalankannya lewat QEMU/KVM, dan menyajikan satu API yang sama untuk berbagai hypervisor. Chapter ini membedah isi ekosistemnya — virsh di baris perintah, virt-manager di desktop, dan cara pandangnya terhadap disk serta jaringan.

libvirt: Satu API untuk Banyak Hypervisor #

libvirt berpusat pada sebuah daemon (dulu libvirtd, kini dipecah menjadi virtqemud dan kawan-kawan) yang berjalan di host dan mengelola domain — istilah libvirt untuk satu mesin virtual. Yang membuat libvirt istimewa adalah lapisan abstraksinya: driver libvirt tersedia untuk QEMU/KVM, Xen, LXC, bahkan VirtualBox, sehingga alat yang sama tetap berlaku ketika hypervisor di bawahnya diganti. Prinsip kerjanya sederhana dan radikal sekaligus: setiap VM sepenuhnya didefinisikan oleh satu dokumen XML. Menyalakan VM, mengubah memorinya, memindahkan disknya — semuanya adalah membaca dan menulis XML, bukan menghafal puluhan argumen baris perintah.

Sebagai konsumen API itu, kita punya dua wajah: virsh untuk terminal dan virt-manager untuk desktop, ditambah virt-install untuk membuat VM baru secara terprogram. Membaca dan mengubah XML domain adalah keterampilan inti memakai libvirt, jadi kita mulai dari satu dokumen minimal yang sesungguhnya:

bash
cat > vm-web.xml <<'EOF'
<domain type="kvm">
  <name>vm-web</name>
  <memory unit="GiB">2</memory>
  <vcpu placement="static">2</vcpu>
  <os>
    <type arch="x86_64" machine="pc-q35-9.0">hvm</type>
  </os>
  <devices>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/var/lib/libvirt/images/vm-web.qcow2"/>
      <target dev="vda" bus="virtio"/>
    </disk>
    <interface type="network">
      <source network="default"/>
      <model type="virtio"/>
    </interface>
  </devices>
</domain>
EOF
echo "=== field yang dibaca libvirt ==="
python3 -c "
import xml.etree.ElementTree as ET
r = ET.parse('vm-web.xml').getroot()
print('name   :', r.findtext('name'))
print('memory :', r.find('memory').get('unit'), r.findtext('memory'))
print('vcpu   :', r.findtext('vcpu'))
print('disk   :', r.find('./devices/disk/source').get('file'))
print('network:', r.find('./devices/interface/source').get('network'))
"

Output yang Dihasilkan:

text
=== field yang dibaca libvirt ===
name   : vm-web
memory : GiB 2
vcpu   : 2
disk   : /var/lib/libvirt/images/vm-web.qcow2
network: default

Mari kita bedah isi XML itu baris demi baris:

  1. Baris 1 (<domain type="kvm">): akar dokumen — type="kvm" menyatakan domain ini dijalankan dengan akselerasi KVM, bukan emulasi murni QEMU.
  2. Baris 2–4 (name, memory, vcpu): identitas dan ukuran mesin — nama domain, memori 2 GiB, dan 2 virtual CPU dengan penempatan statis.
  3. Baris 5–7 (os/type): cara menyalakannya — hvm berarti full virtualization dari firmware, dengan arsitektur x86_64 dan mesin chipset q35.
  4. Baris 9–14 (disk): harddisk virtual — berkas qcow2 dari storage pool default, muncul sebagai /dev/vda di guest lewat bus virtio yang cepat.
  5. Baris 15–18 (interface): kartu jaringan — terhubung ke network bernama default (yang akan kita bedah di bawah), juga dengan model virtio.

Baris-baris python3 di akhir blok sengaja meniru pekerjaan libvirt sendiri: membaca field penting dari XML yang sama persis seperti yang dibaca virsh dumpxml vm-web. Karena seluruh definisi VM hidup di XML, mengubah spesifikasi VM juga berarti mengedit XML lalu mendefinisikan ulang. Berikut pola kerjanya — upgrade RAM dan vCPU:

bash
cat > vm-web.xml <<'EOF'
<domain type="kvm">
  <name>vm-web</name>
  <memory unit="GiB">2</memory>
  <vcpu placement="static">2</vcpu>
</domain>
EOF
sed -i 's|<memory unit="GiB">2</memory>|<memory unit="GiB">4</memory>|' vm-web.xml
sed -i 's|<vcpu placement="static">2</vcpu>|<vcpu placement="static">4</vcpu>|' vm-web.xml
python3 -c "
import xml.etree.ElementTree as ET
r = ET.parse('vm-web.xml').getroot()
print('memory:', r.find('memory').get('unit'), r.findtext('memory'))
print('vcpu  :', r.findtext('vcpu'))
"

Output yang Dihasilkan:

text
memory: GiB 4
vcpu  : 4

Pada mesin libvirt sungguhan, hasil edit seperti ini diserahkan ke virsh define vm-web.xml yang menimpa definisi lama di library libvirt — VM harus dimatikan dulu untuk perubahan sebesar ini. Pola “edit XML, define ulang, nyalakan” inilah yang membuat konfigurasi VM bisa disimpan di git, disalin antar host, dan direview sebelum dipakai.

virsh: Remote Control dari Terminal #

virsh membungkus seluruh API libvirt menjadi kata kerja pendek. Perintah-perintah berikut adalah 90% kebutuhan sehari-hari admin:

PerintahPeran
virsh list --allmendaftar semua domain, termasuk yang sedang mati
virsh start vm-webmenyalakan domain
virsh shutdown vm-webmematikan dengan sopan — mengirim sinyal ACPI seperti menekan tombol power
virsh destroy vm-webmencabut kabel listrik — mematikan paksa tanpa menunggu guest
virsh dumpxml vm-webmencetak XML definisi lengkap domain
virsh dominfo vm-webringkasan satu domain: status, memori, vCPU, autostart
virsh console vm-webmasuk ke console serial guest tanpa layar grafis

Perbedaan shutdown dan destroy layak dihafal sejak dini: yang pertama meminta guest mematikan dirinya secara bersih, sedangkan yang kedua membunuh proses QEMU saat itu juga — filesystem guest berisiko rusak sebagaimana komputer nyata yang listriknya dicabut. Berikut contoh tampilan virsh list --all di host dengan tiga domain:

text
 Id   Nama      Status
---------------------------
 3    vm-web    running
 -    vm-db     shut off
 -    vm-ci     shut off

Domain tanpa nomor Id sedang mati; domain hidup mendapat nomor yang dipakai banyak subperintah lain. Kolom Status inilah yang dicek skrip monitoring sebelum memutuskan mengirim virsh start secara otomatis.

virt-manager dan virt-install #

virt-manager adalah wajah grafis libvirt: jendela daftar VM, console layar guest, grafik konsumsi CPU dan memori, serta wizard pembuatan domain untuk yang tidak mau menyentuh XML. Di balik kesederhanaan tampilannya, wizard ini tetap menulis XML yang sama — tombol “Apply” di form pengaturan virt-manager identik dengan sed dan virsh define yang kita lakukan di atas. Untuk pembuatan terprogram, virt-install mengerjakannya dari terminal:

bash
virt-install \
  --name vm-web --memory 2048 --vcpus 2 \
  --disk path=/var/lib/libvirt/images/vm-web.qcow2,size=20 \
  --cdrom /home/budi/iso/debian-netinst.iso \
  --network network=default --graphics spice

Satu panggilan ini membuat disk qcow2 20 GB baru, mendaftarkan domain bernama vm-web, menghubungkannya ke network default, membuka jendela instalasi dari ISO Debian, lalu menyimpan semuanya sebagai XML — sama persis dengan alur manual tadi, hanya diketik sekali. Di server tanpa layar, cukup ganti --graphics spice menjadi --graphics none --console pty,target_type=serial agar proses instalasi berjalan lewat console serial murni.

Storage Pool dan Network default #

libvirt tidak melihat disk hanya sebagai berkas; disk adalah anggota storage pool — kumpulan penyimpanan yang dikelola terpusat. Pool paling sederhana bertipe dir dengan lokasi default /var/lib/libvirt/images, tempat semua berkas qcow2 seperti pada XML di atas menetap. Pool bertipe lvm memakai volume group sebagai wadahnya: setiap disk virtual menjadi satu logical volume, sehingga fitur LVM seperti snapshot dan resize yang kita pelajari di Chapter LVM otomatis berlaku untuk disk VM.

Jaringan guest ditangani virtual network yang paling terkenal bernama default: libvirt membuat interface bridge virbr0 di host, menjalankan dnsmasq sebagai DHCP server di subnet 192.168.122.0/24, dan menerjemahkan alamat lewat NAT. Guest bisa mengakses dunia luar seolah-olah warnet sendiri, sedangkan dunia luar tidak bisa masuk tanpa aturan penerusan port di host — arah asimetris yang sengaja dipilih demi keamanan default. Perintah virsh net-list --all dan virsh net-dhcp-leases default menampilkan isi tabel ini di host sungguhan.

Peta lengkapnya kini terisi: domain XML sebagai sumber kebenaran, virsh dan virt-manager sebagai penggerak, pool sebagai gudang disk, virbr0 sebagai jembatan jaringan. Namun seluruh mesin ini tetap memvirtualisasi komputer utuh — kernel sendiri, boot sendiri, menit-menit start. Untuk sekadar menjalankan aplikasi, ada pendekatan yang jauh lebih ringan: container yang meminjam kernel host. Kita pindah ke ujung lain spektrum itu di Chapter Container Concepts .

Referensi lanjut: libvirt di Arch Wiki untuk gambaran ekosistemnya, serta halaman manual virsh sebagai kamus lengkap seluruh subperintahnya.