手动构建Openstack镜像
本文以centos7镜像为例,详细介绍手动制作Openstack镜像的步骤,镜像支持一下几个功能:
- 支持密码注入功能(nova boot时通过–admin-pass参数指定设置初始密码)
- 支持根分区自动调整(根分区自动调整为flavor disk大小,而不是原始镜像分区大小)
- 支持动态修改密码(使用nova set-password命令可以修改管理员密码)
镜像的宿主机操作系统为CentOs7.4,开启了VT功能(使用kvm-ok命令验证)并安装了libvirt系列工具,包括virsh、virt-manager、libguestfs-tools等。
下载iso镜像
下载centos7.4.iso镜像,可以选择中国镜像源,相对国外镜像源下载速度会快很多,这里我已经下载好了。
1 2 3 4 5
| # qemu-img info CentOS-7-x86_64-DVD-1708.iso image: CentOS-7-x86_64-DVD-1708.iso file format: raw virtual size: 4.2G (4521459712 bytes) disk size: 4.2G
|
创建虚拟机
首先创建一个qcow2格式镜像文件,用于虚拟机的根磁盘,大小10G就够了。
1 2
| # qemu-img create -f qcow2 centos.qcow2 10G Formatting 'centos.qcow2', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536 lazy_refcounts=off
|
使用以下脚本创建并启动虚拟机:
1 2 3 4 5 6 7 8 9
| NAME=centos ROOT_DISK=centos.qcow2 CDROM=`pwd`/CentOS-7-x86_64-DVD-1708.iso virt-install --virt-type kvm --name $NAME --ram 1024 \ --disk $ROOT_DISK,format=qcow2 \ --network network=default \ --graphics vnc,listen=0.0.0.0 --noautoconsole \ --os-type=linux --os-variant=rhel7 \ --cdrom=$CDROM
|
启动完成后,使用vnc client连接或者使用virt-manager、virt-viewer连接,这里我直接用virt-manager。
安装OS
进入虚拟机控制台可以看到CentOS的启动菜单,选择Install Centos 7,继续选择语言后将进入INSTALLION SUMMARY,其中大多数配置默认即可,SOFTWARE SELECTION选择Minimal Install,INSTALLATION DESTINATION需要选择手动配置分区,我们只需要一个根分区即可,不需要swap分区,文件系统选择ext4或者xfs,存储驱动选择Virtio Block Device,如图:

配置完成后就可以开始安装了,在CONFIGURATION中设置root临时密码,只需要暂时记住这个临时密码,制作完后cloud-init会重新设置root初始密码。
大约几分钟后,即可自动完成安装配置工作,最后点击右下角的reboot重启退出虚拟机。
配置OS
安装好操作系统后,需要进行配置才能作为glance镜像使用,启动虚拟机
1 2 3 4 5
| # virsh list --all Id 名称 状态 ---------------------------------------------------- - centos 关闭 # virsh start centos
|
如果云主机不需要支持root ssh远程登录,需要关闭root远程ssh登录功能,修改配置文件/etc/ssh/sshd_config并修改PermitRootLogin值为no,默认是开启的(这里我不做更改,如果更改需要重启ssh服务生效)。
为了加快安装速度,可以配置为本地软件源仓库,若没有本地镜像仓库,则选择国内的软件源,相对官网的速度下载要快。
1 2 3 4
| # yum -y install wget # cd /etc/yum.repos.d/ && rm -rf * && cd # wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo # wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
|
acpid
acpid是一个用户空间的服务进程, 用来处理电源相关事件,比如将kernel中的电源事件转发给应用程序,告诉应用程序安全的退出,防止应用程序异常退出导致数据损坏。libvirt可以通过向guest虚拟机发送acpid事件触发电源操作,使虚拟机安全关机、重启等操作,相对于强制执行关闭电源操作更安全。通过acpid事件发送开关机信号即我们经常所说的软重启或者软关机。
为了支持软操作,虚拟机需要安装acpid服务,并设置开机自启动:
1 2
| # yum -y install acpid # systemctl enable acpid
|
提示:
- 用户执行重启或者关机操作时,OpenStack会首先尝试调用libvirt的shutdown方法,即软关机。
- 当软关机执行失败或者超时(默认120秒),则会调动libvirt的destroy方法,即强制关机,因此如果虚拟机关机或者重启很慢,很可能是acpid没有正常运行。
- 为了使虚拟机进程安全退出,减少数据损坏风险,尽量使用软操作,硬操作可能导致程序崩溃或者数据丢失。
console log
当操作系统内核崩溃时会报出内核系统crash出错信息,通常启动的时候一闪而过, 而此时系统还没有起来,不能通过远程工具(比如ssh)进入系统查看,我们可以通过配置grub,把这些日志重定向到Serial Console中,这样我们就可以通过Serial console来访问错误信息,以供分析和排错使用。
修改配置文件/etc/default/grub,设置GRUB_CMDLINE_LINUX,:
1
| GRUB_CMDLINE_LINUX="crashkernel=auto console=tty0 console=ttyS0,115200n8"
|
通过这个配置,内核信息会以115200的波特率同时发送到tty0和ttyS0串行端口设备。libvirt可以通过一个普通文件模拟这个串行端口:
1 2 3 4
| <serial type='file'> <source path='/var/lib/nova/instances/99579ce1-f4c4-4031-a56c-68e85a3d037a/console.log'/> <target port='0'/> </serial>
|
这样内核产生的日志发到ttyS0,实际上写到console.log文件中。
OpenStack通过nova console-log命令可以获取该文件内容,查看错误日志。
qemu-guest-agent
qemu-guest-agent是运行在虚拟机内部的一个服务,libvirt会在本地创建一个unix socket,模拟为虚拟机内部的一个串口设备,从而实现了宿主机与虚拟机通信,这种方式不依赖于TCP/IP网络,实现方式简单方便。
1 2 3 4 5
| <channel type='unix'> <source mode='bind' path='/var/lib/libvirt/qemu/org.qemu.guest_agent.0.instance-00003c2c.sock'/> <target type='virtio' name='org.qemu.guest_agent.0'/> <address type='virtio-serial' controller='0' bus='0' port='1'/> </channel>
|
如上宿主机的socket文件为org.qemu.guest_agent.0.instance-00003c2c.sock,在虚拟机内部为/dev/virtio-ports/org.qemu.guest_agent.0。
通过这种方式,宿主机可以发送指令写到socket文件中,虚拟机内部的qemu-guest-agent会轮询查看这个串行设备是否有指令,一旦接收到指令就可以执行对应的脚本,从而实现了宿主机控制虚拟机执行命令的功能,其中最常用的指令就是通过libvirt修改虚拟机密码。更多关于qemu-guest-agent请参考官方文档。
为了支持OpenStack平台动态修改虚拟机密码功能,我们需要手动安装qemu-guest-agent:
1
| # yum install -y qemu-guest-agent
|
修改/etc/sysconfig/qemu-ga配置文件:
1 2 3 4 5 6 7
| virsh qemu-agent-command instance-000028d5 '{"execute":"guest-info"}' | python -m json.tool | grep 'name' | cut -d ':' -f 2 | tr -d '",' ... guest-set-user-password guest-get-fsinfo guest-set-vcpus guest-get-vcpus ...
|
确认包含guest-set-user-password指令,支持修改管理员密码。
zeroconf
zeroconf启动时会自动创建一条路由169.254.0.0/16,而虚拟机访问metadata服务的地址正好是169.254.169.254,如果启动了zeroconf服务,由于路由冲突,虚拟机不能通过169.254.169.254路由到网络节点的metadata服务了。OpenStack虚拟机通常都是通过DHCP获取IP的,因此我们并不需要zeroconf服务。为了虚拟机能够访问metadata服务,我们必须禁止zeroconf服务,关于该问题的更详细讨论可参考bug#983611:
1
| # echo "NOZEROCONF=yes" >> /etc/sysconfig/network
|
cloud-init
接下来安装cloud-init,cloud-init是虚拟机第一次启动时执行的脚本,主要负责从metadata服务中拉取配置信息,完成虚拟机的初始化工作,比如设置主机名、初始化密码以及注入密钥等。
1
| # yum install -y cloud-init
|
growpart
1 2 3 4
| # yum update -y # yum install -y epel-release # yum install -y cloud-utils-growpart.x86.64 # rpm -qa kernel | sed 's/^kernel-//' | xargs -I {} dracut -f /boot/initramfs-{}.img {}
|
完成以上工作后,我们的镜像配置基本结束,删除一些无用文件,清理history命令后执行关机:
移除本地信息
在宿主机上运行以下命名,移除宿主机信息,比如mac地址等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| # virt-sysprep -d centos [ 0.0] Examining the guest ... [ 41.1] Performing "abrt-data" ... [ 42.4] Performing "backup-files" ... [ 44.4] Performing "bash-history" ... [ 44.4] Performing "blkid-tab" ... [ 44.5] Performing "crash-data" ... [ 44.5] Performing "cron-spool" ... [ 44.5] Performing "dhcp-client-state" ... [ 44.5] Performing "dhcp-server-state" ... [ 44.5] Performing "dovecot-data" ... [ 44.5] Performing "logfiles" ... [ 44.7] Performing "machine-id" ... [ 44.7] Performing "mail-spool" ... [ 44.7] Performing "net-hostname" ... [ 44.8] Performing "net-hwaddr" ... [ 44.8] Performing "pacct-log" ... [ 44.8] Performing "package-manager-cache" ... [ 44.8] Performing "pam-data" ... [ 44.8] Performing "passwd-backups" ... [ 44.8] Performing "puppet-data-log" ... [ 44.8] Performing "rh-subscription-manager" ... [ 44.8] Performing "rhn-systemid" ... [ 44.8] Performing "rpm-db" ... [ 44.8] Performing "samba-db-log" ... [ 44.8] Performing "script" ... [ 44.8] Performing "smolt-uuid" ... [ 44.8] Performing "ssh-hostkeys" ... [ 44.8] Performing "ssh-userdir" ... [ 44.8] Performing "sssd-db-log" ... [ 44.9] Performing "tmp-files" ... [ 44.9] Performing "udev-persistent-net" ... [ 44.9] Performing "utmp" ... [ 44.9] Performing "yum-uuid" ... [ 44.9] Performing "customize" ... [ 44.9] Setting a random seed [ 45.4] Performing "lvm-uuids" ...
|
删除虚拟机,镜像制作完成。
1 2 3 4 5 6 7 8 9 10 11 12
| # virsh list --all Id 名称 状态 ---------------------------------------------------- - centos 关闭
# virsh undefine centos 域 centos 已经被取消定义
# virsh list --all Id 名称 状态 ----------------------------------------------------
|
上传镜像
镜像制作完成,上传centos.qcow2到glance服务中
1 2
| # glance image-create --file ./centos.qcow2 --disk-format qcow2 \ --container-format bare --name CentOS-7.2 --progress
|