【Day 81】虚拟化-虚拟磁盘管理
一、存储池(Storage Pool)管理
存储池是 KVM 对存储资源的抽象,用于统一管理虚拟磁盘文件的存储路径,支持本地存储和网络存储,是虚拟机在线迁移的基础。
核心存储对象是虚拟磁盘映像文件(如 qcow2),但也可存储 ISO 镜像、配置文件等虚拟机相关资源,并非仅存磁盘映像文件。
- 存储池 定义了磁盘映像文件的存储位置(本地目录或网络共享目录),并统一管理该位置下的所有虚拟磁盘文件。
- 磁盘映像文件 是虚拟机的 “虚拟硬盘”(如系统盘、数据盘),必须存储在某个存储池对应的路径下,才能被 KVM 识别和管理。
企业虚拟化软件:企业级虚拟化软件通常对存储管理的灵活性和可控性要求较高,多数情况下需要管理员根据企业的存储架构、业务需求等手动创建存储池。
离线迁移
离线迁移是指在虚拟机关机或暂停状态下进行迁移。这种迁移方式不要求必须使用网络存储池,因为虚拟机处于非运行状态,可先将本地存储上的虚拟机磁盘镜像文件、配置文件等复制到外部存储设备(如移动硬盘、USB 闪存盘等),再手动将其复制到目标主机的本地存储位置,或者直接通过网络将本地存储中的相关文件传输到目标主机,从而完成迁移。
在线迁移
在线迁移要求虚拟机在迁移过程中保持运行状态,通常情况下更倾向于使用网络存储池,但也并非绝对强制。
基于网络存储池的优势:使用网络存储池(如 NAS、SAN 等)作为共享存储时,源主机和目标主机都能直接访问存储池中的虚拟机磁盘镜像文件。这样在迁移过程中,只需迁移虚拟机的内存状态、CPU 状态等运行时信息,而无需迁移磁盘数据,大大减少了迁移的数据量和迁移时间,也能保证虚拟机在迁移过程中对磁盘数据的正常读写访问,从而实现无缝迁移。
非网络存储池的情况:在一些特殊场景或特定虚拟化技术实现中,即使没有网络存储池,也能实现在线迁移。例如部分虚拟化系统支持通过网络直接传输磁盘数据的同时,维持虚拟机的运行,采用预拷贝、按需取页等技术来尽量减少迁移过程中的服务中断时间,但这种方式对网络带宽要求较高,且迁移效率和稳定性可能不如基于网络存储池的方式。
查看现有存储池
[root@kvm ~] virsh pool-list --all
# Name State Autostart
# -------------------------------------------
# default active yes # 默认本地存储池(dir类型)
# iso active yes # 自定义ISO镜像存储池
存储池类型及作用
| 类型 | 特点 | 适用场景 | 示例路径 |
|---|---|---|---|
本地存储池 (dir 类型) | 基于本地文件系统目录,配置简单,性能依赖本地磁盘 | 单机测试、非核心业务 | /var/lib/libvirt/images(默认存储池) |
| 网络存储池(nfs/iscsi 类型) | 基于网络共享存储,支持多主机访问 | 虚拟机在线迁移、集群环境 | NFS 共享目录:192.168.140.11:/kvm_image |

查看存储池详细配置
[root@martin-host ~] virsh pool-dumpxml default
<pool type='dir'> # 存储池类型:本地目录<name>default</name> # 存储池名称<uuid>1328db51-967c-4696-a63c-88814221c3ad</uuid> # 唯一标识<capacity unit='bytes'>211654430720</capacity> # 总容量(约197G)<allocation unit='bytes'>20023582720</allocation> # 已使用容量(约18.6G)<available unit='bytes'>191630848000</available> # 剩余容量(约178G)<source> # 本地存储池无source配置</source><target><path>/var/lib/libvirt/images</path> # 存储池对应的本地目录<permissions> # 目录权限配置<mode>0711</mode><owner>0</owner><group>0</group><label>system_u:object_r:virt_image_t:s0</label></permissions></target>
</pool>
网络存储池配置(支持虚拟机在线迁移)
以 NFS 网络存储为例,配置步骤如下:
(1)部署 NFS 服务器(后端存储)
在 NFS 服务器(192.168.140.10)上配置共享目录,允许迁移节点访问。


# 共享目录权限
[root@kvm_nas ~] chmod 777 /kvm-image # 开放权限(生产环境可细化)# 1. 安装NFS服务(CentOS 7)
[root@kvm_nas ~] yum install -y nfs-utils# 2. 创建共享目录
[root@kvm_nas ~] mkdir -p /kvm-image
[root@kvm_nas ~] chmod 777 /kvm-image # 开放权限(生产环境可细化)# 3. 配置NFS共享(允许迁移节点读写访问)
[root@kvm_nas ~] cat /etc/exports
/kvm-image 192.168.140.111(rw,no_root_squash) 192.168.140.20(rw,no_root_squash)
# 说明:192.168.140.111和192.168.140.20为KVM主机IP,rw=读写权限,no_root_squash=保留root权限# 4. 启动NFS服务并设置自启
[root@kvm_nas ~] systemctl start nfs-server
[root@kvm_nas ~] systemctl enable nfs-server
[root@kvm_nas ~] systemctl status nfs-server
[root@kvm_nas ~] chmod o+x /kvm-image/# 5. 验证NFS共享
[root@kvm_nas ~] exportfs -rv # 重新加载共享配置
exporting 192.168.140.111:/kvm-image
exporting 192.168.140.20:/kvm-image(2)KVM 主机挂载 NFS 存储(测试连通性)
在所有 KVM 迁移节点(192.168.140.111 和 192.168.140.20)上测试 NFS 挂载,确保能正常读写。
# 1. 在kvm机器上安装NFS客户端(若未安装)
[root@sul ~] yum install -y nfs-utils# 2. 临时挂载NFS共享目录到/mnt
[root@sul ~] mount -t nfs 192.168.140.10:/kvm-image /mnt# 3. 测试读写权限(创建测试文件)[root@sul ~] touch /mnt/aa
[root@sul ~] ls /mnt/
# aa # 能正常创建文件,说明权限正常# 4. 卸载临时挂载(后续通过存储池管理)
[root@martin-host ~] umount /mnt
不需要手动挂载,不需要在fstab里写挂载信息,这里仅测试。
3. 创建 NFS 类型存储池(KVM 主机)
(1)命令创建
通过 virsh pool-define-as 命令创建 NFS 存储池,统一管理网络存储资源。
# 步骤1:定义NFS存储池(指定名称、类型、NFS服务器IP和共享目录)
[root@martin-host ~]# virsh pool-define-as pool_by_nfs \
--type nfs \
--source-host 192.168.140.11 \ # NFS服务器IP
--source-path /kvm_image \ # NFS共享目录
--target /pool_by_nfs # KVM主机本地挂载点(自动创建)# 步骤2:创建存储池的本地挂载点
[root@martin-host ~]# virsh pool-build pool_by_nfs# 步骤3:启动存储池并设置自启
[root@martin-host ~]# virsh pool-start pool_by_nfs
[root@martin-host ~]# virsh pool-autostart pool_by_nfs# 步骤4:验证存储池状态(已激活,挂载成功)
[root@martin-host ~]# virsh pool-list --allName State Autostart
-------------------------------------------default active yes iso active yes pool_by_nfs active yes # 新创建的NFS存储池# 步骤5:验证挂载结果(NFS目录已挂载到/pool_by_nfs)
[root@sul ~]# df -hT |grep kvm-image
192.168.140.10:/kvm-image nfs4 50G 32M 50G 1% /kvm-imageschgrp -R kvm /kvm-images/
chmod -R 775 /kvm-images/ # 所有者和组都有读写执行权限(2)图形化创建
virt-manager 

#创建目标路径-挂载点,可重名
[root@sul ~] mkdir /kvm-images# 查看 libvirt 配置中指定的用户/组
[root@sul ~]# ps aux | grep qemu-kvm | grep -v grep|head -n 1
# qemu 3985 28.4 3.4 1855952 559316 ? Sl 10月21 197:26 /usr/libexec/qemu-kvm 方法1:
# 给目录添加其他用户的执行权限(允许进入目录)
chmod o+x /kvm-images
# 给镜像文件添加其他用户的读/写权限(允许 qemu 读写)
chmod o+rw /kvm-images/vm-test1.qcow2
方法2:
# 查看文件当前的所属组(假设输出为 root)
ls -l /kvm-images/vm-test1.qcow2
# 将 qemu 用户加入该组(例如 root 组)
usermod -aG root qemu
# 给文件添加组的读/写权限,给目录添加组的执行权限
chmod g+x /kvm-images # 组权限:允许进入目录
chmod g+rw /kvm-images/vm-test1.qcow2 # 组权限:允许读写文件
systemctl restart libvirtd # 添加用户到组后,需要重启 libvirtd 服务让权限生效# 配置权限
# NAS 端是 “权限源头”:必须给共享目录 / 文件设置权限(比如 775),且 kvm 组的 GID 要和 # KVM 端一致 —— 这是基础,NAS 端不给权限,KVM 端再怎么改都没用。
# KVM 端是 “权限承接”:qemu 用户必须属于 kvm 组,同时通过 NFS 挂载正确承接 NAS 端的权限 —— 这样 qemu 才能借助 kvm 组的权限,读写 NAS 上的磁盘文件。#注意关闭/配置SELinux上下文



![]()



4. 配置主机名解析(迁移节点互通)
为避免迁移时因 IP 地址变更导致失败,在所有迁移节点(192.168.140.200 和 192.168.140.10)上配置主机名解析。
# 步骤1:编辑本地hosts文件
[root@ ~]# cat /etc/hosts
192.168.140.111 sul
192.168.140.20 kvm_host2# 步骤2:同步hosts文件到目标节点
[root@martin-host ~] scp /etc/hosts root@192.168.140.10:/etc/hosts
# root@192.168.140.10's password:
# hosts # 100% 222 218.4KB/s 00:00 # 步骤3:验证解析(在目标节点执行)
[root@new-host ~] ping martin-host.linux.com -c 2 # 能正常ping通,解析成功
5. 测试虚拟机在线迁移


在线迁移(Live Migration)要求虚拟机磁盘存储在共享存储池(如 NFS)中,确保源节点和目标节点能访问同一磁盘文件。
前提条件
- 源节点和目标节点已配置相同的 NFS 存储池。
- 虚拟机磁盘文件已迁移到 NFS 存储池。
- 源节点和目标节点之间已配置 SSH 免密登录(可选,避免迁移时输入密码)。
[root@kvm_host2 ~] yum install -y nfs-utils
# 1. 创建本地目录
mkdir -p /kvm-images
# 2. 临时挂载(立即生效)
mount -t nfs 192.168.140.10:/kvm-image /kvm-images
# 3. 永久挂载(写入 /etc/fstab,重启后生效)
echo "192.168.140.10:/kvm-image /kvm-images nfs defaults 0 0" >> /etc/fstab
# 4. 验证挂载是否成功
df -h | grep /kvm-images # 若有输出,说明挂载成功[root@kvm_host2 ~]# virsh pool-list --all 名称 状态 自动开始
-------------------------------------------[root@kvm_host2 ~] yum install -y qemu-kvm qemu-img libvirt virt-install virt-manager libvirt-python libvirt-client virt-viewer
systemctl start libvirtd
systemctl enable libvirtd
systemctl status libvirtd执行在线迁移
# 语法:virsh migrate 虚拟机名 --live 目标节点URI --unsafe(--unsafe跳过安全性检查,测试环境用)
[root@martin-host ~] virsh migrate test2 \
--live qemu+ssh://192.168.140.20:55555/system \ # 目标节点SSH URI
--unsafe # 生产环境建议移除--unsafe,配置TLS加密或共享存储认证# 若未配置免密登录,会提示输入目标节点root密码
# root@192.168.140.20's password# 迁移成功后,在源节点查看虚拟机状态(已迁移,状态为shut off)
[root@sul ~] virsh list --all Id 名称 状态
----------------------------------------------------- test2 关闭# 在目标节点查看虚拟机状态(已运行,迁移成功)
[root@kvm_host2 ~] virsh list --allId 名称 状态
----------------------------------------------------1 test2 running注意:kvm虚拟机配置中包含 SELinux 安全模型相关设置,若当前系统的 libvirt 缺少 SELinux 安全驱动支持(可能是因为系统 SELinux 已禁用或未安装相关组件)。解决方法是移除虚拟机配置中的 SELinux 安全标签,步骤如下:
[root@sul ~]# virsh dumpxml test2 | grep -i selinux<seclabel type='dynamic' model='selinux' relabel='yes'/>
[root@sul ~]# vim /tmp/vm.xml# 移除原配置,删除刚刚查出来的那一行
[root@sul ~]# virsh undefine test2
域 test2 已经被取消定义
[root@sul ~]# # 用修改后的 XML 重新定义
[root@sul ~]# virsh define /tmp/vm.xml
定义域 test2(从 /tmp/vm.xml)[root@sul ~]# virsh start test2
域 test2 已开始[root@sul ~]# virsh migrate test2 --live qemu+ssh://192.168.140.20:55555/system --unsafe
root@192.168.140.20's password: 二、 命令行工具管理虚拟磁盘
1. 查看虚拟磁盘
通过 virsh domblklist 查看虚拟机已挂载的磁盘设备(含系统盘、数据盘、ISO 镜像等),明确磁盘对应的目标设备名(如 vda、hdb)和文件路径。
[root@kvm_host2 ~] virsh domblklist vm01_centos79
# Target Source
# ------------------------------------------------
# hda /var/lib/libvirt/images/vm01_centos79.qcow2 # 系统盘
# hdb /kvm/iso/CentOS-7.9-x86_64-Everything-2009.iso # 安装镜像
# vda /var/lib/libvirt/images/vm01_centos79-1.qcow2 # 数据盘[root@sul ~] virsh domblklist kvm_cenos_002
# 目标 源
# ------------------------------------------------
# vda /var/lib/libvirt/images/vm1_centos002.qcow2
# hdb -
2. 添加磁盘
步骤 1:创建 qcow2 格式磁盘文件
(1)图形化
(2)命令行
先通过 qemu-img create 生成指定大小的虚拟磁盘文件(qcow2 格式支持稀疏存储,节省物理空间)。
[root@sul ~] qemu-img create -f qcow2 /var/lib/libvirt/images/vm01_centos79-2.qcow2 5G
# Formatting '/var/lib/libvirt/images/vm01_centos79-2.qcow2', fmt=qcow2 size=5368709120 encryption=off cluster_size=65536 lazy_refcounts=off # 验证磁盘文件是否创建成功
[root@sul ~] ls /var/lib/libvirt/images/
# vm01_centos79-2.qcow2 步骤 2:挂载磁盘到虚拟机
使用 virsh attach-disk 命令挂载磁盘,需指定磁盘源路径、目标设备名、驱动类型及缓存模式,--persistent 参数确保重启后仍生效。
# --target vdb \ # 目标设备名(需避免与现有设备冲突,如vda已存在则用vdb)
# --subdriver qcow2 \ # 磁盘格式(与创建时一致)
# --cache writeback \ # 缓存模式(回写模式性能更优,默认通写模式更安全)
# --persistent # 持久化配置(否则重启虚拟机后磁盘丢失)
[root@sul ~] virsh attach-disk kvm_cenos_002 --source /var/lib/libvirt/images/vm01_centos79-2.qcow2 --target vdb --type disk --subdriver qcow2 --cache writeback --persistent
# 成功附加磁盘关键说明:磁盘缓存模式对比
// 缓存的存储空间要比实际的存储空间要小得多——缓存的核心价值是 “用小空间换快速度”,而非存储大量数据
| 缓存模式 | 特点 | 适用场景 |
|---|---|---|
| writeback(回写) | 数据先写入缓存,空闲时同步到磁盘,性能高 | 非核心业务、对性能要求高的场景 |
| writethrough(通写) | 数据直接写入磁盘,缓存仅用于读加速,安全性高 | 数据库、核心业务等对数据一致性要求高的场景 |
步骤 3:验证挂载结果
[root@sul ~] virsh domblklist kvm_cenos_002
# 目标 源
# ------------------------------------------------
# vda /var/lib/libvirt/images/vm1_centos002.qcow2
# vdb /var/lib/libvirt/images/vm01_centos79-2.qcow2
# hdb -
# 新挂载磁盘已显示
3. 删除磁盘
步骤 1:卸载虚拟机磁盘
使用 virsh detach-disk 卸载磁盘,指定目标设备名和 --persistent 参数(否则仅卸载运行时磁盘,配置文件中仍存在)。相当于机器拔出,但是硬盘对应的磁盘文件存在。
[root@sul ~] virsh detach-disk kvm_cenos_002 vdb --persistent
# 成功分离磁盘[root@sul ~] virsh domblklist kvm_cenos_002
# 目标 源
# ------------------------------------------------
# vda /var/lib/libvirt/images/vm1_centos002.qcow2
# hdb -步骤 2:删除磁盘文件(可选)
若需彻底清理,手动删除对应的 qcow2 文件。
[root@sul ~] rm -rf /var/lib/libvirt/images/vm01_centos79-2.qcow2
二、qcow2 格式磁盘文件管理
qcow2 是 KVM 默认的虚拟磁盘格式,支持稀疏存储、差量镜像、加密等功能,适用于大多数场景。
| 对比维度 | raw 格式 | qcow2 格式 | vmdk 格式 |
|---|---|---|---|
| 所属生态 | 通用(KVM/QEMU 等) | QEMU/KVM 主流 | VMware 专属(兼容其他平台) |
| 空间占用方式 | 固定大小 | 动态扩容 | 支持固定 / 动态两种方式 |
| 快照支持 | 不支持 | 支持 | 支持(与 VMware 快照功能深度集成) |
| 兼容性 | 极强(跨平台) | 良好(KVM/QEMU 优先) | 主要适配 VMware,其他平台可兼容读取 |
| 典型场景 | 高性能测试、简单存储 | KVM 生产环境、需灵活管理的场景 | VMware 虚拟化环境(服务器 / 桌面端) |
| 对比维度 | raw 格式 | qcow2 格式 |
|---|---|---|
| 核心特点 | 原始镜像,结构简单 | QEMU 主流格式,支持多种高级特性 |
| 空间占用方式 | 固定大小。采用预分配(一次性分配) 方式:创建镜像文件时,会直接占用设定的全部磁盘空间(即使文件内暂无数据)。 | 动态扩容。基于稀疏存储实现动态分配:创建时仅占用少量量初始空间(约几十 KB),随着数据写入逐渐增长,最大不超过设定的容量上限。 |
| 支持功能 | 无快照、加密、压缩等高级功能 | 支持快照(硬盘级快照管理)、加密、压缩、写时复制(COW) |
| 性能表现 | 接近物理磁盘,读写性能略优 | 性能略逊于 raw,但日常场景差距微小 |
| 空间利用率 | 较低(空镜像也占满指定容量) | 较高(仅占用实际存储数据的空间) |
| 兼容性 | 强,支持多数虚拟化工具(KVM、QEMU 等) | 良好,KVM/QEMU 原生支持,适配主流虚拟化场景 |
| 适用场景 | 对性能要求极高、无需快照的场景(如测试) | 需快照备份、空间灵活管理的场景(如生产环境) |
1. 创建 qcow2 磁盘文件
通过 qemu-img create 创建,可指定大小、加密、压缩等参数(默认不加密、不压缩)。

# 创建8G大小的qcow2磁盘
# qemu不指定的话默认是raw
[root@sul ~] qemu-img create -f qcow2 /opt/disk01.qcow2 8G
# Formatting '/opt/disk01.qcow2', fmt=qcow2 size=8589934592 encryption=off cluster_size=65536 lazy_refcounts=off
[root@sul ~] qemu-img create /opt/disk02 5G
# Formatting '/opt/disk02', fmt=raw size=5368709120 # 查看磁盘详细信息(虚拟大小≠实际占用空间)
[root@sul ~]# qemu-img info /opt/disk01.qcow2
# image: /opt/disk01.qcow2
# file format: qcow2 # 文件格式
# virtual size: 8.0G (8589934592 bytes) # 虚拟大小(对外展示的容量)
# disk size: 196K # 实际占用物理空间(稀疏存储特性)
# cluster_size: 65536
# Format specific information:
# compat: 1.1 # 兼容性版本(1.1支持lazy refcounts,提升性能)
# lazy refcounts: false # 延迟引用计数(关闭可提升稳定性,开启可减少IO)[root@sul ~] qemu-img info /opt/disk02
# image: /opt/disk02
# file format: raw
# virtual size: 5.0G (5368709120 bytes)
# disk size: 0[root@sul ~] ls -dlh /opt/disk01.qcow2
# -rw-r--r-- 1 root root 193K 10月 22 11:38 /opt/disk01.qcow2
[root@sul ~] ls -dlh /opt/disk02
# -rw-r--r-- 1 root root 5.0G 10月 22 11:40 /opt/disk02// 给硬盘建快照
qemu-img 
2. 差量镜像:快速创建虚拟机
差量镜像基于原始镜像(父镜像)创建,仅存储与父镜像的差异数据,可大幅节省空间并快速部署多台相同配置的虚拟机。
(1)准备父镜像(基础镜像)
先创建或选择一台配置完成的虚拟机磁盘作为父镜像(如 vm01_centos79.qcow2,已安装系统和基础软件)。
# 确保父镜像处于只读状态(避免修改父镜像影响所有差量镜像)
[root@martin-host ~]# chmod 444 /var/lib/libvirt/images/vm01_centos79.qcow2
(2)创建差量镜像
通过 qemu-img create -b 指定父镜像,生成差量镜像(子镜像)。
[root@sul ~] qemu-img create -f qcow2 \
-b /var/lib/libvirt/images/generic.qcow2 \ # 父镜像路径
/var/lib/libvirt/images/test1.qcow2 # 差量镜像路径
# Formatting '/var/lib/libvirt/images/test1.qcow2', fmt=qcow2 size=21474836480 backing_file='/var/lib/libvirt/images/generic.qcow2' encryption=off cluster_size=65536 lazy_refcounts=off
[root@sul ~] ls /var/lib/libvirt/images/
# generic.qcow2 test1.qcow2
[root@sul ~] qemu-img info /var/lib/libvirt/images/test1.qcow2
# image: /var/lib/libvirt/images/test1.qcow2
# file format: qcow2
# virtual size: 20G (21474836480 bytes)
# disk size: 196K # 仅占用差异空间,节省存储
# cluster_size: 65536
# backing file: /var/lib/libvirt/images/generic.qcow2 # 父镜像路径
# Format specific information:
# compat: 1.1
# lazy refcounts: false
(3)准备虚拟机配置文件
复制父虚拟机的 XML 配置文件,修改唯一标识(名称、UUID、MAC 地址)和磁盘路径。
# 复制基础配置文件
[root@sul ~] cd /etc/libvirt/qemu/
[root@sul qemu]# ls
# autostart generic-2.xml generic.xml networks
[root@sul qemu] cp generic.xml test1.xml
# 编辑配置文件,修改关键参数(避免冲突)
[root@martin-host ~] virsh edit test1.xml
需修改的 5 个核心参数:
- 虚拟机名称:
<name>vm01_centos79</name>→<name>test1_centos79</name> - UUID:
<uuid>xxx</uuid>→ 替换为新 UUID(执行uuidgen生成) - 磁盘路径:
<source file='xxx/vm01_centos79.qcow2'/>→<source file='xxx/test1_centos79.qcow2'/> - MAC 地址:
<mac address='52:54:00:xx:xx:xx'/>→ 修改后 3 段(避免网络冲突) - VNC 端口(若启用):
<graphics type='vnc' port='5900'/>→ 改为未占用端口(如 5901),或者-1
(4)定义并启动虚拟机
# 定义虚拟机(加载修改后的XML配置)
[root@sul qemu] virsh define /etc/libvirt/qemu/test1.xml
# 定义域 test1(从 /etc/libvirt/qemu/test1.xml)
# 查看虚拟机状态(已定义,处于关闭状态)
[root@sul qemu] virsh list --all
# Id 名称 状态
# ----------------------------------------------------
# - test1 关闭
# 启动虚拟机
[root@sul qemu] virsh start test1
# 域 test1 已开始
# 设置开机自启(可选)
[root@sul qemu] virsh autostart test1
# 域 test1标记为自动开始
[root@sul qemu]# virt-manager (5)批量部署虚拟机
基于差量镜像实现批量部署,脚本添加参数校验、日志输出和风险提示,避免误操作。
[root@sul qemu] cp -a /var/lib/libvirt/images/generic.qcow2 /opt/kvm/vm_base.qcow2
[root@sul qemu] mv /etc/libvirt/qemu/generic.xml /opt/kvm/vm_base.xml
[root@sul qemu]# ls /opt/kvm/
vm_base.qcow2 vm_base.xml[root@sul qemu]# vim /opt/kvm/vm_base.xml <name>vm_base</name><source file='/var/lib/libvirt/images/vm_base.qcow2'/>
#!/bin/bash
# 功能:批量部署基于差量镜像的KVM虚拟机
# 依赖:已准备基础镜像(vm_base.qcow2)和基础配置文件(vm_base.xml)
# 风险提示:执行前请备份现有虚拟机,脚本会删除所有已有虚拟机和磁盘文件# 定义基础路径(根据实际环境修改)
kvm_config_dir="/etc/libvirt/qemu"
kvm_image_dir="/var/lib/libvirt/images"
base_config="/opt/kvm/vm_base.xml"
base_image="/opt/kvm/vm_base.qcow2"# 校验基础文件是否存在
if [ ! -f "$base_config" ] || [ ! -f "$base_image" ]; thenecho "错误:基础配置文件或基础镜像不存在,请检查路径!"exit 1
fi# 风险提示与确认
echo "警告:此脚本会删除所有现有虚拟机和磁盘文件,是否继续?(y/n)"
read -r confirm
if [ "$confirm" != "y" ]; thenecho "脚本已取消执行。"exit 0
fi# 1. 清理现有虚拟机(强制关闭并删除定义)
echo "正在清理现有虚拟机..."
for vm_name in $(virsh list --all | awk 'NR>2 {print $2}'); dovirsh destroy "$vm_name" &> /dev/null # 强制关闭运行中的虚拟机virsh undefine "$vm_name" &> /dev/null # 删除虚拟机定义echo "已删除虚拟机:$vm_name"
done# 2. 清理现有磁盘文件
echo "正在清理现有磁盘文件..."
rm -rf "$kvm_image_dir"/*
echo "已清理磁盘目录:$kvm_image_dir"# 3. 批量创建虚拟机
read -p "请输入需部署的虚拟机数量:" number
# 校验输入是否为数字
if ! [[ "$number" =~ ^[0-9]+$ ]] || [ "$number" -le 0 ]; thenecho "错误:请输入有效的正整数!"exit 1
fiecho "开始批量部署$number台虚拟机..."
for i in $(seq "$number"); dovm_name="vm${i}_centos79"vm_config="$kvm_config_dir/${vm_name}.xml"vm_image="$kvm_image_dir/${vm_name}.qcow2"# 复制配置文件cp "$base_config" "$vm_config"# 创建差量镜像qemu-img create -f qcow2 -b "$base_image" "$vm_image" &> /dev/nullif [ $? -ne 0 ]; thenecho "警告:创建虚拟机$vm_name的差量镜像失败,跳过该虚拟机。"continuefi# 修改配置文件中的唯一标识sed -ri "s/vm_base/$vm_name/g" "$vm_config" # 替换虚拟机名称sed -ri "/<uuid>/c \ <uuid>$(uuidgen)</uuid>" "$vm_config" # 生成新UUID# 生成唯一MAC地址(52:54:00:xx:xx:xx格式)vm_mac="52:54:00:$(openssl rand -hex 3 | sed -r 's/(..)(..)(..)/\1:\2:\3/')"sed -ri "/<mac address=/c \ <mac address='$vm_mac'/>" "$vm_config" # 替换MAC地址# 定义虚拟机virsh define "$vm_config" &> /dev/nullif [ $? -eq 0 ]; thenecho "成功部署虚拟机:$vm_name(MAC:$vm_mac)"elseecho "警告:定义虚拟机$vm_name失败,跳过该虚拟机。"fi
doneecho "批量部署完成!可通过 virsh list --all 查看虚拟机状态。"
virsh list --all
[root@sul kvm] vim kvm_manager.sh
[root@sul kvm] bash kvm_manager.sh
# 警告:此脚本会删除所有现有虚拟机和磁盘文件,是否继续?(y/n)
# y
# 正在清理现有虚拟机...
# 已删除虚拟机:kvm_cenos_002
# 已删除虚拟机:test1
# 已删除虚拟机:generic
# 已删除虚拟机:generic-2
# 正在清理现有磁盘文件...
# 已清理磁盘目录:/var/lib/libvirt/images
# 请输入需部署的虚拟机数量:3
# 开始批量部署3台虚拟机...
# 成功部署虚拟机:vm1_centos79(MAC:52:54:00:7a:e6:89)
# 成功部署虚拟机:vm2_centos79(MAC:52:54:00:3a:d9:58)
# 成功部署虚拟机:vm3_centos79(MAC:52:54:00:b8:58:02)
# 批量部署完成!可通过 virsh list --all 查看虚拟机状态。
# Id 名称 状态
# ----------------------------------------------------
# - generic-2 关闭
# - vm1_centos79 关闭
# - vm2_centos79 关闭
# - vm3_centos79 关闭#注意:当虚拟机处于 “暂停”(virsh suspend)或 “保存状态”(virsh save)时,libvirt 会生成一个 .save 格式的状态文件,用于恢复虚拟机状态。此时直接执行 virsh undefine 会被阻止(防止误删导致状态丢失),必须先删除该状态文件才能彻底删除虚拟机配置。
[root@sul kvm] virsh undefine generic-2
错误:域管理的保存映像存在时拒绝取消定义# 查看是否存在保存的映像文件
[root@sul kvm]# ls -l /var/lib/libvirt/qemu/save/
# 总用量 381280-rw-------. 1 root root 390430528 10月 22 10:43 generic-2.save
[root@sul kvm] rm -rf /var/lib/libvirt/qemu/save/generic-2.save [root@sul kvm] systemctl restart libvirtd
[root@sul kvm] virsh undefine generic-2
# 域 generic-2 已经被取消定义[root@sul kvm] virsh list --all | awk 'NR>2 {print $2}'
# vm1_centos79
# vm2_centos79
# vm3_centos79





