# 5. KVM 存储管理

2024年7月16日16分钟阅读

- FormalSciences/ComputerScience
- OperatingSystem/Virtualization
- KVM

## KVM 存储

### 存储概念

KVM（Kernel-based Virtual Machine）存储是指在 KVM 虚拟化环境中，为虚拟机提供的存储资源。KVM 支持多种存储类型，包括磁盘映像文件、逻辑卷管理（LVM）和网络存储。虚拟机的存储设备可以像物理机的硬盘一样使用，并且可以通过不同的存储格式和协议进行管理和访问。

### 虚拟机存储类型

#### 磁盘映像文件（qcow2, raw）

类型 | 特点 | 使用场景
--- | --- | ---
qcow2 (QEMU Copy On Write version 2) | 支持动态分配、快照、压缩和加密。磁盘空间在实际使用时才分配，可以节省存储空间。 | 适合需要多快照和动态存储分配的环境。
raw | 不支持快照、压缩和加密，直接映射磁盘数据。性能更高，适合需要最大化性能的场景。 | 适合高性能需求和简单存储管理的环境。

#### 其他常见磁盘映像文件类型

类型 | 特点 | 使用场景
--- | --- | ---
qcow (QEMU Copy On Write) | qcow2 的前身，支持动态分配和快照，但性能和功能不及 qcow2。 | 已有 qcow 格式的旧环境。
vmdk (Virtual Machine Disk) | 主要用于 VMware 虚拟机，可以兼容 KVM。支持多种虚拟磁盘格式和快照。 | 需要在 KVM 和 VMware 之间进行迁移的环境。
vdi (Virtual Disk Image) | 主要用于 Oracle VirtualBox 虚拟机，可以兼容 KVM。支持动态分配和快照。 | 需要在 KVM 和 VirtualBox 之间进行迁移的环境。
vhd/vhdx (Virtual Hard Disk) | 主要用于 Microsoft Hyper-V 虚拟机，可以兼容 KVM。vhdx 是 vhd 的改进版本，支持更大容量和更高性能。 | 需要在 KVM 和 Hyper-V 之间进行迁移的环境。

#### 逻辑卷管理（LVM）

逻辑卷管理（LVM）提供灵活的存储管理，可以动态调整逻辑卷大小、快照和卷组管理。性能较高，适合企业级应用和需要高性能、灵活存储管理的环境。

1. 创建物理卷和卷组：

       sudo pvcreate /dev/sdX
       sudo vgcreate vg_kvm /dev/sdX

2. 创建逻辑卷：

       sudo lvcreate -n lv_myvm -L 20G vg_kvm

#### 网络存储（NFS, iSCSI）

NFS（Network File System）通过网络共享文件系统，适合共享存储和集中存储管理，以及多台虚拟机需要共享同一存储资源的环境。

挂载 NFS 存储：

    sudo mount -t nfs server:/path/to/nfs /mnt/nfs

iSCSI（Internet Small Computer Systems Interface）：

通过网络提供块级存储，适合高性能需求的存储应用，以及需要集中管理和高性能存储访问的环境。

1. 安装 iSCSI 客户端：

    sudo apt install open-iscsi  # Ubuntu
    sudo yum install iscsi-initiator-utils  # CentOS/RHEL

1. 发现和登录 iSCSI 目标：

    sudo iscsiadm -m discovery -t sendtargets -p <iSCSI_server_IP>
    sudo iscsiadm -m node --login

### 配置系统存储支持

#### 确认存储驱动加载情况

1. 检查存储驱动：

   使用 `lsmod` 命令检查存储驱动是否加载：

       lsmod | grep -E 'virtio_blk|virtio_scsi'

2. 加载存储驱动：

   如果存储驱动未加载，可以手动加载：

       sudo modprobe virtio_blk
       sudo modprobe virtio_scsi

#### 准备存储设备和挂载点

1. 准备本地存储设备：

   分区和格式化存储设备：

       sudo fdisk /dev/sdX
       sudo mkfs.ext4 /dev/sdX1

   创建挂载点并挂载：

       sudo mkdir -p /mnt/kvm_storage
       sudo mount /dev/sdX1 /mnt/kvm_storage

2. 准备网络存储设备（NFS 例子）：

   安装 NFS 客户端：

       sudo apt install nfs-common  # Ubuntu
       sudo yum install nfs-utils  # CentOS/RHEL

   挂载 NFS 共享：

       sudo mkdir -p /mnt/nfs_storage
       sudo mount -t nfs server:/path/to/nfs /mnt/nfs_storage

3. 配置自动挂载：

   编辑 `/etc/fstab` 文件，添加以下内容确保重启后自动挂载：

       /dev/sdX1 /mnt/kvm_storage ext4 defaults 0 2
       server:/path/to/nfs /mnt/nfs_storage nfs defaults 0 0

通过以上步骤，可以为 KVM 环境配置各种存储支持，包括磁盘映像文件、LVM 和网络存储。确保存储驱动已加载，并准备好存储设备和挂载点，为虚拟机提供可靠的存储资源。

## 配置存储池

### 存储池是什么

#### 存储池的概念

存储池（Storage Pool）是 KVM 虚拟化环境中的一种抽象概念，用于管理和组织底层存储资源。存储池可以包含多个存储卷（Storage Volume），每个存储卷对应虚拟机的一个磁盘映像文件、逻辑卷或网络存储块。通过存储池，管理员可以更方便地管理和分配存储资源。

#### 存储池的类型

类型 | 特点 | 使用场景
--- | --- | ---
目录存储池 (Directory Storage Pool) | 使用本地或挂载的目录作为存储池。简单易用，适合中小型部署。 | 适合中小型部署。
逻辑卷存储池 (LVM Storage Pool) | 基于 LVM（Logical Volume Manager）创建和管理逻辑卷。提供灵活的卷管理和快照功能。 | 适合企业级部署。
网络存储池 (Network Storage Pool) | 使用网络存储协议（如 NFS、iSCSI）创建存储池。适合分布式存储和集中存储管理。 | 适合分布式存储和集中存储管理。

### 创建和管理目录存储池

#### 使用 `virsh` 创建目录存储池

1. 创建目录存储池：

   创建一个目录存储池的 XML 配置文件，例如 `dir-pool.xml`：

       <pool type='dir'>
         <name>dir-pool</name>
         <target>
           <path>/mnt/kvm_storage</path>
         </target>
       </pool>

2. 定义并启动存储池：

   使用 `virsh` 命令定义并启动目录存储池：

       sudo virsh pool-define dir-pool.xml
       sudo virsh pool-start dir-pool
       sudo virsh pool-autostart dir-pool

#### 配置目录存储池

1. 查看存储池信息：

       sudo virsh pool-info dir-pool

2. 查看存储池中的存储卷：

       sudo virsh vol-list dir-pool

3. 创建存储卷：

       sudo virsh vol-create-as dir-pool volume1 10G

### 创建和管理逻辑卷存储池

#### 使用 `virsh` 创建 LVM 存储池

1. 创建 LVM 存储池：

   创建一个 LVM 存储池的 XML 配置文件，例如 `lvm-pool.xml`：

       <pool type='logical'>
         <name>lvm-pool</name>
         <source>
           <device path='/dev/vg_kvm'/>
           <name>vg_kvm</name>
           <format type='lvm2'/>
         </source>
         <target>
           <path>/dev/vg_kvm</path>
         </target>
       </pool>

2. 定义并启动存储池：

   使用 `virsh` 命令定义并启动 LVM 存储池：

       sudo virsh pool-define lvm-pool.xml
       sudo virsh pool-start lvm-pool
       sudo virsh pool-autostart lvm-pool

#### 配置 LVM 存储池

1. 查看存储池信息：

       sudo virsh pool-info lvm-pool

2. 查看存储池中的存储卷：

       sudo virsh vol-list lvm-pool

3. 创建存储卷：

       sudo virsh vol-create-as lvm-pool lv_volume1 20G

### 创建和管理网络存储池

#### 使用 `virsh` 创建 NFS 存储池

1. 创建 NFS 存储池：

   创建一个 NFS 存储池的 XML 配置文件，例如 `nfs-pool.xml`：

       <pool type='netfs'>
         <name>nfs-pool</name>
         <source>
           <host name='nfs-server'/>
           <dir path='/path/to/nfs'/>
         </source>
         <target>
           <path>/mnt/nfs_storage</path>
         </target>
       </pool>

2. 定义并启动存储池：

   使用 `virsh` 命令定义并启动 NFS 存储池：

       sudo virsh pool-define nfs-pool.xml
       sudo virsh pool-start nfs-pool
       sudo virsh pool-autostart nfs-pool

#### 使用 `virsh` 创建 iSCSI 存储池

1. 创建 iSCSI 存储池：

   创建一个 iSCSI 存储池的 XML 配置文件，例如 `iscsi-pool.xml`：

       <pool type='iscsi'>
         <name>iscsi-pool</name>
         <source>
           <host name='iscsi-server'/>
           <device path='/dev/sdX'/>
         </source>
         <target>
           <path>/dev/disk/by-path/</path>
         </target>
       </pool>

2. 定义并启动存储池：

   使用 `virsh` 命令定义并启动 iSCSI 存储池：

       sudo virsh pool-define iscsi-pool.xml
       sudo virsh pool-start iscsi-pool
       sudo virsh pool-autostart iscsi-pool

#### 配置网络存储池

1. 查看存储池信息：

       sudo virsh pool-info nfs-pool
       sudo virsh pool-info iscsi-pool

2. 查看存储池中的存储卷：

       sudo virsh vol-list nfs-pool
       sudo virsh vol-list iscsi-pool

3. 创建存储卷：

       sudo virsh vol-create-as nfs-pool volume1 10G
       sudo virsh vol-create-as iscsi-pool volume2 20G

## 配置存储卷

### 存储卷的概念

**存储卷（Storage Volume）是存储池（Storage Pool）中的一个逻辑单元，类似于传统文件系统中的文件。**存储卷为虚拟机提供存储空间，用于存储操作系统、应用程序和数据。每个存储卷可以对应一个磁盘映像文件、逻辑卷或网络存储块。通过存储卷，管理员可以灵活管理和分配存储资源。

### 创建和管理磁盘映像文件

#### 使用 `virsh` 创建磁盘映像文件

1. 创建磁盘映像文件：

   使用 `virsh` 创建一个磁盘映像文件：

       sudo virsh vol-create-as dir-pool mydisk.qcow2 20G --format qcow2

   以上命令将在 `dir-pool` 存储池中创建一个名为 `mydisk.qcow2` 的磁盘映像文件，大小为 20GB，格式为 qcow2。

2. 查看磁盘映像文件信息：

   查看创建的磁盘映像文件信息：

       sudo virsh vol-info mydisk.qcow2 --pool dir-pool

#### 配置磁盘映像文件的大小和格式

1. 调整磁盘映像文件大小：

   可以使用 `qemu-img` 工具调整磁盘映像文件的大小：

       qemu-img resize /path/to/mydisk.qcow2 +10G

   以上命令将 `mydisk.qcow2` 的大小增加 10GB。

2. 转换磁盘映像文件格式：

   可以使用 `qemu-img` 工具转换磁盘映像文件的格式：

       qemu-img convert -f qcow2 -O raw /path/to/mydisk.qcow2 /path/to/mydisk.raw

   以上命令将 `mydisk.qcow2` 转换为 `mydisk.raw`，格式从 qcow2 转换为 raw。

### 创建和管理逻辑卷

#### 使用 `virsh` 创建逻辑卷

1. 创建逻辑卷：

   使用 `virsh` 创建一个逻辑卷：

       sudo virsh vol-create-as lvm-pool lv_mydisk 20G

   以上命令将在 `lvm-pool` 存储池中创建一个名为 `lv_mydisk` 的逻辑卷，大小为 20GB。

2. 查看逻辑卷信息：

   查看创建的逻辑卷信息：

       sudo virsh vol-info lv_mydisk --pool lvm-pool

#### 配置逻辑卷的大小和格式

1. 调整逻辑卷大小：

   可以使用 `lvresize` 工具调整逻辑卷的大小：

       sudo lvresize -L +10G /dev/vg_kvm/lv_mydisk

   以上命令将 `lv_mydisk` 的大小增加 10GB。

2. 格式化逻辑卷：

   在使用逻辑卷之前，需要对其进行格式化：

       sudo mkfs.ext4 /dev/vg_kvm/lv_mydisk

通过以上步骤，可以使用 `virsh` 创建和管理磁盘映像文件和逻辑卷，并灵活配置其大小和格式。这些存储卷为虚拟机提供了可靠和高效的存储解决方案。

## 虚拟机的存储配置

### 使用 `virsh` 添加和删除虚拟机磁盘

添加虚拟机磁盘

1. 创建一个新的磁盘映像文件（如果需要）：

       sudo qemu-img create -f qcow2 /var/lib/libvirt/images/mydisk.qcow2 20G

2. 使用 `virsh` 命令编辑虚拟机的 XML 配置文件：

       sudo virsh edit <vm_name>

3. 在 `<devices>` 部分中添加以下内容，指定新的磁盘设备：

       <disk type='file' device='disk'>
         <driver name='qemu' type='qcow2'/>
         <source file='/var/lib/libvirt/images/mydisk.qcow2'/>
         <target dev='vdb' bus='virtio'/>
         <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
       </disk>

4. 保存并退出编辑器，启动或重启虚拟机以使新磁盘生效：

       sudo virsh start <vm_name>

删除虚拟机磁盘

1. 使用 `virsh` 命令编辑虚拟机的 XML 配置文件：

       sudo virsh edit <vm_name>

2. 找到需要删除的 `<disk>` 节点，并将其删除：

       <disk type='file' device='disk'>
         <driver name='qemu' type='qcow2'/>
         <source file='/var/lib/libvirt/images/mydisk.qcow2'/>
         <target dev='vdb' bus='virtio'/>
         <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
       </disk>

3. 保存并退出编辑器，启动或重启虚拟机以应用更改：

       sudo virsh start <vm_name>

### `virsh` 配置虚拟机的启动磁盘

1. 使用 `virsh` 命令编辑虚拟机的 XML 配置文件：

       sudo virsh edit <vm_name>

2. 在 `<os>` 部分中，找到 `<boot dev='...'>` 节点并调整顺序。例如，将磁盘设备设为首选启动设备：

       <os>
         <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>
         <boot dev='hd'/>
         <boot dev='cdrom'/>
       </os>

3. 保存并退出编辑器，启动或重启虚拟机以应用更改：

       sudo virsh start <vm_name>

#### 配置虚拟机 BIOS 设置

1. 使用 `virsh` 命令编辑虚拟机的 XML 配置文件：

       sudo virsh edit <vm_name>

2. 在 `<os>` 部分中，添加或修改 `<bios>` 节点。例如，启用 BIOS 引导菜单：

       <os>
         <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>
         <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
         <nvram>/var/lib/libvirt/qemu/nvram/<vm_name>.fd</nvram>
         <bootmenu enable='yes'/>
       </os>

3. 保存并退出编辑器，启动或重启虚拟机以应用更改：

       sudo virsh start <vm_name>

## 高级存储管理

### 快照管理

#### 创建和管理磁盘快照

快照是虚拟机在某一时刻的状态，包括虚拟机的磁盘和内存状态。通过快照，您可以在需要时恢复虚拟机到之前的状态。

创建磁盘快照

使用 `virsh` 创建磁盘快照：

    sudo virsh snapshot-create-as <vm_name> <snapshot_name> --disk-only --atomic

以上命令创建一个仅包含磁盘状态的快照。

管理磁盘快照

使用 `virsh` 列出所有快照：

    sudo virsh snapshot-list <vm_name>

恢复快照

使用 `virsh` 恢复快照：

    sudo virsh snapshot-revert <vm_name> <snapshot_name>

#### 扩展存储池容量

扩展目录存储池

确保文件系统有足够的空间，然后直接添加更多存储卷到目录存储池即可。

扩展 LVM 存储池

1. 添加新的物理卷到卷组：

       sudo pvcreate /dev/sdX
       sudo vgextend vg_kvm /dev/sdX

2. 更新存储池配置：

       sudo virsh pool-refresh lvm-pool

扩展网络存储池

对于 NFS 和 iSCSI，直接在网络存储服务器上扩展存储容量，然后刷新存储池即可。

#### 缩减存储池容量

缩减 LVM 存储池

1. 移动逻辑卷中的数据到其他物理卷：

       sudo pvmove /dev/sdX

2. 移除物理卷并减少卷组大小：

       sudo vgreduce vg_kvm /dev/sdX
       sudo pvremove /dev/sdX

缩减目录存储池和网络存储池

一般不直接缩减这些存储池，建议清理不需要的存储卷以释放空间。

### 磁盘镜像和克隆

#### 创建磁盘镜像

创建磁盘镜像

使用 `qemu-img` 创建磁盘镜像：

    qemu-img create -f qcow2 /var/lib/libvirt/images/mydisk.qcow2 20G

转换磁盘镜像格式

使用 `qemu-img` 转换磁盘镜像格式：

    qemu-img convert -f qcow2 -O raw /path/to/mydisk.qcow2 /path/to/mydisk.raw

#### 克隆虚拟机磁盘

1. 使用 `qemu-img` 克隆磁盘映像：

       qemu-img create -f qcow2 -b /var/lib/libvirt/images/source-disk.qcow2 /var/lib/libvirt/images/clone-disk.qcow2

2. 使用 `virsh` 定义新的虚拟机，并指定克隆的磁盘映像：

   创建虚拟机 XML 文件：

       <domain type='kvm'>
         <name>clone-vm</name>
         <memory unit='KiB'>1048576</memory>
         <vcpu placement='static'>1</vcpu>
         <os>
           <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>
         </os>
         <devices>
           <disk type='file' device='disk'>
             <driver name='qemu' type='qcow2'/>
             <source file='/var/lib/libvirt/images/clone-disk.qcow2'/>
             <target dev='vda' bus='virtio'/>
             <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
           </disk>
         </devices>
       </domain>

3. 使用 `virsh` 定义并启动新的虚拟机：

       sudo virsh define /path/to/clone-vm.xml
       sudo virsh start clone-vm