KVM 高级功能部署

目录

一、案例分析

1.1、案例概述

1.2、案例前置知识点 

1)KVM 虚拟机迁移 

2)KSM 内核同页合并 

1.3、案例环境 

1)本案例环境 

2)案例需求 

3)案例实现思路 

二、案例实施 

2.1、静态迁移 

 1)在源宿主机上准备虚拟机

 2)提取磁盘和配置文件

3)配置和启动目标虚拟机 

2.2、基于共享存储的动态迁移 

1)配置 NFS 共享存储 

2)挂载 NFS 目录 

3)创建动态迁移的虚拟机 

4)动态迁移 

5)生成配置文件 

 6)验证迁移结果

2.3、基于数据块的动态迁移 

1)依赖包安装 

2) 迁移前准备工作

 3)检查资源池

4)创建同名磁盘文件 

5)执行迁移操作 

6)验证迁移结果 

2.4、KSM 

 1)KSM 服务介绍

2)配置 KSM 优化内存 


一、案例分析

1.1、案例概述

企业内部为了使服务器资源达到最大化利用,通常都会进行 KVM 虚拟化,每台服务器上运行多台 KVM 虚拟机。随着 KVM 虚拟机数量的不断增多,个别服务器会出现资源过载现象,这时候就需要对部分 KVM 虚拟机进行迁移,迁移到负载相对较低的服务器上。 

为了解决以上问题,针对可停机的 KVM 虚拟机,可使用静态迁移的方式来迁移 KVM 虚拟机。针对在线提供服务、不可停机的 KVM 虚拟机,可使用基于共享存储的动态迁移或基于数据块的动态迁移来完成迁移工作。最终按业务类型将虚拟机重新调配、合理布局,以保证服务器一直处于良好的运行状态。除了迁移之外,还可以在 KVM 宿主机上开启 KSM 内核同页合并,以达到节省内存、降低负载的目的。 

1.2、案例前置知识点 

1)KVM 虚拟机迁移 

KVM 虚拟机迁移,是将某一虚拟机上的环境和软件完全复制到另一台物理机上继续运行。KVM 虚拟机迁移可以优化系统负载、重新规划 KVM 虚拟机布局并简化 KVM 虚拟机的管理维护工作。 

KVM 虚拟机迁移的主要应用场景如下所示。

  • 当一台 KVM 宿主机的负载比较高时,可将源 KVM 宿主机上的部分虚拟机迁移到负载较低的 KVM 宿主机中,以保证服务质量。 
  • 通过 KVM 虚拟机迁移将多台负载较低的 KVM 宿主机上的 KVM 虚拟机集中迁移到某一 台 KVM 宿主机上,从而达到节约资源的目的。
  • 在升级 KVM 宿主机硬件设备时,可以将 KVM 宿主机上运行的 KVM 虚拟机迁移到其他 KVM 宿主机上,以解决对硬件的依赖,从而实现业务不中断情况下对物理硬件设备的升级。
  • 跨地域迁移,实现 KVM 虚拟机的远程迁移。

根据迁移方式的不同,可将迁移分为静态迁移(static magration)和动态迁移(live migration)。二者的区别是:静态迁移时会有一段时间虚拟机中的服务是不可用的,而动态迁移则没有明显的服务暂停时间。 

  • 静态迁移 

静态迁移需要先关闭要迁移的 KVM 虚拟机,并拷贝它的磁盘文件和配置文件到目标 KVM 宿主机,然后恢复启动,从而实现静态迁移。如果 KVM 虚拟机的磁盘文件存储在 KVM 宿主机本地,在静态迁移时需要拷贝磁盘文件和配置文件;如果 KVM 虚拟机的磁盘文件存储在共享存储上,在静态迁移时,只需要拷贝 KVM 虚拟机的配置文件,KVM 虚拟机的磁盘文件可通过挂载共享存储到本地目录的方式来获取。针对 KVM 虚拟机磁盘文件存储位置 的不同,在静态迁移时需要做适当的调整。 

  • 动态迁移

动态迁移是保证 KVM 虚拟机上运行的应用正常提供服务的同时,让 KVM 虚拟机在不同的 KVM 宿主机之间进行迁移。动态迁移的过程仅有非常短暂的停机时间,甚至可以忽略不计,同时 KVM 虚拟机上已经打开的应用连接不会断开,依然保持不变。KVM 的动态迁移有两种方式:一种是基于共享存储的动态迁移,另一种是基于数据块的动态迁移。 

基于共享存储的动态迁移:

基于共享存储的动态迁移是在 KVM 虚拟机迁移开始后,被迁移的 KVM 虚拟机依然保 持在源 KVM 宿主机上运行。与此同时,KVM 虚拟机的内存页被传输到目标 KVM 宿主机之 上。QEMU/KVM 会监控并记录迁移过程中所有已被传输的内存页的任何修改,并在所有内存页传输完成后再开始传输在前面传输过程中被更改的内存页内容。QEMU/KVM 也会评估迁移过程中的传输速度,当剩余的内存数据量能够在一个可设定的时间周期内完成传输, QEMU/KVM 将会关闭源宿主机上的 KVM 虚拟机,再将剩余的数据量传输到目标宿主机, 最后通过传输过来的内存内容在目标宿主机上恢复 KVM 虚拟机的运行状态。如此即可完成 KVM 基于共享存储的动态迁移。如果 KVM 虚拟机中内存使用量非常大且修改频繁,内存中数据被不断修改的速度大于 KVM 能够传输的内存速度,该情况下无法使用动态迁移, 只能使用静态迁移方法来进行 KVM 虚拟机迁移。

基于数据块的动态迁移:

如果对使用本地存储的 KVM 虚拟机进行在线迁移,就要用到基于数据块的动态迁移。 上述基于共享存储的动态迁移,为了实现动态迁移,源 KVM 宿主机和目标宿主机需要连接 共享存储服务,而基于数据块的动态迁移,共享存储不再是动态迁移的必要条件。在迁移过程中,KVM 虚拟机只使用本地存储,不再需要共享存储的支持,因此迁移环境比较简单, 迁移的源宿主机和目标宿主机只需要保持以太网连接即可。因为少了共享存储,所以降低了动态迁移的难度。

2)KSM 内核同页合并 

KSM(Kernel SamePage Merging)被称为内核同页合并。KSM 允许内核在两个或多个进程之间共享完全相同的内存页。KSM 让内核扫描正在运行中的程序并比较它们的内存,如果发现它们的内存区域或内存页是完全相同的,就将相同的内存合并为一个单一的内存页,并将其标识为“写时复制(copy-on-write)”,这样可以起到节省系统内存使用量的作用。如果有进程试图去修改被合并且被标识为“写时复制”的内存页,就为该进程复制出一个新的内存页供其使用。 

在 QEMU/KVM 中,一个 KVM 虚拟机就是一个 QEMU 进程,所以使用 KSM 也可以实现多个 KVM 虚拟机之间相同内存合并。如果在同一 KVM 宿主机上的多个 KVM 虚拟机运行的是相同的操作系统或应用程序,则 KVM 虚拟机之间的相同内存页数量就可能比较多, 这种情况下使用 KSM 的效果就会更加显著。在 KVM 环境下使用 KSM ,只有那些相同的内存页才是可以被共享合并的,并且 KSM 只会识别并合并那些不会干扰客户机运行、不会影响 KVM 宿主机或 KVM 虚拟机的安全内存页。因此,在 KVM 虚拟化环境中,KSM 能够提高内存的利用率。 

KSM 最初是为了在 KVM 虚拟化中使用而开发的,不过它对非虚拟化系统依然非常有 用。KSM 可以提高 KVM 宿主机中内存的使用效率,所以一般建议开启 KSM 功能。由于 KSM 必须有一个或多个进程去检测和找出完全相同且可以用于合并的内存页,所以 KSM 虽然能够让内存使用量降低,但是 KVM 宿主机中的 CPU 使用量会有一定程度的升高,因此可能会带来隐蔽的性能问题。在实际生产环境中使用 KSM 需要进行适当配置,以便达到较好的平衡。KSM 节省内存的效果与 KVM 虚拟机操作系统及 KVM 虚拟机中运行的应用程序有关,如果 KVM 虚拟机上的操作系统及其上运行的应用程序相同,节省内存的效果就会很显著,甚至有可能节省超过 50%的内存。反之,如果 KVM 虚拟机操作系统不同,且运行的应用程序也都大不相同,KSM 节省内存的效果就不明显,节省的内存甚至可能达不到 5%。 

在使用 KSM 时,为了防止内存过载,最好保证系统的交换分区(swap space)足够大。虽然 KSM 可以通过内存页合并而减少内存使用量,但是 KVM 虚拟机在运行过程中可能会修改 KSM 合并的内存页。修改这些内存页采用的方式是将这些内存页先复制出来,再进行修改,这样就会占用内存空间,因此可能会导致系统内存不足,这时就需要足够的交换空间来保证系统的正常运行。 

1.3、案例环境 

1)本案例环境 

本案例中使用三台服务器模拟 KVM 虚拟机迁移,具体的网络拓扑如下图所示。

 

 动态迁移

案例环境如下表所示:

主机操作系统IP 地址主要软件
kvm01CentOS 7.6 x86192.168.23.213Qemu-kvm、libvirt
kvm02CentOS 7.6 x86192.168.23.214Qemu-kvm、libvirt、qemu-kvm-ev
kvmnfsCentOS 7.6 x86192.168.23.215nfs-utils

2)案例需求 

  1. 通过静态迁移实现 KVM 虚拟机的迁移。
  2. 通过基于共享存储的动态迁移方式实现 KVM 虚拟机的迁移。
  3. 通过基于数据块的动态迁移方式实现 KVM 虚拟机的迁移。
  4. 实现 KSM 内存优化。 

3)案例实现思路 

  1. 通过拷贝磁盘文件和配置文件的方式实现静态迁移。
  2. 通过配置 NFS 共享服务,实现基于共享存储的动态迁移。
  3. 通过基于数据块的方式实现动态迁移。 
  4. 针对同类型 KVM 虚拟机和应用使用 KSM 来优化内存。

二、案例实施 

2.1、静态迁移 

使用源宿主机 kvm01 和目标宿主机 kvm02 来完成静态迁移。首先在源宿主机 kvm01 上创建虚拟机 test01,虚拟机 test01 的数据放在本地磁盘。然后将虚拟机 test01 从源宿主机 kvm01 迁移到目标宿主机 kvm02 上,并进行一些相应的配置。 

 1)在源宿主机上准备虚拟机

在源宿主机 kvm01 上进行迁移前的准备工作。 

[root@centos7-13 ~]# hostnamectl set-hostname kvm01
[root@centos7-13 ~]# bash
[root@kvm01 ~]# yum -y install qemu-kvm qemu-kvm-tools virt-install qemu-img bridge-utils libvirt
[root@kvm01 ~]# cat /proc/cpuinfo | grep vmx
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 arat umip pku ospke gfni vaes vpclmulqdq movdiri movdir64b md_clear spec_ctrl intel_stibp flush_l1d arch_capabilities
[root@kvm01 ~]# lsmod | grep kvm
kvm_intel             188740  0 
kvm                   637515  1 kvm_intel
irqbypass              13503  1 kvm
[root@kvm01 ~]# systemctl start libvirtd
[root@kvm01 ~]# systemctl enable libvirtd
[root@kvm01 ~]# cd /etc/sysconfig/network-scripts/
[root@kvm01 network-scripts]# cp ifcfg-ens32 ifcfg-br0
[root@kvm01 network-scripts]# vim  ifcfg-ens32
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="none"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
NAME="ens32"
UUID="eebf1a51-e1aa-482d-91c6-178818b3ecd8"
DEVICE="ens32"
ONBOOT="yes"
#IPADDR="192.168.23.213"
#PREFIX="24"
#GATEWAY="192.168.23.2"
#DNS1="202.96.128.86"
BRIDGE=br0
[root@kvm01 network-scripts]# vim ifcfg-br0
TYPE="Bridge"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="none"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
NAME="br0"
DEVICE="br0"
ONBOOT="yes"
IPADDR="192.168.23.213"
PREFIX="24"
GATEWAY="192.168.23.2"
DNS1="202.96.128.86"
[root@kvm01 network-scripts]# systemctl restart network
[root@kvm01 network-scripts]# ip add | grep br0
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 192.168.23.213/24 brd 192.168.23.255 scope global noprefixroute br0
[root@kvm01 ~]# fdisk /dev/sdb 
[root@kvm01 ~]# mkfs.xfs /dev/sdb1
[root@kvm01 ~]# mkdir /data
[root@kvm01 ~]# mount /dev/sdb1 /data
[root@kvm01 ~]# vim /etc/fstab
......//省略部分内容
/dev/sdb1 /data xfs defaults 0 0
[root@kvm01 ~]# cd /data/
[root@kvm01 data]# mkdir store iso
[root@kvm01 data]# ls
iso  store
[root@kvm01 ~]# ll -h /data/iso/  将镜像上传
总用量 4.5G
-rw-r--r-- 1 root root 4.5G 4月   9 11:02 CentOS-7-x86_64-DVD-2207-02.iso
  • 创建虚拟机 test01 

创建虚拟机 test01 的方法既可以参考之前章节使用 virt-manager 图形界面创建虚拟机,也可以在文本格式下使用 virt-install 命令来创建虚拟机。本章使用 virt-install 命令在源宿主机 kvm01 上面创建虚拟机 test01。在执行 virt-install 命令之前,需要提前准备 VNC Viewer 软件,其主要作用是在本地 Windows 上来连接 KVM 虚拟机,方便管理。VNC Viewer 软件如下图所示。 

 VNC Viewer 软件界面

单击上图中菜单栏的“File”,选择“New connection”,新建到虚拟机的连接。“VNC Server” 和“Name”填写宿主机的 IP 地址,如下图所示。其中,“5901”是执行 virt-install 安装命令时分配给对应虚拟机的端口,可以自己定义,通常都是以 5901 开始逐个递增。 

 创建 VNC 连接

单击“OK”确认之后,会生成对应的连接。如下图所示 

 VNC 连接生成

以上 VNC 的相关配置完成后,就可以通过文本方式创建 test01 虚拟机了。具体操作命令如下所示。 

[root@kvm01 ~]# virt-install -n test01 -r 1024 --vcpus=1 --disk path=/data/store/test01.qcow2,size=10 -w bridge:br0 --virt-type=kvm --accelerate --autostart -c /data/iso/CentOS-7-x86_64-DVD-2207-02.iso --vnc --vncport=5901 --vnclisten=0.0.0.0

virt-install 安装命令各选项的具体作用如下所示:

  1. -n:指定虚拟机的名字。
  2. -r:指定内存大小。
  3. --vcpu:指定虚拟 CPU 个数。
  4. --disk:指定磁盘文件放置位置及大小。
  5. -w:制定所使用的网桥。
  6. --autostart:设置虚拟机在宿主机开机时启动。
  7. -c:指定镜像文件。
  8. --vncport:通过 vnc viewer 连接的端口。
  9. --vnclisten:通过 vnc viewer 连接的 IP。 

上述命令执行后忽略如下所示报错信息,立刻双击打开上图中 VNC Viewer 创建的连接“192.168.23.213:5901”。 

WARNING  未检测到操作系统,虚拟机性能可能会受到影响。使用 --os-variant 选项指定操作系统以获得最佳性能。
WARNING  无法连接到图形控制台:没有安装 virt-viewer。请安装 'virt-viewer' 软件包。
WARNING  没有控制台用于启动客户机,默认为 --wait -1

开始安装......
正在分配 'test01.qcow2'                                                                                    |  10 GB  00:00:00     
ERROR    unsupported format character '奠(0xffffffe7) at index 47
域安装失败,您可以运行下列命令重启您的域:
'virsh start virsh --connect qemu:///system start test01'
否则请重新开始安装。

之所以会出现上述“WARNING”和“ERROR”信息,是因为宿主机的 CentOS 系统采用了文本方式安装,没有图形化界面。这种情况不影响虚拟机的正常使用,可使用 VNC Viewer 软件来开始 CentOS 系统的安装,如下图所示。

 test01 虚拟机安装界面

通过 VNC Viewer 安装 test01 虚拟机的具体过程这里省略,实际就是 CentOS 7.6 系统的安装过程,等虚拟机的操作系统安装完成后,test01 虚拟机就安装完成了 。

  •  配置虚拟机 test01 可通过 console 登录

如果在宿主机 kvm01 上想要实现通过 virsh console 命令连接到虚拟机 test01,需要在 test01 虚拟机上进行如下配置。 

 添加 ttyS0 终端

  • 标记虚拟机 test01 当前 IP 地址 
[root@kvm01 ~]# virsh console test01
连接到域 test01
换码符为 ^]  //输入 Enter 键


CentOS Linux 7 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64

test01 login: root
Password: 
Last login: Tue Apr  9 11:40:53 on tty1
[root@test01 ~]# ip add | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.23.142/24 brd 192.168.23.255 scope global noprefixroute dynamic ens3

从上述命令执行结果中可以得知,迁移前虚拟机 test01 的 IP 地址是 192.168.23.142。若想从虚拟机 test01 中退出,可以使用“Ctrl+]”组合键来实现。 

 2)提取磁盘和配置文件

在宿主机 kvm01 上,将虚拟机 test01 的磁盘文件和 xml 配置文件上传到目标宿主机 kvm02 上。 

  • 查看虚拟机 test01 当前状态 
[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 2     test01                         running
  • 关闭虚拟机 test01 
[root@kvm01 ~]# virsh shutdown test01
域 test01 被关闭

[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     test01                         关闭
  • 导出虚拟机 test01 的 xml 配置文件 
[root@kvm01 ~]# virsh dumpxml test01 > ~/test01.xml
[root@kvm01 ~]# ll
总用量 8
-rw-------. 1 root root 1769 3月  26 09:49 anaconda-ks.cfg
-rw-r--r--  1 root root 3408 4月   9 11:49 test01.xml
  • 定位虚拟机 test01 的磁盘文件 
[root@kvm01 ~]# virsh domblklist test01
目标     源
------------------------------------------------
hda        /data/store/test01.qcow2
hdb        -
  • 拷贝配置文件和磁盘文件到目标宿主机 kvm02 上 
[root@kvm01 ~]# scp test01.xml 192.168.23.214:/etc/libvirt/qemu/
The authenticity of host '192.168.23.214 (192.168.23.214)' can't be established.
ECDSA key fingerprint is SHA256:zOL41F94RnflLuQ0Nn2JjhdpUfPLQFnaw7WPJJ3XXgw.
ECDSA key fingerprint is MD5:3c:83:19:bf:6f:5e:92:c9:72:a1:6c:8d:b6:f4:70:d7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.23.214' (ECDSA) to the list of known hosts.
root@192.168.23.214's password: 
test01.xml                                                                                          100% 3408     1.5MB/s   00:00    
[root@kvm01 ~]# scp /data/store/test01.qcow2 192.168.23.214:/data/store/
root@192.168.23.214's password: 
test01.qcow2                                                                                        100%   10GB  60.4MB/s   02:49  

3)配置和启动目标虚拟机 

在目标宿主机 kvm02 上,对拷贝过来的虚拟机 test01 的数据进行重新定义,启动之后验证虚拟机 test01 的 IP 地址信息是否正确。 

  • 查看被迁移过来的配置文件和磁盘文件 
[root@kvm02 ~]# ls /etc/libvirt/qemu/
networks  test01.xml
[root@kvm02 ~]# ls /data/store/
test01.qcow2
  • 重新定义虚拟机 test01 
[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------

[root@kvm02 ~]# virsh define /etc/libvirt/qemu/test01.xml 
定义域 test01(从 /etc/libvirt/qemu/test01.xml)

[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     test01                         关闭
  • 启动虚拟机 test01 
[root@kvm02 ~]# virsh start test01
域 test01 已开始

[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 1     test01                         running
  • 连接虚拟机 test01 并验证 IP 地址信息 
[root@kvm02 ~]# virsh console test01
连接到域 test01
换码符为 ^]  //按 Enter 键进入 test01


CentOS Linux 7 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64

test01 login: root
Password: 
Last login: Tue Apr  9 11:44:11 on ttyS0
[root@test01 ~]# ip add | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.23.142/24 brd 192.168.23.255 scope global noprefixroute dynamic ens3

至此虚拟机 test01 已实现从源宿主机 kvm01 到目标宿主机 kvm02 的静态迁移。 

2.2、基于共享存储的动态迁移 

在 kvmnfs 服务器上部署 NFS 服务并创建共享目录实现共享存储。在源宿主机 kvm01 和目标宿主机 kvm02 上分别挂载共享目录。被迁移虚拟机的磁盘文件存储在共享目录内, 最终实现虚拟机从源宿主机 kvm01 迁移到目标宿主机 kvm02 上。 

1)配置 NFS 共享存储 

在 kvmnfs 服务器上面配置 NFS 服务实现共享存储。 

  • 在 kvmnfs 服务器上面安装 NFS 服务 
[root@kvmnfs ~]# yum -y install nfs-utils
  • 配置共享目录 

在 NFS 服务的配置文件 /etc/exports 中,配置共享目录及相应权限。设置 192.168.23.0/24 网段对/data 共享目录可读写、同步共享目录等权限。 

[root@kvmnfs ~]# mkdir /data
[root@kvmnfs ~]# vim /etc/exports
/data 192.168.23.0/24(rw,sync,no_root_squash)
  • 启动并查看 NFS 服务 
[root@kvmnfs ~]# systemctl enable nfs
[root@kvmnfs ~]# systemctl enable rpcbind
[root@kvmnfs ~]# systemctl start nfs
[root@kvmnfs ~]# systemctl start rpcbind
[root@kvmnfs ~]# showmount -e localhost
Export list for localhost:
/data 192.168.23.0/24

2)挂载 NFS 目录 

在 kvm01 和 kvm02 两台宿主机上,先创建本地数据目录,之后再分别挂载 NFS 目录, 并设置开机自动挂载。下面以宿主机 kvm01 为例进行操作演示。 

  • 源宿主机 kvm01 上查看 NFS 共享目录 
[root@kvm01 ~]# showmount -e 192.168.23.215
Export list for 192.168.23.215:
/data 192.168.23.0/24
  • 源宿主机 kvm01 上创建 kgc 目录 
[root@kvm01 ~]# mkdir /data/kgc
  • 源宿主机 kvm01 上挂载共享目录 
[root@kvm01 ~]# mount -t nfs 192.168.23.215:/data /data/kgc/
[root@kvm01 ~]# mount
......//省略部分内容
192.168.23.215:/data on /data/kgc type nfs4 (rw,relatime,vers=4.1,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.23.213,local_lock=none,addr=192.168.23.215)
  • 源宿主机 kvm01 上设置自动挂载 
[root@kvm01 ~]# vim /etc/fstab
......//省略部分内容
192.168.23.215:/data /data/kgc nfs defaults 0 0

3)创建动态迁移的虚拟机 

在源宿主机 kvm01 上,新建虚拟机 test02,用于测试基于共享存储的动态迁移。 

  • 创建虚拟机 test02 

创建虚拟机 test02,创建完后查看虚拟机 test02 当前状态。虚拟机 test02 的虚拟磁盘存放到了之前创建的共享目录/data/kgc 下。 

[root@kvm01 ~]# virt-install -n test02 -r 1024 --vcpus=1 --disk path=/data/kgc/test02.qcow2,size=10 -w bridge:br0 --virt-type=kvm --accelerate --autostart -c /data/iso/CentOS-7-x86_64-DVD-2207-02.iso --vnc --vncport=5902 --vnclisten=0.0.0.0
[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 4     test02                         running
 -     test01                         关闭

[root@kvm01 ~]# virsh domblklist test02
目标     源
------------------------------------------------
hda        /data/kgc/test02.qcow2
hdb        -
  • 登录虚拟机 test02 并查看 IP 地址 
[root@kvm01 ~]# virsh console test02
连接到域 test02
换码符为 ^]  //按 Enter 键进入 test02


CentOS Linux 7 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64

test02 login: root
Password: 
Last login: Tue Apr  9 14:34:02 on tty1
[root@test02 ~]# ip add | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.23.143/24 brd 192.168.23.255 scope global noprefixroute dynamic ens3

从上述命令执行结果可以得知,虚拟机 test02 的 IP 地址是 192.168.23.143 

4)动态迁移 

  • 查看 kvm01 和 kvm02 两台宿主机上虚拟机的运行状态 
[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 4     test02                         running  //kvm01 上 test02 运行
 -     test01                         关闭

[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     test01                         关闭  //kvm02 上无 test02
  •  在源宿主机 kvm01 上执行迁移命令

在开始执行迁移操作之前,首先在本地 Windows 机器上面 ping 虚拟机 test02 的 IP 地址,用于迁移过程中观察是否存在网络中断情况。具体的 ping 命令如下图所示。 

 下面开始执行迁移操作。

[root@kvm01 ~]# virsh migrate --live --verbose test02 qemu+ssh://192.168.23.214/system tcp://192.168.23.214
root@192.168.23.214's password: 
错误:不安全的迁移:Migration may lead to data corruption if disks use cache != none or cache != directsync

如果迁移命令在执行时出现上述错误,根据提示修改虚拟机 test02 的配置文件,加入标注为红色的字体部分,具体方法如下。 

[root@kvm01 ~]# virsh shutdown test02
域 test02 被关闭

[root@kvm01 ~]# virsh edit test02
......//省略部分内容
     33   <devices>
     34     <emulator>/usr/libexec/qemu-kvm</emulator>
     35     <disk type='file' device='disk'>
     36       <driver name='qemu' type='qcow2' cache="none"/>  //在36行添加 cache="none"
     37       <source file='/data/kgc/test02.qcow2'/>
     38       <target dev='hda' bus='ide'/>
     39       <address type='drive' controller='0' bus='0' target='0' unit='0'/>
     40     </disk>
......//省略部分内容
[root@kvm01 ~]# virsh start test02
域 test02 已开始

[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 5     test02                         running
 -     test01                         关闭

[root@kvm01 ~]# virsh migrate --live --verbose test02 qemu+ssh://192.168.23.214/system tcp://192.168.23.214
root@192.168.23.214's password: 
迁移: [100 %]
  • 查看迁移过程是否中断 

从下图中可以看到,在迁移过程中并未中断

 迁移过程网络 ping 值

  • 查看迁移后虚拟机的状态 
[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     test01                         关闭
 -     test02                         关闭

[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 2     test02                         running
 -     test01                         关闭

迁移之后源宿主机 kvm01 上虚拟机 test02 被关闭,目标宿主机 kvm02 上虚拟机 test02 处于启动状态。 

5)生成配置文件 

完成上述操作之后,基于共享存储的动态迁移已经实现了虚拟机 test02 从源宿主机kvm01 转移到目标宿主机 kvm02 上,但是其配置文件并没有一起迁移过来,此时还需要根据当前运行的虚拟机test02 生成对应的配置文件,并重新定义。 

  • 创建虚拟机 test02 配置文件 
[root@kvm02 ~]# ls -l /etc/libvirt/qemu/
总用量 4
drwx------ 3 root root   42 4月   9 11:46 networks
-rw------- 1 root root 3631 4月   9 11:56 test01.xml
[root@kvm02 ~]# virsh dumpxml test02 > /etc/libvirt/qemu/test02.xml
[root@kvm02 ~]# ls -l /etc/libvirt/qemu/
总用量 12
drwx------ 3 root root   42 4月   9 11:46 networks
-rw------- 1 root root 3631 4月   9 11:56 test01.xml
-rw-r--r-- 1 root root 4391 4月   9 14:56 test02.xml
  • 定义虚拟机 test02 配置文件 
[root@kvm02 ~]# virsh define /etc/libvirt/qemu/test02.xml 
定义域 test02(从 /etc/libvirt/qemu/test02.xml)

 6)验证迁移结果

查看虚拟机 test02 的 IP 地址,验证迁移是否成功。 

[root@kvm02 ~]# virsh console test02
连接到域 test02
换码符为 ^]  //按 Enter 键进入 test02


CentOS Linux 7 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64

test02 login: root
Password: 
Last login: Tue Apr  9 14:51:09 on tty1
[root@test02 ~]# ip add | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.23.143/24 brd 192.168.23.255 scope global noprefixroute dynamic ens3

至此,KVM 基于共享存储的动态迁移已经完成。 

2.3、基于数据块的动态迁移 

要实现基于数据块的动态迁移,首先要安装 qemu-kvm-ev。并且在目标宿主机上提前生成同名的空白磁盘文件,最后再通过数据块进行动态迁移。 

1)依赖包安装 

CentOS 7 默认安装的 qemu-kvm 包是不支持数据块动态迁移的,需要单独安装 qemu-kvm-ev。在 kvm01 和 kvm02 两台宿主机中都需要安装 qemu-kvm-ev。下面以源宿主机 kvm01 为例进行 qemu-kvm-ev 的安装操作演示。 

[root@kvm01 ~]# yum -y install centos-release-qemu-ev
[root@kvm01 ~]# yum -y install qemu-kvm-ev

2) 迁移前准备工作

  • 源宿主机 kvm01 上的准备 
[root@kvm01 ~]# tail -2 /etc/hosts
192.168.23.213 kvm01
192.168.23.214 kvm02
[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     test01                         关闭
 -     test02                         关闭

[root@kvm01 ~]# virsh start test01
域 test01 已开始

[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 6     test01                         running
 -     test02                         关闭
  • 目标宿主机 kvm02 上的准备 
[root@kvm02 ~]# tail -2 /etc/hosts
192.168.23.213 kvm01
192.168.23.214 kvm02
[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 2     test02                         running
 -     test01                         关闭

[root@kvm02 ~]# virsh undefine test01
域 test01 已经被取消定义

[root@kvm02 ~]# ls /data/store/
test01.qcow2
[root@kvm02 ~]# rm -rf /data/store/*
[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 2     test02                         running

 3)检查资源池

确保 kvm01 和 kvm02 两台宿主机拥有相同的资源池,若没有,则需创建。 

[root@kvm01 ~]# virsh pool-list --all
 名称               状态     自动开始
-------------------------------------------
 iso                  活动     是       
 kgc                  活动     是       
 store                活动     是

[root@kvm02 ~]# virsh pool-list --all
 名称               状态     自动开始
-------------------------------------------

创建 kvm02 资源池 

[root@kvm02 ~]# virsh pool-define-as --name iso --type dir --target /data/iso
定义池 iso

[root@kvm02 ~]# virsh pool-build iso
构建池 iso

[root@kvm02 ~]# virsh pool-autostart iso
池 iso 标记为自动启动

[root@kvm02 ~]# virsh pool-start iso
池 iso 已启动

[root@kvm02 ~]# virsh pool-define-as --name kgc --type dir --target /data/kgc
定义池 kgc

[root@kvm02 ~]# virsh pool-build kgc
构建池 kgc

[root@kvm02 ~]# virsh pool-autostart kgc
池 kgc 标记为自动启动

[root@kvm02 ~]# virsh pool-start kgc
池 kgc 已启动

[root@kvm02 ~]# virsh pool-define-as --name store --type dir --target /data/store
定义池 store

[root@kvm02 ~]# virsh pool-build store
构建池 store

[root@kvm02 ~]# virsh pool-autostart store
池 store 标记为自动启动

[root@kvm02 ~]# virsh pool-start store
池 store 已启动

[root@kvm02 ~]# virsh pool-list --all
 名称               状态     自动开始
-------------------------------------------
 iso                  活动     是       
 kgc                  活动     是       
 store                活动     是       

4)创建同名磁盘文件 

[root@kvm02 ~]# qemu-img create -f qcow2 /data/store/test01.qcow2 10G
Formatting '/data/store/test01.qcow2', fmt=qcow2 size=10737418240 cluster_size=65536 lazy_refcounts=off refcount_bits=16

5)执行迁移操作 

[root@kvm01 ~]# virsh migrate test01 qemu+ssh://192.168.23.214/system --live --persistent --undefinesource --copy-storage-all --verbose
root@192.168.23.214's password: 
迁移: [100 %]

6)验证迁移结果 

[root@kvm01 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     test02                         关闭  //kvm01 上 test01 已经被迁移

[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 2     test02                         running
 3     test01                         running  //kvm02 上 test01 处于开启状态

至此,基于数据块的动态迁移已经完成。 

2.4、KSM 

当前主流的操作系统大多都支持 KSM,因为 KSM 可以合并相同的内存页,减少虚拟机内存的使用量。这样有利于提高 CPU 的工作效率,加快数据缓存效率,同时可以节省更多的内存空间来缓存额外的磁盘数据。 

KSM 适用于宿主机过载的情况下。KSM 通过减少每个虚拟机实际占用的内存数,可以让多个虚拟机分配的内存数量之和大于物理内存数量。而对于相同类型的虚拟机,在物理内存量不变的情况下,可以在一个宿主机中创建更多虚拟机,从而提高虚拟化部署的密度,同时也可以提高物理资源的利用效率。 

 1)KSM 服务介绍

KSM 是在 Linux 2.6 内核版本中被添加进去的,目前大多数常用的、主流的 Linux 发行版都默认支持 KSM 技术,执行以下命令即可检查当前 Linux 系统是否支持 KSM。 

[root@kvm02 ~]# egrep -i ksm /boot/config-3.10.0-1160.71.1.el7.x86_64 
CONFIG_KSM=y  //结果为 y 表示支持

KSM 服务在 CentOS 7 内是以 ksmd 作为守护进程的,针对该服务的一些配置文件, 都在目录“/sys/kernel/mm/ksm”下。 

[root@kvm02 ~]# ls -l /sys/kernel/mm/ksm/
总用量 0
-r--r--r-- 1 root root 4096 4月   9 15:28 full_scans
-rw-r--r-- 1 root root 4096 4月   9 15:28 max_page_sharing
-rw-r--r-- 1 root root 4096 4月   9 15:28 merge_across_nodes
-r--r--r-- 1 root root 4096 4月   9 15:28 pages_shared
-r--r--r-- 1 root root 4096 4月   9 15:28 pages_sharing
-rw-r--r-- 1 root root 4096 4月   9 15:28 pages_to_scan
-r--r--r-- 1 root root 4096 4月   9 15:28 pages_unshared
-r--r--r-- 1 root root 4096 4月   9 15:28 pages_volatile
-rw-r--r-- 1 root root 4096 4月   9 15:28 run
-rw-r--r-- 1 root root 4096 4月   9 15:28 sleep_millisecs
-r--r--r-- 1 root root 4096 4月   9 15:28 stable_node_chains
-rw-r--r-- 1 root root 4096 4月   9 15:28 stable_node_chains_prune_millisecs
-r--r--r-- 1 root root 4096 4月   9 15:28 stable_node_dups

KSM 的常用配置的作用分别如下所示

  1. max_page_sharing:设置每个 KSM 页面允许的最大共享数量。这个配置设置了重复数据删除限制,以避免虚拟内存 rmap 列表变得太大。max_page_sharing 最小值为 2, 因为新创建的 KSM 页面至少有两个共享器。
  2. merge_across_nodes:指定是否可以合并来自不同 numa 节点的页面。当设置为 0 时, ksm 只合并物理页面并驻留在同一 numa 节点的内存区域中,可以降低访问共享页面 的延迟。
  3. pages_to_scan:在 KSM 进程休眠之前会去扫描的内存数量。
  4. run:控制 ksmd 进程是否运行,默认值为 0。要激活 ksm 必须设置其值为 1。如果 设置为 0,表示停止运行 ksmd, 但会保留已经合并的内存页;如果设置为 1,表示马 上运行 ksmd 进程;设置为 2 表示停止运行 ksmd,并分离已经合并的所有内存页, 但是保留已经注册为合并的内存区域给下一次使用。
  5. sleep_millisecs:设置 ksmd 进程休眠的时间(单位:毫秒),即为 ksmd 进程两次运 行之间的间隔。
  6. stable_node_chains_prune_millisecs: 在 stable_node“ 链 ” 中链接的整个stable_node“dups”列表被周期性地扫描,以删除陈旧的 stable_nodes。该参数的值用 于调节重复扫描的时间(单位:毫秒)。 

2)配置 KSM 优化内存 

在目标宿主机 kvm02 上,有 test01 和 test02 两台虚拟机。现在通过克隆的方式再创建两台新的虚拟机。然后开启这四台虚拟机,等四台虚拟机都启动后,观察内存使用情况。等内存使用量不再变化后,启动 KSM 服务,过 5 分钟,观察内存使用量的变化情况。 

  • 克隆虚拟机 
[root@kvm02 ~]# virt-clone -o test02 -n test03 -f /data/store/test03.qcow2 
WARNING  设置图形设备端口为自动端口,以避免相互冲突。
正在分配 'test03.qcow2'                                                                                    |  10 GB  00:00:57     

成功克隆 'test03'。
[root@kvm02 ~]# virt-clone -o test02 -n test04 -f /data/store/test04.qcow2 
WARNING  设置图形设备端口为自动端口,以避免相互冲突。
正在分配 'test04.qcow2'                                                                                    |  10 GB  00:00:56     

成功克隆 'test04'。
  • 启动4台虚拟机 
[root@kvm02 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 3     test01                         running
 4     test02                         running
 5     test03                         running
 6     test04                         running
  • 记录开启 KSM 之前内存使用情况 
[root@kvm02 ~]# free -m  //确保虚拟机都开启好后,内存不再变化
              total        used        free      shared  buff/cache   available
Mem:           7963        1547         137          11        6278        6127
Swap:          1023           1        1022
  •  启动 KSM 服务

在 CentOS 7 系统中,通过 ksm 和 ksmtuned 两个服务来动态调节 KSM 的运行情况, 要想保证两个服务的存在,需要 qemu-kvm-common 这个 RPM 包的支持。执行以下命令启动 ksm 和 ksmtuned 这两个服务。 

[root@kvm02 ~]# systemctl start ksm
[root@kvm02 ~]# systemctl start ksmtuned

当 ksm 服务启动后,需要检查/sys/kernel/mm/ksm/run 文件的值是否为 1,若为 0 则 KSM 功能不会生效,需要将其置为 1。 

[root@kvm02 ~]# echo 1 > /sys/kernel/mm/ksm/run

在 KSM 服务启动之后,KSM 能够最多共享系统物理内存一半的内存页。而 ksmtuned 服务一直保持循环执行,以调用 ksm 服务来运行。

  • 对比 KSM 开启之后的内存使用情况 
[root@kvm02 ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:           7963        1067         634          11        6262        6608
Swap:          1023           1        1022

对比 KSM 开启前后内存的使用情况,“used”从开始的 1547M 降到了 1067M,说明节约了系统内存。 

至此,KVM 虚拟机的各种迁移及 KSM 内存优化已经介绍完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/531620.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot+vue药店药品进销存采购管理系统0z10z

本系统采用intellij idea支持eclipse 项目架构&#xff1a;B/S架构web 开发语言&#xff1a;java 前端技术&#xff1a;vue.jsElementUi 后端框架&#xff1a;django、mybatis、Springmvc 运行环境&#xff1a;win10/win11、jdk1.8 可行性论证 社会可行性 开发本系统&#xff…

XC6206稳压芯片

mark 662k XC6206 的基本特性。这是一个 SOT23封装的 3.3V 稳压器。它输出最大工作电流为 100mA 最大特点便宜 参考链接 XC6206稳压芯片 (qq.com)https://mp.weixin.qq.com/s?__bizMzA5NjQyNjc2NQ&mid2452268489&idx1&sn90e920c596e3c2a382f81929c6313977&c…

Linux--进程的概念(一)

目录 一、冯诺依曼体系结构二、操作系统2.1 什么是操作系统2.2 操作系统的意义 三、进程3.1 进程的基本概念3.2 描述进程——PCB3.3 进程和程序的区别3.4 task_struct-PCB的一种3.5 task_struct的内容分类 四、如何查看进程4.1 通过系统文件查看进程4.2 通过ps指令查看进程 五、…

《公安机关互联网安全监督检查规定》系列之“解决方案”

随着中国互联网和信息网络飞速发展&#xff0c;无线网络普及到国内各个家庭和公共场所&#xff0c;成为人们日常办公和生活娱乐不可或缺的一部分。无线网络在创造商业价值、带来工作和生活便捷的同时&#xff0c;也同样让犯罪份子有了可乘之机&#xff0c;越来越多的网络违法活…

如何通过数据验证防止 Web API 攻击 - Web API 安全指南

充分的数据保护和用户保密是网页开发者的主要责任。因此&#xff0c;在构建 API 终端时&#xff0c;确保最高可能的安全性至关重要。 应用程序安全是客户端和服务器开发者共同的责任&#xff0c;一方的疏忽可能会造成灾难性后果。统计数据显示&#xff0c;2023 年的数据泄露导…

windows安装Redis,Mongo,ES并快速基本掌握开发流程

前言 这里只是一些安装后的基础操作&#xff0c;后期会学习更加深入的操作 基础操作 前言RedisRedis启动idea集成Redisjedis技术 Mongodbwindows版Mongodb的安装idea整合Mongodb ES(Elasticsearch)ESwindows下载ES文档操作idea整合ES低级别ES整合高级别ES整合 Redis Redis是…

HarmonyOS 开发-Grid和List内拖拽交换子组件位置

介绍 本示例分别通过onItemDrop()和onDrop()回调&#xff0c;实现子组件在Grid和List中的子组件位置交换。 效果图预览 使用说明&#xff1a; 拖拽Grid中子组件&#xff0c;到目标Grid子组件位置&#xff0c;进行两者位置互换。拖拽List中子组件&#xff0c;到目标List子组件…

【进阶六】Python实现SDVRPTW常见求解算法——自适应大邻域算法(ALNS)

基于python语言&#xff0c;采用经典自适应大邻域算法&#xff08;ALNS&#xff09;对 带硬时间窗的需求拆分车辆路径规划问题&#xff08;SDVRPTW&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整2.1 需求拆分2.2 需求拆分后的服务时长取值问题 3. 求解结果4…

CADMap3D2024 2023下载地址及安装教程

CAD Map 3D是由Autodesk开发的一款专业的地图制作和GIS&#xff08;地理信息系统&#xff09;软件。它是AutoCAD系列软件的一个扩展&#xff0c;提供了一系列特定于地理数据的工具和功能。 CAD Map 3D主要用于处理和管理与地理空间相关的数据&#xff0c;在地图制作、城市规划…

洗地机哪个品牌质量好?四大高口碑优质款式直入

如今&#xff0c;保持家居地面清洁整洁已成为生活中的重要任务。在这方面&#xff0c;洗地机作为一种高效的清洁工具备受青睐。然而&#xff0c;市场上的洗地机种类繁多&#xff0c;选择起来常常让人头疼。所以&#xff0c;哪个品牌的洗地机质量更好呢&#xff1f;以下是几款备…

Java 继承

1 继承 1.1 为什么需要继承 Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是 现实世界错综复杂&#xff0c;事物之间可能会存在一些关联&#xff0c;那在设计程序是就需要考虑 比如&…

论文笔记:面向实体的多模态对齐与融合网络假新闻检测

整理了2022TMM期刊 Entity-Oriented Multi-Modal Alignment and Fusion Network for Fake News Detection&#xff09;论文的阅读笔记 背景模型改进的动态路由算法Cross-Modal Fusion 实验 背景 现有的假新闻方法对多模态特征进行各种跨模态交互和融合&#xff0c;在检测常见假…

刷题之Leetcode203题(超级详细)

203.移除链表元素 力扣题目链接(opens new window)https://leetcode.cn/problems/remove-linked-list-elements/ 题意&#xff1a;删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] …

C++ stl容器vector的认识与简单使用

目录 前言&#xff1a; 本篇文档图片引用自&#xff1a;https://cplusplus.com/reference/vector/vector/ 1.vector的结构 2.迭代器类型 3.构造函数 4.迭代器 反向迭代器遍历 const迭代器 5.容量 maxsize shrink_to_fit reverse resize 6.修改 insert和erase 7.…

心跳机制原理学习

心跳机制 应用场景&#xff1a; 在长连接下&#xff0c;有可能很长一段时间都没有数据往来。理论上说&#xff0c;这个连接是一直保持连接的&#xff0c;但是实际情况中&#xff0c;如果中间节点出现什么故障是难以知道的。更要命的是&#xff0c;有的节点&#xff08;防火墙…

4月6号排序算法(2)

堆排序 讲堆排序之前我们需要了解几个定义 什么叫做最大堆&#xff0c;父亲节点&#xff0c;以及孩子节点 将根节点最大的堆叫做最大堆或大根堆&#xff0c;根节点最小的堆叫做最小堆或小根堆。 每个节点都是它的子树的根节点的父亲 。 反过来每个节点都是它父亲的孩子 。 …

Matplotlib实现数据可视化

Matplotlib是Python中应用较为广泛的绘图工具之一&#xff0c;首次发布于2007年。它在函数设计上参考了MATLAB&#xff0c;因此名字以"Mat"开头&#xff0c;中间的"plot"代表绘图功能&#xff0c;结尾的"lib"表示它是一个集合。Matplotlib支持众…

HarmonyOS实战开发-短时任务

介绍 本示例主要展示后台任务中的短时任务。 通过ohos.resourceschedule.backgroundTaskManager &#xff0c;ohos.app.ability.quickFixManager 等接口实现应用热更新的方式去展现短时任务机制。 效果预览 使用说明 1.安装本应用之前&#xff0c;先编译好未签名的应用包&a…

【MPI并行程序】完美解决Attempting to use an MPI routine before initializing MPI

文章目录 错误原因解决方案 最近在写并行程序&#xff0c;犯了一个小错误&#xff0c;记录一下&#xff0c;以防止以后再犯。 Attempting to use an MPI routine before initializing MPI&#xff08;在初始化 MPI 之前尝试使用 MPI 例程&#xff09; 错误原因 这个错误通常是因…

MySQL学习笔记2——基础操作

基础操作 一、增删改查1、添加数据2、删除数据3、修改数据4、查询语句 二、主键三、外键和连接1、外键2、连接 一、增删改查 1、添加数据 INSERT INTO 表名[(字段名[,字段名]…)] VALUES (值的列表); --[]表示里面的内容可选添加数据分为插入数据记录和插入查询结果 插入数据…