When managing a VM Guest on the VM Host Server itself, it is possible to access the complete file system of the VM Host Server in order to attach or create virtual hard disks or to attach existing images to the VM Guest.
However, this is not possible when managing VM Guests from a remote host. For this reason, libvirt
supports so called “Storage Pools” which can be accessed from remote machines.
libvirt
knows two different types of storage: volumes and pools.
- Storage Volume
A storage volume is a storage device that can be assigned to a guest - a virtual disk or a CD/DVD/floppy image. Physically (on the VM Host Server) it can be a block device (a partition, a logical volume, etc.) or a file.
- Storage Pool
Physically it can be one of the following types:
- A directory for hosting image files.0
- The files can be either one of the supported disk formats (raw, qcow2, or qed), or ISO images.
- Use a complete physical disk as storage.
- A partition is created for each volume that is added to the pool.
- Specify a partition to be used in the same way as a file system directory pool (a directory for hosting image files).
- The only difference to using a file system directory is the fact that
libvirt
takes care of mounting the device.
- Set up a pool on an iSCSI target.
- You need to have been logged into the volume once before, in order to use it with
libvirt
- Volume creation on iSCSI pools is not supported, instead each existing Logical Unit Number (LUN) represents a volume.
- Each volume/LUN also needs a valid (empty) partition table or disk label before you can use it.
- If missing, use fdisk to add it
fdisk -cu /dev/disk/by-path/ip-192.168.2.100:3260-iscsi-iqn.2010-10.com.example:[...]-lun-2
- Use a LVM volume group as a pool.
- You may either use a pre-defined volume group, or create a group by specifying the devices to use.
- Storage volumes are created as partitions on the volume.
- At the moment, multipathing support is limited to assigning existing devices to the guests.
- Volume creation or configuring multipathing from within
libvirt
is not supported.
- Specify a network directory to be used in the same way as a file system directory pool (a directory for hosting image files).
- The only difference to using a file system directory is the fact that
libvirt
takes care of mounting the directory. - Supported protocols are NFS and glusterfs.
- Use an SCSI host adapter in almost the same way a an iSCSI target.
- It is recommended to use a device name from
/dev/disk/by-*
rather than the simple/dev/sd
, since the latter may changeX
Managing Storage with virsh
create a storage pool
virsh pool-define directory_pool.xml
Directory Pool
<pool type="dir"> <name>virtimages</name> <target> <path>/var/lib/virt/images</path> </target> </pool>
Filesystem pool
This block device will be mounted and files managed in the directory of its mount point.
<pool type="fs"> <name>virtimages</name> <source> <device path="/dev/VolGroup00/VirtImages"/> </source> <target> <path>/var/lib/virt/images</path> </target> </pool>
Network filesystem pool
Instead of requiring a local block device as the source, it requires the name of a host and path of an exported directory. It will mount this network filesystem and manage files within the directory of its mount point.
<pool type="netfs"> <name>virtimages</name> <source> <host name="nfs.example.com"/> <dir path="/var/lib/virt/images"/> <format type='nfs'/> </source> <target> <path>/var/lib/virt/images</path> </target> </pool>
Logical volume pools
This provides a pool based on an LVM volume group. For a pre-defined LVM volume group, simply providing the group name is sufficient, while to build a new group requires providing a list of source devices to serve as physical volumes.
<pool type="logical"> <name>HostVG</name> <source> <device path="/dev/sda1"/> <device path="/dev/sdb1"/> <device path="/dev/sdc1"/> </source> <target> <path>/dev/HostVG</path> </target> </pool>
Disk volume pools
This provides a pool based on a physical disk. Volumes are created by adding partitions to the disk.
<pool type="disk"> <name>sda</name> <source> <device path='/dev/sda'/> </source> <target> <path>/dev</path> </target> </pool>
iSCSI volume pools
This provides a pool based on an iSCSI target. Volumes must be pre-allocated on the iSCSI server, and cannot be created via the libvirt APIs. Since /dev/XXX names may change each time libvirt logs into the iSCSI target, it is recommended to configure the pool to use /dev/disk/by-path
or /dev/disk/by-id
for the target path.
<pool type="iscsi"> <name>virtimages</name> <source> <host name="iscsi.example.com"/> <device path="demo-target"/> </source> <target> <path>/dev/disk/by-path</path> </target> </pool>
SCSI volume pools
This provides a pool based on a SCSI HBA. Volumes are preexisting SCSI LUNs, and cannot be created via the libvirt APIs. Since /dev/XXX names aren't generally stable, it is recommended to configure the pool to use /dev/disk/by-path
or /dev/disk/by-id
for the target path.
<pool type="scsi"> <name>virtimages</name> <source> <adapter name="host0"/> </source> <target> <path>/dev/disk/by-path</path> </target> </pool>
RBD pools
This storage driver provides a pool which contains all RBD images in a RADOS pool. RBD (RADOS Block Device) is part of the Ceph distributed storage project.
This backend only supports Qemu with RBD support. Kernel RBD which exposes RBD devices as block devices in /dev is not supported. RBD images created with this storage backend can be accessed through kernel RBD if configured manually, but this backend does not provide mapping for these images.
Images created with this backend can be attached to Qemu guests when Qemu is build with RBD support (Since Qemu 0.14.0).
<pool type="rbd"> <name>myrbdpool</name> <source> <name>rbdpool</name> <host name='1.2.3.4' port='6789'/> <host name='my.ceph.monitor' port='6789'/> <host name='third.ceph.monitor' port='6789'/> <auth username='admin' type='ceph'> <secret uuid='2ec115d7-3a88-3ceb-bc12-0ac909a6fd87'/> </auth> </source> </pool>
Listing Pools and Volumes
virsh pool-list –details
virsh pool-info POOL
virsh vol-list --details POOL
Starting, Stopping and Deleting Pools
virsh pool-destroy POOL
virsh pool-delete POOL
virsh pool-start POOL
Adding, Cloning, Deleting Volumes to a Storage Pool
virsh vol-create-as virtimages newimage 12G --format qcow2 --allocation 4G
vol-cloneNAME_EXISTING_VOLUME
NAME_NEW_VOLUME
--poolPOOL
virsh vol-deleteNAME
--poolPOOL
在libvirt上使用LVM存储设备
http://www.ibm.com/developerworks/cn/linux/l-cn-libvirt-lvm/
引言
libvirt 是一组可与 Linux 上多种虚拟机交互的管理工具集。它支持的虚拟机有 KVM/QEMU、Xen、LXC、OpenVZ、virtual Box、vmware ESX/GSX、Hyper-V 等。为了使虚拟机获得更强大的后端存储能力,libvirt 提供了对各种存储介质的支持,包括本地文件系统,网络文件系统,iSCSI,LVM 等多种后端存储系统。LVM(Linux 卷管理)系统是如今 Linux 服务器广泛使用的存储设备。本文阐述的方法适用于 KVM/QEMU 虚拟机,主要涉及在 libvirt 中使用 LVM 存储设备的方法,使用基于 libvirt 的命令行虚拟机管理工具 virsh。
libvirt 中的存储管理独立于虚拟机管理。也就是存储池和存储卷的操作独立于虚拟机的操作存在,因此进行存储管理时,不需要有虚拟机的存在,可以当虚拟机需要存储资源时再进行分配,非常灵活。
libvirt支持后端存储的类型
为了将不同的后端存储设备以统一的接口供虚拟机使用,libvirt 将存储管理分为两个方面:存储卷 (volume) 和存储池 (pool)。
存储卷是一种可以分配给虚拟机使用的存储设备。在虚拟机中与一个挂载点对应,而物理上可以是一个虚拟机磁盘文件或一个真实的磁盘分区。
存储池是一种可以从中生成存储卷的存储资源,后端可以支持以下存储介质:
- 目录池:以主机的一个目录作为存储池,这个目录中包含文件的类型可以为各种虚拟机磁盘文件、镜像文件等。
- 本地文件系统池:使用主机已经格式化好的块设备作为存储池,支持的文件系统类型包括 ext2,ext3,vfat 等。
- 网络文件系统池:使用远端网络文件系统服务器的导出目录作为存储池。默认为 NFS 网络文件系统。
- 逻辑卷池:使用已经创建好的 LVM 卷组,或者提供一系列生成卷组的源设备,libvirt 会在其上创建卷组,生成存储池。
- 磁盘卷池:使用磁盘作为存储池。
- iSCSI 卷池:使用 iSCSI 设备作为存储池。
- SCSI 卷池:使用 SCSI 设备作为存储池。
- 多路设备池:使用多路设备作为存储池。
Libvirt 中存储对象的状态转换
Libvirt 中的三类存储对象:存储池、存储卷、设备的状态转换关系如图 1 所示。
图 1.libvirt 中存储对象状态转换图
存储卷从存储池中划分出来,存储卷分配给虚拟机成为可用的存储设备。存储池在 libvirt 中分配的 id 标志着它成为 libvirt 可管理的对象,生成卷组 vg(volume group) 就有了可划分存储卷的存储池,状态为活跃 (active) 状态才可以执行划分存储卷的操作。
libvirt 使用逻辑卷池的准备
重新配置和编译
由于 libvirt 默认编译不支持 LVM,因此需要重新编译 libvirt 方可使用。使用 --with-storage-lvm 选项重新配置 libvirt 源码并重新编译 libvirt:
清单 1. 重新编译 libvirt
$./autogen.sh --with-storage-lvm – system $make
准备生成卷组的物理磁盘
在 host 中使用 fdisk 工具将物理卷格式化为 Linux LVM 格式(ID 为 8e)。生成的物理卷应为以下格式:
清单 2. 物理卷格式
$sudo fdisk -l /dev/sdc1 1 478 963616+ 8e Linux LVM /dev/sdc2 479 957 965664 8e Linux LVM
准备生成存储池的 xml 文件
将 xml 文件放在主机目录 /etc/libvirt/storage 下。以下给出 xml 文件的例子:
清单 3. 生成存储池的 xml 文件
<pool type="logical"> <name>lvm_pool</name> <source> <device path="/dev/sdc1"/> <device path="/dev/sdc2"/> </source> <target> <path>/lvm_pool</path> </target> </pool>
pool 的类型为 logical 表示使用的存储池类型为 LVM,源路径为在 host 中物理卷所在的路径,目的路径为 host 机中生成存储池的目标映射路径,后续生成的逻辑卷将在 host 的该目录下。
建立libvirt存储池
首次建立存储池
先由之前的 xml 文件定义一个存储池,若 libvirtd 启动之前 xml 文件已在 /etc/libvirt/storage 目录下,则 libvirtd 启动之后会自动定义存储池,可省去此步。
清单 4. 定义存储池
$virsh pool-define /etc/libvirt/storage/lvm_pool.xml
完成后就会在 libvirt 中定义一个不活跃的存储池,但这个池对应的卷组还未被初始化。可以看到生成的池状态为不活跃的:
清单 5. 查看卷组的状态
$virsh pool-list – all 名称 状态 自动开始 ----------------------------------------- default 活动 yes directory_pool 活动 yes lvm_pool 不活跃 no
建立存储池将生成存储池对应的卷组。
清单 6. 建立存储池
$virsh pool-build lvm_pool
此步完成后, host 上就生成了一个名为 lvm_pool 的卷组。
清单 7. 查看 host 上生成的卷组
$sudo vgdisplay --- Volume group --- VG Name lvm_pool System ID Format lvm2
以下命令在需要使用存储池时让存储池处于活跃状态
清单 8. 开始存储池
$virsh pool-start lvm_pool
创建存储池
创建存储池的操作相当于 pool-define 操作和 pool-start 操作的组合,也就是说,创建操作适用于卷组已经生成但还没有在 libvirt 中被管理起来的情况。
清单 9. 创建存储池
$virsh pool-create /etc/libvirt/storage/lvm_pool.xml
清单 10. 完成创建后的状态
$virsh pool-list 名称 状态 自动开始 ----------------------------------------- default 活动 yes directory_pool 活动 yes lvm_pool 活动 no
从存储池中分配卷
存储池为活跃的且已经生成了对应的卷组时,便可从存储池中划分逻辑卷供后续使用。
清单 11. 创建卷
$virsh vol-create-as --pool lvm_pool --name vol3 --capacity 30M
其中 --pool 指定分配逻辑卷所属存储池(卷组),name 指定逻辑卷名称,capacity 指定分配的卷大小。
清单 12. 查看存储池中的卷组
virsh # vol-list pic_pool2 名称 路径 ----------------------------------------- vol1 /dev/lvm_pool/vol1 vol2 /dev/lvm_pool2/vol2 vol3 /dev/lvm_pool2/vol3
在虚拟机中使用卷
清单 13. 将卷分配给虚拟机
$virsh attach-disk – domain dom1 – -source /dev/pic_pool2/vol1 – -target sda
其中 domain 选项指定逻辑卷要附加的虚拟机,source 选项指定逻辑卷在主机的路径,target 指定在虚拟机中的设备名。
这一步完成之后,重启虚拟机就可以在虚拟机中看到 /dev/sda 设备。在虚拟机中这个 /dev/sda 是一个裸设备,只需要进一步分区格式化就可以挂载使用了。
清单 14. 查看卷分配是否成功
$virsh domblklist dom1 Target Source ------------------------------------------------ vda /var/lib/libvirt/images/redhat2.img hdc - sda /dev/pic_pool2/vol3
清单 15. 将卷从虚拟机上分离
virsh # detach-disk – -domain dom1 --target sda
这时在虚拟机上就看不到 /dev/sda 设备了,逻辑卷已从虚拟机中成功分离。
删除存储池中的卷
卷被删除之后,卷所对应的存储空间即被归还到存储池内。
清单 16. 删除存储池中的卷
virsh # vol-delete vol3 --pool pic_pool2 卷vol3被删除
存储池的停用、删除和取消定义
停用存储池
存储池停止使用之后,它上面的所有存储卷的状态都变得不可用,即使用它的虚拟机都看不见这个设备。也不能从这个存储池中创建新卷。
清单 17. 停用存储池
virsh # pool-destroy pic_pool2 销毁池 pic_pool2
删除存储池
彻底删除一个存储池后,libvirt 就不再管理这个存储池所对应的所有资源,存储池在 host 机中对应的卷组也被删除。
清单 18. 删除存储池
virsh # pool-delete pic_pool2 池 pic_pool2 被删除
取消存储池定义
即使删除了存储池,它仍然在 libvirt 存储驱动中占有一定的资源,可以看到这个池。
清单 19. 删除存储池后的状态
$virsh pool-list – all 名称 状态 自动开始 ----------------------------------------- default 活动 yes directory_pool 活动 yes lvm_pool 不活跃 no
使用 pool-undefine 取消存储池的定义后,存储池所占用的资源完全被释放,存储驱动器中查看不到该存储池的存在了。
清单 20. 取消存储池定义
$virsh pool-undefine lvm_pool