KVM 虚拟机磁盘扩容

概述

在 KVM 环境中,通常通过创建一个各种格式的磁盘来安装虚拟机,可能创建时你觉得大小够用,但是可能用着用着到了某一天你发现你的磁盘容量不够用了,很多程序都打不开,你可能会很慌,其实并不需要慌,因为有很多方法可以给你的虚拟机扩容,哈哈哈,如:

  • 通过virsh attach-disk添加一个新的磁盘
  • 通过virsh attach-device添加一个新的存储设备
  • 直接给原来用的磁盘扩容

上面的三种方法都能实现给你的虚拟机扩容,但是本文想介绍的是第三种方法,直接给安装了虚拟机的磁盘来扩容,这样的好处是在你的主机上看来一个虚拟机就是一个磁盘,管理方便,而且只通过这一个磁盘来分享迁移你的虚拟机,也是更方便。

#创建虚拟机

  1. 创建磁盘

    1
    $ qemu-img create -f qcow2 centos.qcow2 50G

    这里创建了一个50G的磁盘,格式为qcow2,这种格式的特点是分配给虚拟机的实际使用的磁盘的大小是动态增长的,并不是一下子把所有的空间都给配给虚拟机,可以通过命令查看磁盘信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ qemu-img info centos.qcow2
    image: centos.qcow2
    file format: qcow2
    virtual size: 50G (53687091200 bytes)
    disk size: 1.2G
    cluster_size: 65536
    Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

    可以看到50G的磁盘目前的实际大小只有1.2个G。

  2. 安装虚拟机

    可以通过 virt-manager 通过图形界面安装,但是我一般都是通过远程连接服务器的,所以常用命令行安装虚拟机,命令如下:

    1
    2
    3
    4
    5
    6
    $ virt-install --virt-type kvm --name test-centos --ram 2048 --vcpus=1 \
    --cdrom CentOS-7-x86_64-Minimal-1804.iso \
    --disk path=test-centos.qcow2,format=qcow2 \
    --network network=default,model=virtio \
    --graphics vnc,listen=0.0.0.0 --noautoconsole \
    --os-type=linux

    系统安装的过程就不介绍了,但在安装系统的过程中,对于磁盘分区部分一般分两个区,根目录 / 和 交换分区 swap

  3. 查看虚拟机磁盘

    • 查看磁盘空间信息

      1
      2
      3
      4
      5
      6
      7
      8
      9
      $ df -lh
      Filesystem Size Used Avail Use% Mounted on
      /dev/sda2 46G 1.1G 45G 3% /
      devtmpfs 909M 0 909M 0% /dev
      tmpfs 920M 0 920M 0% /dev/shm
      tmpfs 920M 8.5M 911M 1% /run
      tmpfs 920M 0 920M 0% /sys/fs/cgroup
      tmpfs 184M 0 184M 0% /run/user/1000
      tmpfs 184M 0 184M 0% /run/user/0

      可以看到 /dev/sda2 被挂载到了系统根目录 /

    • 查看系统磁盘分区

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      # fdisk -l
      Disk /dev/sda: 53.7 GB, 53687091200 bytes, 104857600 sectors
      Units = sectors of 1 * 512 = 512 bytes
      Sector size (logical/physical): 512 bytes / 512 bytes
      I/O size (minimum/optimal): 512 bytes / 512 bytes
      Disk label type: dos
      Disk identifier: 0x00015299

      Device Boot Start End Blocks Id System
      /dev/sda1 2048 8390655 4194304 82 Linux swap / Solaris
      /dev/sda2 * 8390656 104857599 48233472 83 Linux

      我这里系统磁盘被成了两个区:/dev/sda1 和 /dev/sda2,就是我们前面说的一个用于交换分区,另一个用于挂载到根目录。

      注:磁盘分区信息中可以看到原来我们 50个G 的磁盘到这里怎么变成 53.7GB 了呢?其实只是单位不一样而已,前面我们用的是 GiB 为单位,这两个单位的计算方式不同,1 GiB = 1024*1024*1024 Bytes,而 1GB = 1000*1000*1000 Bytes

      到这里,假如我们发现磁盘空间不够用了,接下来就来看看如何给虚拟机的磁盘扩容吧。

磁盘扩容

  1. 首先将我们的虚拟机关机,然后进行磁盘扩容,在服务器主机上操作:

    1
    2
    # qemu-img resize centos.qcow2 60G
    Image resized.

    上面我们把磁盘大小扩成了 60G

  2. 重启虚拟机,在虚拟机内,使用 fdisk 指令对磁盘进行分区:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    # fdisk /dev/sda     #我们的整块磁盘是sda,对整个磁盘进行分区
    Command (m for help): p

    Disk /dev/sda: 64.4 GB, 64424509440 bytes, 125829120 sectors #磁盘大小变成64.4GB了,扩容成功
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk label type: dos
    Disk identifier: 0x00015299

    Device Boot Start End Blocks Id System
    /dev/sda1 2048 8390655 4194304 82 Linux swap / Solaris
    /dev/sda2 * 8390656 104857599 48233472 83 Linux #结束sector号小于磁盘的总数

    Command (m for help): n
    Partition type:
    p primary (2 primary, 0 extended, 2 free)
    e extended
    Select (default p): e #添加扩展分区
    Partition number (3,4, default 3): 3 #分区号,填写默认的3
    First sector (104857600-125829119, default 104857600): #直接回车选择默认
    Using default value 104857600
    Last sector, +sectors or +size{K,M,G} (104857600-125829119, default 125829119): #回车选择默认
    Using default value 125829119
    Partition 3 of type Extended and of size 10 GiB is set

    Command (m for help): p #再次查看分区表

    Disk /dev/sda: 64.4 GB, 64424509440 bytes, 125829120 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk label type: dos
    Disk identifier: 0x00015299

    Device Boot Start End Blocks Id System
    /dev/sda1 2048 8390655 4194304 82 Linux swap / Solaris
    /dev/sda2 * 8390656 104857599 48233472 83 Linux
    /dev/sda3 104857600 125829119 10485760 5 Extended #新添加的扩展分区

    Command (m for help): n #再添加逻辑分区,因为扩展分区是不能格式化后挂载的
    Partition type:
    p primary (2 primary, 1 extended, 1 free)
    l logical (numbered from 5)
    Select (default p): l #逻辑分区
    Adding logical partition 5
    First sector (104859648-125829119, default 104859648): #回车选择默认
    Using default value 104859648
    Last sector, +sectors or +size{K,M,G} (104859648-125829119, default 125829119): #回车选择默认
    Using default value 125829119
    Partition 5 of type Linux and of size 10 GiB is set

    Command (m for help): p

    Disk /dev/sda: 64.4 GB, 64424509440 bytes, 125829120 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk label type: dos
    Disk identifier: 0x00015299

    Device Boot Start End Blocks Id System
    /dev/sda1 2048 8390655 4194304 82 Linux swap / Solaris
    /dev/sda2 * 8390656 104857599 48233472 83 Linux
    /dev/sda3 104857600 125829119 10485760 5 Extended
    /dev/sda5 104859648 125829119 10484736 83 Linux #新添加的逻辑分区

    Command (m for help): w #保存分区配置,并退出
    The partition table has been altered!

    Calling ioctl() to re-read partition table.

    WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
    The kernel still uses the old table. The new table will be used at
    the next reboot or after you run partprobe(8) or kpartx(8)
    Syncing disks. #需要重启或者重新获取分区表
    #
  3. 重新获取分区表:

    1
    # partprobe
  4. 格式化分区:

    可以先查看一下其他分区是什么格式的文件系统:

    1
    2
    # mount |grep /dev/sda
    /dev/sda2 on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

    /dev/sda2xfs 格式的,CentOS 7默认文件系统格式是xfs,在CentOS 6以及之前的版本,使用的是ext文件系统格式,CentOS 6是ext4格式、CentOS 5是ext3格式。那我们也把 /dev/sda5 格式化成一样格式的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # mkfs -t xfs /dev/sda5     #-t 指定格式 
    meta-data=/dev/sda5 isize=512 agcount=4, agsize=655296 blks
    = sectsz=512 attr=2, projid32bit=1
    = crc=1 finobt=0, sparse=0
    data = bsize=4096 blocks=2621184, imaxpct=25
    = sunit=0 swidth=0 blks
    naming =version 2 bsize=4096 ascii-ci=0 ftype=1
    log =internal log bsize=4096 blocks=2560, version=2
    = sectsz=512 sunit=0 blks, lazy-count=1
    realtime =none extsz=4096 blocks=0, rtextents=0
  5. 挂载磁盘:

    1
    # mount /dev/sda5  /mnt/newdisk

    /dev/sda5 挂载到 /mnt/newdisk,需要注意的是,newdisk 最好是一个空文件夹,不然挂载之后文件夹内的文件将会暂时隐藏,直到你卸载到磁盘后才能恢复。

  6. 查看磁盘空间信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # df -lh
    Filesystem Size Used Avail Use% Mounted on
    /dev/sda2 46G 1.1G 45G 3% /
    devtmpfs 909M 0 909M 0% /dev
    tmpfs 920M 0 920M 0% /dev/shm
    tmpfs 920M 8.5M 911M 1% /run
    tmpfs 920M 0 920M 0% /sys/fs/cgroup
    tmpfs 184M 0 184M 0% /run/user/1000
    /dev/sda5 10G 33M 10G 1% /mnt/newdisk

    到这里就基本上结束了,你的磁盘又多了 10个G 的容量,可以正常读写磁盘啦。

命令附录

这里先介绍几个会用到的关于Linux磁盘操作指令:

  1. df 指令:磁盘信息命令

    • 语法:

      1
      $ df [OPTION]... [FILE]...
    • 功能说明:

      使用 df 指令查看磁盘空间的信息。指令可以查看指定文件系统的占用情况。如果指令中未指定文件名,将显示当前所有挂载的文件系统的可用空间。

    • 参数说明:

      参数 说明
      -a 显示包括0区块在内的所有文件系统的情况
      -h 以可读性较高的方式显示信息
      -H 相当于“-h”但在计算时,1K=1000,而不是1024
      -i 显示 inode 节点信息
      -k 区块大小为1024字节
      -l 尽显示本地文件系统
      –no-sync 取得磁盘信息前,忽略 sync 指令
      -P 输出 POSIX 格式
      –sync 在取得磁盘信息前,先执行 sync 指令
      -T 显示文件系统类型
      –block-size= 指定区块大小
      -t filesystem-type 只显示选定文件系统的磁盘信息
      -x filesystem-type 不显示选定文件系统的磁盘信息
      –help 帮助信息
      –version 版本信息
    • 常用命令:$ df -lh

  2. fdisk 指令:Linux磁盘分区命令

    • 语法:

      1
      2
      3
      fdisk [options] <disk>    change partition table
      fdisk [options] -l <disk> list partition table(s)
      fdisk -s <partition> give partition size(s) in blocks
    • 功能说明:

      fdisk 指令是Linux下管理分区的程序。应用该程序不仅可以创建磁盘分区,还可以对磁盘进行维护,改变分区类型。

    • 参数说明:

      参数 说明
      -b 指定各分区大小
      -l 列出分区表情况
      -s 输出指定分区大小到标准输出设备
      -u 与“-l”参数搭配,显示分区数目
      -v 版本信息

      【fdisk 程序指令】

      • a:设置/删除可引导分区标记
      • d:删除指定分区
      • l:列出分区类型
      • m:显示 fdisk 程序指令
      • n:新建分区
      • p:列出当前分区信息
      • q:退出 fdisk 分区,对更改不保存
      • t:改变分区 ID
      • v:检测当前分区信息
      • w:退出 fdisk 分区,保存更改

      注:不同的版本略差别

  3. mkfs 指令:建立各种文件系统

    • 语法:

      1
      # mkfs [options] [-t <type>] [fs-options] <device> [<size>]
    • 功能说明:

      mkfs 指令可用来在指定的设备上建立各种文件系统,它通过调用相关的程序来执行文件系统的构建,本身并不执行系统构建。

    • 参数说明:

      参数 说明
      -c 在创建文件系统之前,检查是否有损坏的区块
      fs 指定建立文件系统时的参数,针对不同的文件系统的参数不同
      -t 指定要创建的文件系统的类型,默认为ext2
      -v 显示详细的处理信息
      -V 版本信息
    • 常用命令

      1
      # mkfs -t ext3 /dev/sda3
  4. mount 指令:挂载文件系统

    • 语法:

      1
      # mount [options] <source> <directory>
    • 功能说明:

      使用 mount 指令可将指定设备挂载到已存在的目录。当文件系统挂载完成后,用户可通过该目录进行操作,来实现对指定设备的文件读写等操作。

    • 必要参数说明:

      参数 说明
      指定要挂载的设备
      指定要挂载的目录
    • 常用示例:

      1
      # mount /dev/sda3  /mnt