如何调整虚拟机磁盘的大小?


23

无论如何,是否有必要调整虚拟机磁盘的大小?假设将磁盘大小从32GB增加到64GB。我在Ubuntu服务器11.10 64位上运行KVM / Qemu。谢谢。

Answers:


27

在基于Debian的发行版上,您应该virt-resize改用。现在,它几乎可以处理所有事情。假设您的映像名为Win7(为什么不这样)。首先,请确保您的VM已关闭:

安装工具:

# apt-get install libguestfs-tools

获取您的VM磁盘的位置:

# virsh dumpxml Win7 | xpath -e /domain/devices/disk/source
Found 2 nodes in stdin:
-- NODE --
<source file="/var/lib/libvirt/images/Win7.img" />
-- NODE --
<source file="/var/lib/libvirt/images/Win7.iso" />

您可能需要进行/var/lib/libvirt/images/Win7.img以下调整:

# virt-filesystems --long --parts --blkdevs -h -a /var/lib/libvirt/images/Win7.img
Name       Type       MBR  Size  Parent
/dev/sda1  partition  07   100M  /dev/sda
/dev/sda2  partition  07   32G   /dev/sda
/dev/sda   device     -    32G   -

创建您的64G磁盘:

# truncate -s 64G /var/lib/libvirt/images/outdisk

您需要扩展/ dev / sda2(而不是启动分区):

# virt-resize --expand /dev/sda2 /var/lib/libvirt/images/Win7.img /var/lib/libvirt/images/outdisk
Examining /var/lib/libvirt/images/Win7.img ...
 100% [progress bar] --:--
**********

Summary of changes:

/dev/sda1: This partition will be left alone.

/dev/sda2: This partition will be resized from 32G to 64G.  The 
    filesystem ntfs on /dev/sda2 will be expanded using the 
    'ntfsresize' method.

**********
Setting up initial partition table on outdisk ...
Copying /dev/sda1 ...
Copying /dev/sda2 ...
 100% [progress bar] 00:00
 100% [progress bar] 00:00
Expanding /dev/sda2 using the 'ntfsresize' method ...

Resize operation completed with no errors.  Before deleting the old 
disk, carefully check that the resized disk boots and works correctly.

进行备份以防万一(mv如果不想备份,请使用):

# cp /var/lib/libvirt/images/Win7.img /var/lib/libvirt/images/Win7.img.old
# mv /var/lib/libvirt/images/outdisk /var/lib/libvirt/images/Win7.img

现在启动!

有关更多信息:man virt-resize


3
不必在最后一步中进行备份(如果映像很大,并且您不希望/不需要额外的磁盘空间),您可以做,virsh edit virt_name然后将磁盘源的路径更改为新磁盘。然后,如果它不起作用,则将其改回来再试一次。用2可以制作3张图像并没有多大意义
Mike

1
或者您可以简单地使用mv而不是cp作为第一个命令。除了节省磁盘空间外,这种方式还将大大加快速度。
凯文·基恩

6
要注意的一件事是,即使原始图像具有类型,目的地实例也将是raw类型。如果您想维护实例qcow2类型,则应应用如下转换:qemu-img convert -O qcow2 /var/lib/libvirt/images/outdisk /var/lib/libvirt/images/outdisk.qcow2
注销2015年

1
而且,virt-resize甚至还有一个可爱的ncurses进度微调器。
David McNeill

18

我建议您在执行任何操作之前,先完整复制磁盘映像,然后在所有中断时将其复制回来以重新开始。

您需要做三件事:

1)增大磁盘映像。在您的主机中:

qemu-img resize foo.qcow2 +32G

现在,您的来宾可以看到更大的磁盘,但是仍然具有旧的分区和文件系统。

2)扩大磁盘映像内的分区。为此,您需要在来宾中启动LiveCD,因为您将无法弄乱已挂载的分区。这是相当复杂的,可能是最危险的部分。这里要复制的内容很多,所以我现在只链接。您想做这样的事情:

http://www.howtoforge.com/linux_resizing_ext3_partitions_p2

或2b)如果您只想要更多的存储空间,则创建新分区会更简单(更安全)。使用fdisk或cfdisk或任何您喜欢的方式-现在您应该在来宾磁盘上看到一大堆未分配的空间。

3)最后,如果您调整了现有分区的大小,则使新的更大分区内的文件系统更大(无论如何,这实际上在上面链接的指南中)。在客人内部:

resize2fs /dev/sda1

感谢您及时回复。看起来是可行的解决方案。我要出外几天,但是下周回到办公室后,我会尝试一下并报告是否可行。
Tong Wang

1
另一个问题:如果要缩小磁盘,是否以相反的顺序执行步骤?像:1.缩小文件系统;2.缩小分区;3.缩小磁盘映像。对?
Tong Wang'2

是的,resize2fs可以缩小也可以增长,但是显然它将在文件系统中需要足够的可用空间。当缩小分区时,我会保留不必要的余量,以免您不小心将文件系统的末端砍掉了:)
Cesium 2012年

您绝对可以将已挂载的分区弄乱
以太太太(

4

我认为Caesium的答案很好,我只是想写下一些其他命令来实现相同的目的。

假设您有一个disk.img带有磁盘映像的文件,即该文件具有一个分区表和一个或多个分区,并说您想使最后一个分区更大。你要做的就是

1)增大整个文件,例如4GiB。一种快速的方法是使用dd

dd if=/dev/zero of=disk.img bs=1c seek=4G count=0

2)使用fdisk使分区更大(我希望我可以使用部分或更好的工具来完成此操作……有人吗?)

fdisk disk.img

键入p以打印出分区表并查找分区的起始扇区,例如,分区2从扇区106496开始。

您要做的是从分区表中删除该分区,并创建一个新分区,该分区从完全相同的扇区开始,而在下一个扇区结束。然后,分区将包含有效的文件系统。

输入d并给出要删除的分区号。(Gu!)

键入n并提供所需的分区号,然后输入起始扇区。您必须使用与以前相同的起始扇区。最后给出终端扇区,或者只是让fdisk选择可以使用的最高扇区。

键入w将更改写回到磁盘映像文件,然后退出fdisk。

3)现在您需要调整文件系统的大小。为此,您需要磁盘映像内文件系统的偏移量(=)。如果知道扇区大小(通常为512),则可以从扇区号中计算出该值,也可以使用parted

parted disk.img u b p

parted可以将命令用作命令行参数,因此这意味着“单位字节”和“打印”,因此它将打印分区表并将字节用作uint大小。)

这会打印出分区的开始和结束。假设您的分区始于54525952,然后使用制作一个回送阻止设备losetup

losetup -f --show -o 54525952 disk.img 

losetup例如,告诉您选择了哪个开发者/dev/loop0。现在您可以使用resize2fs

resize2fs /dev/loop0

最后移除回路装置

losetup -d /dev/loop0


-1
#include <stdio.h>

static unsigned long auxfilesize(FILE* fp) {

    unsigned long len=0;
    int c=0;


    while ( (c = fgetc(fp)) != -1 ) {
        len++;
    }

    return len;
}


static unsigned long aux_copyNBytesFromTo(FILE* from, FILE* to,
                                    unsigned long fromSize, 
                                    unsigned long bytes) {

    unsigned long iter = 0;
    while ( iter++ < fromSize ) {
        int c = fgetc(from);
        fputc(c, to);

    }
    iter-=1; 
    if ( fromSize < bytes ) {
        while ( iter++ < bytes ) {
            fputc(0, to);
        }
    }
    return iter;
}


int main(int argc, char **argv) {
    FILE *from = fopen(argv[1], "rb");
    FILE *to = fopen(argv[2], "wb" );
    unsigned long l = auxfilesize(from);

    rewind(from); 

    aux_copyNBytesFromTo(from, to, l, (l + l/2)) ;

    fclose(from);
    fclose(to);

}

这个简单的程序将N字节添加到虚拟映像的末尾。我使用Windows XP的Paragon分区映像来合并新创建的映像。在这里工作正常。


未使用的静态函数“ auxfilesize”,“ aux_copyNBytesFromTo”。为什么要提供帮助?
AB

没用过?我不明白这个问题。它们都被使用。
Ilian Zapryanov

结果是未分配的字节和操作系统的新硬盘。您必须格式化它。如果您要问为什么foo-s是静态的。它只是为我节省了原型,为什么不呢。这是一个简单的程序,用我的业余时间在2分钟内编写出来:)没什么特别的或最佳的。
Ilian Zapryanov

3
您可以使用现有的工具,例如ddtruncate...
rudimeier '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.