3

kvm系列专题:克隆和快照

 2 years ago
source link: https://www.zsythink.net/archives/4247
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

kvm系列专题:克隆和快照

开启精彩搜索

在使用虚拟机时,”克隆”和”快照”都是比较常用的功能,今天就来聊聊怎样在KVM中使用它们。

先聊聊克隆,我通常的做法是,创建一个安装好系统和必要工具的虚拟机,将这个虚拟机当做模板,通过模板机克隆出新的虚拟机,这样做的好处是可以快速创建出同系统版本的虚拟机,而且免去了一些重复的必要配置,比如一些最小化安装时不包含的常用命令,或者一些密钥,都可以提前在模板机中配置好,克隆出的新机改一下IP地址,就可以直接使用了。

此处假设,kvm1是模板机,我们将会通过kvm1模板机克隆出新的主机。
注:我重新做了测试环境,之前的虚拟机删除了,重新建了kvm1,不影响我们测试

[root@cos7 qemu]# virsh list --all
Id Name State
----------------------------------------------------
2 kvm1 running
[root@cos7 qemu]# virsh list --all
 Id    Name                           State
----------------------------------------------------
 2     kvm1                           running
[root@cos7 qemu]# virsh list --all Id Name State ---------------------------------------------------- 2 kvm1 running

被克隆的主机不能处于running状态,只能是暂停或者停止状态,所以此处先把kvm1停止,然后通过virt-clone命令克隆kvm1模板,命令如下:

[root@cos7 qemu]# virsh shutdown kvm1
Domain kvm1 is being shutdown
[root@cos7 qemu]# virsh domstate kvm1
shut off
[root@cos7 qemu]# virt-clone --auto-clone -o kvm1 -n kvm2
WARNING The requested volume capacity will exceed the available pool space when the volume is fully allocated. (512000 M requested capacity > 186903 M available)
Allocating 'kvm2.qcow2' | 500 GB 00:00:04
Clone 'kvm2' created successfully.
[root@cos7 qemu]# virsh shutdown kvm1
Domain kvm1 is being shutdown

[root@cos7 qemu]# virsh domstate kvm1
shut off

[root@cos7 qemu]# virt-clone --auto-clone -o kvm1 -n kvm2
WARNING  The requested volume capacity will exceed the available pool space when the volume is fully allocated. (512000 M requested capacity > 186903 M available)
Allocating 'kvm2.qcow2'                                  | 500 GB  00:00:04     

Clone 'kvm2' created successfully.
[root@cos7 qemu]# virsh shutdown kvm1 Domain kvm1 is being shutdown [root@cos7 qemu]# virsh domstate kvm1 shut off [root@cos7 qemu]# virt-clone --auto-clone -o kvm1 -n kvm2 WARNING The requested volume capacity will exceed the available pool space when the volume is fully allocated. (512000 M requested capacity > 186903 M available) Allocating 'kvm2.qcow2' | 500 GB 00:00:04 Clone 'kvm2' created successfully.

如上所示,关闭kvm1虚拟机后,我们可以通过virsh domstate命令查看了kvm1虚拟机的状态,确认kvm1虚拟机关闭后,我们执行了virt-clone –auto-clone -o kvm1 -n kvm2命令,此命令表示通过kvm1虚拟机自动克隆出kvm2虚拟机,-o对应的虚拟机为克隆源,-n对应的虚拟机为新克隆出的虚拟机。
执行上述命令时,发出了一个WARNING告警,告警大概的意思是,当前存储池只有180G左右的大小(我的测试宿主机一共就200G空间),而虚拟机对应的磁盘最大可以到500G左右(当前虚拟机磁盘文件并不大,因为没有预分配所有空间,但是最大可以撑到500G),如果虚拟机的磁盘沾满,所需空间是超出存储池大小的,也就是说,虚拟机的磁盘指定最大值大于了宿主机的可用空间(500G > 180G),所以出现了上述警告,我们在做实验时,可能看不到这个警告,因为你的宿主机磁盘空间可能远远大于虚拟机磁盘文件的最大可占用值,所以并不会提示这个信息,不提示是正常的,不过,即使出现上述提示,也不影响我们做实验。

克隆完成后,可以看到kvm2虚拟机对应的配置文件以及磁盘镜像文件,如下:

[root@cos7 ~]# ls /etc/libvirt/qemu
kvm1.xml kvm2.xml networks
[root@cos7 ~]# ls /var/lib/libvirt/images/
kvm1.qcow2 kvm2.qcow2
[root@cos7 ~]# ls /etc/libvirt/qemu
kvm1.xml  kvm2.xml  networks
[root@cos7 ~]# ls /var/lib/libvirt/images/
kvm1.qcow2  kvm2.qcow2
[root@cos7 ~]# ls /etc/libvirt/qemu kvm1.xml kvm2.xml networks [root@cos7 ~]# ls /var/lib/libvirt/images/ kvm1.qcow2 kvm2.qcow2

如果对比kvm1和kvm2的配置文件,会发现uuid、mac地址的信息都是不同的。
启动kvm2以后,登录到kvm2中,会发现主机名,IP地址等信息仍然与kvm1相同,这是因为,克隆命令并不能修改虚拟机内部的信息(可以理解为克隆命令只能修改宿主机中能控制的虚拟硬件信息),我们可以登入虚拟机后手动修改,或者编写一个脚本来修改,修改完成后,即可当一个新的虚拟主机来使用了,我通常只修改主机名、root密码以及静态IP地址。

其实,如果想要修改新克隆出的机器中的内容,除了登录进去修改,还可以借助virt-sysprep或者guestfish命令,在不启动虚拟机的情况下修改虚拟机中的内容,使用virt-sysprep命令需要安装libguestfs-tools,而且需要注意,virt-sysprep命令会默认清除虚拟机中的一些信息,比如.ssh目录等,所以应该根据情况选择是否使用virt-sysprep命令,这些命令不是此处讨论的重点,我们继续向下聊。

除了“克隆”,“快照”也是非常实用的功能,在某个时间为一个虚拟机创建快照,可以快速的进行时间点还原,方便我们在虚拟机中进行一些测试。

虚拟机快照分为内部快照和外部快照,内部快照只支持qcow2格式,外部快照支持更多的格式的磁盘,内部快照的数据包含在虚拟机的磁盘镜像文件中,外部快照会单独使用一个磁盘镜像文件,除了内部快照和外部快照,也可以单独对磁盘创建快照,我们不考虑那么多,此处只演示内部快照的常用命令。

克隆虚拟机的命令非常简单,示例如下

[root@cos7 ~]# virsh snapshot-create kvm1
Domain snapshot 1636006069 created
[root@cos7 ~]#
[root@cos7 ~]# virsh snapshot-list kvm1
Name Creation Time State
------------------------------------------------------------
1636006069 2021-11-04 14:07:49 +0800 running
[root@cos7 ~]# virsh snapshot-create kvm1
Domain snapshot 1636006069 created
[root@cos7 ~]# 
[root@cos7 ~]# virsh snapshot-list kvm1
 Name                 Creation Time             State
------------------------------------------------------------
 1636006069           2021-11-04 14:07:49 +0800 running
[root@cos7 ~]# virsh snapshot-create kvm1 Domain snapshot 1636006069 created [root@cos7 ~]# [root@cos7 ~]# virsh snapshot-list kvm1 Name Creation Time State ------------------------------------------------------------ 1636006069 2021-11-04 14:07:49 +0800 running

使用virsh snapshot-create kvm1命令会为kvm1主机的当前状态创建一个快照,使用virsh snapshot-list kvm1可以查看kvm1虚拟机的快照列表,从上例的快照列表可以看出,virsh snapshot-create命令生成的快照的名字是一串时间戳数字,上例中的1636006069就是2021-11-04 14:07:49的Unix时间戳,如果想要在创建快照时,指定快照的名称,则需要使用virsh snapshot-create-as命令(多了-as),示例如下:

[root@cos7 ~]# virsh snapshot-create-as kvm1 snap2
Domain snapshot snap2 created
[root@cos7 ~]#
[root@cos7 ~]# virsh snapshot-list kvm1
Name Creation Time State
------------------------------------------------------------
1636006069 2021-11-04 14:07:49 +0800 running
snap2 2021-11-04 14:11:09 +0800 running
[root@cos7 ~]# virsh snapshot-create-as kvm1 snap2
Domain snapshot snap2 created
[root@cos7 ~]# 
[root@cos7 ~]# virsh snapshot-list kvm1
 Name                 Creation Time             State
------------------------------------------------------------
 1636006069           2021-11-04 14:07:49 +0800 running
 snap2                2021-11-04 14:11:09 +0800 running
[root@cos7 ~]# virsh snapshot-create-as kvm1 snap2 Domain snapshot snap2 created [root@cos7 ~]# [root@cos7 ~]# virsh snapshot-list kvm1 Name Creation Time State ------------------------------------------------------------ 1636006069 2021-11-04 14:07:49 +0800 running snap2 2021-11-04 14:11:09 +0800 running

上例表示为kvm1虚拟机创建一个名为snap2的快照,virsh snapshot-create-as命令还可以在创建快照时添加注释,比如在注释中描述这个快照的作用,命令如下,下例中的–domain参数用于指定虚拟机名称,–name参数用于指定快照名称,–description参数用于指定快照对应的描述信息。

[root@cos7 ~]# virsh snapshot-create-as --domain kvm1 --name snap3 --description 'test snapshot3'
Domain snapshot snap3 created
[root@cos7 ~]# virsh snapshot-create-as --domain kvm1 --name snap3 --description 'test snapshot3'
Domain snapshot snap3 created
[root@cos7 ~]# virsh snapshot-create-as --domain kvm1 --name snap3 --description 'test snapshot3' Domain snapshot snap3 created

创建完成包含注释的虚拟机后,再次查看快照列表,发现并不能看到对应的注释信息,如下:

[root@cos7 ~]# virsh snapshot-list kvm1
Name Creation Time State
------------------------------------------------------------
1636006069 2021-11-04 14:07:49 +0800 running
snap2 2021-11-04 14:11:09 +0800 running
snap3 2021-11-04 14:13:32 +0800 running
[root@cos7 ~]# virsh snapshot-list kvm1
 Name                 Creation Time             State
------------------------------------------------------------
 1636006069           2021-11-04 14:07:49 +0800 running
 snap2                2021-11-04 14:11:09 +0800 running
 snap3                2021-11-04 14:13:32 +0800 running
[root@cos7 ~]# virsh snapshot-list kvm1 Name Creation Time State ------------------------------------------------------------ 1636006069 2021-11-04 14:07:49 +0800 running snap2 2021-11-04 14:11:09 +0800 running snap3 2021-11-04 14:13:32 +0800 running

那么在哪里能够看到快照的注释信息呢?其实,我们可以直接查看快照对应的配置文件,在快照对应的配置文件中,会有相应的注释信息(如果有添加注释的话),以及其他关于快照状态的详细配置,没错,快照和虚拟机一样,都有对应的xml配置文件,快照配置文件的默认目录为/var/lib/libvirt/qemu/snapshot/,由于目前我们只为kvm1虚拟机创建了快照,所以在对应的目录中只能看到kvm1的快照配置文件,示例如下:

[root@cos7 ~]# ll /var/lib/libvirt/qemu/snapshot/
total 0
drwxr-xr-x 2 root root 62 Nov 4 14:13 kvm1
[root@cos7 ~]#
[root@cos7 ~]# ll /var/lib/libvirt/qemu/snapshot/kvm1
total 24
-rw------- 1 root root 6714 Nov 4 14:11 1636006069.xml
-rw------- 1 root root 6760 Nov 4 14:13 snap2.xml
-rw------- 1 root root 6799 Nov 4 14:13 snap3.xml
[root@cos7 ~]# ll /var/lib/libvirt/qemu/snapshot/
total 0
drwxr-xr-x 2 root root 62 Nov  4 14:13 kvm1
[root@cos7 ~]# 
[root@cos7 ~]# ll /var/lib/libvirt/qemu/snapshot/kvm1
total 24
-rw------- 1 root root 6714 Nov  4 14:11 1636006069.xml
-rw------- 1 root root 6760 Nov  4 14:13 snap2.xml
-rw------- 1 root root 6799 Nov  4 14:13 snap3.xml
[root@cos7 ~]# ll /var/lib/libvirt/qemu/snapshot/ total 0 drwxr-xr-x 2 root root 62 Nov 4 14:13 kvm1 [root@cos7 ~]# [root@cos7 ~]# ll /var/lib/libvirt/qemu/snapshot/kvm1 total 24 -rw------- 1 root root 6714 Nov 4 14:11 1636006069.xml -rw------- 1 root root 6760 Nov 4 14:13 snap2.xml -rw------- 1 root root 6799 Nov 4 14:13 snap3.xml

如果想要查看某个快照的配置文件中的内容,也没有必要进入/var/lib/libvirt/qemu/snapshot/目录中查看,只需要执行virsh snapshot-dumpxml命令即可,比如,我想要查看kvm1虚拟机的snap3快照的配置文件,只需要执行如下命令,snap3的配置文件内容就会被打印出来

virsh snapshot-dumpxml kvm1 snap3
virsh snapshot-dumpxml kvm1 snap3
virsh snapshot-dumpxml kvm1 snap3

执行上述命令后,在标签中,即可看到snap3的注释信息。

与虚拟机的配置文件一样,快照的配置文件也是自动生成的,不要直接修改这些文件,如果想要修改,则需要使用virsh snapshot-edit命令进行修改,上例中,第一个快照是通过virsh snapshot-create命令创建的,所以,快照名是以时间戳命名的,通过virsh snapshot-edit命令配合–rename参数可以达到修改快照名称的目的,但是注意,不要这样做!因为实际测试发现,通过virsh snapshot-edit命令修改快照名称后,快照无法使用,只能再次改回原名后才能够正常使用,而且修改完快照名称后,如果快照有子快照,会自动与子快照解除父子关系,快照的父子关系一会儿我们会看到,不过现在,我们要聊的重点是,不要修改快照的名称,因为,执行man virsh命令查看帮助,找到snapshot-edit章节,可以看到如下一段描述。
If –rename is specified, then the edits can change the snapshot name. If –clone is specified, then changing the snapshot name will create a clone of the snapshot metadata. If neither is specified, then the edits must not change the snapshot name. Note that changing a snapshot name must be done with care, since the contents of some snapshots, such as internal snapshots within a single qcow2 file, are accessible only from the original name.
上面这段话的重点是,如果虚拟机只有一个qcow2文件,当我们创建了内部快照后,只能通过原名称去访问,而测试中的虚拟机就是只有一个qcow2磁盘文件的虚拟机。

如果需要做快照的虚拟机有多个qcow2文件组成(不同的qcow2对应的不同的磁盘挂载),那么,在创建快照时,应该加上–atomic参数,以便保证创建快照操作的原子性,示例命令如下

virsh snapshot-create kvm1 --atomic
virsh snapshot-create-as kvm1 snap5 --atomic
virsh snapshot-create kvm1 --atomic
或者
virsh snapshot-create-as kvm1 snap5 --atomic
virsh snapshot-create kvm1 --atomic 或者 virsh snapshot-create-as kvm1 snap5 --atomic

在有多个qcow2磁盘的情况下,加上–atomic参数后,可以确保所有磁盘都创建快照成功,或者所有磁盘创建快照都不成功,而不会出现部分成功,部分不成功的情况。

目前,我们已经为kvm1创建了三个快照,先创建的1636006069快照,然后创建的snap2快照,最后创建的snap3快照,这三个快照是有父子关系的,我们可以通过–tree参数,查看快照间的关系,示例如下

[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
+- snap2
+- snap3
[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
  |
  +- snap2
      |
      +- snap3
[root@cos7 ~]# virsh snapshot-list kvm1 --tree 1636006069 | +- snap2 | +- snap3

从上例可以看出, 1636006069是snap2的父快照,snap2是snap3的父快照。
其实,我们也可以通过 virsh snapshot-info 命令,查看某个快照的概览信息,比如,查看1636006069快照的概览信息,如下

[root@cos7 ~]# virsh snapshot-info kvm1 1636006069
Name: 1636006069
Domain: kvm1
Current: no
State: running
Location: internal
Parent: -
Children: 1
Descendants: 2
Metadata: yes
[root@cos7 ~]# virsh snapshot-info kvm1 1636006069
Name:           1636006069
Domain:         kvm1
Current:        no
State:          running
Location:       internal
Parent:         -
Children:       1
Descendants:    2
Metadata:       yes
[root@cos7 ~]# virsh snapshot-info kvm1 1636006069 Name: 1636006069 Domain: kvm1 Current: no State: running Location: internal Parent: - Children: 1 Descendants: 2 Metadata: yes

如上所示,1636006069快照没有Parent,也就是说,它没有父快照,但是它有一个Children,也就是说,它有一个子快照,也就是snap2,对于1636006069来说,它有两个Descendants,也就是说,它有两个子孙,即子快照snap2和孙快照snap3,当我们查看snap2的快照概览信息时,可以发现,它的Parent的名字就是1636006069,如下

[root@cos7 ~]# virsh snapshot-info kvm1 snap2
Name: snap2
Domain: kvm1
Current: no
State: running
Location: internal
Parent: 1636006069
Children: 1
Descendants: 1
Metadata: yes
[root@cos7 ~]# virsh snapshot-info kvm1 snap2
Name:           snap2
Domain:         kvm1
Current:        no
State:          running
Location:       internal
Parent:         1636006069
Children:       1
Descendants:    1
Metadata:       yes
[root@cos7 ~]# virsh snapshot-info kvm1 snap2 Name: snap2 Domain: kvm1 Current: no State: running Location: internal Parent: 1636006069 Children: 1 Descendants: 1 Metadata: yes

除了通过snapshot-info查看快照的父快照,也可以通过snapshot-parent查看某个快照的父快照是谁,示例如下

[root@cos7 ~]# virsh snapshot-parent kvm1 snap3
snap2
[root@cos7 ~]# virsh snapshot-parent kvm1 snap3
snap2
[root@cos7 ~]# virsh snapshot-parent kvm1 snap3 snap2

假设,我们现在创建了很多快照,但是不知道目前虚拟机的状态距离哪个快照最近,我们可以使用virsh snapshot-current命令查看,虚拟机的状态在哪个快照状态之后,示例如下:
16360105350961.jpg
执行上述命令后,会打印出最近的快照的配置文件信息,如上图所示,当前kvm1主机的状态处于snap3快照之后,换句话说就是,kvm1主机当前的状态,是基于snap3快照的状态发展而来的,如果我们将kvm1恢复到snap2快照的状态,那么kvm1最近的快照将会变成snap2。
上例中,snap3快照的整个配置信息都打印了出来,如果不想查看这些信息,只想知道最近的快照名,可以加上–name参数,如下

[root@cos7 ~]# virsh snapshot-current kvm1 --name
snap3
[root@cos7 ~]# virsh snapshot-current kvm1 --name
snap3
[root@cos7 ~]# virsh snapshot-current kvm1 --name snap3

如果想要恢复到某个快照的状态,可以使用virsh snapshot-revert命令,如下

[root@cos7 ~]# virsh snapshot-revert kvm1 --snapshotname snap2
[root@cos7 ~]# virsh snapshot-revert kvm1 --snapshotname snap2
[root@cos7 ~]# virsh snapshot-revert kvm1 --snapshotname snap2

上述命令表示,将kvm1恢复到snap2快照的状态,恢复完成后,kvm1当前的状态离snap2快照的状态最近,如下

[root@cos7 ~]# virsh snapshot-current kvm1 --name
snap2
[root@cos7 ~]# virsh snapshot-current kvm1 --name
snap2
[root@cos7 ~]# virsh snapshot-current kvm1 --name snap2

如果想要恢复到最近的快照,也可以不指定快照名称,而是直接使用如下命令恢复到最近的快照。

[root@cos7 ~]# virsh snapshot-revert kvm1 --current
[root@cos7 ~]# virsh snapshot-revert kvm1 --current
[root@cos7 ~]# virsh snapshot-revert kvm1 --current

如果快照确定已经没有用了,可以删除对应的快照,使用virsh snapshot-delete命令删除快照,删除快照时,可以只删除指定的快照,也可以连同指定快照的后裔快照一起删除,或者只删除指定快照的后裔快照,为了方便示例,我又创建除了几个快照,目前所有快照的关系如下:

[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
+- snap2
+- snap3
+- snap4
+- snap5
+- snap6
+- snap7
+- snap8
[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
  |
  +- snap2
      |
      +- snap3
      +- snap4
          |
          +- snap5
              |
              +- snap6
                  |
                  +- snap7
                      |
                      +- snap8
[root@cos7 ~]# virsh snapshot-list kvm1 --tree 1636006069 | +- snap2 | +- snap3 +- snap4 | +- snap5 | +- snap6 | +- snap7 | +- snap8

由于我刚才把kvm1的状态恢复到了snap2,所以创建的snap4快照和snap3是平级的。
假设我只想要删除snap7快照,执行如下命令即可

[root@cos7 ~]# virsh snapshot-delete kvm1 snap7
Domain snapshot snap7 deleted
[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
+- snap2
+- snap3
+- snap4
+- snap5
+- snap6
+- snap8
[root@cos7 ~]# virsh snapshot-delete kvm1 snap7
Domain snapshot snap7 deleted

[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
  |
  +- snap2
      |
      +- snap3
      +- snap4
          |
          +- snap5
              |
              +- snap6
                  |
                  +- snap8
[root@cos7 ~]# virsh snapshot-delete kvm1 snap7 Domain snapshot snap7 deleted [root@cos7 ~]# virsh snapshot-list kvm1 --tree 1636006069 | +- snap2 | +- snap3 +- snap4 | +- snap5 | +- snap6 | +- snap8

如果我想要在删除snap6快照的同时,将其所有后裔快照一并删除,只需要加上–children参数即可,如下

[root@cos7 ~]# virsh snapshot-delete kvm1 snap6 --children
Domain snapshot snap6 deleted
[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
+- snap2
+- snap3
+- snap4
+- snap5
[root@cos7 ~]# virsh snapshot-delete kvm1 snap6 --children
Domain snapshot snap6 deleted

[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
  |
  +- snap2
      |
      +- snap3
      +- snap4
          |
          +- snap5        
[root@cos7 ~]# virsh snapshot-delete kvm1 snap6 --children Domain snapshot snap6 deleted [root@cos7 ~]# virsh snapshot-list kvm1 --tree 1636006069 | +- snap2 | +- snap3 +- snap4 | +- snap5

如果我只想要删除snap2的所有后裔快照,但是不想删除snap2快照本身,只需要加上–children-only参数即可,如下

[root@cos7 ~]# virsh snapshot-delete kvm1 snap2 --children-only
Domain snapshot snap2 children deleted
[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
+- snap2
[root@cos7 ~]# virsh snapshot-delete kvm1 snap2 --children-only
Domain snapshot snap2 children deleted

[root@cos7 ~]# virsh snapshot-list kvm1 --tree
1636006069
  |
  +- snap2
[root@cos7 ~]# virsh snapshot-delete kvm1 snap2 --children-only Domain snapshot snap2 children deleted [root@cos7 ~]# virsh snapshot-list kvm1 --tree 1636006069 | +- snap2

克隆和快照的常规操作就先聊到这里,以后有其他的咱们接着聊。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK