Vấn đề: Cần chạy máy ảo trên Linux server mà không có GUI
Bạn muốn test một distro mới, dựng môi trường sandbox để thử script nguy hiểm, hoặc cần chạy song song nhiều hệ thống cùng lúc. VirtualBox là lựa chọn quen thuộc — nhưng trên server Ubuntu không màn hình thì cài VirtualBox để làm gì? Và ngay cả khi có màn hình, VirtualBox thường bị lỗi module sau mỗi lần update kernel — phải chạy lại sudo /sbin/vboxconfig là chuyện mình gặp đến chán.
Mình đang chạy homelab với Proxmox VE quản lý 12 VM và container — đây là playground để test mọi thứ trước khi đưa lên production. Proxmox thực chất xây trên KVM. Vậy tại sao không dùng thẳng KVM trên Ubuntu khi cần setup gọn nhẹ hơn, không phải cài thêm cả một distro riêng?
Phân tích: KVM khác VirtualBox ở điểm nào quan trọng?
KVM (Kernel-based Virtual Machine) là hypervisor loại 1, chạy thẳng trên phần cứng qua CPU virtualization extension (Intel VT-x hoặc AMD-V). Nó được tích hợp vào Linux kernel từ phiên bản 2.6.20 — tức là đã có mặt trên mọi distro modern mà không cần cài thêm gì. VirtualBox thì khác: hypervisor loại 2, hoạt động như ứng dụng bình thường trên host OS, có thêm một lớp overhead ở giữa.
Ba lý do mình chuyển hẳn sang KVM thay vì VirtualBox cho server:
- Hiệu năng sát native: VM chạy qua KVM có thể đạt 95–98% hiệu năng so với máy thật, đặc biệt với disk I/O và network khi dùng virtio driver
- Không bị break sau kernel update: KVM là module kernel chính thức, không phải DKMS module bên ngoài như VirtualBox — update kernel xong vẫn chạy bình thường
- Quản lý linh hoạt: virsh (CLI), virt-manager (GUI), Cockpit (web UI) — tùy môi trường mà chọn tool phù hợp
Các bước cài đặt KVM trên Ubuntu
Bước 1: Kiểm tra CPU có hỗ trợ hardware virtualization
Skip bước này, cài xong mới biết CPU không hỗ trợ — mất công từ đầu:
egrep -c '(vmx|svm)' /proc/cpuinfo
Kết quả lớn hơn 0 là được. Ra 0 thì cần vào BIOS bật VT-x (Intel) hoặc AMD-V. Cách xem rõ ràng hơn:
sudo apt install cpu-checker -y
kvm-ok
Output mong đợi: KVM acceleration can be used.
Bước 2: Cài đặt KVM và các công cụ đi kèm
sudo apt update
sudo apt install -y \
qemu-kvm \
libvirt-daemon-system \
libvirt-clients \
bridge-utils \
virtinst \
virt-manager
Mỗi package có vai trò riêng:
qemu-kvm: engine chính để emulate phần cứng và chạy VMlibvirt-daemon-system: daemon quản lý VM qua Unix socket, cung cấp API thống nhấtlibvirt-clients: bộ CLI gồmvirsh— lệnh chính dùng hàng ngàybridge-utils: cần nếu muốn VM lấy IP trực tiếp trên LAN (bridge network)virtinst: cung cấpvirt-installvàvirt-clonevirt-manager: GUI quản lý VM (chỉ cần nếu có desktop environment)
Bước 3: Thêm user hiện tại vào group libvirt và kvm
Không làm bước này, mọi lệnh virsh đều phải gõ sudo — khá phiền:
sudo usermod -aG libvirt $USER
sudo usermod -aG kvm $USER
Sau đó logout và login lại. Muốn áp dụng ngay mà không cần logout:
newgrp libvirt
Bước 4: Đảm bảo libvirt daemon đang chạy
sudo systemctl enable --now libvirtd
systemctl status libvirtd
Status active (running) là ổn. Lần đầu cài, default NAT network của libvirt (virbr0) chưa tự start — cần bật thủ công:
virsh net-list --all
virsh net-start default
virsh net-autostart default
Cách tốt nhất: Tạo và quản lý VM bằng virsh + virt-install
Tạo VM đầu tiên từ ISO
Download ISO trước (ví dụ Ubuntu Server 22.04), rồi chạy virt-install:
virt-install \
--name ubuntu-test \
--ram 2048 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/ubuntu-test.qcow2,size=20,format=qcow2 \
--os-variant ubuntu22.04 \
--network network=default \
--graphics none \
--console pty,target_type=serial \
--location /home/user/ubuntu-22.04-live-server-amd64.iso \
--extra-args 'console=ttyS0,115200n8 serial'
Ba tham số hay gây nhầm lẫn:
--disk format=qcow2: disk động — file trên host chỉ chiếm dung lượng thực sự đang dùng, không chiếm đủ 20GB ngay--os-variant ubuntu22.04: KVM dùng thông tin này để optimize settings (IO scheduler, clock, etc.) — sai OS variant có thể ảnh hưởng hiệu năng. Xem danh sách:osinfo-query os | grep ubuntu--graphics none --console pty: serial console thay vì VNC/SPICE — phù hợp server không có màn hình, SSH vào quản lý từ xa
Các lệnh virsh dùng hàng ngày
# Xem danh sách VM (kể cả đang tắt)
virsh list --all
# Bật / tắt VM
virsh start ubuntu-test
virsh shutdown ubuntu-test # Tắt an toàn (gửi ACPI signal)
virsh destroy ubuntu-test # Tắt cứng (như rút điện)
# Kết nối vào console
virsh console ubuntu-test
# Thoát console: Ctrl + ]
# Snapshot trước khi làm gì đó rủi ro
virsh snapshot-create-as ubuntu-test snap-before-upgrade
virsh snapshot-revert ubuntu-test snap-before-upgrade
virsh snapshot-list ubuntu-test
# Xóa VM và toàn bộ disk
virsh undefine ubuntu-test --remove-all-storage
Clone VM — tiết kiệm thời gian đáng kể
Cài từ đầu mỗi lần cần VM mới rất tốn thời gian. Cách làm thực tế hơn: chuẩn bị một VM “base” đã có OS và các package cơ bản, rồi clone khi cần. virt-clone xong trong vài chục giây thay vì cả tiếng cài OS:
# Tắt VM gốc trước
virsh shutdown ubuntu-base
# Clone
virt-clone \
--original ubuntu-base \
--name ubuntu-clone-1 \
--auto-clone
Sau khi clone, SSH vào VM mới và đổi hostname + regenerate SSH host key:
sudo hostnamectl set-hostname ubuntu-clone-1
sudo rm /etc/ssh/ssh_host_*
sudo dpkg-reconfigure openssh-server
Xem tài nguyên và resize disk
# Monitor real-time CPU/RAM của các VM
virt-top
# Xem disk images đang có
virsh vol-list --pool default
# Resize disk (VM phải tắt trước)
sudo qemu-img resize /var/lib/libvirt/images/ubuntu-test.qcow2 +10G
# Sau đó vào trong VM chạy growpart + resize2fs để OS nhận disk mới
Lỗi thường gặp và cách xử lý
virsh báo “permission denied” dù đã add group
Nguyên nhân hay gặp nhất: chưa logout/login sau khi usermod. Chạy groups mà không thấy libvirt trong output — đó là vấn đề. Fix nhanh không cần logout:
newgrp libvirt
virsh list --all
VM tạo xong nhưng boot lên màn hình đen
Thường do --os-variant không đúng. Với distro mới, libvirt cũ có thể chưa có entry — dùng osinfo-query os | grep ubuntu để xem tên chính xác. Không tìm thấy thì dùng --os-variant linux2022 thay thế.
Không ping được từ VM ra ngoài internet
Default network dùng NAT — kiểm tra xem default network có đang chạy không:
virsh net-list --all
# Nếu thấy "default" ở trạng thái "inactive":
virsh net-start default
Bridge network là bước tiếp theo nếu VM cần IP riêng trên cùng dải LAN với host. Nhưng với mục đích lab và test, NAT mặc định là đủ — đơn giản, không cần đụng đến cấu hình mạng của host.
