返回 登录
0

Openstack虚拟机镜像深度实践

虚拟机镜像(以下简称镜像)是Openstack云计算平台不可或缺的一部分。利用各种定制化的镜像,我们可以快速创建出满足不同目的的虚拟机。例如,利用一个安装并配置了Apache、Mysql和PHP的Linux操作系统镜像,就可以在Openstack平台上秒级创建出多台LAMP服务器,可以直接用于部署或者开发。

要充分利用好镜像的优势,关键就是掌握好如何制作定制化的镜像,这往往也伴随着如何测试和管理这些镜像。本文主要介绍:1. 制作满足Openstack要求的镜像的流程;2. 利用devstack对制作好的镜像进行测试。

本文出现的命令和配置都是实际测试可行的,可以直接复制使用;但本文更多是介绍各个操作配置的原理和目的,这样即使在不同的运行环境,我们仍可以把握关键细节,完成镜像的制作和测试。

主要内容

  • 原理和流程简介
  • 准备工作
  • 制作镜像
  • 测试镜像
  • 附录

原理和流程简介

虚拟机镜像实际就是一个包含整个虚拟磁盘内容的文件,这个虚拟磁盘也就是虚拟机的系统盘,包含可以引导启动的操作系统。所谓定制化的镜像,就是在这个(虚拟)系统盘上安装好需要的软件,保存好需要的配置,最后清理掉不必要的临时文件和日志等数据。最简单直观的定制方式,就是用一个干净的镜像作为系统盘创建一台虚拟机,安装好需要的操作系统,然后就可以像平时的操作那样安装需要的软件,保存配置,再利用工具清理不需要的数据,最后关闭虚拟机,镜像就定制化完成了。当然,我们也可以使用已经制作好的镜像直接创建虚拟机,这样可以省略操作系统和一些软件的安装步骤。

所谓Openstack虚拟机镜像,就是满足一些要求(安装特定的软件,配置特定的服务等)的镜像,从而配合完成Openstack计算平台的镜像相关功能。

测试镜像也很简单,就是把制作好的镜像导入Openstack平台,使用它来创建虚拟机,测试各个功能是否正常运作。搭建一个Openstack平台用于测试的方式很多种,本文选择了devstack,因为devstack的安装步骤很简单,而且很轻量,可以直接安装在一台虚拟机中。

准备工作

本文的例子所在运行环境的操作系统为Centos 7,并利用基于libvirt的一系列工具来创建和管理虚拟机,针对的虚拟化技术(hypervisor)为QEMU/KVM。
libvirt和kvm分别是Openstack上面最常用的工具和虚拟化平台。

1.安装好虚拟化工具

yum install qemu libvirt-client virt-manager virt-viewer guestfish libguestfs-tools virt-top

2.创建虚拟子网

目的:因为虚拟机在安装软件过程中需要连通互联网,最简单的办法就是利用libvirt创建一个虚拟子网,虚拟机通过dhcp分配虚拟子网的ip,通过NAT的方式访问外网。

图片描述

2.1 准备虚拟网络资源的xml文件default.xml:

<network>
  <name>default</name>
  <bridge name="virbr0"/>
  <forward/>
  <ip address="192.168.122.1" netmask="255.255.255.0">
    <dhcp>
      <range start="192.168.122.2" end="192.168.122.254"/>
    </dhcp>
  </ip>
</network>

2.2 配置:

\# virsh net-define /usr/share/libvirt/networks/default.xml
Network default defined from /usr/share/libvirt/networks/default.xml
\# virsh net-autostart default
Network default marked as autostarted
\# virsh net-start default
Network default started

2.3 修改系统配置/etc/sysctl.conf:

net.ipv4.ip_forward = 1

环境准备好了,可以开始制作镜像了。

制作镜像

制作Linux镜像

Linux镜像需要满足:

1.配置SSH server开机运行。
2.禁用防火墙。
3.开机时支持磁盘分区和改变大小。
4.支持ssh公钥访问虚拟机。
5.运行和使用user data和metadata(如修改root密码,执行用户脚本等)。
6.操作系统内核支持Virtio。
7.没有写死的MAC地址信息。

其中1、2很容易操作,本文使用的Centos 7安装盘默认安装后就满足了。3、4、5三条,只需要安装一个cloud-init的服务就可以了。

cloud-init是一系列python脚本和工具,负责云实例最开始的初始化工作。具体运行原理参考附录:cloud-init工作原理。

第6条,Virtio是提高KVM类型的虚拟机I/O(存储和网络)性能的一种技术。目前常用的Linux发行版本内核都直接支持了,如果你的安装版本有特殊需求,可以查看这里。
关于Virtio的细节,可以参考附录:虚拟机性能优化.

第7条,使用工具virt-sysprep清理。

下面以Centos 7.1的安装为例,其他发行版本可以参考Openstack的文档:

1.准备好ISO安装文件,下载。

2.创建一个磁盘:qemu-img create -f qcow2 image.qcow2 20G
因为针对的是KVM,因此本文使用的镜像格式是qcow2(QEMU copy-on-write version 2),关于镜像格式更多细节,可查看附录:镜像格式。镜像大小没有特殊要求,根据需求即可。镜像完成后是可以通过qemu-img增大的,但是一般很难缩小。

3.创建并启动虚拟机:

使用virt-install命令进行创建,通过vnc图形界面安装(本地需要安装一个vnc客户端来访问vnc界面):

virt-install --virt-type kvm --cpu cpu64-rhel6 --ram 2048 \
--name image_name \
--disk path=image.qcow2,format=qcow2,device=disk,bus=virtio \
--network network=default,model=virtio \
--graphics vnc,listen=0.0.0.0,password=Yourpassw0rd --noautoconsole \
--os-type=linux \
--extra-args="console=ttyS0,115200n8 console=tty0" \
--location=/path/to/installer.iso

或者通过虚拟console(命令行)界面安装,执行virsh console image_name进入console界面,ctrl+]退出:

virt-install --virt-type kvm --cpu cpu64-rhel6 --ram 2048 \
--name image_name \
--disk path=image.qcow2,format=qcow2,device=disk,bus=virtio \
--network network=default,model=virtio \
--os-type=linux \
--nographics \
--extra-args="console=tty0 console=ttyS0,115200n8 serial" \
--location=/path/to/installer.iso

这些命令参数的含义多数都比较直观,其中:

–cpu cpu64-rhel6:虚拟机的cpu特性集合,因为不同物理机的cpu特性都不同,为了保证虚拟机在不同物理机之间迁移时的cpu兼容性,Openstack平台往往会指定一个虚拟的cpu特性集合(物理机cpu特性的子集),用于所有的虚拟机。其他集合可以通过cat /usr/share/libvirt/cpu_map.xml查看。这里的cpu64-rhel6只是个示例,根据实际情况指定即可。

–graphics vnc,listen=0.0.0.0,password=Yourpassw0rd:通过vnc的方式提供安装界面,通过virsh vncdisplay image_name来查看vnc监听端口(vnc端口通常从tcp端口5900开始)。然后就可以使用vnc客户端进行操作。例如noVNC。

–location=/path/to/installer.iso和–extra-args=”console=tty0 console=ttyS0,115200n8 serial”:指定ISO安装文件路径,在内核启动阶段,应用指定的参数。

4.按照步骤要求安装操作系统(比如设置root密码,设置时区,网络和分区等)。

5.如果虚拟机dhcp没有正确配置,需要配置一下。centos 7的话,需要编辑/etc/sysconfig/network-scripts/ifcfg-ens3(根据网卡接口名字不同),修改ONBOOT=yes,然后执行service network restart。

6.弹出虚拟cd,关机并重启

virsh attach-disk --type cdrom --mode readonly image_name "" hdb
virsh destroy image_name
virsh start image_name

7.重新登录(virsh console image_name或者ssh或者vnc),然后就可以安装基本的服务和修改配置:

\# 安装ACPI
yum install acpid
chkconfig acpid on
\# 安装NetworkManager,用于网卡的自动发现及管理
yum install NetworkManager
chkconfig NetworkManager on
\# 安装cloud-init
yum install cloud-init
\# 禁用默认的zeroconf route
echo "NOZEROCONF=yes" >> /etc/sysconfig/network

8.关机shutdown -h now。

9.关机后回到宿主机,执行virt-sysprep -d image_name,擦除虚拟机镜像中的无用数据(MAC地址等)。

10.取消虚拟机:virsh undefine image_name。

11.这个镜像(image.qcow2)就可以用了。
因为我们通常对同一个Linux版本制作多种镜像,没必要每次都从头开始。我们可以跳过1 - 7步骤,基于一个已经制作好了的镜像创建虚拟机,登录后进行具体的定制化行为,然后再完成8 - 10:

virt-install --virt-type kvm --cpu cpu64-rhel6 --ram 2048 \
    --name image_name \
    --disk path=image.qcow2,format=qcow2,device=disk,bus=virtio \
    --network network=default,model=virtio \
    --graphics vnc,listen=0.0.0.0,password=Yourpassw0rd \
    --noautoconsole --os-type=linux --import

制作Windows镜像

Windows镜像的制作和Linux会有所不同:

Windows平台上是通过一个和cloud-init类似的服务,cloudbase-init,来帮助虚拟机初始化的。Windows平台要额外安装virtio-win驱动,才能使用Virtio来提高I/O性能。下面以Windows 2008为例:

1.准备好Windoes 2008的ISO安装盘。

2.准备好Virtio驱动的ISO安装盘,下载地址

3.创建一个磁盘镜像:

qemu-img create -f qcow2 ws2008.qcow2 20G

4.创建并启动虚拟机:

 virt-install --connect qemu:///system \
  --name image_name --ram 2048 --vcpus 2 \
  --network network=default,model=virtio \
  --disk path=image.qcow2,format=qcow2,device=disk,bus=virtio \
  --cdrom /path/to/win2008_installer.iso \
  --disk path=/path/to/virtio-win-0.1.102.iso,device=cdrom \
  --graphics vnc,listen=0.0.0.0,password=Yourpassw0rd \
  --os-type windows --os-variant win2k8

5.通过vnc进入安装界面,开始安装过程。

6.安装Virtio驱动。

当安装程序进入选择系统盘的步骤时,会找不到可用磁盘,这是理所当然的(因为相关驱动还没安装)。此时选择“加载启动”(Load drivers),找到virtio-win的目录,选择合适的驱动,安装即可(因为例子中安装的是Windows 2008 64bit,因此选择的是amd64下的Win2008)。要安装两种驱动:VirtIO SCSI和network。安装完成后就可以看到可用磁盘了。

7.选择系统盘,继续安装步骤。

8.以Administrator身份进入桌面,打开cmd,完成Virtio的安装:

C:\pnputil -i -a E:\PATH\TO*.INF

9.安装Cloudbase-init,打开Powershell(如果默认没有安装,先安装),并运行:
C:\powershell
C:\Set-ExecutionPolicy Unrestricted
用IE打开http://www.cloudbase.it/downloads/CloudbaseInitSetup_Stable_x64.msi,下载并安装。

这个过程中可能需要:1. 关闭IE安全增强设置;2. 下载的msi文件需要右键点击属性,Unblock。

安装过程中,需要指定以下几项:

- Username: Administrator
- Network adapter to configure: Red Hat VirtIO Ethernet Adapter
- Serial port for logging: COM1

安装向导的最后,勾选Run Sysprep和Shutdown,最后点击完成,系统自动关机。

10.关机完成后镜像已经可用了,不过Cloudbase-init还多是默认配置,可以重新开机virsh start image_name,根据实际需求修改配置,具体参考文档。

本文例子做了如下修改:打开配置文件C:\Program Files\Cloudbase Solustions\Cloudbase-Init\conf\cloudbase-init.conf,修改如下几项,配置ConfigDrive的方式:

mtu_use_dhcp_config=false
ntp_use_dhcp_config=false
metadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService

11.正常关机,virsh undefine image_name,镜像就制作完成了。

12.同样的,如果要针对同一个Windows版本安装不同软件,可以使用已有的镜像进行安装。

测试镜像

如果仅仅使用devstack用于测试镜像,可以将devstack安装在一台虚拟机上,不用时直接关闭,这里的优化可以参考附录:虚拟机性能优化。

搭建devstack的步骤(如果是安装在虚拟机上同样适用):

1.创建stack账号,添加sudo权限,并登录stack:

adduser stack
echo “stack ALL=(ALL) NOPASSWD: ALL” >> /etc/sudoers
su - stack

2.安装git:sudo yum install -y git

3.下载devstack源码:git clone https://git.openstack.org/openstack-dev/devstack并cd devstack

4.选定指定的Openstack版本,如:git checkout stable/juno

5.配置文件~/devstack/local.conf:

[[local|localrc]]
FLOATING_RANGE=192.168.122.224/27
FIXED_RANGE=10.11.12.0/24
FIXED_NETWORK_SIZE=256
FLAT_INTERFACE=ens3
ADMIN_PASSWORD=123
DATABASE_PASSWORD=123
RABBIT_PASSWORD=123
SERVICE_PASSWORD=123
SERVICE_TOKEN=123
LIBVIRT_TYPE=kvm
LOGFILE=$DEST/logs/stack.sh.log
\# nova相关配置
[[post-config|$NOVA_CONF]]
[libvirt]
inject_password=true
inject_partition=-1
cpu_mode=custom
cpu_model=cpu64-rhel6

6.安装并启动devstack:./stack:
第一次执行时会安装许多库和下载代码

7.启动完后,为了让Dashboard中创建虚拟机页面支持设置admin密码,需要修改/opt/stack/horizon/openstack_dashboard/local/local_settings.py:

OPENSTACK_HYPERVISOR_FEATURES = {
'can_set_mount_point': False,
'can_set_password': True,
}

8.如果有防火墙,打开80和6080端口:

firewall-cmd --add-port=80/tcp
firewall-cmd --add-port=6080/tcp
firewall-cmd --reload

devstack的使用方式:

1.确保是以stack用户登录。

2.进入devstack目录,执行source openrc admin admin,即使用admin身份(密码在配置文件中指定了)操作openstack。

3.然后就可以使用命令行工具了。
也可以通过Dashboard(80端口)和VNC(6080)以web界面来操作openstack。如果安装在虚拟机,且虚拟机运行在虚拟子网上,可以通过iptables等工具将虚拟机80和6080端口NAT映射到外网,进而访问。

具体测试流程:

1.在devstack机器上,su - stack && cd devstack && source openrc admin admin

2.导入镜像到glance:

glance image-create --name image_name --disk-format=qcow2 --container-format=bare --is-public=True --file /path/to/image.qcow2

3.浏览器打开devstack的80端口,通过horizon界面用刚才导入的镜像创建虚拟机。
4.测试确保几点:

  • 虚拟机成功创建
  • -创建操作没有错误日志(通过实例页面的日志Tab查看)
  • ssh_key或者admin密码正确设置,能够成功登录
  • 登录后,检查之前安装的软件或做的配置

总结

制作虚拟机镜像的方式有很多种,本文介绍了一种直观的方式:通过创建虚拟机,用平时使用操作系统的方式来定制化需求。另外还值得一提的一个工具,Diskimage-builder,可以用于自动化地创建镜像,使得定制化和测试镜像都变得更容易,但是相比本文介绍的方式也有一些不足:一是有一定的学习成本,二是目前只支持部分常用的Linux发行版本。
测试镜像的方式同样也很多,本文是通过devstack搭建一个最简的Openstack平台环境,把镜像直接导入平台,测试各个操作是否成功,日志是否无异常。


附录

问题和解决
制作Windows镜像时,报错无法从CD boot。

这是由于virt-install误把Virtio的ISO文件当做安装盘,解决办法:使用floppy盘的方式安装Virtio驱动:

1.下载vfd格式的Virtio驱动安装文件。
2.将–disk path=/path/to/virtio-win-0.1.102.iso,device=cdrom替换为–disk path=/path/to/virtio-win-0.1.102_amd64.vfd,device=floppy

cloud-init工作原理

cloud-init是一系列python脚本和工具,负责云实例最开始的初始化工作(修改主机名、注入ssh-key文件、设置root密码等)。cloud-init是一个通用方案,还适用于Openstack外的多种云平台。

cloud-init安装在虚拟机中,在第一次启动时,会根据本地配置去获取Datasources。Datasources包含了cloud-init初始化虚拟机时所需的配置数据:来自用户的userdata和来自平台的metadata。通常userdata包含yaml文件、运行脚本等多种格式的文件,而metadata包含了主机名、实例id、显示名等云平台相关的细节。

云平台提供Datasource的方式很多,Openstack默认的方式是通过http server提供Datasource:虚拟机访问默认的http://169.254.169.254,Openstack会对这个地址重定向,最终指向自己的metadata server。

镜像格式

虚拟机镜像格式最简单的是raw格式,可以认为是一个位等价的块设备文件(对/dev/sda使用dd命令进行复制)。此外还有很多格式,各自有不同的特点,如:ISO(主要用于CD或DVD)、VDI(VirtualBox使用)、VHD/VHDX(微软Hyper-V使用)、VMDK(VMware使用)。

QCOW2(QEMU copy-on-write version 2)则常用于KVM虚拟机,相比raw格式,qcow2格式的文件体积更小,更利于保存和上传。qcow2格式还支持快照(snapshot)功能(raw不支持),因此需要时,Openstack会自动将raw格式的镜像转换成qcow2格式。

虚拟机性能优化

关于虚拟化,先梳理几个概念:

  • Hardware Virtualization:本文使用的QEMU/KVM就是属于这一类虚拟化,虚拟化出一个硬件平台(硬件机器),在这之上可以跑不同的操作系统(Linux、Windows等)(区别于Operating-system-level Virtualization,虚拟化的实例都是同一个操作系统;也就是Docker那一类的技术。)。Hardware Virtualization又有几种区分: - Full Virtualization:完整地模拟客户操作系统所需的所有硬件。客户操作系统不知道自己是跑在物理机还是虚拟机上
    图片描述
    -Paravirtualization(“Para-”:“beside”或“alongside”):为了降低模拟一些硬件的难度,以及避免一些模拟带来的性能消耗,hypervisor(虚拟层)可以提供和底层硬件类似的软件接口。客户操作系统需要做修改或者安装一些驱动来和这些软件接口通信。客户操作系统知道自己是跑在物理机还是虚拟机上。
    图片描述
  • Hardware-assisted Virtualization:在物理硬件上提供特性支持(直接虚拟化硬件资源),从而提高Hardware Virtualization的性能和安全性:
    – CPU虚拟化:Intel virtualization (VT-x)或AMD virtualization (AMD-V)
    – I/O虚拟化:Intel VT-d或AMD-Vi
    – 内存虚拟化
    – GPU虚拟化
    – ……

图片描述
这些硬件虚拟化特性需要在BIOS中打开。

  • 使用KVM
    QEMU/KVM创建虚拟机有两种模式emulator(QEMU)和virtualizer(KVM)。其中KVM需要依赖于Hardware-assisted CPU Virtualization(VT-x或者AMD-V),通过在宿主机cpu上执行客户机代码,从而可以获得接近原生的性能。KVM并不支持CPU的paravirtualization,但是支持对设备驱动的paravirtualization从而提高I/O性能。
    使用KVM需要确保CPU硬件支持(要在BIOS中打开)和Linux内核模块支持。

  • 使用host的cpu model
    如果不需要考虑虚拟机的迁移等问题,可以直接对虚拟机暴露全部宿主机的CPU特性(包括硬件虚拟化的特性),从而更好地利用cpu提升性能。相关命令指定–cpu host即可。

  • 打开KVM-based nested virtualization
    为了能够在创建的虚拟机中跑KVM(KVM上跑KVM),需要在物理机上允许KVM-based nested virtualization。对于Intel-based的机器:
    •检查nested KVM Kernel是否打开
    cat /sys/module/kvm_intel/parameters/nested
    N
    Y代表打开,N代表关闭
    •临时移走KVM intel Kernel模块,打开nested virtualization,再重新加载:

sudo rmmod kvm-intel
sudo sh -c "echo 'options kvm-intel nested=y' >> /etc/modprobe.d/dist.conf"
sudo modprobe kvm-intel

•确保正确打开:

cat /sys/module/kvm_intel/parameters/nested
Y
modinfo kvm_intel | grep nested
parm:           nested:bool
  • 使用Virtio
    因为本文使用libvirt来管理KVM虚拟机,最方便的提升I/O性能的方式就是Virtio(此外还有其他方式提高KVM虚拟机I/O,例如利用VT-d给KVM虚拟机直接分配设备)。
    Virtio是一种paravirtualization,只能运行兼容Virtio的客户机(Linux内核支持,Windows需要安装相关驱动)。Para-virtualized设备列表:
    • network device (virtio-net)
    • block device (virtio-blk)
    • controller device (virtio-scsi)
    • serial device (virtio-serial)
    • balloon device (virtio-balloon)

相关命令指定virtio模式即可。

作者简介:蔡凯捷,现就职于绿星云科技,高级工程师,负责Openstack相关领域的研发工作。爱好云计算、开源项目、Web相关话题。曾任腾讯基础架构部门研发工程师,拥有互联网分布式系统多年研发经验。绿星云科技(深圳)有限公司(www.gstarcloud.com)是一家迅速崛起的互联网公司,专注于公有云服务。基于不断创新的软硬件平台架构、高效的运营管理流程和热情高涨的事业心,为客户打造易用、可靠、高性价比的云计算服务平台。该平台集中了弹性计算、分布式块存储和软件定义网络(SDN)等IaaS核心技术和能力,以秒级部署、在线迁移、分布式数据库、CDN加速等功能,为用户提供一站式云计算服务。本文为绿星云科技独家供稿,已得到官方的独家授权发布。

责编:魏伟,关注OpenStack。欢迎技术文章投稿,投稿邮箱weiwei@csdn.net

评论