在Debian上使用KVM和Virsh替代Vagrant
速览
本文介绍了如何在Debian系统上使用KVM和Virsh工具来管理虚拟机,以替代传统的Vagrant。KVM提供更轻量、更高效的虚拟化体验,Virsh则提供命令行管理功能。这对于需要更底层控制虚拟化环境的开发者和运维人员具有实际意义。
AI 深度解读
放弃 Vagrant:在 Debian 上使用 KVM 和 Virsh 管理虚拟机
背景
作者自 2010 年起一直使用 Vagrant 管理虚拟机生命周期,先后搭配 VirtualBox 和 libvirt/KVM 后端。Vagrant 的 box 机制和内置 Ansible 支持曾带来便利。然而,随着对 Linux 内核虚拟化技术理解的加深,作者开始质疑为何要在原生支持的 KVM 之上再叠加 Vagrant 这一抽象层——KVM 自 Linux 2.6.20 起已合并入内核,本身具备完整的虚拟机创建和管理能力。经过数年“懒惰”妥协(仅将后端从 VirtualBox 切换到 libvirt),作者最终决定彻底移除 Vagrant,直接使用 KVM + libvirt + virsh 管理虚拟机。这一转变不仅简化了工作流,也让作者重新获得了对技术栈的掌控感。
核心内容
KVM、libvirt 与 virsh 的关系
- KVM(Kernel-based Virtual Machine) 使 Linux 内核能充当 hypervisor,通过内核虚拟化模块创建和运行虚拟机。确认 KVM 是否启用:
lsmod | ag kvm输出kvm_intel和kvm模块;或检查/dev/kvm是否存在。 - libvirt 是一个库和网络守护进程,管理 KVM 以及其他虚拟化平台(Xen、LXC、QEMU)。它提供统一的编程接口和命令行工具,使不同 hypervisor 之间的切换不改变管理命令。安装:
sudo apt-get install libvirt-daemon-system。 - virsh 是 libvirt 的命令行前端(另有 GUI 前端 virt-manager)。它提供与 libvirt 守护进程交互的抽象层,常用命令包括:
domblkinfo、domblkstat、domid、domiflist、domifstat、dominfo、dommemstat、domname、domstate、domuuid等(获取虚拟机信息);hostname、nodeinfo、capabilities(获取宿主机信息);connect、destroy、dumpxml、edit、list、reboot、shutdown、start、undefine(管理操作)。安装:sudo apt-get install libvirt-clients virtinst(同时安装virt-install)。
作者强调概念模型为:用户 → virsh → libvirt → KVM。
升级后遇到的串口输出问题(ruh-roh)
作者将 Debian 从 bookworm 升级到 trixie 后,启动虚拟机时无法获得串口输出。原本通过 virt-install 命令传递的内核引导参数(如 console=ttyS0,115200)似乎未写入虚拟机的 GRUB 配置。排查方法:登录虚拟机,检查 /etc/default/grub 中的 GRUB_CMDLINE_LINUX 和 GRUB_CMDLINE_LINUX_DEFAULT 行。若有修改,需执行 sudo grub-mkconfig -o /boot/grub/grub.cfg && sudo reboot。
作者决定采用更稳健的方案:使用预置(preseed)配置文件自动安装虚拟机,避免依赖引导参数动态传递。这种方式使构建过程具有确定性和可版本化管理,并可预装基础软件,后续再通过 cloud-init 等工具在创建时添加定制软件。
预置(Preseeding)与 virt-install 实践
Preseeding 即通过预先提供安装过程中所有问题的答案(本地化、用户名密码、安装包等)来自动化创建虚拟机。Debian 官方提供了示例预配置文件。作者给出一个 virt-install 命令示例:
$ virt-install \
--connect qemu:///system \
--name kilgore-trout \
--memory 8192 \
--extra-args="preseed/file=/preseed.cfg console=ttyS0,115200n8" \
--initrd-inject ./preseed.cfg \
--install debian13 \
--disk size=40 \
--filesystem type=mount,source=/home/btoll/libvirt/kilgore-trout/mnt,target=shared,accessmode=mapped,driver.type=path,driver.wrpolicy=immediate \
--network network=default \
--...
其中 --extra-args 同时指定了 preseed 文件路径和串口参数;--initrd-inject 将本地的 preseed.cfg 注入到 initrd 中;--filesystem 设置宿主机与虚拟机之间的共享目录(通过 virtio-fs 或 9p 等实现)。
关键要点
- 放弃 Vagrant 的理由:Vagrant 对于轻量级个人使用而言过于臃肿;KVM 已内置于 Linux 内核,无需额外抽象层;直接使用原生工具让工作流更简单、可控。
- KVM、libvirt、virsh 三层架构:KVM 提供底层虚拟化,libvirt 提供统一管理接口,virsh 提供命令行操作入口。
- 安装与验证:通过 apt 安装
libvirt-daemon-system、libvirt-clients和virtinst;用lsmod | ag kvm或/dev/kvm确认 KVM 模块加载。 - 升级后的串口问题:引导参数可能未正确写入 GRUB,改用 preseed 文件注入可避免该问题。
- Preseeding 的优势:自动化安装、确定性构建、版本可控;可预装基础软件,后续用 cloud-init 等灵活扩展。
- 实际命令示例:
virt-install支持注入 preseed 文件、设置共享目录、指定网络等,覆盖完整虚拟机创建流程。
意义与影响
这篇文章展示了一个资深开发者主动简化技术栈、回归底层原语的心路历程。它提醒我们:在技术选型时,不应因习惯或便利而保留不必要的抽象层。直接使用 KVM + libvirt 不仅减少了一个依赖项(Vagrant),还降低了对第三方工具更新和兼容性问题的依赖。Preseeding 的引入使得虚拟机创建过程变得完全可重复和可审计,这在基础设施即代码(IaC)实践中至关重要。此外,作者对升级后问题的处理方式(从调试参数传送到改用静态配置文件)体现了工程中的“确定性优于魔法”原则。对于正在使用 Vagrant 但想更深入学习 Linux 虚拟化的读者,这篇文章提供了一个清晰的迁移路径和实用的命令参考。
