virsh建立虚拟机,核心就两条路:一条是用virt-install命令配合安装源交互式创建,另一条是先写好XML配置文件再通过virsh define导入,完事之后用virsh start启动即可。这篇文章把这套流程拆成可落地的步骤,帮你在Linux服务器上快速搭起虚机环境。
virsh创建虚拟机命令详解:两种主流方式一次说清
在实际运维中,我们常遇到“没显示器、没IPMI、只有SSH”的场景,virsh作为libvirt的客户端工具,干的就是这个活在纯命令行环境下把虚拟机“捏”出来,用virsh创建虚拟机的底层逻辑只有两种:
- 通过
virt-install这种辅助工具生成XML,再调libvirt的API创建虚机。 - 自己手写或复制一份XML定义文件,通过
virsh define让libvirt“认领”这个虚机。
这两种方式的差距主要在“灵活度”和“上手难度”上,virt-install更像“引导式安装”,手把手帮你生成配置;XML方式则像“裸写代码”,每个参数都自己说了算,行业内不少人认为,想真正理解virsh的工作原理,两种方法都得试一遍。
环境准备:先确认KVM和libvirt就位
很多朋友在这步就翻车。virsh本身只是个客户端,底层没有KVM模块和libvirtd服务,一切命令都是白搭。
安装和验证分三步走:
- 检查CPU是否支持虚拟化,执行
grep -Eo '(vmx|svm)' /proc/cpuinfo,有输出就说明支持,没输出的话需要去BIOS里打开VT-x或AMD-V。 - 安装KVM相关组件,在CentOS/RHEL系列上执行
yum install -y qemu-kvm libvirt virt-install,Ubuntu/Debian上改成apt install -y qemu-kvm libvirt-daemon-system virtinst。 - 启动libvirtd服务并设置开机自启,执行
systemctl start libvirtd && systemctl enable libvirtd。
动手创建虚拟机之前,建议先跑一遍virsh version,看到“Using library: libvirt”以及“Running hypervisor: QEMU”这两行,才说明环境处于健康状态,别忘了确认存储池和网络池默认存在,用virsh pool-list --all和virsh net-list --all看一眼,多数发行版默认会建好default网络(NAT模式),存储池则是按照“目录+文件”的方式,指向/var/lib/libvirt/images。
如何用virsh创建虚拟机:实操virt-install完整流程
virt-install是和virsh高度搭配的命令行工具,它本身不直接属于virsh,但生成的虚机由virsh统一管理。
这步的成败关键在于“安装源”和“存储分配”两项参数,下面用一个CentOS 7虚机的创建过程做例子,逐步过一遍命令。
第一步:准备系统镜像和磁盘镜像文件
先下载好一个CentOS 7的ISO镜像,通常放到/var/lib/libvirt/boot/目录下,方便libvirt统一读取权限,然后创建一个虚拟磁盘,有两种方式:
- 用
qemu-img create -f qcow2 /var/lib/libvirt/images/centos7.qcow2 50G预先建一个QCOW2格式的动态磁盘,这种格式的特点是占用空间随实际使用量增长,建50G的文件初始只有几百KB。 - 不预先创建,直接在virt-install命令里用
--disk size=50参数,让virt-install自动生成裸格式或QCOW2格式的磁盘。
建议优先用方式一,因为可以预先指定磁盘的总线类型(比如
bus=virtio,性能比默认的IDE高出不少)和缓存模式。
第二步:编写virt-install启动命令
网上搜“virsh安装虚拟机命令”,大多贴的是“全参数在手写”版本的命令行,核心命令模板如下:
virt-install
--name centos7-test
--ram 4096
--vcpus 4
--disk path=/var/lib/libvirt/images/centos7.qcow2,format=qcow2,bus=virtio
--os-variant centos7.0
--network network=default,model=virtio
--graphics vnc,listen=0.0.0.0,port=5910
--cdrom /var/lib/libvirt/boot/CentOS-7-x86_64-Minimal-1815.iso
这个命令拆开看,每个参数都是一个关键的决定:
--name:给虚机起个唯一的名字,后续这个虚机的所有virsh操作都依赖这个名字。--ram和--vcpus:分配内存大小和CPU核数。内存以MB为单位,4096就是4GB,这个参数在虚机启动后可以用virsh setmem动态调,但最大不能超过启动时设定的上限。--disk:指定磁盘路径、格式、总线类型。bus=virtio意味着I/O路径更短、性能损耗更小,建议没有特殊依赖就用virtio。--network:选择网络模式。network=default走NAT,虚机能上外网但外部访问不到虚机;model=virtio同样是半虚拟化网卡,提速明显。--graphics:图形输出方式,服务器上通常没有显示器,用VNC监听在指定端口,然后本地的VNC客户端怼过去就能看到安装画面。--os-variant:优化虚拟机参数以匹配指定操作系统,减少不必要的兼容性检测,这个参数可以先执行osinfo-query os查一下支持哪些系统版本。
执行命令后,如果看到“Starting install…”字样,说明安装流程已经跑起来了。
第三步:通过VNC完成操作系统安装
命令执行后,虚拟机会自动从CDROM引导启动,但当前的终端只会停留在“域名安装仍在进行中”的状态,这时候我们打开本机的VNC客户端,连着“服务器IP:5910”这个地址,就能看到CentOS的图形安装界面了。
系统安装完,会自动重启。重启后再执行virsh list --all,你会看到这个虚机的状态是“running”。
顺便说一句,如果手头没有VNC客户端,也有另一种选择:用--location参数指向网络安装源,配合--extra-args传入kickstart文件实现全自动无人值守安装,这种方式更进阶,但灵活性更高,适合批量创建相同配置的虚机。
从XML文件入手:如何用virsh自定义创建虚拟机
当你有多个相同配置的虚机要建,或者要去复现别人环境里的某台机器时,用XML文件来定义虚拟机会更高效,即使virsh虚拟机的创建过程全都包含在XML文件的几百行内容里了,我们也只需要动几个关键段落。
拿到基础XML模板
最稳妥的方式,是从现有虚机里“导”一份:
virsh dumpxml centos7-test > /etc/libvirt/qemu/new-vm.xml
然后编辑这个文件,重点修改以下字段:
<name>标签:改成新虚机的名字,比如web-server-02。<uuid>标签:删掉或改成新的UUID,不然会和原虚机冲突。<memory>和<vcpu>标签:按需调整。<source>标签:指定不同的镜像路径或ISO来源。<mac address>标签:如果不想让虚拟机的MAC地址和原虚机一样,就改掉。<disk>章节里<source file>的值:必须改成新虚机的磁盘路径,否则两台虚机共用一块磁盘,是Ceph这类分布式存储也不建议这么干的。
改完保存后,执行:
virsh define /etc/libvirt/qemu/new-vm.xml
系统会返回“Domain new-vm defined from /etc/libvirt/qemu/new-vm.xml”,这一步只定义了虚机的“零件表”,不会真正启动,接下来可以执行virsh start new-vm拉起来跑。
用云镜像让“创建”变成“关联”
除了走“安装系统”这条路,还有一种很常用的做法:直接下载现成的qcow2云镜像,用XML文件指向它,或者用virt-install的--import参数导入。
比如在CentOS 8或Ubuntu 22.04上,很多人在KVM虚拟化上跑OpenStack时,用的就是这种“镜像即虚机”的思路,行业共识认为,这种方式的安装时间从原来的半小时缩到秒级,因为你跳过了操作系统的安装步骤。
具体操作用virt-install表达的话,就那么几行:
virt-install
--name ubuntu-cloud
--ram 2048
--vcpus 2
--disk path=/var/lib/libvirt/images/ubuntu-cloud.qcow2,format=qcow2
--import
--network network=default
--os-variant ubuntu22.04
--import的意思就是“别引导安装程序,直接启动现有磁盘里的系统”,另外还可以配合--cloud-init参数传递用户名和SSH公钥,一台虚机10秒之内就能拎起来用,特别适合大量临时测试环境的搭建。
虚拟机常见问题排查:virsh操作报错怎么办
创建过程不见得一次就走顺,日常运维中也常遇到下面这几类问题。
error: Failed to connect socket to '/var/run/libvirt/libvirt-sock'
这个问题的原因,基本就是libvirtd服务没启动或没重启,按顺序排查:
- 执行
systemctl status libvirtd看服务状态。 - 若服务是挂的,执行
systemctl start libvirtd再跑一次virsh version。
error: operation failed: domain 'xxx' already exists
虚机名称重复了,先virsh list --all看看已存在的名字,选个不冲突的名字再创建。
创建虚机后无法上网
先看虚拟机的网卡是否ONBOOT,NAT模式下,用户在虚机内部执行ip addr看是否有IP地址,如果没拿到DHCP地址,执行dhclient eth0或重配网卡配置文件,宿主机上用virsh net-dhcp-leases default可以查到分配给虚机的IP。
VNC连接不上图形界面
先确认监听地址不是回环地址,很多人在宿主机上执行命令时,会把--graphics vnc的listen参数默认成0.0.1,这样就约等于拒绝了外部连接,改成0.0.0的同时,还要留意防火墙是否放行了对应端口。
用virsh日常管理虚拟机
虚机建立只是第一步,日常管理和运维才是常态,常用的操作指令,这里一并列出来:
virsh list:查看当前正在运行的虚机。virsh list --all:查看所有虚机(包括关机状态)。virsh start <虚拟机名>:启动指定虚机。virsh shutdown <虚拟机名>:发送ACPI关机指令(需要虚机内装了ACPI驱动)。virsh destroy <虚拟机名>:强制断电,相当于直接拔电源线。virsh autostart <虚拟机名>:设置物理机开机时自动启动虚机。virsh edit <虚拟机名>:直接修改该虚机的XML配置,改完自动检测语法并让配置生效。
强制断电(destroy)和正常关机(shutdown)是两个经常被混淆的操作,在虚机无响应的时候,destroy确实是无奈之举,但频繁使用会有数据损坏风险,命令行模式下多用shutdown而不是destroy。
常见问题解答
做好备份习惯,上面的流程基本就够日常使用了,下面再把几个高频问题单独拿出来聊两句。
virsh创建虚拟机没有VNC显示怎么办?
VNC连不上时,优先检查VNC端口是否被防火墙挡了,以及在命令里是否加了listen=0.0.0.0参数,执行virsh vncdisplay <虚拟机名>,可以查看当前虚机占用的VNC显示编号(比如1表示端口5901)。“使用SSH X11转发还得开图形环境”这种想法完全可以省略,直连VNC端口就是最省事的方式。
virsh和virt-manager有什么区别?
virsh是纯命令行工具,适合放在无人值守的服务器上跑;virt-manager是图形化工具,本质上就是一个“给virsh穿了件外套”的软件,两者的底层都是libvirt API,操作虚拟机的效果完全一致。virsh能做到的事,virt-manager基本都做得到,反之亦然,区别只在于你手头的环境适合哪种操作方式。
想让创建的虚拟机开机自启,怎么设置?
复制粘贴virsh autostart <虚拟机名>这条命令即可,执行之后,libvirt会在/etc/libvirt/qemu/autostart/目录下生成一个符号链接,让libvirtd服务启动时自动拉起该虚机,如果想取消自动启动,执行virsh autostart --disable <虚拟机名>,把这个符号链接删掉就行。
KVM平台上用virsh建立虚拟机,其实不复杂,无非是“准备镜像、配置硬件参数、引导安装、日常维护”这个套路。选择virt-install走交互式创建路径,还是写XML文件做模板化定义,取决于你的场景需要,表格式清单化准备工作清单,能帮你省掉不少排错时间:
- 确认CPU支持虚拟化且BIOS已开启。
- 确认libvirtd服务处于运行状态。
- 准备系统ISO或云镜像文件。
- 规划好虚机名称、内存、CPU、磁盘大小。
- 确定网络模式及各接口的网卡类型。
顺着这个清单往下走,KVM虚拟机创建就顺理成章地完成了,遇到不明白的参数,用man virsh或virt-install --help随时查,整个命令行生态就是这么一套自成体系的交互方式。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/727713.html





