目录

制作虚拟机镜像

中心思想:通过 libvirt 运行一个虚拟机(domain),并保存其对应的 domain 的镜像文件与配置文件,然后就可以在其他机器通过 virsh define + start 或者 virt-install 启动。

说明:下面环境都是在 centos 上制作基于 KVM 的虚拟机镜像。

1 从 ISO 镜像安装

最基本的安装方式,通过安装并运行一个新的虚拟机,然后得到对应的配置文件与镜像文件。

1.1 手动安装

最基本的安装方式,通过 ISO 文件进行安装:

  1. 下载 ISO 镜像文件,镜像文件在各个镜像站中就可以找到。(因为不使用图形界面,所以下载的是非图形化的 ISO)

  2. 通过 virt-install 命令安装镜像(因为使用的是非图形化的安装,所以参数有一些不一样)

    1
    2
    3
    4
    
    virt-install --name guest1_fromiso --memory 2048 --vcpus 2 \
        --disk size=8 --location CentOS-7-x86_64-DVD-2003.iso \
        --os-type Linux --os-variant=centos7.0  --virt-type kvm \
        --boot menu=on  --graphics none --console pty --extra-args 'console=ttyS0'
    

    其中要注意几个参数:

    • 因为我们是安装非图形化,所以需要 --location 参数指定 iso,并指定 --boot menu=on 打开安装菜单,最后还需要指定安装信息的输出 --console pty --extra-args 'console=ttyS0' 这样安装菜单才能正常展示出来

    • --graphics none 指定非图形化;

    • --network bridge=virbr0,指定网络模式,这里指定 libvirt 默认创建的 bridge 网卡,可以认为这是一个 libvirt 维护内网,安装时选择 dhcp 就可以获得一个可用的内网地址;

      具体 libvirt 的网络模型,后面再单独研究下。

    • -- disk size=8,disk 参数用于指定系统盘,这里指定自动创建一个 8G 的 qcow2 文件,作为系统盘(默认镜像文件保存在 /var/lib/libvirt/images/)目录下;

    这时就会进入虚拟机的安装步骤,具体安装步骤就不赘述了。

    /posts/cloud/vm/%E5%88%B6%E4%BD%9C%E8%99%9A%E6%8B%9F%E6%9C%BA%E9%95%9C%E5%83%8F/img1.png
  3. 安装成功后,可以看到 domain 就被创建了,这就可以得到它的配置文件与镜像文件了。

    1
    2
    3
    4
    
    $ virsh list
    Id    Name                           State
    ----------------------------------------------------
    18    guest1_fromiso                 running
    

1.2 自动安装

可以看到,手动安装需要人为在菜单中选择、配置,这不适用于多个虚拟机的安装。而 RedHat 创建了 kickstart 安装方法,使得整个虚拟机安装流程变得自动化。

这块不了解,具体见红帽官方文档:KICKSTART INSTALLATIONS

2 使用 Cloud Image

当然,上面制作过程中耗时都在安装系统上了,而各个云厂商的虚拟机数量那么多,肯定不会一台台去安装操作系统了。所以,目前最常见的都是直接下载已经安装过系统的虚拟机镜像文件。

但是这样的虚拟机是没有特殊配置的,例如密码、hostname 都是一致的,所以 cloud-init 出现,用于在第一次启动虚拟机时进行系统的配置。

所以,最快速的制作方法就是:虚拟机镜像文件 + cloud-init 配置。

2.1 cloud-init

下面内容都来自于文档,这里仅为自己做个记录。

首先明确 cloud init 的功能:系统第一次启动时,cloud init 相关的进程会根据配置信息去进行系统的配置,包括:设置 hostname、ssh key、password 等;

2.1.1 基本概念

  • metadata:包含服务器信息,用于 cloud-init 配置;

  • userdata:包含 cloud-init 系统配置信息,可以是 文件,脚本,yaml 文件等;

  • datasource:cloud-init 读取配置数据的来源,包含大部分云厂商,当然,也可以来自本地的文件 (NoCloud datasource);

2.1.2 运行过程

cloud init 设置包括五个阶段:

  1. Generator

    机器启动阶段,systemd 的一个 generator 将会决定是否将 cloud-init.target(target 可以简单认为特定事件下触发的一组 unit)包含在启动过程中。这就表示启动 cloud-init。

    默认情况下,generator 会启动 cloud-init,除非以下情况:

    • /etc/cloud/cloud-init.disabled 文件存在;
    • 内核启动命令行 /proc/cmdline 中包含 “cloud-init=disabled”。如果是容器中运行,会读取环境变量 KERNEL_CMDLINE

    而下面的步骤,就是由 target 包含的各个 unit 执行的。

  2. Local

    cloud-init-local.service 执行,主要目的:找到 “local” 的 datasource,根据配置网络。

    配置网络有三种情况:

    1. 首先,根据传入配置 “metadata” 配置网络;
    2. 当上面情况失败,直接配置 “dhcp on eth0”;
    3. 如果 /etc/cloud/cloud.cfg 配置文件中禁用了网络:network: {config: disabled},那么就不进行网络配置;
  3. Init、Config、Final 阶段

    对应 service 为 cloud-init.servicecloud-config.servicecloud-final.service

    通过 local 阶段,网络已经配置好了,并且已经得到了 metadata。而 /etc/cloud/cloud.cfg 配置定义了剩下三个阶段对应的任务,也就是 module。

    /posts/cloud/vm/%E5%88%B6%E4%BD%9C%E8%99%9A%E6%8B%9F%E6%9C%BA%E9%95%9C%E5%83%8F/img2.png

    cloud init 通过一些缓存信息来判断机器是否经过初始化,通过 cloud-init clean 也可以手动清理缓存信息。

    /var/log/cloud-init.log 记录了 cloud-init 运行的完整过程。

2.2 制作镜像

下面就开始进行镜像制作:

  1. 下载 cloud image,这里使用中科大提供的:

    1
    
    $ wget  https://mirrors.ustc.edu.cn/centos-cloud/centos/7/images/CentOS-7-x86_64-GenericCloud-2003.qcow2
    
    修改密码

    当然,该镜像其实就可以直接进行 virt-install 来启动(因为我们没有配置文件,所以通过 virt-install 来启动并生成配置文件),但是不知道密码,也搜不到,无法登陆进入。不过你也可以使用下面命令来设置密码后进行登陆:

    1
    
    $ virt-customize -a CentOS-7-x86_64-GenericCloud-2003.qcow2 --root-password password:yourpassword
    
  2. 因为 cloud-init 需要一个 datasource,而我们没有使用云厂商,所以使用 NoCloud 形式,按照官方示例创建一个 disk 文件。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    # 创建 user-data 与 meta-date 配置文件
    $ cat meta-data
    instance-id: guest1
    local-hostname: guest1
    
    $ cat user-data
    #cloud-config
    chpasswd:
        expire: false
        list: |
        root: password1
    ssh_pwauth: True
    
    # 生成 disk 文件,包含 userdata 与 metadata 配置数据
    $ genisoimage  -output seed.iso -volid cidata -joliet -rock user-data meta-data
    
  3. 创建并运行虚拟机。

    1
    2
    3
    4
    5
    
    $ virt-install --memory 2048 --vcpus 2 --name guest2 \
        --disk CentOS-7-x86_64-GenericCloud-2003.qcow2 --disk seed.iso \
        --os-type Linux --os-variant centos7.0 --virt-type kvm \
        --graphics none --network default \
        --import
    
    • --disk CentOS-7-x86_64-GenericCloud-2003.qcow2:制定系统盘;
    • --import:跳过安装过程,因为已经安装好操作系统,不需要进行安装过程;
    • --disk seed.iso:传递 cloud-init datasource 信息;

    虚拟机启动过程中,可以看到 cloud-init 配置信息的一些打印:

    /posts/cloud/vm/%E5%88%B6%E4%BD%9C%E8%99%9A%E6%8B%9F%E6%9C%BA%E9%95%9C%E5%83%8F/img3.png

    最后根据配置的密码成功进入:

    /posts/cloud/vm/%E5%88%B6%E4%BD%9C%E8%99%9A%E6%8B%9F%E6%9C%BA%E9%95%9C%E5%83%8F/img4.png
  4. CentOS-7-x86_64-GenericCloud-2003.qcow2 就是虚拟机经过配置的镜像文件,而 libvirt 启动所需的配置文件就是 /etc/libvirt/qemu/guest1.xml

参考