OpenStack镜像管理与制作(二)

课前回顾

云平台镜像定制三种方式详细对比

对比维度 方式一:基于预制镜像与快照 方式二:使用系统修改工具(Guestfish/Guestmount) 方式三:手动创建虚拟磁盘镜像
核心原理 1. 从官方源获取预制镜像。
2. 以此镜像启动一个虚拟机实例。
3. 登录实例进行配置修改(如安装软件、修改配置)。
4. 对该实例创建快照,快照即生成新的定制镜像。
1. 选择一个基础镜像文件(如.qcow2)。
2. 使用 Guestfish(交互式命令行)或 Guestmount(挂载到宿主机目录)工具。
3. 直接读写镜像内的文件系统,无需启动虚拟机。
4. 修改完成后卸载工具,得到定制后的镜像文件。
1. 使用 KVM/Virt-install 等虚拟化工具。
2. 从一个纯净的操作系统ISO安装文件开始。
3. 像安装物理机一样,通过VNC远程连接,完整地安装操作系统和所需软件。
4. 安装配置完成后,关闭虚拟机,其磁盘文件即为定制好的镜像。
技术门槛
过程直观,类似于常规的服务器运维。只需要会操作Linux系统和OpenStack控制台。

需要了解Guestfish的命令行操作,或理解Guestmount的挂载概念。需要清楚目标系统配置文件的位置。

需要熟悉虚拟化技术、操作系统安装过程、驱动注入(如Windows需加载VirtIO驱动)和复杂的后期优化(如安装Cloudbase-Init)。
定制深度 中度定制
适合在已有系统上进行应用层的定制,如:
- 安装软件包(如Nginx, Java)。
- 修改系统配置(如SSH, 内核参数)。
- 创建用户、部署代码。
深度定制(系统层)
适合进行底层系统的修改,如:
- 直接修改 /etc/shadow重置root密码。
- 编辑系统启动脚本(如 /root/.bashrc)。
- 注入文件、修改固件配置等。
尤其适合无法或不想启动实例的场景,如修复系统密码。
完全定制
定制程度最高,从零开始构建。
- 选择特定的系统版本和组件。
- 精细分区。
- 安装特定驱动和优化补丁。
- 是制作非标准系统(如Windows、BSD)或需要特定安全基线镜像的唯一或最佳途径
效率与速度 较快
省去了操作系统安装的时间。定制过程是在运行的系统中进行,速度快。但需要经历启动实例 -> 配置 -> 关机 -> 打快照的完整周期。
非常快
直接对镜像文件进行操作,无需启动整个操作系统内核,效率极高。是进行小范围修改最快的方法。
非常慢
需要完整经历操作系统安装、更新、软件安装、配置等所有步骤,耗时最长。
主要优势 - 简单易用,容易理解和上手。
- 无缝集成云平台工作流。
- 利于快速迭代和测试。
- 高效快捷,尤其适合小修改。
- 不依赖云平台,可在任意Linux主机上进行。
- 强大灵活,可进行底层修改。
- 控制力极强,可打造最纯净、最符合要求的镜像。
- 是制作非Linux系统高度专用镜像标准方法
主要劣势 - 定制深度受限于运行的实例环境。
- 镜像中可能包含临时文件、缓存等冗余数据,需要清理。
- 依赖于云平台的快照功能。
- 有技术门槛,需要熟悉工具和系统结构。
- 某些复杂的软件安装和配置不如在运行系统中方便。
- 操作有风险,直接修改文件系统可能导致镜像损坏。
- 耗时费力,整个过程非常漫长。
- 技术复杂,涉及虚拟化、网络、存储、操作系统等多个领域。
- 难以自动化和批量处理。
典型应用场景 - 为Java应用快速定制一个包含JDK和Tomcat的CentOS镜像。
- 基于官方Ubuntu镜像安装Python环境,用于数据科学项目。
- 批量重置一批镜像的root密码。
- 在所有基础镜像中统一植入一个公司的CA证书。
- 修复一个因配置文件错误而无法启动的镜像。
- 为企业环境定制一个符合安全规范的Windows Server镜像,并预装必要的代理软件。
- 制作一个包含特定硬件驱动或特殊文件系统的Linux镜像。
- 需要从特定版本ISO开始构建,且无预制镜像可用时。

虚拟机镜像制作方法

OpenStack平台所使用的镜像文件是一种虚拟机镜像,我们简称为镜像。而虚拟机镜像本质上是一个包含虚拟磁盘的单个文件,该虚拟磁盘上安装了可引导的操作系统。

上一节课已经介绍了通过下载官方预制的虚拟机镜像,这种途径获取到的镜像文件大都默认禁用SSH密码身份验证,同时包含cloud-init来支持SSH密钥对和用户数据的注入。通过密钥实现登录之后可以做进一步的定制,最后通过创建快照重新生成新的虚拟机镜像。

以上这种获取、修改、生成新的镜像的方法容易理解、实现过程简单,适用于需要进行轻度定制的场景。如果需要进行深度的定制或者需要定制特定平台的镜像文件时可以通过更多的途径制作镜像。

其他制作虚拟机镜像的方法:

  • 通过工具(Guestfish,guestmount)修改虚拟机镜像
  • 通过工具(Diskimage-builder)创建虚拟机镜像
  • 手动创建虚拟机镜像

实验环境准备

设置控制节点快照版本项目12

  • 右键虚拟机控制节点 -> 设置 -> 处理器,将虚拟化引擎里的勾全部取消,启动控制节点

    1696954933617.png
  • 使用WinSCP工具将需要定制的镜像上传到控制节点,将文件从左侧的windows本地文件D:\云计算上课环境\镜像-文档拖动到右侧的虚拟机内部。

    1696956085852.png

Guestfish使用

Guestfish是一个用于访问和修改虚拟机磁盘镜像的工具,它提供了一种交互式方式来浏览、修改虚拟机的文件系统。

Guestfish安装配置

  • Guestfish软件包安装

    [root@controller ~]# yum -y install libguestfs-tools
  • 执行命令安装libvirt服务。

    [root@controller ~]# yum -y install libvirt
  • 修改libvirt配置vi /etc/libvirt/qemu.conf

    [root@controller ~]# vi /etc/libvirt/qemu.conf
    1696912515114.png
  • 启动libvirt服务。

    [root@controller ~]# systemctl start libvirtd

镜像定制

定制内容是设置centos镜像的root和centos账户的直接登录、开启bash后利用字符打印一个图案。

  1. 安装openssl,生成加密的字符串并复制用于设置root密码。

    [root@controller ~]# yum -y install openssl
    [root@controller ~]# openssl passwd -1 123123
    $1$vNor7zoi$MrzvyJiIETqxfoO.zxgIL0
  2. 需要修改的虚拟机镜像文件名为CentOS-7-x86_64-GenericCloud-2003.qcow2,通过以下命令以root身份挂载为读写模式:

    [root@controller ~]# guestfish --rw -a CentOS-7-x86_64-GenericCloud-2003.qcow2
    
    Welcome to Guestfish, the libguestfs filesystem interactive shell for
    editing virtual machine filesystems.
    
    Type: 'help' for help on commands
    'man' to read the manual
    'quit' to quit the shell
    
    ><fs>

    此时进入Guestfish的会话,提示符为><fs>

    1696954607319.png
  3. 首先在Guestfish提示符下使用run命令启动一个虚拟机才能执行其他操作,该虚拟机将用于执行所有文件操作。

    ><fs> run
  4. 通过list-filesystems命令查看文件系统。

    ><fs> list-filesystems

    作业1:上传显示的镜像分区信息。

  5. 挂载包含根目录的分区并修改文件/etc/shadow用来给root账户设置密码。

    ><fs> mount /dev/sda1 /
    ><fs> vi /etc/shadow

    在文件的第一行的第一、二个冒号中间插入之前复制的所生成的root密码。

    1696956445209.png
  6. 修改/etc/cloud/cloud.cfg文件。

    在第58行下添加plain_text_passwd: '000000'字段用来给centos用户设置初始密码000000

    1696817529748.png
  7. 使用vi修改/root/.bashrc文件,设置bash自启动命令,添加以下命令到最后。

    echo '....................................................................................................'
    echo '....................................................................................................'
    echo '....................................................................................................'
    echo '..........................:*@@@@@@#=...........:-=====--:...........................................'
    echo '........................:#@@@@@@@@@@@-.:+*#%%+-:.........:-+#*=......:+#%%#*:.......................'
    echo '.......................:@@@@@@@@@@@@@@%-.......................:*%:+@@@@@@@@@@*.....................'
    echo '.......................#@@@@@@@@@@@@@-..........  .................#@@@@@@@@@@@@=...................'
    echo '......................=@@@@@@@@@@@-...................................%@@@@@@@@@@...................'
    echo '......................=@@@@@@@@@%:.....................................%@@@@@@@@@:..................'
    echo '........................%@@@@@@#.......................................-@@@@@@@@@...................'
    echo '...............#@#.......*@@@@%.........................................-@@@@@@@+...................'
    echo '........+@@+..#@@%........:*@@-..........................................=@@@@%-........+*:.........'
    echo '........*@@%..%@@#..........:*............................................%#=:.........+@@%.........'
    echo '........-@@@..@@@=..........*.............................................-+......#@@=.=@@%.........'
    echo '.....=%%@@@@#*@@@..........*-..............................................#:.....#@@@%@@@%.........'
    echo '....-@@@@@@@@@@@#.........=*...............................................++......=%@@@@@@@@@@=....'
    echo '....-@@@@@@@@@@@@-........%:...............................................=*.......:@@@@@@@@@@@#...'
    echo '.....@@@@@@@@@@@@........-*................................................:#........@@@@@@@@@@@@*..'
    echo '.....#@@@@@@@@@@#......:%@=.................................................@*......:@@@@@@@@@@@@+..'
    echo '......@@@@@@@@@@*.....#@@@:.................................................@@#......#@@@@@@@@@@-...'
    echo '......@@@@@@@@@@%-...:@@@@+.................................................@@@%:......+@@@@@@@@-...'
    echo '......*@@@@@@@@@@@*=.:@@@@%:................................................@@@@@......+@@@@@@@%:...'
    echo '......-@@@@@@@@@@@@@@@@@@@@%:..............................................+@@@@@%.....=@@@@@@@%....'
    echo '.......%@@@@@@@@@@@@@@@@@@@@@*............................................=@@@@@@@@@@@@@@@@@@@@#....'
    echo '.......:@@@@@@@@@@@@@@@@@@@@@@@=........................................:#@@@@@@@@@@@@@@@@@@@@@#....'
    echo '........+@@@@@@@@@@@@@@@@@@@@@@@@%-...................................:#@@@@@@@@@@@@@@@@@@@@@@@%....'
    echo '.........%@@@@@@@@@@@@@@@@@@@@@@@@@@+.............................:=#@@@@@@@@@@@@@@@@@@@@@@@@@@=....'
    echo '..........=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*-:..................-+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=.....'
    echo '............=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*.......'
    echo '................:-=+##%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@%*=:.........'
    echo '....................................................................................................'
    echo '....................................................................................................'
  8. 卸载挂载点、退出guestfish视图

    ><fs> umount /
    ><fs> exit

验证定制结果

  1. 启动控制节点计算节点,登录192.168.10.20控制台。

  2. 通过命令行上传镜像到openstack

    [root@controller ~]# source admin-login
    [root@controller ~]# openstack image create --disk-format qcow2 --container-format bare   --public --file CentOS-7-x86_64-GenericCloud-2003.qcow2 centos7
  3. 创建网络实例类型,不会的参考前面的笔记。

  4. 创建Centos实例并使用root账户登录(密码是上文配置的123123)验证结果,应该会显示下图所示的屏保动画。

    1697171722897.png

作业2:上传登录后的截图

Guestmount使用

Guestmount是一个用于挂载虚拟机磁盘镜像的工具,它允许在宿主机上将虚拟机磁盘镜像挂载为宿主机文件系统的一部分,从而可以直接访问和修改虚拟机镜像中的文件。Guestmount可以在不启动虚拟机的情况下进行操作,提供了对镜像中文件的读写访问权限。通过Guestmount,可以像操作本地文件系统一样,使用标准的文件操作命令(例如cp、mv、rm 等)

  • Guestmount用法示例

    1. 假设需要修改的虚拟机镜像文件名为centos63_desktop.img,从该文件中挂载根分区到/mnt目录。

      # guestmount -a centos63_desktop.qcow2 -m /dev/vg_centosbase/lv_root --rw /mnt
    2. 当预先不知道具体的挂载点时可以通过选项-i自动决定所用的挂载点。

      # guestmount -a centos63_desktop.qcow2 -i --rw /mnt
    3. 修改完成后卸载挂载点。

      # umount /mnt

Diskimage-builder使用

Diskimage-builder(DIB)是一个用于创建定制化操作系统磁盘镜像的工具。它是一个开源项目,旨在帮助开发者和系统管理员构建适合特定用途的操作系统镜像,例如用于虚拟机、容器、云平台等环境。

  1. Diskimage-builder安装。

    # yum -y install diskimage-builder
  2. 创建一个通用的Ubuntu虚拟磁盘镜像。

    # disk-image-create ubuntu vm
  3. 还可以通过设置命令行选项或者环境变量实现其他镜像的构造。

    # disk-image-create -a armhf ubuntu vm
  4. 除此之外还可以通过YAML文件描述需要构造的镜像。

    # 元素列表,表示构建镜像时要包含的元素
    elements:
    - centos7-minimal
    - install-packages
    
    # 镜像类型,指定生成的镜像格式
    image_types:
    - qcow2
    - raw
    
    # 操作系统发行版和版本
    release: centos7
    
    # 构建参数和配置
    properties:
    # 用户名和密码
    user: myuser
    password: mypassword

手动定制虚拟磁盘镜像

除了可以通过上述的工具在已有的虚拟磁盘文件的基础上进行修改以外还可以手动定制虚拟磁盘镜像,这个过程需要通过ISO CD文件安装操作系统后通过VNC远程安装windows-server虚拟机完成定制。主要分为以下几步:

  1. 通过kvm+qemu方案安装操作系统虚拟机。

  2. 通过vnc连接虚拟机后实现进一步配置、定制。

  3. 上传定制好的系统镜像到OpenStack平台完成验证。

作业与实验环境

超星网址
虚拟机使用Centos7.9,登录账户:root,密码:000000

  1. 设置虚拟机和宿主机共享

    • Cenots7.9关机状态右键->设置,选择选项->共享文件夹->总是启用并添加本地C盘内的镜像文件所在目录:学生机路径D:\云计算上课环境\镜像-文档

      1695229067851.png
    • 安装vm-tools并挂载设备

      [root@localhost ~]# yum -y install open-vm-tools
      [root@localhost ~]# vmhgfs-fuse .host:/ /mnt/hgfs/ -o subtype=vmhgfs-fuse,allow_other
      # 查看共享的文件列表,包含"cn_windows_server_2012_r2_with_update_x64_dvd_6052725.iso"、"virtio-win-0.1.185.iso"两个文件
      [root@localhost ~]# ls /mnt/hgfs/镜像-文档
      # 关闭SELinux
      [root@localhost ~]# setenforce 0
  2. 安装虚拟化相关的软件包。

    [root@localhost ~]#curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    [root@localhost ~]#curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
    # virt-install 是一个命令行工具,用于在虚拟化环境中创建和安装虚拟机
    [root@localhost ~]# yum install -y qemu-kvm libvirt virt-install
    # 上面安装如果报错的,需要根据进程ID强制关闭占用的进程
    [root@localhost ~]# kill -9 <每个人进程的ID>
  3. 修改/etc/libvirt/qemu.conf,设置libvirt root权限和VNC远程虚拟机配置。

    1697515972974.png 1697515691473.png
  4. 启动libvirt服务,关闭防火墙服务。

    [root@localhost ~]# systemctl disable --now firewalld
    [root@localhost ~]# systemctl enable --now libvirtd
  5. 创建大小为20G的qcow2格式的虚拟磁盘文件。

    # 这里创建的虚拟磁盘文件实际位于Windows上面
    [root@localhost ~]# qemu-img create -f qcow2 /mnt/hgfs/镜像-文档/ws2012.qcow2 20G
    Formatting 'ws2012.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=21474836480 lazy_refcounts=off refcount_bits=16

windows-server系统安装

  1. 进入共享目录

    [root@localhost ~]# cd /mnt/hgfs/镜像-文档
  2. 执行virt-install命令启动Win-server操作系统。

    virt-install --connect qemu:///system \
    --name ws2012 --ram 2048 --vcpus 2 \
    --network network=default,model=virtio \
    --disk path=ws2012.qcow2,format=qcow2,device=disk,bus=virtio \
    --cdrom cn_windows_server_2012_r2_with_update_x64_dvd_6052725.iso \
    --disk path=virtio-win-0.1.185.iso,device=cdrom \
    --graphics vnc,listen=0.0.0.0 --os-type windows --os-variant win2k12 \
    --boot cdrom,menu=on
    • 其他虚拟机管理命令

      1. 列出虚拟机:virsh list --all

      2. 强制停止虚拟机:virsh destroy <虚拟机名字>

      3. 删除虚拟机:virsh undefine <虚拟机名字>

      4. 关闭虚拟机:virsh shutdown <虚拟机名字>

      5. 重启虚拟机:virsh reboot <虚拟机名字>

      6. 打开虚拟机:virsh start <虚拟机名字>

  3. 打开RealNVC工具,在地址栏输入虚拟机的ip:<端口>通过VNC远程登录启动的windows server虚拟机。

    1697516314212.png

    如果没有看到系统安装界面,在远程窗口中点击发送ctrl+alt+delete重启虚拟机,选择CD-ROM所在分区启动。

    1697517877178.png 1697517645685.png

    作业3:在系统安装界面截图上传。
    系统密钥:NB4WH-BBBYV-3MPPC-9RCMV-46XCB
    安装系统时选择第二个带GUI桌面的标准版,安装方式选择第二个。

    1697517974873.png 1697518045888.png
  4. 选择加载驱动程序->浏览从以下路径加载scsi和网络驱动。

    D:\virtio-win-0.1.185\viostor\2k12r2\amd64
    D:\virtio-win-0.1.185\NETKVM\2k12r2\amd64

    1696737648562.png
  5. 选择驱动器0、点下一步安装系统等系统安装完成后重启。

  6. 如果没有看到系统安装界面,在远程窗口中点击发送ctrl+alt+delete重启虚拟机,选择Virtio disk所在分区启动。

    1697518236332.png
  7. 进入系统后使用win+x进入系统->更改设置->远程,按下图配置允许远程登录。

    1697463771888.png 1696739233738.png
  8. 回到windows虚拟机下载Cloudbase-Init并安装。

    开始菜单打开IE浏览器,地址栏输入https://cloudbase.it/downloads/CloudbaseInitSetup_1_1_2_x64.msi下载软件后运行。

  9. 启动安装向导后设置初始化选项、完成安装。

    1696739847088.png 1696739859425.png 1696739903072.png 1696739922332.png
  10. localhost虚拟机查看ws2012的运行状态。

    [root@localhost ~]# virsh list --all
    Id    Name                           State
    ----------------------------------------------------
    -     ws2012                         shut off

验证windows-server定制结果

  1. 将生成的ws2012.qcow2传到Windows本地桌面、然后关闭localhost

  2. 打开控制节点和计算节点,上传ws2012.qcow2镜像到OpenStack。

  3. 执行source admin-login命令行登录,在控制节点上执行以下命令创建虚拟网络、子网、实例类型。

    1. 创建网络

      [root@controller ~]# openstack network create --share --external --provider-network-type flat --provider-physical-network provider --project admin test_net
    2. 创建子网

      [root@controller ~]# openstack subnet create --network test_net --subnet-range 192.168.20.0/24 --gateway 192.168.20.2 --allocation-pool start=192.168.20.128,end=192.168.20.140 --dns-nameserver 114.114.114.114 test_subnet
    3. 创建实例类型

      [root@controller ~]# openstack flavor create --public test_flavor --id auto --ram 2048 --disk 20 --vcpus 2
  4. 登录图形界面创建实例查看控制台。

1697509896041.png

作业3:windows实例启动并登录后截图上传。