本文的所有设置环境都是基于上一篇文“KVM安装”里的一键安装脚本的环境,自行安装的KVM缺少某些组件可能会设置失败。

常用命令、常见操作

virsh list --all #查看虚拟机状态,确保已暂停或关机
virsh destroy [源主机名] #强制关闭虚拟机
virsh suspend [源主机名] #暂停虚拟机
virsh resume [源主机名] #恢复虚拟机(从暂停状态恢复)
virsh define [xml配置文件] #定义虚拟机

参考资料:http://www.cnblogs.com/lin1/p/5776280.html


忘记虚拟机的密码

重置虚拟机的密码(Linux)

确定可以执行命令:virt-edit
如果找不到命令,就安装libguestfs-tools
sudo yum install libguestfs-tools      # Fedora/RHEL/CentOS
sudo apt-get install libguestfs-tools  # Debian/Ubuntu

关闭虚拟机:virsh shutdown [虚拟机名称]

生成新的密码串
# openssl是一个加密工具,-1 是指普通加密,hello为key , 123456 才是密码
openssl passwd -1 -salt 'hello' '123456'

virt-edit -d [虚拟机名称] /etc/shadow
# 视kvm image大小情况而定,一般一两分钟就可以打开,
# 字段以:进行分割,第二项就行密码,对应账户的密码换成上面生成的;

保存退出,启动虚拟机,就可以用最新的密码登录了。

参考:https://blog.csdn.net/linzhaolover/article/details/52846091


迁移系统、压缩镜像

# 该操作耗时很长,但可以把500G的磁盘(时间使用200G左右)压缩到23G左右
qemu-img convert -c -O qcow2 centos7_kvm.img new-centos7_kvm.img

参考:https://www.bbsmax.com/A/D854WbYWJE/
https://blog.csdn.net/scucscheng/article/details/51799199

创建硬盘

qemu-img create -f qcow2 /root/web2_02.qcow2 100G
# 第一条命令会直接占用100G空间。
qemu-img create -f qcow2 -opreallocation=metadata  /root/web2_02.qcow2 100G
# 重要参数:-opreallocation=metadata 预分配磁盘,硬盘空间不会立即占用,注意:ext3不支持此参数,ext4支持。

参考:
http://www.cnblogs.com/bass6/p/5755131.html
http://www.sijitao.net/1768.html(qemu-img的各种作用)


安装虚拟机

# 最简便(自动连接上vnc,中断后要自己手动链接vnc)
virt-install --name ubuntu12 \
  --ram 4096 \
  --vnc --vncport=5910 \
  --disk path=/media/leo/data/Ubuntu12.04.5.img,size=40 \
  --network bridge=br0 \
  --cdrom /media/leo/data/ubuntu-12.04.5-desktop-amd64.iso \
  -d

# 以下两种都是在后台运行,需要手动连接vnc
# raw格式磁盘
virt-install --name=Ubuntu12 
	--ram 4096 \
	--vcpus=2 \
	--disk path=/media/leo/data/Ubuntu12.04.5.img,size=40,bus=virtio \
	--accelerate \
	--cdrom=/media/leo/data/ubuntu-12.04.5-desktop-amd64.iso \
	--vnc --vncport=5910 --vnclisten=0.0.0.0 \
	--network bridge=br0,model=virtio \
	--noautoconsole

# qcow2磁盘(qcoow2格式要先创建磁盘文件才可以安装)
qemu-img create -f /media/leo/data/Ubuntu12.04.5.img 40G
virt-install --name=Ubuntu12 
	--ram 4096 \
	--vcpus=2 \
	--disk path=/media/leo/data/Ubuntu12.04.5.img,format=qcow2,size=40,bus=virtio \
        --os-variant=Linux
	--accelerate \
	--cdrom=/media/leo/data/ubuntu-12.04.5-desktop-amd64.iso \
	--vnc --vncport=5910 --vnclisten=0.0.0.0 \
	--network bridge=br0,model=virtio \
	--noautoconsole

参数说明:
--name指定虚拟机名称
--ram分配内存大小。
--vcpus分配CPU核心数,最大与实体机CPU核心数相同
--disk指定虚拟机镜像,size指定分配大小单位为G。
--network网络类型,此处用的是默认,一般用的应该是bridge桥接。
--accelerate加速
--cdrom指定安装镜像iso
--vnc启用VNC远程管理,一般安装系统都要启用。
--vncport指定VNC监控端口,默认端口为5900,端口不能重复。
--vnclisten指定VNC绑定IP,默认绑定127.0.0.1,这里改为0.0.0.0。
--os-type=linux,windows
--os-variant=win7(系统类型,很多,不一一列出)


清理快照

适用于virsh snapshot命令删除,但适用qemu-img info依然能看到快照的情况(一般是硬盘空间为0,但是使用virsh snapshot命令去清楚导致清楚失败)

qemu-img info [qcow2文件路径]
qemu-img snapshot -d [快照名] [qcow2文件路径]

启动虚拟机报错:Image is corrupt; cannot be opened read/write

一般在磁盘没什么空间并使用qemu-img命令清除快照会出现磁盘错误问题。

# 检查修复磁盘错误
qemu-img check -r all /xxx/centos65_x86.qcow2 

启动虚拟机报错:error: the CPU is incompatible with host CPU

这是配置文件中CPU类型设置不对,改一下就行了

error: the CPU is incompatible with host CPU: Host CPU does not provide required features: hle, rtm, rdseed, adx, smap, 3dnowprefetch

如:

<cpu mode='custom' match='exact' check='partial'>
    <model fallback='allow'>Haswell-noTSX</model>
</cpu>

libvirt死锁

由于删除虚拟机快照意外中断等,导致再次操作虚拟机卡死的情况,可以尝试以下方法解决。

报错:
Error starting domain: Timed out during operation: cannot acquire state change lock
libvirtError: Timed out during operation: cannot acquire state change lock

解决:
virsh undefine [centos7]
systemctl restart libvirtd
virsh define [centos7]

依然不行可以尝试修改一下的domain的xml文件中的name标签,给虚拟机改个名字;再重新define一下;还是不行就按下一个错误处理,转换磁盘为raw格式。

参考:https://www.chenyudong.com/archives/libvirt-problem-and-resolution.html


删除快照后磁盘无法修复 & 导致libvirt死锁

使用qemu-img snapshot -dvirsh snapshot-delete命令删除快照后,出现启动失败,一般是磁盘文件被破坏了,使用qemu-img check -r修复一下就好了;但是有时会出现修复失败的情况,报错:File too large之类的;或者删除快照卡死,修复磁盘卡死等问题,一个比较好且省时间的方法就是转换磁盘格式。

# 一般用的qcow2是支持快照的,raw是不支持快照的;因快照冗余,或删除有残留等,无法修复。
# 可以转换为raw格式,就可以忽略掉快照部分。
qemu-img convert -f qcow2 diskimage.qcow2 -O raw diskimage.raw
# 注意用qemu-img看看磁盘大小,预留充足空间
# 然后改一下xml就行了。

解决kvm虚拟机windows系统间歇性网络中断的问题

现象:

  • 突然之间,网络完全中断,无法从网络访问虚拟机
  • 用virt-manager或者console登录虚拟机,发现虚拟机还在正常工作,没有崩溃
  • 使用 service network restart重启物理机网络服务,可以立即恢复网络
  • 网络负载越大,故障出现的频率越高。轻网络负载的机器,没有出现故障

几个解决办法:
第1种:使用 e1000替代原有的windows网卡(推荐)

第2种:使用 vhost_net 模块

echo vhost_net > /etc/modules
modprobe vhost_net
然后重新启动虚拟机,libvirtd就会自动使用 vhost_net

偶尔新建虚拟机win时会出现内网IP能互相ping通,且能ping通部分外网IP,如:8.8.8.8,但是就是无法外网,且无法通过内网IP访问本机服务;可能是KVM的问题,重启网络服务即可;故障无法复现

参考:https://blog.csdn.net/Z_YTTT/article/details/53121369


xml文件修改

可以用virsh edit [虚拟机名]编辑配置或者vim编辑xml文件;**修改后要关闭虚拟机,再开启才生效,直接重启是不生效的。**如果是用Virtual Machine Manager修改,有些是可以立刻生效的。

kvm中虚机xml定义格式说明https://www.hongweipeng.com/index.php/archives/1152/

光驱(光驱启动)

增加光驱,直接编辑xml文件,在磁盘区增加以下这一段,不想挂载ISO文件就直接删除这一行<source file='/sas_raid5/iso/virtio-win.iso'/>这一行就行了。删除光驱就删除以下一段代码。
设置光驱启动把栏中的改为

    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <source file='/sas_raid5/iso/virtio-win.iso'/>
      <target dev='sdb' bus='scsi'/>
      <readonly/>
      <address type='drive' controller='0' bus='0' target='0' unit='1'/>
    </disk>

增加硬盘

增加硬盘,直接编辑xml文件,在磁盘区增加以下这一段,注意dev='sdc'unit='2'不要和现有的重复。<boot order='1'/>启动顺序也要注意;硬盘路径写对。

创建硬盘文件。

    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/sas_raid5/kvm/Wefly_Api2_02.qcow2'/>
      <target dev='sdc' bus='scsi'/>
      <address type='drive' controller='0' bus='0' target='0' unit='2'/>
    </disk>

从现有虚拟机制作模板(静态迁移)

当需要在不同主机(或者是跨网)部署多各个虚拟机时,一台一台安装就很麻烦。只要不管配置多少,网络怎么套用模板时都是可以修改的。分4步走。这里,迁移到新的kvm宿主机上,直接移动文件,也不用修改名称,mac,磁盘路径等等,就是所谓的静态迁移

  • 1,选一个已有的虚拟机做模板机原型(搭建好你需要的环境,网卡开启DHCP(目标机网段不通无法联机))
  • 2,关机,并克隆成新虚拟机(qcow2格式硬盘使用了多少,克隆出来的就是多少)
  • 3,copy或web分发到目标主机上。
  • 4,修改配置,导入,启动。

在源主机上:

virsh list --all                        #查看虚拟机状态,确保已暂停或关机
virsh suspend [源主机名]                 #暂停虚拟机
virsh resume [源主机名]                  #恢复虚拟机(从暂停状态恢复)
#开始克隆:virt-clone -o [源主机名(上一不看到的名)] -n [新主机名] -f /sas_raid5/[新主机名].qcow2(硬盘文件存储位置)
例:virt-clone -o Web_Api2 -n template01 -f /sas_raid5/template01.qcow2

virsh domblklist template01             #查看克隆出来的虚拟机使用了那些硬盘文件(列出了的都是要copy到新机上的)
cp /etc/libvirt/qemu/template01.xml /sas_raid5/      #拷贝虚拟机的xml配置文件到镜像目录,一起发送到远程目标主机  

# 文件拷贝到目标机后,别忘了在Virtual Machine Manager删掉克隆出来的模板。或者用virsh undefine [虚拟机名]

在目标机上:

#把源主机上对应的qcow2(镜像文件)copy、SCP、FTP、http(wget)到本地
wget -O http://172.16.16.90/template01.qcow2 /sas_raid5/kvm_data/new_sys.qcow2
wget -O http://172.16.16.90/template01.xml /etc/libvirt/qemu/new_sys.xml      #配置文件一般是次目录,也可以放其他目录
vim /etc/libvirt/qemu/new_sys.xml
#修改以下3点
1,修改虚拟机名,如果模板没有删除的话这里还要改uuid避免和模板冲突,随便该一位数字就行
<domain type='kvm'>
  <name>new_sys</name>
  <uuid>b4299ae2-e66b-45ea-b5e8-8fdc353d17d9</uuid>


2,修改硬盘路径
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/sas_raid5/kvm_data/new_sys.qcow2'/>
      <target dev='sda' bus='scsi'/>

3,,修改主机MAC地址,桥接卡
 <interface type='bridge'>
      <mac address='51:34:ec:7b:1c:72'/>
      <source bridge='br1'/>
# 重要!!!
# MAC随便改,和现有机子不冲突就行(如果模板机忘记开启DHCP的话,这里可以设置成和你要桥接的网卡一样的MAC,这样开机通过Virtual Machine Manager内置vnc可以进入系统开启DHCP,然后关机,再改MAC,不改MAC无法上网)


virsh define /etc/libvirt/qemu/new_sys.xml         #重载文件(会加入虚拟机列表,变为可管理)
#记得用命令或在Virtual Machine Manager面板删除模板。

这时用virsh list --all或在Virtual Machine Manager可以看到主机了,然后修改CPU,内存;这两个如果在配置文件中改需要自己计算大小,比较麻烦,所以用Virtual Machine Manager改。

完成后启动就OK了,再设置静态IP。设置开机自启动


libguestfs-tools工具

安装后会有一堆的命令

[root@Center_kvm ~]# virt
virt-admin               virt-filesystems          virt-ls                  virt-tar-out
virt-alignment-scan      virt-format              virt-make-fs             virt-top
virt-builder             virtfs-proxy-helper      virt-manager             virt-v2v
virt-cat                 virt-get-kernel          virt-p2v-make-disk       virt-v2v-copy-to-local
virt-clone               virt-host-validate       virt-p2v-make-kickstart  virt-viewer
virt-copy-in             virt-index-validate      virt-pki-validate        virt-what
virt-copy-out            virt-inspector           virt-rescue              virt-win-reg
virt-customize           virt-install             virt-resize              virt-xml
virt-df                  virtlockd                virt-sparsify            virt-xml-validate
virt-diff                virt-log                 virt-sysprep             
virt-edit                virtlogd                 virt-tar-in  

libguestfs-tools工具的部分命令使用方便,但是执行速度比较慢。

virsh list --all   #查看虚拟机名称,之后要用到
libguestfs-tools工具中的命令都可以用:`[命令] --help`的方式查看帮助

下面是几个常用的命令,其他命令也是类似的用法

virt-df

类似于虚拟机本地“df”命令,列出磁盘存储情况。

virt-df -h [虚拟机名称]

[root@Center_kvm ~]# virt-df -h zabbix
Filesystem                                Size       Used  Available  Use%
zabbix:/dev/sda1                         1014M       196M       818M   20%
zabbix:/dev/cl/home                        45G       284K        45G    1%
zabbix:/dev/cl/root                        50G       8.9G        41G   18%

virt-cat

类似于虚拟机本地"cat"命令

virt-cat -d [虚拟机名称] [路径]
  
[root@Center_kvm ~]# virt-cat -d zabbix /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost
127.0.0.1 centos74.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

virt-edit

类似于虚拟机本地"vi"命令,使用这个命令需要关闭虚拟机

virt-edit -d [虚拟机名称] [文件路径]        #编辑虚拟机里面的文件
virt-edit -a [虚拟硬盘文件路径] [文件路径]   #编辑虚拟硬盘里的文件

virt-ls

类似于虚拟机本地"ls"命令

virt-ls -d [虚拟机名称] [目录路径]

virsh domifaddr

查看网卡信息

virsh domifaddr [虚拟机名称] --source agent

参考:https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Virtualization_Deployment_and_Administration_Guide/chap-QEMU_Guest_Agent.html


virt-copy-out

复制虚拟机文件到宿主机(真机)本地磁盘,(虚机 ----->>真机)类似于本地"cp"命令

virt-copy-out -d [虚拟机名称] [虚机机文件或目录] [真机文件或目录]
例:virt-copy-out -d zabbix /data/www/index.html /root

virt-copy-in

复制宿主机(真机)本地文件到虚拟机磁盘,(真机 ----->>虚机)类似于本地"cp"命令

virt-copy-in -d [虚拟机名称] [真机文件或目录] [虚机机文件或目录]
例:virt-copy-in -d zabbix xxx.tar.gz /root

远程连接virt-manager

Windows

在win机上安装xshell和xmanager
打开xshell,配置好ssh连接;在连接属性的tunneing中,勾选 Forwarding X11 connection to选项,可以正常打开virt-manager的图形界面。
mark
然后终端输入virt-manager就可以连接virt-manager了。


Linux

直接安装即可。

用virt-manager连接其他主机时,会出现无限重联的情况,在界面中是没有密码输入框的;
或提示:Unable to connect to libvirt.
You need to install openssh-askpass or similar to connect to this host.

可以用命令行运行virt-manager --no-fork来运行virt-manager,新建连接,之后回到命令行输入密码连接。就可以连接成功了。但是一停止后台就会断开;可以做免密登录。


Mac

因为是移植的开源项目,还有更多bug!

Github:https://github.com/jeffreywildman/homebrew-virt-manager
大多数问题可以在问题列表找到:https://github.com/jeffreywildman/homebrew-virt-manager/issues

安装:

# 安装时间非常漫长,多次中断,重试即可
brew tap jeffreywildman/homebrew-virt-manager
brew install virt-manager virt-viewer

brew cask install xquartz
 
安装完成重启系统

使用:

# 命令行执行(使用套接字连接)
virt-manager -c 'qemu+ssh://root@IP:端口/system?socket=/var/run/libvirt/libvirt-sock' --no-fork --debug

# 界面连接
https://blog.51cto.com/quliren/2055550



KVM Install Windows Server 2012(R2)、Windows Server 2016

安装virtio-win

官网:http://fedoraproject.org/wiki/Windows_Virtio_Drivers
需要virtio-win可以yum安装,yum源没有就添加源,这是在Linux中安装virtio-win,为安装WIN提供接口。

cat > /etc/yum.repos.d/virtio-win.repo <EOF
# virtio-win yum repo
# Details: https://fedoraproject.org/wiki/Windows_Virtio_Drivers
 
[virtio-win-stable]
name=virtio-win builds roughly matching what was shipped in latest RHEL
baseurl=http://fedorapeople.org/groups/virt/virtio-win/repo/stable
enabled=1
skip_if_unavailable=1
gpgcheck=0
 
[virtio-win-latest]
name=Latest virtio-win builds
baseurl=http://fedorapeople.org/groups/virt/virtio-win/repo/latest
enabled=0
skip_if_unavailable=1
gpgcheck=0
 
[virtio-win-source]
name=virtio-win source RPMs
baseurl=http://fedorapeople.org/groups/virt/virtio-win/repo/srpms
enabled=0
skip_if_unavailable=1
gpgcheck=0
EOF

yum clean all && yum makecache && yum install -y virtio-win

下载virtio-win驱动

这是在WIN中安装virtio-win驱动,然后才能调用Linux的接口提供的资源。
官网:http://fedoraproject.org/wiki/Windows_Virtio_Drivers
mark
下载好放入kvm指定的镜像目录

开始安装

在Virtual Machine Manager中设置CPU,内存、硬盘(选SCSI,不要IDE,太慢了),设置CDROM为WIN安装盘,再增加一个设备来挂载virtio-win(看你下载的是ISO还是vfd,2012R2建议ISO,2016建议vfd),设置win iso安装盘第一启动。
安装时加载驱动
mark
选择系统版本2012(R2)的选2k12(R2),2016的为2K16
mark
选择加载vioscsi驱动,这样就能挂载硬盘,进行系统安装了,安装好后再来安装网卡驱动,CPU驱动什么的(直接在inf文件上右键安装)。

参考:https://enginx.cn/2017/02/25/kvm%E5%AE%89%E8%A3%85windows-server-2016.html


报错:安装WIN,虚拟机启动界面报没有引导设备

这可能是WIN开机不能加载SCSI驱动的原因,把光驱设置为SATA就行了,安装完了再改为SCSI;磁盘一开始就用SCSI;安装好后修改可能造成蓝屏。


win虚拟机新增硬盘无法格式化,磁盘写保护(The media is write protected)

正常情况下,增加了新的硬盘在Linux中是直接可以分区使用的了,但是在win中无法进行分区,及任何写入操作;磁盘也处于离线状态。解决方法如下:

打开cmd


C:\> diskpart                       #打开磁盘管理工具

list disk                           #列出所有硬盘,同时能看到是否在线
select disk [id]                    #选择要操作的磁盘,就是上一步中看到的磁盘编号,例:select disk 2
online disk                         #使磁盘在线
attributes disk clear readonly      #去除磁盘写保护
automount enable                    #开启自动挂载(貌似是默认开启的)
# 到了这步应该是可以在磁盘管理中新建分区的了,如果还是Unallocated状态,无法新建分区。接着执行以下命令
clean                               #直接把分区删了
creat partition primary             #创建分区
# 然后在磁盘管理中把此分区删了再重建。(或者format fs=ntfs(或fat32) quick label="磁盘名称" )

虚拟机开机自启动

当宿主机重启后,虚拟机并不会自动启动,需要人工启动,但是可以自动启动
法1:virsh autostart 虚拟名称

法2:
进入**/etc/libvirt/qemu/** 目录可以看到虚拟机的配置文件,一个虚拟机对应一个文件。
在此目录下新建文件夹autostart :mkdir autostart
创建要开机自启的虚拟机的软链接:

ln -s /etc/libvirt/qemu/Ubuntu16.xml autostart/

之后如果重启了宿主机,对应的虚拟机也会自动启动了。


快照

查看虚拟机状态:virsh list --all

# 查看快照:
qemu-img snapshot -l /kvm/xxxx.qcow2
或
virsh snapshot-list [虚拟机名]

# 查看最新快照信息: virsh snapshot-current 虚拟机名

# 创建快照:
qemu-img snapshot -c [快照名] /kvm/xxxx.qcow2
或
virsh snapshot-create-as [虚拟机名] [快照名]

# 恢复快照:
qemu-img snapshot -a [快照名] /kvm/xxxx.qcow2
或
virsh snapshot-revert [虚拟机名] [快照名]

# 删除快照: 
qemu-img snapshot -d [快照名] /kvm/xxxx.qcow2
或
virsh snapshot-delete [虚拟机名] [快照名]

快照存放目录:/var/lib/libvert/qemu/snapshot/虚拟机名称/


在开机状态下创建快照报错:error: operation failed: Failed to take snapshot: Error -22 while writing VM

这个qemu1.5版本在Centos7上不兼容的bug;目前(2017年7月15日)还没有被修复;但是找到了解决方法,安装qemu-kvm-rhev来替代qemu-kvm

# 添加qemu-kvm-rhev源,代替qemu-kvm,是为了修复无法开机创建快照的bug。
cat > /etc/yum.repos.d/qemu-kvm-rhev.repo <<EOF
[qemu-kvm-rhev]
name=oVirt rebuilds of qemu-kvm-rhev
baseurl=http://resources.ovirt.org/pub/ovirt-3.5/rpm/el7Server/
mirrorlist=http://resources.ovirt.org/pub/yum-repo/mirrorlist-ovirt-3.5-el7Server
enabled=1
skip_if_unavailable=1
gpgcheck=0
EOF


yum remove qemu-kvm -y && yum update -y
yum install -y qemu-kvm-rhev
# 完成之后重启生效

参考:
https://www.redhat.com/archives/libvirt-users/2014-November/msg00106.html
http://www.cookiesinn.org/create_kvm_snapshot


在开机状态下创建快照报错:error: operation failed: Failed to take snapshot: State blocked by non-migratable device '0000:00:05.0/ich9_ahci'

解决:
方法一:
将虚拟机关机,然后更改一下DVD,硬盘等接口,使用VirtIO或SCSI(不建议用IDE,太慢了),只有全部更换了才能移除SATA。
硬件面板移除Controller SATA重新开机就正常了。

方法二:
关闭虚拟机编辑xml文件,

# 修改引用了SATA的磁盘为其他连接类型,如VirtIO或SCSI,比如:scsi;注意修改设备类型,sda、vda之类的(一般可以不改)。
# 修改以下这一段中的sata为你上一步设置的类型,比如:scsi
    <controller type='pci' index='0' model='pci-root'/>
    <controller type='sata' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </controller>

# 总共就修改两处;修改好virsh define一下,启动机子就可以设置快照了。

参考:http://masysma.lima-city.de/37/how_to_transition_from_virtualbox_to_kvm.xhtml


启动虚拟机报错:

error: Failed to start domain XXXXXX
error: internal error: process exited while connecting to monitor: 2017-11-24T10:13:44.656456Z qemu-kvm: -machine pc-i440fx-rhel7.2.0,accel=kvm,usb=off,dump-guest-core=off: unsupported machine type
Use -machine help to list supported machines
这个是因为修改了machine信息的问题,和上一个有点类似;win机会出现,linux一般不会有这个问题,修改为其他类型一般就行了

错误:开始域 XXXXX 失败
错误:operation failed: guest CPU doesn't match specification: extra features: arat,abm

解决:

# 获取qemu-kvm支持的machine列表
/usr/libexec/qemu-kvm -machine help   #Centos
/usr/bin/kvm -machine help            #Ubuntu

一般选择一个如:pc-i440fx-2.6,替换掉xml文件中的相应的pc-i440fx-rhel7.2.0就行了。

快照的回滚、合并等各种操作,单镜像多实例

http://www.cnblogs.com/jython/p/4301954.html


动态迁移(不用关闭系统)

KVM动态迁移目前有两种,一种是基于共享存储的动态迁移,一种是基于数据块的动态迁移,需要qemu-kvm-0.12.2以上版本支持,OEL6.3版本是qemu-kvm-0.12.1.2,其它发行版可能有支持。本人未在Centos 7上测试。

基于共享存储的动态迁移比较简单,其实就是系统的硬盘文件放在文件服务器(nfs、smb等等)上面,在两台kvm宿主机上都挂载该目录(硬盘文件挂载的目录路径保持一致。)xml配置文件中定义了磁盘路径(当两台kvm宿主机的磁盘路径也一样时就直接可以漂移过来了)。

第一步:
在目标kvm宿主机上挂载nfs的目录到指定文件夹(目录和源kvm宿主机一样;源kvm宿主机一般在开始规划时就是这样做了,方便以后进行动态迁移)。nfs要与这两台kvm宿主机在同一个内网中。

第二步:
执行迁移命令:

# 192.168.10.160是目标kvm宿主机的ip
virsh migrate --live --verbose [虚拟机名] qemu+ssh://192.168.10.160/system tcp://192.168.10.160

接着输入目标kvm主机的root密码,当迁移100%时就完成了。迁移过程中源kvm宿主机上该虚拟机会暂停或关闭几秒钟,随后会被删除,然后就会在目标kvm宿主机上启动。
**注意:**如果报错:error: Unsafe migration: Migration may lead to data corruption if disks use cache != none
在命令最后加上--unsafe即可。

参考:http://www.coooz.com/archives/833

第三步:
导出配置、重新定义配置文件:
因为迁移过来时是通过ssh登录启动虚拟机的,虚拟机的配置文件还在源kvm宿主机上,在目标kvm宿主机的硬盘上没有该配置文件,但是在内存中有。所以可以直接导出。

virsh dumpxml [虚拟机名] > /etc/libvirt/qemu/[虚拟机名].xml
virsh define /etc/libvirt/qemu/[虚拟机名].xml

查看是否正常运行,完成迁移。


自动创建虚拟机

先制作好虚拟机模板,就是安装好一个虚拟机作为模板,这个虚拟机设置好内存,cpu等,动态IP(重要,因为不知道目标环境的网段)
一键创建虚拟机的脚本,参考:http://blog.chinaunix.net/uid-26719405-id-4886126.html
上面的那个脚本并不能很好的解决问题。虽然上创建了,但是我们不知道创建的虚拟机的IP,需要一些改进,有空再修改一下脚本

1.可以在脚本运行之后显示IP:arp -a(通过mac[脚本中有定义MAC]过滤出IP)
2.创建好虚拟机后可以通过脚本修改配置文件中的标签(该标签要自己加入,默认上没有的,加入后可以通过virsh list看到)参考:<a href="https://www.ilanni.com/?p=7378">https://www.ilanni.com/?p=7378</a><br /> 3.这时虚拟机的ip还是动态IP,可以在脚本中生成设置静态ip的脚本,比如sed语句,再scp到生成的虚拟机里运行(在虚拟机里执行脚本可能有点困难),也可以用virt-XXX工具,直接执行多条命令修改虚拟机配置文件。</p> <p>到了这时,自动创建虚拟机才算上完成了。</p> <hr /> <h1 id="virsh-console连接虚拟机ssh方式连接">virsh console连接虚拟机(ssh方式连接)</h1> <p>新安装一台虚拟机后,是无法通过virsh console 命令连入虚拟机中的,这时我们需要开启虚拟机的console功能。</p> <p>**Centos7:**在虚拟机里运行<code>grubby --update-kernel=ALL --args="console=ttyS0"</code><br /> 重启即可用virsh console加ID号或Name连接(virsh list可以看到)。</p> <p><strong>注:按 ctrl+] 组合键退出virsh console</strong></p> <p><strong>Centos6</strong>的就比教麻烦一点,参考:<a href="http://www.cnblogs.com/xieshengsen/p/6215168.html">http://www.cnblogs.com/xieshengsen/p/6215168.html</a></p> <hr /> <h1 id="迁移系统">迁移系统</h1> <h2 id="迁移kvm到vmware-vm">迁移KVM到VMware VM</h2> <p><a href="http://foolishfish.blog.51cto.com/3822001/1429125/">http://foolishfish.blog.51cto.com/3822001/1429125/</a></p> <hr /> <h2 id="迁移vmware-vm到kvm">迁移vmware VM到KVM</h2> <p>有多种命令迁移或转换磁盘;建议转换为qcow2格式,支持快照功能。KVM也可以直接启动vmdk(RAW)格式的磁盘文件(在KVM中不支持快照)</p> <p>如果图方便可以不转换磁盘;直接转换配置文件再修改一下就行了。</p> <pre><code>apt-get install -y virt-goodies vmware2libvirt –f centos7-mini.vmx > centos7-mini.xml virsh define centos7-mini.xml 然后再修改配置,最好用virt-manager, 磁盘:磁盘都添加上;VMware的磁盘会链接其他磁盘;用virt-manager依次添加磁盘时被链接过的会有提示。 再修改boot(要测试一下才知道是那个磁盘)、网络、内存、CPU等。 </code></pre> <p>参考:<br /> <a href="http://blog.csdn.net/epugv/article/details/15504029">http://blog.csdn.net/epugv/article/details/15504029</a><br /> <a href="http://www.linuxidc.com/Linux/2012-09/70027.htm">http://www.linuxidc.com/Linux/2012-09/70027.htm</a><br /> <a href="https://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm3/">https://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm3/</a></p> <hr /> <h2 id="virtualbox-虚拟机迁移到kvm">VirtualBox 虚拟机迁移到KVM</h2> <p>安装目录下<code>C:\Program Files\Oracle\VirtualBox>VBoxManage.exe</code>有这个工具。先转为RAW格式,然后再转为qcow2格式。</p> <p>参考:<br /> <a href="http://blog.csdn.net/starshine/article/details/7032316">http://blog.csdn.net/starshine/article/details/7032316</a></p> <hr /> <h1 id="调整cpu内存调优">调整CPU、内存、调优</h1> <p>virsh edit或vi编辑配置文件也行,centos6的话cpu不支持动态调整。<br /> 第一次开启配置动态调整后,一定要关闭虚拟机,再开启虚拟机才会生效。(重启是不行的,重启并没有重新加载xml文件)</p> <pre><code>virsh edit [虚拟机名] # 有这样一段配置 <memory unit='KiB'>4194304</memory> #最大使用的内存大小 <currentMemory unit='KiB'>4194304</currentMemory> #当前内存大小 <vcpu placement='static'>2</vcpu> #固定使用2个cpu,如果要cpu动态调整,改为<vcpu placement='auto' current='2'>4</vcpu>这样就默认使用2个,最多使用4个。 # 修改一下 <memory unit='KiB'>8194304</memory> #最大使用的内存大小 <currentMemory unit='KiB'>4194304</currentMemory> #当前内存大小 <vcpu placement='auto'>4</vcpu> #动态调整CPU,默认1个核,最多4个 </code></pre> <p>修改好保存退出,关闭虚拟机,再启动虚拟机(不是重启)就生效了。<br /> 之后一般会自动去调整cpu和内存使用量,也可以手工设置</p> <pre><code>virsh setmem [虚拟机名] 6G #内存可以改大或改小,立刻生效 virsh setvcpus [虚拟机名] 3 #cpu在centos上只能改大(立刻生效),改小只能修改xml文件后关闭再开启 </code></pre> <p>参考:<br /> <a href="http://blog.csdn.net/hshl1214/article/details/62046736">http://blog.csdn.net/hshl1214/article/details/62046736</a><br /> <a href="http://bbs.qy.com.cn/thread-1108-1-1.html">http://bbs.qy.com.cn/thread-1108-1-1.html</a><br /> <a href="http://xiaoli110.blog.51cto.com/1724/1607863">http://xiaoli110.blog.51cto.com/1724/1607863</a><br /> <a href="http://www.cnblogs.com/nmap/p/6369180.html">http://www.cnblogs.com/nmap/p/6369180.html</a></p> <hr /> <h1 id="内存共享">内存共享</h1> <p>KVM有着内存共享的强大功能,内存共享通过一项名为内核同页合并(Kernel Samp-page Merging,KSM)的功能来实现。KSM扫描每个虚拟机的内存,如果虚拟机用于相同的内存页面,KSM将这些页面合并到一个在虚拟机之间共享的页面,仅存储一个副本。可以提供内存利用率。<strong>所以即使是16G的内存,却可以创建6个4G的虚拟机(其中超过8G是共享的内存)</strong>;要在linux下实现内存合并,只需要启动KSM,ksmtuned服务即可。</p> <pre><code># 在宿主机上运行命令 systemctl start ksm systemctl start ksmtuned systemctl enable ksm systemctl enable ksmtuned </code></pre> <hr /> <h1 id="内存气球">内存气球</h1> <pre><code>virsh qemu-monitor-command [虚拟机名] --hmp --cmd balloon 1500 #单位是M,1500就是1.5G,也可以直接加单位。 </code></pre> <hr /> <h1 id="硬盘扩容">硬盘扩容</h1> <p>硬盘扩容分格式,qcow2和ram,这两个格式扩容的方式基本是相同的。<br /> 如果创建磁盘时使用了preallocation=metadata 选项,并且扩容的分区采用ext分区则无法扩容。可以修改为xfs分区或新增硬盘方式扩容。</p> <h2 id="qcow2在原有磁盘文件上扩容适合lvm分区">qcow2在原有磁盘文件上扩容(适合lvm分区)</h2> <pre><code># 查看磁盘信息 qemu-img info MSSQL01-01.qcow2 image: MSSQL01-01.qcow2 file format: qcow2 virtual size: 80G (85899345920 bytes) disk size: 4.8G cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: true refcount bits: 16 corrupt: false # 增加空间 qemu-img resize MSSQL01-01.qcow2 +120G # 查看磁盘信息 qemu-img info MSSQL01-01.qcow2 image: MSSQL01-01.qcow2 file format: qcow2 virtual size: 200G (214748364800 bytes) disk size: 4.8G cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: true refcount bits: 16 corrupt: false # 重启虚拟机,不要用restart,重新加载配置文件 virsh destroy MSSQL virsh start MSSQL # 登陆虚拟机,磁盘挂载的空间并没有增加 [root@MSSQL01 ~]# fdisk -l Disk /dev/vda: 214.7 GB, 214748364800 bytes, 419430400 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: 0x000b2765 Device Boot Start End Blocks Id System /dev/vda1 * 2048 2099199 1048576 83 Linux /dev/vda2 2099200 167772159 82836480 8e Linux LVM # 增加分区(把新增加的未使用部分划分为新的分区) [root@MSSQL01 ~]# fdisk /dev/vda Welcome to fdisk (util-linux 2.23.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p #可以看到现在有两个分区了 Disk /dev/vda: 214.7 GB, 214748364800 bytes, 419430400 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: 0x000b2765 Device Boot Start End Blocks Id System /dev/vda1 * 2048 2099199 1048576 83 Linux /dev/vda2 2099200 167772159 82836480 8e Linux LVM Command (m for help): n #已经有两个分区了,再增加一个 Partition type: p primary (2 primary, 0 extended, 2 free) e extended Select (default p): p Partition number (3,4, default 3): 3 #MBR格式硬盘最多4个主分区,目前有两个了,还剩2个; First sector (167772160-419430399, default 167772160): Using default value 167772160 Last sector, +sectors or +size{K,M,G} (167772160-419430399, default 419430399): Using default value 419430399 Partition 3 of type Linux and of size 120 GiB is set Command (m for help): p #新增一个主分区 Disk /dev/vda: 214.7 GB, 214748364800 bytes, 419430400 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: 0x000b2765 Device Boot Start End Blocks Id System /dev/vda1 * 2048 2099199 1048576 83 Linux /dev/vda2 2099200 167772159 82836480 8e Linux LVM /dev/vda3 167772160 419430399 125829120 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. # 然后再把这个/dev/vda3 加入到lvm里面去: [root@MSSQL01 ~]# ls /dev/vda3 #如果提示没有这个分区,需要重启一下 [root@MSSQL01 ~]# reboot [root@MSSQL01 ~]# fdisk -l #已经增加了vda3了 Disk /dev/vda: 214.7 GB, 214748364800 bytes, 419430400 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: 0x000b2765 Device Boot Start End Blocks Id System /dev/vda1 * 2048 2099199 1048576 83 Linux /dev/vda2 2099200 167772159 82836480 8e Linux LVM /dev/vda3 167772160 419430399 125829120 83 Linux [root@MSSQL01 ~]# pvcreate /dev/vda3 #创建物理卷 [root@MSSQL01 ~]# pvs PV VG Fmt Attr PSize PFree /dev/vda2 cl lvm2 a-- <79.00g 0 /dev/vda3 lvm2 --- 120.00g 120.00g #把/dev/vda3加入vg中,cl是vg名称(可以用vgdisplay查看) [root@MSSQL01 ~]# vgextend cl /dev/vda3 Volume group "cl" successfully extended [root@MSSQL01 ~]# vgs VG #PV #LV #SN Attr VSize VFree cl 2 3 0 wz--n- 198.99g <120.00g [root@MSSQL01 ~]# lvdisplay #查看根分区的路径(要扩容根分区) [root@MSSQL01 ~]# lvextend -l +100%FREE /dev/cl/root #扩容lv Size of logical volume cl/root changed from <47.79 GiB (12234 extents) to <167.79 GiB (42953 extents). Logical volume cl/root successfully resized. # 重设空间,先查看分区格式 [root@MSSQL01 ~]# df -Th Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/cl-root xfs 48G 3.3G 45G 7% / /dev/mapper/cl-home xfs 24G 33M 24G 1% /home /dev/vda1 xfs 1014M 231M 784M 23% /boot [root@MSSQL01 ~]# resize2fs /dev/cl/root #适合ext格式 [root@MSSQL01 ~]# xfs_growfs /dev/cl/root #适合xfs格式 [root@MSSQL01 ~]# df -h #可以看到已经扩容了 Filesystem Size Used Avail Use% Mounted on /dev/mapper/cl-root 168G 3.3G 165G 2% / /dev/mapper/cl-home 24G 33M 24G 1% /home /dev/vda1 1014M 231M 784M 23% /boot </code></pre> <p>**注:**如果提示 This image format does not support resize, 检查一下你qemu-img create的时候,是否有加 preallocation=metadata 选项,如果有,就不能resize了。</p> <h2 id="virt-resize扩容解决加了preallocationmetadata选项不能用resize的问题">virt-resize扩容(解决加了preallocation=metadata选项不能用resize的问题)</h2> <p>原理是把旧磁盘的内容克隆到新磁盘上,然后删掉就磁盘。</p> <pre><code>yum install -y libguestfs-tools qemu-img create -f qcow2 new-disk-name.qcow2 40G #创建目标大小的磁盘文件 virt-resize --expand /dev/sda1 old-disk-name.qcow2 new-disk-name.qcow2 # 检查 virt-df -h new-disk-name.qcow2 # 启动磁盘 mv old-disk-name.qcow2 old-disk-name.qcow2.bak mv new-disk-name.qcow2 old-disk-name.qcow2 chmod 755 old-disk-name.qcow2 启动虚拟机,没问题就可以删除就的磁盘了,rm old-disk-name.qcow2.bak </code></pre> <p>参考:<a href="http://libguestfs.org/virt-resize.1.html">http://libguestfs.org/virt-resize.1.html</a></p> <p>文件太大可以装换一下就小了(空洞文件系统):</p> <pre><code>qemu-img convert -O qcow2 old-disk-name.qcow2 new-disk-name.qcow2 rm old-disk-name.qcow2 mv new-disk-name.qcow2 old-disk-name.qcow2 </code></pre> <hr /> <h2 id="新加硬盘扩容">新加硬盘扩容</h2> <pre><code>创建磁盘: qemu-img create -f qcow2 /data/MSSQL02.qcow2 100G 关闭虚拟机: virsh destroy MSSQL 编辑配置文件: virsh edit MSSQL 复制增加如下:注意是vdb,qcow2 <disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='none'/> <source file='/data/MSSQL02.qcow2'/> <target dev='vdb' bus='virtio'/> </disk> 开启虚拟机:virsh start MSSQL 进入虚拟机:virsh console MSSQL 分区: fdisk /dev/vdb 格式化:mkfs.ext4 /dev/vdb 挂载:vim /etc/fstab,添加一行:/dev/vdb /mnt ext4 defaults 0 0 mount -a 然后mnt就可以使用了 [root@MSSQL01 ~] cd /mnt [root@MSSQL01 ~] touch 123.txt </code></pre> <p>也可以按照上面的方法把 /dev/vdb 加入到 lvm里面去。</p> <hr /> <h1 id="centos7环境下全自动创建kvm虚拟机未测试">Centos7环境下全自动创建kvm虚拟机(未测试)</h1> <p>本人未测试,搬运,原文:https://<a href="http://www.idiyrom.com/18.html">www.idiyrom.com/18.html</a><br /> 可以改造为openstack自动创建主机。</p> <p>1、自动配置外网、内网ip<br /> 2、自动设置主机名<br /> 3、自动扩容数据盘<br /> 4、可预设定vnc、root密码<br /> 5、需要注意的是:模板磁盘格式只能使用raw</p> <pre><code>#!/bin/bash export PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin" dateTime=$(date +%Y%m%d%H%M%S) tmpDiskFile="/vmdata/template/template_os" tmpDiskFile1="/vmdata/template/template_data" vmDir="/vmdata" test -d $vmDir || mkdir -p $vmDir help() { cat >> /dev/stdout <<EOF Usage: $(basename $0) vmname vcpu memory ip [TempleteDiskFile] | -h Example: ./$(basename $0) vmname=ebs-1 vcpu=1 memory=512M datasize=10 ip=192.168.7.71 Example: ./$(basename $0) -h //print help infomations EOF } error() { echo -e "input parameter error: $1 \n please try again!" } if [[ "$#" -eq 0 || "$1" == "-h" ]]; then help exit 0 fi for line in $@ do case $line in vmname*) vmName=$(echo $line | awk -F "=" '{print $2}') ;; vcpu*) vCpu=$(echo $line | awk -F "=" '{print $2}') if ! echo $vCpu | grep '^[0-9]$' > /dev/null; then error $line help exit 1 fi ;; memory*) memTmp=$(echo $line | awk -F "=" '{print $2}') memNum=$(echo ${memTmp:0:${#memTmp}-1}) memUnit=$(echo ${memTmp:0-1} | tr '[a-z]' '[A-Z]') if ! echo $memNum | grep '[0-9]' > /dev/null; then error $line help exit 1 fi if [[ "$memUnit" != "G" && "$memUnit" != "M" && "$memUnit" != "K" ]]; then error $line help exit 1 fi ;; datasize*) datasize=$(echo $line | awk -F "=" '{print $2}') if ! echo $datasize | grep '^[0-9]' > /dev/null; then error $line help exit 1 fi ;; diskfile*) diskFile=$(echo $line | awk -F "=" '{print $2}') if [ ! -f "$diskFile" ]; then error $line help exit 1 fi ;; ip*) vmIp=$(echo $line | awk -F "=" '{print $2}') if ! echo $vmIp | grep '[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}' > /dev/null; then error $line help exit 1 fi ;; *) error $line help exit 1 ;; esac done if [ -z "$vmName" ] || [ -z "$vCpu" ] || [ -z "$memNum" ] || [ -z "$vmIp" ]; then echo -e "input parameter incomplete: $@" help exit 1 fi if [ -z "$diskFile" ]; then echo -e "not assign Templete diskfile, use default Templete diskfile: $tmpDiskFile " diskFile=$tmpDiskFile fi if [ -z "$diskFile1" ]; then echo -e "not assign Templete diskfile1, use default Templete diskfile1: $tmpDiskFile1 " diskFile1=$tmpDiskFile1 fi read -p "please input vnc passwd:" vncpasswd if [ -z $vncpasswd ] ;then vncpasswd=`echo $RANDOM|md5sum|cut -c 1-6` fi create_config() { memUnit="$memUnit"iB cat > $vmDir/$vmName/$vmName.xml <<EOF <domain type='kvm'> <name>$vmName</name> <uuid>$vmUuid</uuid> <memory unit='$memUnit'>$memNum</memory> <currentMemory unit='$memUnit'>$memNum</currentMemory> <vcpu placement='static'>$vCpu</vcpu> <os> <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type> <boot dev='cdrom'/> <boot dev='hd'/> <bootmenu enable='yes'/> </os> <features> <acpi/> <apic/> </features> <clock offset='utc'> <timer name='rtc' tickpolicy='catchup'/> <timer name='pit' tickpolicy='delay'/> <timer name='hpet' present='no'/> </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <pm> <suspend-to-mem enabled='no'/> <suspend-to-disk enabled='no'/> </pm> <devices> <emulator>/usr/libexec/qemu-kvm</emulator> <disk type='file' device='disk'> <driver name='qemu' type='raw'/> <source file='$vmDir/$vmName/$vmNameos'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </disk> <disk type='file' device='disk'> <driver name='qemu' type='raw'/> <source file='$vmDir/$vmName/$vmNamedata'/> <target dev='vdb' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x16' function='0x0'/> </disk> <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <target dev='hda' bus='ide'/> <readonly/> <address type='drive' controller='0' bus='0' target='0' unit='0'/> </disk> <controller type='usb' index='0' model='ich9-ehci1'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x7'/> </controller> <controller type='usb' index='0' model='ich9-uhci1'> <master startport='0'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0' multifunction='on'/> </controller> <controller type='usb' index='0' model='ich9-uhci2'> <master startport='2'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x1'/> </controller> <controller type='usb' index='0' model='ich9-uhci3'> <master startport='4'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x2'/> </controller> <controller type='pci' index='0' model='pci-root'/> <controller type='ide' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> </controller> <controller type='virtio-serial' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </controller> <interface type='bridge'> <mac address='$vmMac'/> <source bridge='br0'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface> <interface type='bridge'> <mac address='$vmMac1'/> <source bridge='br1'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x13' function='0x0'/> </interface> <serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target type='serial' port='0'/> </console> <channel type='unix'> <target type='virtio' name='org.qemu.guest_agent.0'/> <address type='virtio-serial' controller='0' bus='0' port='1'/> </channel> <input type='tablet' bus='usb'> <address type='usb' bus='0' port='1'/> </input> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' passwd='$vncpasswd'> <listen type='address' address='0.0.0.0'/> </graphics> <video> <model type='cirrus' vram='16384' heads='1' primary='yes'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </video> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </memballoon> </devices> </domain> EOF } create_mac() { test -f /tmp/mac.py && rm -f /tmp/mac.py cat > /tmp/mac.py <<EOF #!/usr/bin/python # macgen.py script to generate a MAC address for Red Hat Virtualization guests # import random # def randomMAC(): mac = [ 0x54, 0x52, 0x00, random.randint(0x00, 0x7f), random.randint(0x00, 0xff), random.randint(0x00, 0xff) ] return ':'.join(map(lambda x: "%02x" % x, mac)) # print randomMAC() EOF vmMac=$(python /tmp/mac.py) vmMac1=$(python /tmp/mac.py) } create_uuid() { vmUuid=$(uuidgen) } define_kvm() { virsh define $vmDir/$vmName/$vmName.xml if [ $? -ne 0 ]; then echo -e "virsh define $vmName.xml error!" exit 1 fi virsh start $vmName if [ $? -ne 0 ]; then echo -e "virsh start $vmName error!" exit 1 fi virsh list vncPort=$(virsh vncdisplay $vmName) vncIp=`ifconfig br0|grep -w inet|awk '{print $2}'` echo -e "VNC IP and Port is: $vncIp$vncPort" echo -e "$vmName vnc passwd:$vncpasswd \n" } modify_disk() { #vmHostName=$(echo $vmIp | awk -F "." '{print "YN-" $3 "-" $4}') vmIpPri=172.16.$(echo $vmIp | awk -F "." '{print $3 "." $4}') sectorSize=$(parted $vmDir/$vmName/$vmNameos unit s print | awk '/Sector size/{print $4}' | awk -F "B" '{print $1}') sst=$(parted $vmDir/$vmName/$vmNameos unit s print | awk '/ 1 /{print $2}') startSector=${sst:0:${#sst}-1} offSet=$(($startSector*$sectorSize)) mnttemp=/tmp/$vmName mkdir -p $mnttemp mount -o loop,offset=$offSet $vmDir/$vmName/$vmNameos $mnttemp if [ $? -ne 0 ]; then echo -e "mount $vmDir/$vmName/$vmNameos failed! " exit 1 fi tmpIp1="$mnttemp/etc/sysconfig/network-scripts/ifcfg-eth0" tmpIp2="$mnttemp/etc/sysconfig/network-scripts/ifcfg-eth1" sed -i "/^127.0/a\127.0.0.1 $vmName" $mnttemp/etc/hosts sed -i "s/IPADDR=/IPADDR=$vmIp/g" $tmpIp1 sed -i "s/IPADDR=/IPADDR=$vmIpPri/g" $tmpIp2 read -p "please input root passwd:" newpasswd if [ -z $newpasswd ] ;then newpasswd=`echo $RANDOM|md5sum|cut -c 7-12` fi sed -i "s/passwdtemp/$newpasswd/g" $mnttemp/root/set.sh sed -i "s/vmnametemp/$vmName/g" $mnttemp/root/set.sh sed -i "s/tempdisksize/$tempdisksize/g" $mnttemp/root/set.sh sed -i "/^touch/a\/root/set.sh" $mnttemp/etc/rc.d/rc.local sleep 1 umount $mnttemp sleep 1 rm -rf $mnttemp } dots() { sec=$1 while true do echo -e ".\c" sleep $sec done } vmNameos="$vmName"_os vmNamedata="$vmName"_data test -d $vmDir/$vmName || mkdir -p $vmDir/$vmName if [ -f "$vmDir/$vmName/$vmName.xml" ]; then mv $vmDir/$vmName/$vmName.xml $vmDir/$vmName/$vmName.xml.$dateTime echo -e "$vmDir/$vmName/$vmName.xml exist, rename $vmDir/$vmName/$vmName.xml.$dateTime " fi echo -e "create virtual machine config file: $vmDir/$vmName/$vmName.xml ..." create_mac create_uuid create_config if [ ! -f "$diskFile" ]; then echo -e "$diskFile not found, Please try again!" exit 1 fi if [ ! -f "$diskFile1" ]; then echo -e "$diskFile1 not found, Please try again!" exit 1 fi if [ -f "$vmDir/$vmName/$vmNameos" ]; then mv $vmDir/$vmName/$vmNameos $vmDir/$vmName/$vmNameos.$dateTime echo -e "$vmDir/$vmName/$vmName exist, rename $vmDir/$vmName/$vmName.$dateTime " fi echo -e "create virtual machine disk file: $vmDir/$vmName/$vmNameos ..." dots 3 & bgPid=$! cp $diskFile $vmDir/$vmName/$vmNameos kill $bgPid echo -e "create virtual machine disk file: $vmDir/$vmName/$vmNamedata ..." cp $diskFile1 $vmDir/$vmName/$vmNamedata tempdisksize=$[datasize -5] if [ $tempdisksize -gt 0 ];then qemu-img resize $vmDir/$vmName/$vmNamedata +${tempdisksize}G fi echo echo -e "modify virtual machine IP and Hostname..." modify_disk echo -e "define virtual machine ..." define_kvm echo -e "$vmName ip: $vmIp\n" echo -e "$vmName nip: $vmIpPri\n" echo -e "$vmName root passwd:$newpasswd \n" echo -e "create KVM virtual machine:$vmName finish! \n" </code></pre> <p>由于需要自动完成ip、主机名、root密码等,需要在制作模板时,加入以下脚本</p> <pre><code>cat /root/set.sh #!/bin/bash (echo "passwdtemp";sleep 1;echo "passwdtemp") | passwd > /dev/null hostnamectl --static set-hostname vmnametemp sed -i "s/\/root\/set.sh//g" /etc/rc.d/rc.local tempdata=tempdisksize if [ $tempdata -gt 0 ];then umount /home fdisk -S 56 /dev/vdb << EOF d n p 1 wq EOF resize2fs -f /dev/vdb1 mount -a fi rm $0 reboot </code></pre> <hr /> <hr /> <h1 id="kvm-文件格式">KVM 文件格式</h1> <p>这里说的KVM文件格式,其实就是在安装虚拟机时选定的文件扩展名格式,也是硬盘格式(磁盘镜像格式);不同的格式有不同的功能和特性。</p> <p>目前主要有那些格式来作为虚拟机的镜像:</p> <h2 id="raw">raw</h2> <p>不支持snapshot;老牌的格式了,用一个字来说就是裸,也就是赤裸裸,你随便dd一个file就模拟了一个raw格式的镜<br /> 像。由于裸的彻底,性能上来说的话还是不错的。目前来看,KVM和XEN默认的格式好像还是这<br /> 个格式。因为其原始,有很多原生的特性,例如直接挂载也是一件简单的事情。</p> <p>裸的好处还有就是简单,支持转换成其它格式的虚拟机镜像对裸露的它来说还是很简单的(如果<br /> 其它格式需要转换,有时候还是需要它做为中间格式),空间使用来看,这个很像磁盘,使用多<br /> 少就是多少(du -h看到的大小就是使用大小),但如果你要把整块磁盘都拿走的话得全盘拿了<br /> (copy镜像的时候),会比较消耗网络带宽和I/O。接下来还有个有趣的问题,如果那天你的硬盘<br /> 用着用着不够用了,你咋办,在买一块盘。但raw格式的就比较犀利了,可以在原来的盘上追加空间:<br /> <code>dd if=/dev/zero of=zeros.raw bs=1024k count=4096</code>(先创建4G的空间)</p> <p><code>cat foresight.img zeros.raw > new-foresight.img</code>(追加到原有的镜像之后)</p> <h2 id="host-device">host_device</h2> <p>在需要将镜像转化到不支持空洞的磁盘设备时需要用这种格式来代替raw格式。</p> <h2 id="cow">cow</h2> <p>用户模式Linux(User-Mode Linux)的Copy-On-Write的镜像文件格式。曾经qemu的写时拷贝的镜像格式,目前由于历史遗留原因不支持窗口模式。从某种意义上来说是个弃婴,还没得它成熟就死在腹中,后来被qcow格式所取代。</p> <h2 id="qcow">qcow</h2> <p>一代的qemu的cow格式,刚刚出现的时候有比较好的特性,但其性能和raw格式对比还是有很大的<br /> 差距,目前已经被新版本的qcow2取代。其性能可以看链接:<a href="http://www.linux-kvm.org/page/Qcow2">http://www.linux-kvm.org/page/Qcow2</a></p> <h2 id="qcow2">qcow2</h2> <p>现在比较主流的一种虚拟化镜像格式,经过一代的优化,目前qcow2的性能上接近raw裸格式的性<br /> 能。<br /> qcow2的格式,几点还是比较突出的,qcow2的snapshot,可以在镜像上做N多个快照:<br /> 更小的存储空间,即使是不支持holes的文件系统也可以(这下du -h和ls -lh看到的就一样了)<br /> 支持Copy-on-write<br /> 支持多个snapshot,对历史snapshot进行管理<br /> 支持zlib的磁盘压缩<br /> 支持AES的加密</p> <h2 id="vmdk">vmdk</h2> <p>兼容VMware 4以上的镜像文件格式(Virtual Machine Disk Format)。<br /> VMware的格式,这个格式说的蛋疼一点就有点牛X,原本VMware就是做虚拟化起家,自己做了一<br /> 个集群的VMDK的pool,做了自己的虚拟机镜像格式。又拉着一些公司搞了一个OVF的统一封包<br /> 。从性能和功能上来说,vmdk应该算最出色的,由于vmdk结合了VMware的很多能力,目前来看,<br /> KVM和XEN使用这种格式的情况不是太多。但就VMware的Esxi来看,它的稳定性和各方面的能力<br /> 还是可圈可点。</p> <h2 id="vdi">vdi</h2> <p>兼容Oracle(Sun)VirtualBox1.1的镜像文件格式(Virtual Disk Image)。SUN收购了VirtualBox,Oracle又收购了SUN,这么说呢,vdi也算虚拟化这方面的一朵奇葩,可惜的<br /> 是入主的两家公司。SUN太专注于技术(可以说是IT技术最前端也不为过),Oracle又是开源杀手<br /> (mysql的没落)。单纯从能力上来说vdi在VirtualBox上的表现还是不错的。也是不错的workstation<br /> 级别的产品。</p> <h2 id="vpc">vpc</h2> <p>兼容Microsoft的Virtual PC的镜像文件格式(Virtual Hard Disk format)。</p> <h2 id="sheepdog">sheepdog</h2> <p>是日本NTT实验室发起的,为QEMU/KVM做的一个开源的分布式存储系统,为KVM虚拟提供块存储。它无单点故障(无类似于元数据服务器的中央节点),方便扩展(已经支持上千的节点数量),其配置简单、运维成本较低,总的来说,具有高可用性、易扩展性、易管理性等优势。<br /> sheepdog项目,官方网站为:<a href="http://www.osrg.net/sheepdog/">http://www.osrg.net/sheepdog/</a> 。<br /> 目前,国内的淘宝公司对该项目也有较大的贡献,详情可见如下的淘宝sheepdog项目的网站:<a href="http://sheepdog.taobao.org">http://sheepdog.taobao.org</a></p> <hr /> <h2 id="镜像格式装换">镜像格式装换</h2> <p>此步骤使用qemu-img工具实现,如果机器上没有,可以通过rpm或yum进行安装,包名为qemu-img。<br /> qemu-img是专门虚拟磁盘映像文件的qemu命令行工具。</p> <pre><code>参数说明:convert 将磁盘文件转换为指定格式的文件 -f 指定需要转换文件的文件格式 -O 指定要转换的目标格式 </code></pre> <p>转换完成后,将新生产一个目标映像文件,原文件仍保存。<br /> 通用方法:</p> <pre><code># 不需要指定来源格式,指定目标格式就行 qemu-img convert centos.XXX -O qcow2 centos.qcow2 </code></pre> <p>具体命令如下:<br /> <strong>raw->qcow2</strong>:<code>qemu-img convert -f raw centos.img -O qcow2 centos.qcow2</code></p> <p><strong>VMDK–>qcow2</strong>:<code>qemu-img convert -f vmdk -O qcow2 SLES11SP1-single.vmdk SLES11SP1-single.img</code><br /> <a href="http://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm3/index.html">http://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm3/index.html</a></p> <p><strong>qcow2–>raw</strong>:<code>qemu-img convert -f qcow2 -O qcow2 image-raw.raw image-raw-converted.qcow</code></p> <p>参考:<br /> <a href="http://blog.chinaunix.net/uid-14735472-id-4220089.html">http://blog.chinaunix.net/uid-14735472-id-4220089.html</a><br /> <a href="http://smilejay.com/2012/08/qemu-image-format">http://smilejay.com/2012/08/qemu-image-format</a></p> <p><strong>qcow2/raw–>vhd</strong>:</p> <pre><code>qemu-img convert -f qcow2 -O vhd image.qcow2 image-converted.vhd qemu-img convert -f raw -O vpc image.raw image-converted.vhd </code></pre> <hr /> <h2 id="kvm虚拟化环境中的时区设置">kvm虚拟化环境中的时区设置</h2> <p><a href="http://m.mamicode.com/info-detail-1289153.html">http://m.mamicode.com/info-detail-1289153.html</a></p> <hr /> <h1 id="高级应用技巧">高级应用、技巧</h1> <p>改配置文件,内存、存储共享,内存气球,虚拟机调用真机虚拟化:<a href="http://www.lmyw.net.cn/?p=1249">http://www.lmyw.net.cn/?p=1249</a><br /> 磁盘IO优化:<a href="http://blog.csdn.net/dylloveyou/article/details/71515880">http://blog.csdn.net/dylloveyou/article/details/71515880</a><br /> CPU,内存动态调整、各种优化:<a href="http://www.cnblogs.com/nmap/p/6369180.html">http://www.cnblogs.com/nmap/p/6369180.html</a><br /> KVM虚拟化CPU技术总结:http://xiaoli110.blog.51cto.com/1724/1607863<br /> KVM详解:<a href="http://www.cnblogs.com/sammyliu/p/4543110.html">http://www.cnblogs.com/sammyliu/p/4543110.html</a><br /> kvm虚拟化学习笔记:<a href="http://blog.51cto.com/koumm/1288795">http://blog.51cto.com/koumm/1288795</a></p> <hr /> </article> <div class="post-copyRight relative"> <i class="fa-solid fa-copyright absolute"></i> <div class="author"> <span class="name">文章作者:</span> <span class="text">Leo</span> </div> <div class="url"> <span class="name">本文链接:</span> <span class="text"> <a class="permalink" href="/archives/kvm%E9%85%8D%E7%BD%AE%E5%BA%94%E7%94%A8%E6%8A%A5%E9%94%99" target="_blank">/archives/kvm%E9%85%8D%E7%BD%AE%E5%BA%94%E7%94%A8%E6%8A%A5%E9%94%99</a> </span> </div> <div class="declaration"> <span class="name">版权声明:</span> <span class="text">本站所有文章除特别声明外,均采用 <a class="link" href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a class="link" href="/" target="_blank">LeoLan的小站</a>!</span> </div> </div> <div class="post-abstract"> <span class="categories"> <a class="link inline-block text-center" href="/categories/%E8%99%9A%E6%8B%9F%E5%8C%96" > <i class="fa-regular fa-folders"></i> <span class="name">虚拟化</span> </a> </span> <span class="tags"> <a class="link inline-block text-center" href="/tags/kvm" style="--spec-color: #cfd3d7" > <i class="fa-regular fa-tags"></i> <span class="name">kvm</span> </a> </span> </div> <div class="post-support"> <div class="title text-center">喜欢就支持一下吧</div> <div class="content flex flex-justify-content-center"> <div class="share relative item cursor-pointer inline-flex flex-direction-column flex-justify-content-center flex-align-items-center"> <i class="fa-light fa-arrow-up-right-from-square"></i> <span>分享</span> <ul class="share-dropdown absolute z-50"> <li class="dropdown-item"> <a href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=/archives/kvm%E9%85%8D%E7%BD%AE%E5%BA%94%E7%94%A8%E6%8A%A5%E9%94%99&title=KVM配置、应用、报错&pics=&summary="> <span class="icon inline-flex flex-justify-content-center flex-align-items-center"> <i class="fa-regular fa-atom-simple"></i> </span> <span class="name">QQ空间</span> </a> </li> <li class="dropdown-item"> <a href="https://connect.qq.com/widget/shareqq/index.html?url=/archives/kvm%E9%85%8D%E7%BD%AE%E5%BA%94%E7%94%A8%E6%8A%A5%E9%94%99&title=KVM配置、应用、报错&pics=&desc="> <span class="icon inline-flex flex-justify-content-center flex-align-items-center"> <i class="fa-brands fa-qq"></i> </span> <span class="name">QQ好友</span> </a> </li> <li class="dropdown-item copy-permalink"> <span class="icon inline-flex flex-justify-content-center flex-align-items-center"> <i class="fa-regular fa-link"></i> </span> <span class="name">复制链接</span> </li> </ul> </div> </div> </div> </section> <aside class="aside w-25"> <div class="sticky post-sticky"> <section class="aside-item card post-tocbot"> <h1 class="aside-title"> <i class="fas fa-stream"></i> <span class="name">目录</span> </h1> <div class="toc"></div> </section> <section class="aside-news-post aside-item card"> <h1 class="aside-title"> <i class="fas fa-history"></i> <span class="name">最新文章</span> </h1> <ul class="content"> <li class="item flex flex-align-items-center"> <a href="/archives/python%E9%A1%B9%E7%9B%AE%E4%BB%A3%E7%A0%81%E5%8A%A0%E5%AF%86" class="cover overflow-hidden"> <img class="block w-100 h-100" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="http://api.btstu.cn/sjbz/?lx=fengjing&time=854?index=0" alt="Python项目代码加密" onerror="this.src=`data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=`"> </a> <div class="desc flex-1"> <a href="/archives/python%E9%A1%B9%E7%9B%AE%E4%BB%A3%E7%A0%81%E5%8A%A0%E5%AF%86" class="title text-link text-clamp">Python项目代码加密</a> <time class="block" datetime="2020-06-15T17:21:00Z">2020-06-16 01:21</time> </div> </li> <li class="item flex flex-align-items-center"> <a href="/archives/%E6%8C%82%E8%BD%BD%E5%90%84%E7%A7%8D%E7%9B%98%E5%88%B0linux" class="cover overflow-hidden"> <img class="block w-100 h-100" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="http://api.btstu.cn/sjbz/?lx=fengjing&time=854?index=1" alt="挂载各种盘到Linux" onerror="this.src=`data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=`"> </a> <div class="desc flex-1"> <a href="/archives/%E6%8C%82%E8%BD%BD%E5%90%84%E7%A7%8D%E7%9B%98%E5%88%B0linux" class="title text-link text-clamp">挂载各种盘到Linux</a> <time class="block" datetime="2020-04-20T17:42:00Z">2020-04-21 01:42</time> </div> </li> <li class="item flex flex-align-items-center"> <a href="/archives/kafka" class="cover overflow-hidden"> <img class="block w-100 h-100" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="http://api.btstu.cn/sjbz/?lx=fengjing&time=854?index=2" alt="kafka" onerror="this.src=`data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=`"> </a> <div class="desc flex-1"> <a href="/archives/kafka" class="title text-link text-clamp">kafka</a> <time class="block" datetime="2020-04-08T12:46:00Z">2020-04-08 20:46</time> </div> </li> <li class="item flex flex-align-items-center"> <a href="/archives/crawlab%E7%88%AC%E8%99%AB%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0%E9%83%A8%E7%BD%B2" class="cover overflow-hidden"> <img class="block w-100 h-100" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="http://api.btstu.cn/sjbz/?lx=fengjing&time=854?index=3" alt="Crawlab爬虫管理平台部署" onerror="this.src=`data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=`"> </a> <div class="desc flex-1"> <a href="/archives/crawlab%E7%88%AC%E8%99%AB%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0%E9%83%A8%E7%BD%B2" class="title text-link text-clamp">Crawlab爬虫管理平台部署</a> <time class="block" datetime="2020-04-07T18:24:00Z">2020-04-08 02:24</time> </div> </li> <li class="item flex flex-align-items-center"> <a href="/archives/goland" class="cover overflow-hidden"> <img class="block w-100 h-100" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="http://api.btstu.cn/sjbz/?lx=fengjing&time=854?index=4" alt="GoLand" onerror="this.src=`data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=`"> </a> <div class="desc flex-1"> <a href="/archives/goland" class="title text-link text-clamp">GoLand</a> <time class="block" datetime="2020-04-07T15:39:16Z">2020-04-07 23:39</time> </div> </li> <li class="item flex flex-align-items-center"> <a href="/archives/%E5%B5%8C%E5%85%A5%E5%BC%8F%E8%BD%AF%E7%A1%AC%E4%BB%B6" class="cover overflow-hidden"> <img class="block w-100 h-100" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-lazy-src="http://api.btstu.cn/sjbz/?lx=fengjing&time=854?index=5" alt="嵌入式软硬件" onerror="this.src=`data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=`"> </a> <div class="desc flex-1"> <a href="/archives/%E5%B5%8C%E5%85%A5%E5%BC%8F%E8%BD%AF%E7%A1%AC%E4%BB%B6" class="title text-link text-clamp">嵌入式软硬件</a> <time class="block" datetime="2020-04-06T23:42:00Z">2020-04-07 07:42</time> </div> </li> </ul> </section> </div> </aside> </main> <footer class="footer text-center"> <div class="copyright">© 2020 - 2024 By LeoLan的小站</div> <div class="icp"> <a href="https://beian.miit.gov.cn/?token=0a8070f6-065c-4796-89be-75528400a7a4#/Integrated/index">备案号:粤ICP备16026009号</a> </div> <div class="powered">Powered by <a class="halo" href="https://halo.run/" target="_blank">Halo</a> | 🌈 Theme by <a class="theme" title="当前主题:Butterfly" href="https://github.com/dhjddcn/halo-theme-butterfly" target="_blank">小红</a></div> </footer> <div class="adsorption z-80 fixed"> <button class="show-tocbot btn-effect text-center none" type="button" title="目录"> <i class="fas fa-list-ul"></i> </button> <button class="switch-model block btn-effect text-center" type="button" title="浅色和深色模式转换"> <i class="fas fa-adjust"></i> </button> <button class="back-top block btn-effect text-center" type="button" title="回到顶部"> <i class="fa-solid fa-up"></i> </button> </div> <div class="global-mask fixed w-100 z-100 h-100 left-0 top-0 none"></div> </div> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/plugins/jquery/jquery.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/plugins/lazyLoad/lazyLoad.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/plugins/universe/universe.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/plugins/Qmsg/Qmsg.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/js/global.min.js?v=2.0.5"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/plugins/fancybox/fancybox.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/plugins/clipboard/clipboard.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/plugins/tocbot/tocbot.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/js/post.min.js?v=2.0.5"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/halo-theme-butterfly/templates/assets/plugins/busuanzi/busuanzi.pure.mini.js"></script> </body> </html>