[实验] 通过 Nginx + Keepalived 实现网站负载均衡加高可用

纪念:站主于 2021 年 2 月完成了此开源实验,并将过程中的所有命令经过整理和注释以后,形成以下教程

步骤目录:

步骤一:拓扑图
1.1 服务器列表
1.2 拓扑图
1.3 拓扑图简介

步骤二: 系统环境要求

步骤三:搭建网站服务
3.1 在 web1 上搭建网站服务
3.1.1 在 web1 上安装 Nginx
3.1.2 给 web1 制定网页
3.1.3 启动 Nginx 并将它设置为开机自启
3.2 在 web2 上搭建网站服务
3.2.1 在 web2 上安装 Apache
3.2.2 给 web2 制定网页
3.2.3 启动 Apache 并将它设置为开机自启

步骤四:搭建代理服务
4.1 安装 Nginx
4.2 修改 Nginx 配置文件
4.3 启动 Nginx 并将它设置为开机自启

步骤五:搭建高可用服务
5.1 安装 Keepalived
5.2 创建 Keepalived 检查脚本
5.3 修改 proxy1 上的 Keepalived 配置文件
5.4 修改 proxy2 上的 Keepalived 配置文件
5.5 启动 Keepalived 并将它设置为开机自启

步骤六:测试 web 负载均衡加高可用
6.1 正常情况下测试网站服务
6.2 在单节点故障的情况下测试网站服务
6.2.1 关闭 proxy1、proxy2、web1、web2 中的任意一台服务器
6.2.2 测试网站服务

具体的操作步骤:

步骤一:拓扑图
1.1 服务器列表

client enp1s0: 172.16.1.99

proxy1 enp1s0: 172.16.0.101
enp7s0: 172.16.1.101
virtual IP: 172.16.1.100

proxy2 enp1s0: 172.16.0.102
enp7s0: 172.16.1.102

web1 enp1s0: 172.16.0.11

web2 enp1s0: 172.16.0.12

1.2 拓扑图

                      proxy1                                       web1
                      enp7s0:172.16.1.101 enp1s0:172.16.0.101      enp1s0:172.16.0.11
                      virtual IP:172.16.1.100
client
enp1s0:172.16.1.99
                      proxy2                                       web2
                      enp7s0:172.16.1.102 enp1s0:172.16.0.102      enp1s0:172.16.0.12

1.3 拓扑图简介

1) web1 安装 Nginx,web2 安装 Apache 实现网站服务
2) proxy1 和 proxy2 安装 Nginx 实现网站代理,轮询代理 web1、web2 上的网站服务实现负载均衡
3) 虚拟 IP 172.16.1.90 通过 Keepalived 默认放在 proxy1 的 enp7s0 网卡上,如果 proxy1 宕机或者检测到自己 Nginx 代理进程死掉,则虚拟 IP 172.16.1.90 则挂在 proxy2 的 enp7s0 网卡上实现高可用
4) 如果 web1 和 web2 中有一台服务器宕机,则 proxy1 和 proxy2 会自动不再向这台服务器请求网站服务,直到它恢复正常
5) 最终达到的效果是 client 向虚拟 IP 请求网站服务,此时如果 proxy1 正常就代表虚拟 IP 轮询调度 web1 和 web2 上的网站服务,再返回给 client。如果 proxy1 宕机则由 proxy2 代表虚拟 IP 完成次操作

步骤二: 系统环境要求

1) 所有服务器的系统都需要是 CentOS 8 版本
2) 所有服务器都要关闭防火墙
3) 所有服务器都要关闭 SELinux
4) 所有服务器系统都要配置好可用的软件源
5) 需要按照拓扑图给对应的服务器配置好 IP 地址和主机名
6) client 的 enp1s0 网卡、proxy1 的 enp7s0 网卡和 proxy2 的 enp7s0 网卡要可以相互 ping 通自己和对方的 IP
7) proxy1 的 enp1s0 网卡、proxy2 的 enp1s0 网卡、web1 的 enp1s0 网卡和 web2 的 enp1s0 网卡要可以相互 ping 通自己和对方的 IP 地址

步骤三:搭建网站服务
3.1 在 web1 上搭建网站服务
3.1.1 在 web1 上安装 Nginx

(只在 web1 上执行以下步骤)

# yum -y install nginx

3.1.2 给 web1 制定网页

(只在 web1 上执行以下步骤)

# echo web1 > /usr/share/nginx/html/index.html

3.1.3 启动 Nginx 并将它设置为开机自启

(只在 web1 上执行以下步骤)

# systemctl enable --now nginx

3.2 在 web2 上搭建网站服务
3.2.1 在 web2 上安装 Apache

(只在 web2 上执行以下步骤)

# yum -y install httpd

3.2.2 给 web2 制定网页

(只在 web2 上执行以下步骤)

# echo web2 > /var/www/html/index.html

3.2.3 启动 Apache 并将它设置为开机自启

(只在 web2 上执行以下步骤)

# systemctl enable --now httpd

步骤四:搭建代理服务
4.1 安装 Nginx

(分别在 proxy1 和 proxy2 上执行以下步骤)

# yum -y install nginx

4.2 修改 Nginx 配置文件

(分别在 proxy1 和 proxy2 上执行以下步骤)

# vi /etc/nginx/nginx.conf

将部分内容修改如下:

......
http {
    upstream webserver {
        server 172.16.0.11:80;
        server 172.16.0.12:80;
    }
......
    server {
        listen       80;

        location / {
        proxy_pass http://webserver;
        }
    }
......
}

4.3 启动 Nginx 并将它设置为开机自启

(分别在 proxy1 和 proxy2 上执行以下步骤)

# systemctl enable --now nginx

步骤五:搭建高可用服务
5.1 安装 Keepalived

(分别在 proxy1 和 proxy2 上执行以下步骤)

# yum -y install keepalived

5.2 创建 Keepalived 检查脚本

(分别在 proxy1 和 proxy2 上执行以下步骤)

# vi /etc/keepalived/nginx_check.sh

创建以下内容:

#!/bin/bash

if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
    systemctl stop nginx
    sleep 5
    if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
        systemctl stop keepalived
    fi
fi

(补充:这里以检测 Nginx 没启动就启动 Nginx,5 秒后 Nginx 要是还没有启动就关闭 keepalived 为例)

5.3 修改 proxy1 上的 Keepalived 配置文件

(只在 proxy1 上执行以下步骤)

# vim /etc/keepalived/keepalived.conf

将全部内容修改如下:

! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id proxy1
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2
weight 20
}

vrrp_instance VI_1 {
    state MASTER
    interface enp7s0
    virtual_router_id 90
    priority 101
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
    chk_nginx
    }
    virtual_ipaddress {
        172.16.1.100
    }
}


补充:
1) script “/etc/keepalived/nginx_check.sh” 代表使用的检测脚本是 /etc/keepalived/nginx_check.sh
2) interface enp7s0 代表虚拟 IP 将挂载在 enp7s0 网卡上
3) priority 代表修建级是 101,数字越大优先级越高
4) 172.16.1.100 代表虚拟 IP 是 172.16.1.100

5.4 修改 proxy2 上的 Keepalived 配置文件

(只在 proxy2 上执行以下步骤)

# vim /etc/keepalived/keepalived.conf

将全部内容修改如下:

! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id proxy1
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2
weight 20
}

vrrp_instance VI_1 {
    state MASTER
    interface enp7s0
    virtual_router_id 90
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
    chk_nginx
    }
    virtual_ipaddress {
        172.16.1.100
    }
}


补充:
1) script “/etc/keepalived/nginx_check.sh” 代表使用的检测脚本是 /etc/keepalived/nginx_check.sh
2) interface enp7s0 代表虚拟 IP 将挂载在 enp7s0 网卡上
3) priority 代表修建级是 99,数字越大优先级越高
4) 172.16.1.100 代表虚拟 IP 是 172.16.1.100

5.5 启动 Keepalived 并将它设置为开机自启

(分别在 proxy1 和 proxy2 上执行以下步骤)

# systemctl enable --now keepalived.service

步骤六:测试网站负载均衡加高可用
6.1 正常情况下测试网站服务

(只在 client 上执行以下步骤)

# curl 172.16.1.100

(补充:重复以上命令会发现重复显示 web1 和 web2)

6.2 在单节点故障的情况下测试网站服务
6.2.1 关闭 proxy1、proxy2、web1、web2 中的任意一台服务器

(只在 proxy1、proxy2、web1、web2 中的任意一台服务器上执行以下步骤)

# poweroff

6.2.2 测试网站服务

(只在 client 上执行以下步骤)

# curl 172.16.1.100

(补充:重复以上命令会发现重复显示 web1 和 web2)

随笔 10

人类曾因为各种原因,表现出了对同类的忠诚和自我牺牲。而在人类所有的忠诚和自我牺牲中,最为坚固的,莫过于,对此人人格魅力、优秀品质或出众能力的认可和崇敬,同时与此人拥有共同的人生目标和美好的理想,并愿意共同为这些目标和理想而努力。这一现象,会让爱情、友情、亲情以及普世的博爱变得无比牢固,任凭海枯石烂也屹立不倒。

所以,祝大家对他(她)人的忠诚,以及他(她)人对你的忠诚不仅仅是出于共同的经历和责任,还包括我以上所述的内容。既是指爱情,也是指友情,也是指亲情,也是指博爱……

随笔 9

银色的细雨敲打着充满叹息的大地
起起伏伏的声线,努力表达着自己心中那份苦涩的温柔
唯美的风景被交替的四季驱使, 无法坚持住自己最美丽的样子
守望着那些看不见的星辰,那些消失了的宇宙。该以什么之名,幻想出一种怎样的梦境?
不管是清晰还是模糊,不管是胸有成竹还是力不从心。诞生于这个世界的意义,应从当下开始去创造
心中的启明星,会在静谧中,开始自己璀璨亦朦胧的闪耀

[步骤] KVM 虚拟机模板的创建 (openSUSE Leap 15 版)

注意:

在创建 KVM 虚拟机之前要先安装 KVM 并创建 KVM 虚拟网络

软件准备:

在 openSUSE 官网上下载安装系统所需要的镜像:

https://software.opensuse.org/distributions/leap

正文:

步骤目录:

步骤一:理解创建 KVM 虚拟机模板的目的

步骤二:为这个虚拟机创建硬盘文件
1.1 创建硬盘文件
1.2 确认硬盘文件已创建

步骤三:使用 KVM 和刚刚创建的硬盘文件新安装一台虚拟机
3.1 启动 KVM 的 virt-manager
3.2 在 virt-manager 上的左上角点击文件之后 “点击新建虚拟机”
3.2.1 选择以本地安装介质的方式安装系统
3.2.2 选择安装系统的系统镜像
3.2.3 设置内存大小和 CPU 核心数
3.2.4 选择用刚刚创建的硬盘文件来安装系统
3.2.5 给虚拟机命名并选择虚拟网络
3.2.6 开始安装系统
3.2.7 进入 “Language, Keyboard and License Agreement” 后选择系统语言,再点击 “Next”
3.2.8 当出现 “Activate online repositories now?” 时,点击 “No”
3.2.9 进入 “System Role” 后选择 “Server”,再点击 “Next”
3.2.10 进入 “Suggested Partitioning” 后点击 “Guided Setup”
3.2.11 进入 “Partitioning Scheme” 后点击 “Next”
3.2.12 进入 “Filesystem Options” 后 “File System Type“ 选择 “XFS”,再点击 “Next”
3.2.13 回到 “Suggested Partitioning” 后点击 “Next”
3.2.14 进入 “Clock and Time Zone” 后选择时区,再点击 “Next”
3.2.15 进入 “Local User” 后选择 “Skip User Creation” 并点击 “Next”
3.2.16 进入 “Authentication for the System Administrator “root”” 后给 root 设置密码,再点击 “Next”
3.2.17 如果出现 “YaST2 The password is too simple” 则点击 “Yes”
3.2.18 进入 “Installation Settings” 后点击 “Next”
3.2.19 当出现 “Confirm Installation” 时点击 “Install”
3.2.20 当出现 “The system will reboot now…” 时,点击 “Ok”
3.2.21 在安装系统的过程中需要注意的内容总结

步骤四:进入新创建虚拟机修改配置
4.1 添加 Console 配置
4.1.1 修改 grub 内核配置文件
4.1.2 使修改的 grub 内核配置生效
4.2 将系统自动挂载的硬盘从使用 uuid 换成硬件路径
4.2.1 显示根分区的 UUID
4.2.2 在自动挂载文件里将根分区的 UUID 换成硬件路径
4.3 删除不用的软件
4.4 进行分区扩展
4.4.1 安装分区扩展软件
4.4.2 设置开机自动扩容根目录
4.4.2.1 创建开机自动扩容根目录的配置文件
4.4.2.2 给开机自启配置文件相应的权限
4.5 只使用本地软件源(选做)
4.5.1 禁用所有软件源(选做)
4.5.2 添加本地软件源(选做)
4.5.3 添加本地软件源(选做)
4.6 修改虚拟机系统的名称
4.7 启用 serial 服务实现通过 virsh console 命令控制虚拟机
4.8 清除虚拟系统的历史命令
4.9 关闭虚拟机

步骤五:修改新创建的虚拟机配置文件

步骤六:此时就可以将此虚拟机的硬件文件作为模板进行批量克隆虚拟机了

具体的操作步骤:

步骤一:理解创建 KVM 虚拟机模板的目的

主要用于批量克隆出新的 KVM 机器,节约创建新虚拟机的时间

步骤二:为这个虚拟机创建硬盘文件
1.1 创建硬盘文件

(只在真机上执行以下步骤)

# qemu-img create -f qcow2 /var/lib/libvirt/images/template_opensuse_leap_15_10g.qcow2 10G

(补充:这里以创建 10G 大小的 template_opensuse_leap_15_10g.qcow2 硬盘文件为例)

1.2 确认硬盘文件已创建

(只在真机上执行以下步骤)

# ls /var/lib/libvirt/images/ | grep template_opensuse_leap_15_10g.qcow2

(补充:这里以确认 template_opensuse_leap_15_10g.qcow2 硬盘文件为例)

步骤三:使用 KVM 和刚刚创建的硬盘文件新安装一台虚拟机
3.1 启动 KVM 的 virt-manager

(只在真机上执行以下步骤)

# virt-manager

3.2 在 virt-manager 上的左上角点击文件之后 “点击新建虚拟机”

(只在真机上执行以下步骤)

(步骤略)

3.2.1 选择以本地安装介质的方式安装系统

(只在真机上执行以下步骤)

(图:1)

3.2.2 选择安装系统的系统镜像

(只在真机上执行以下步骤)

(图:2)

(补充:这里以使用 openSUSE-Leap-15.2-DVD-x86_64.iso 系统镜像为例)

3.2.3 设置内存大小和 CPU 核心数

(只在真机上执行以下步骤)

(图:3)

(补充:这里以设置 2048 MiB 内容和 2 核 CPU 为例)

3.2.4 选择用刚刚创建的硬盘文件来安装系统

(只在真机上执行以下步骤)

(图:4)

(补充:这里以使用 template_opensuse_leap_15_10g.qcow2 硬盘文件为例)

3.2.5 给虚拟机命名并选择虚拟网络

(只在真机上执行以下步骤)

(注意:虚拟网络必须提前创建好)

(图:5)

(补充:这里以将虚拟机命名为 template_opensuse_leap_15_10g 并使用 0 网络为例)

3.2.6 开始安装系统

(只在真机上执行以下步骤)

(图:6)

3.2.7 进入 “Language, Keyboard and License Agreement” 后选择系统语言,再点击 “Next”

(只在真机上执行以下步骤)

(图:7)

3.2.8 当出现 “Activate online repositories now?” 时,点击 “No”

(只在真机上执行以下步骤)

(图:8)

3.2.9 进入 “System Role” 后选择 “Server”,再点击 “Next”

(只在真机上执行以下步骤)

(图:9)

3.2.10 进入 “Suggested Partitioning” 后点击 “Guided Setup”

(只在真机上执行以下步骤)

(图:10)

3.2.11 进入 “Partitioning Scheme” 后点击 “Next”

(只在真机上执行以下步骤)

(图:11)

3.2.12 进入 “Filesystem Options” 后 “File System Type“ 选择 “XFS”,再点击 “Next”

(只在真机上执行以下步骤)

(图:12)

3.2.13 回到 “Suggested Partitioning” 后点击 “Next”

(只在真机上执行以下步骤)

(图:13)

3.2.14 进入 “Clock and Time Zone” 后选择时区,再点击 “Next”

(只在真机上执行以下步骤)

(图:14)

3.2.15 进入 “Local User” 后选择 “Skip User Creation” 并点击 “Next”

(只在真机上执行以下步骤)

(图:15)

3.2.16 进入 “Authentication for the System Administrator “root”” 后给 root 设置密码,再点击 “Next”

(只在真机上执行以下步骤)

(图:16)

3.2.17 如果出现 “YaST2 The password is too simple” 则点击 “Yes”

(只在真机上执行以下步骤)

(图:17)

3.2.18 进入 “Installation Settings” 后点击 “Next”

(只在真机上执行以下步骤)

(图:18)

3.2.19 当出现 “Confirm Installation” 时点击 “Install”

(只在真机上执行以下步骤)

(图:19)

3.2.20 当出现 “The system will reboot now…” 时,点击 “Ok”

(只在真机上执行以下步骤)

(图:20)

3.2.21 在安装系统的过程中需要注意的内容总结

(只在真机上执行以下步骤)

1) 一定要使用刚刚创建的 template_opensuse_leap_15_10g.qcow2 作为安装虚拟机的硬件文件
2) 虚拟机网络 “0” 要提前创建好
3) 只分一个分区,只设置一个挂载点挂载到根,使用标准硬盘,硬盘格式是 XFS
4) 选择最小化安装系统

步骤四:进入新创建虚拟机修改配置
4.1 添加 Console 配置
4.1.1 修改 grub 内核配置文件

(只在虚拟机上执行以下步骤)

# vi /etc/default/grub

将全部内容修改如下:

# If you change this file, run 'grub2-mkconfig -o /boot/grub2/grub.cfg' afterwards to update
# /boot/grub2/grub.cfg.

# Uncomment to set your own custom distributor. If you leave it unset or empty, the default
# policy is to determine the value from /etc/os-release
GRUB_DISTRIBUTOR=
GRUB_DEFAULT=saved
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=8
GRUB_CMDLINE_LINUX_DEFAULT="splash=silent mitigations=auto quiet"
GRUB_SERIAL_COMMAND="serial --unit=1 --speed=115200"
GRUB_CMDLINE_LINUX="biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8"
GRUB_DISABLE_LINUX_UUID="true"
GRUB_ENABLE_LINUX_LABEL="true"
GRUB_DISABLE_RECOVERY="true"

# Uncomment to automatically save last booted menu entry in GRUB2 environment

# variable `saved_entry'
# GRUB_SAVEDEFAULT="true"
#Uncomment to enable BadRAM filtering, modify to suit your needs

# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
# GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
#Uncomment to disable graphical terminal (grub-pc only)

GRUB_TERMINAL="gfxterm"
# The resolution used on graphical terminal
#note that you can use only modes which your graphic card supports via VBE

# you can see them in real GRUB with the command `vbeinfo'
GRUB_GFXMODE="auto"
# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
# GRUB_DISABLE_LINUX_UUID=true
#Uncomment to disable generation of recovery mode menu entries

# GRUB_DISABLE_RECOVERY="true"
#Uncomment to get a beep at grub start

# GRUB_INIT_TUNE="480 440 1"
GRUB_BACKGROUND=
GRUB_THEME=/boot/grub2/themes/openSUSE/theme.txt
SUSE_BTRFS_SNAPSHOT_BOOTING="true"
GRUB_DISABLE_OS_PROBER="false"
GRUB_ENABLE_CRYPTODISK="n"
GRUB_CMDLINE_XEN_DEFAULT="vga=gfx-1024x768x16"

4.1.2 使修改的 grub 内核配置生效

(只在虚拟机上执行以下步骤)

# grub2-mkconfig -o grub

4.2 将系统自动挂载的硬盘从使用 uuid 换成硬件路径
4.2.1 显示根分区的 UUID

(只在虚拟机上执行以下步骤)

# blkid
/dev/vda1: UUID="53ee2f87-89b8-4cd7-a4dc-0957d28f4831" TYPE="xfs" PARTUUID="3d8377ef-01"

(补充:这里的 UUID 是: 53ee2f87-89b8-4cd7-a4dc-0957d28f4831)

4.2.2 在自动挂载文件里将根分区的 UUID 换成硬件路径

(只在虚拟机上执行以下步骤)

# vi /etc/fstab

将以下内容:

......
UUID=53ee2f87-89b8-4cd7-a4dc-0957d28f4831 /                   xfs     defaults        0 0

(补充:这里的 UUID 是: 53ee2f87-89b8-4cd7-a4dc-0957d28f4831)

修改为:

......
/dev/vda1 /                   xfs     defaults        0 0

4.3 删除不用的软件

(只在虚拟机上执行以下步骤)

# zypper -n rm firewalld-*

4.4 进行分区扩展
4.4.1 安装分区扩展软件

(只在虚拟机上执行以下步骤)

# zypper -n in growpart

4.4.2 设置开机自动扩容根目录
4.4.2.1 创建开机自动扩容根目录的配置文件

# vim /etc/init.d/after.local

创建以下内容:

/usr/bin/growpart /dev/sda1
/usr/sbin/xfs_growfs /

4.4.2.2 给开机自启配置文件相应的权限

# chmod 755 /etc/init.d/after.local

4.5 只使用本地软件源(选做)
4.5.1 禁用所有软件源(选做)

(只在虚拟机上执行以下步骤)

# zypper mr -da

4.5.2 添加本地软件源(选做)

(只在虚拟机上执行以下步骤)

# zypper ar -fcg http://10.0.0.254/openSUSE-Leap-15/ lan

(注意: http://10.0.0.254/openSUSE-Leap-15/ 需要根据真实环境的情况进行更改)

4.5.3 添加本地软件源(选做)

(只在虚拟机上执行以下步骤)

# zypper ref

4.6 修改虚拟机系统的名称

(只在虚拟机上执行以下步骤)

# hostnamectl set-hostname template_opensuse_leap_15_10g

4.7 启用 serial 服务实现通过 virsh console 命令控制虚拟机

(只在虚拟机上执行以下步骤)

# systemctl start serial-getty@ttyS0
# systemctl enable serial-getty@ttyS0

4.8 清除虚拟系统的历史命令

(只在虚拟机上执行以下步骤)

# history -c

4.9 关闭虚拟机

(只在虚拟机上执行以下步骤)

# poweroff

步骤五:修改新创建的虚拟机配置文件

删除配置文件里 cdrom 相关的部分

# vim /etc/libvirt/qemu/template_opensuse_leap_15_10g.xml

删除以下内容:

......
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <source file='/test/iso/openSUSE-Leap-15.2-DVD-x86_64.iso'/>
      <target dev='sda' bus='sata'/>
      <readonly/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
......

步骤六:此时就可以将此虚拟机的硬件文件作为模板进行批量克隆虚拟机了

(只在真机上执行以下步骤)