OpenStack镜像制作知多少?
最近在做OpenStack镜像,愈发觉得镜像制作看似简单,实则内涵很大学问。围绕“制作Linux/Windows镜像、实现原理、配置文件内容和自定义定制”等方面,其广度和深度,完全够写一本书了。
大多情况下,镜像制作者只在镜像中安装Cloud-init服务,但镜像其实还可以有更多有用的配置。常见地,对镜像的需求包括但不限于:
• 初始化主机名hostname;
• 初始化用户名和密码;
• 初始化网卡IP地址;
• 初始化秘钥对keypair;
• 配置ssh、防火墙;
• 修改虚拟机用户密码等;
本文CentOS 7镜像为例,详细介绍手动制作OpenStack镜像的详细步骤以及支持修改密码的方式。
一、制作Centos镜像
1.1安装系统
检查制作镜像的服务器是否支持KVM,有vmx字样输出则表示支持。
# cat /proc/cpuinfo | egrep 'vmx|svm'
安装virt系列工具
# yum -y install qemu-kvm libvirt virt-install bridge-utils qemu-img
# systemctl start libvirtd.service && systemctl status libvirtd.service
首先创建一个qcow2格式的镜像文件,用于虚拟机的根磁盘,大小40G就够了。
# qemu-img create -f qcow2 centos7.1.qcow2 40G
然后将下载的Centos7.1 iso系统文件存放到指定目录下,使用以下命令创建并启动虚拟机:
# virt-install --virt-type kvm --name centos-7.1 --ram 1024 --vcpus=1
--disk centos7.1.qcow2,format=qcow2
--network network=default
--graphics vnc,listen=0.0.0.0 --noautoconsole
--os-type=linux --os-variant=rhel7
--cdrom=CentOS-7-1.iso
参数说明:
--virt-type kvm:使用kvm硬件虚拟化,可提升安装系统速度和性能。
--ram 1024 --vcpus=1:指定虚拟机内存和vcpu大小为1G/1核。
查看VNC端口号
# virsh vncdisplay centos-7.1
:0
0代表是5900,大于0的从5900之后递增。例如,显示:1,则代表5901
在自己的PC机上,使用vnc工具登录,执行操作系统安装和配置。
推荐使用的VNC:Tightvnc、UltraVNC、VNC Viewer、tigervnc
说明
SOFTWARE SELECTION选择Minimal Install。INSTALLATION DESTINATION需要选择手动配置分区,我们只需要一个/根分区即可,不需要swap分区,文件系统选择ext4,存储驱动选择Virtio Block Device,Device Type选择Standard Partition。
配置完成后就可以开始安装了。对于云场景,云服务提供商应当引导用户根磁盘只存放系统用,而数据应当放在另外的数据盘上。
安装完毕后,点击reboot,然而并不会启动,所以还需要通过virsh启动。
# virsh list --all
Id Name State
----------------------------------------------------
- centos-7.1 shut off
# virsh start centos-7.1
1.2 配置系统
配置网卡开机自启动:
# vi /etc/sysconfig/network-scripts/ifcfg-ens3
...
ONBOOT=yes
# systemctl restart network.service
查看虚拟机的IP地址:
# ip a
设置系统时间为CST时区(北京时间)。
# mv /etc/localtime /etc/localtime.bak
# ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# date
如果云主机需要支持root ssh远程登录,需要开启root远程ssh登录功能,修改配置文件/etc/ssh/sshd_config中的PermitRootLogin值为yes,重启ssh服务生效:
# systemctl restart sshd
安装acpid软件。acpid是一个用户空间的服务进程, 用来处理电源相关事件,比如将kernel中的电源事件转发给应用程序,告诉应用程序安全的退出,防止应用程序异常退出导致数据损坏。libvirt可以通过向guest虚拟机发送acpid事件触发电源操作,使虚拟机安全关机、重启等操作,相对于强制执行关闭电源操作更安全。通过acpid事件发送开关机信号即我们经常所说的软重启或者软关机。
为了支持软操作,虚拟机需要安装acpid服务,并设置开机自启动:
# yum install -y acpid && systemctl enable acpid
安装cloud-init软件,实现虚拟机的初始化工作,比如设置主机名、初始化密码以及注入密钥等。
# yum install -y cloud-init && systemctl start cloud-init && systemctl enable cloud-init
注意:CentOS系列的系统,其虚拟机的主机名默认会自动生成xxx.novalocal格式的hostname。若要取消,则执行如下命令进入cloudinit/sources文件夹。编辑文件,参照如下内容修改。
vim /usr/lib/python2.7/site-packages/cloudinit/sources/__init__.py
执行如下命令,删除__init__.pyc文件和优化编译后的__init__.pyo文件。
rm -f __init__.pyc
rm -f __init__.pyo
执行如下命令,清理日志信息。
rm -rf /var/lib/cloud/*
rm -rf /var/log/cloud-init*
检查Cloud-init工具相关配置是否成功。执行以下命令,无错误发生,说明Cloud-init配置成功。
cloud-init init --local
正确安装的Cloud-init会显示Cloud-init的版本详细信息,并且无任何错误信息。
禁止zeroconf服务。当一些操作系统使用DHCP获取IP地址失败时,会尝试通过zeroconf服务配置。zeroconf启动时会自动创建一条路由169.254.0.0/16,而虚拟机访问metadata服务的地址正好是169.254.169.254,如果启动了zeroconf服务,由于路由冲突,虚拟机不能通过169.254.169.254路由到网络节点的metadata服务了。OpenStack虚拟机通常都是通过DHCP获取IP的,因此我们并不需要zeroconf服务。为了虚拟机能够访问metadata服务,我们必须禁止zeroconf服务。
为了虚拟机能够访问metadata服务,必须禁止zeroconf服务。
# echo "NOZEROCONF=yes" >> /etc/sysconfig/network
配置console。当操作系统内核崩溃时会报出内核系统crash出错信息,通常启动的时候一闪而过, 而此时系统还没有起来,不能通过远程工具(比如ssh)进入系统查看,我们可以通过配置grub,把这些日志重定向到Serial Console中,这样我们就可以通过Serial console来访问错误信息,以供分析和排错使用。这样内核产生的日志发到ttyS0,实际上写到console.log文件中。OpenStack通过nova console-log命令可以获取该文件内容,查看错误日志。修改/etc/default/grub文件添加如下内容。
# vim /etc/default/grub
GRUB_CMDLINE_LINUX="crashkernel=auto console=tty0 console=ttyS0,115200n8"
更新grub配置生效
# grub2-mkconfig -o /boot/grub2/grub.cfg
安装 cloud-utils-growpart。以支持虚拟机系统盘自动扩容。虚拟机制作镜像时指定了根分区大小(比如前面设置的40GB),为了使虚拟机能够自动调整为flavor disk指定的根磁盘大小如50GB,即自动扩容,执行安装命令:
# yum install cloud-utils-growpart -y
约束条件
• 根分区文件系统为xfs的镜像不支持自动扩容。
• 有LVM分区的镜像不支持自动扩容。
• 推荐使用文件系统为ext3、ext4的单分区镜像。
• Windows系统不支持。
说明
CentOS 6 要实现分区自动扩展,要安装以下三个包
yum -y install cloud-init cloud-utils-growpart dracut-modules-growroot
新生成 initramfs
dracut -f
systemctl enable cloud-init
安装QGA。qemu-guest-agent是运行在虚拟机内部的一个服务,libvirt会在本地创建一个unix socket,模拟为虚拟机内部的一个串口设备,从而实现了宿主机与虚拟机通信,这种方式不依赖于TCP/IP网络,实现方式简单方便。为了支持OpenStack平台动态修改虚拟机密码功能,需要安装qemu-guest-agent。
# yum -y install qemu-guest-agent
修改/etc/sysconfig/qemu-ga配置文件:
FSFREEZE_HOOK_PATHNAME=/etc/qemu-ga/fsfreeze-hook
TRANSPORT_METHOD="virtio-serial"
DEVPATH="/dev/virtio-ports/org.qemu.guest_agent.0"
LOGFILE="/var/log/qemu-ga/qemu-ga.log"
PIDFILE="/var/run/qemu-ga.pid"
BLACKLIST_RPC=""
FSFREEZE_HOOK_ENABLE=0
重启qemu-guest-agent
# systemctl restart qemu-guest-agent
执行查看qemu-guest-agent支持的指令(在制作镜像的服务器上执行)
# virsh qemu-agent-command centos-7.1 '{"execute":"guest-info"}' | python -m json.tool | grep 'name' | cut -d ':' -f 2 | tr -d '",'
确认输出包含guest-set-user-password指令,支持修改管理员密码。
删除一些无用文件,清理history命令后执行关机:
# history -c
# poweroff
清除虚拟机内部的MAC地址信息:
# virt-sysprep -d centos-7.1
使虚拟机脱离libvirt管理:
# virsh undefine centos-7.1
压缩镜像:
qemu-img convert -c -O qcow2 <源文件> <目标文件>
# qemu-img convert -c -O qcow2 centos7.1.qcow2 Centos7.1.qcow2
可见,压缩效果是非常明显的。
此时镜像就制作完成了,接下来上传至OpenStack镜像服务中即可,一般使用界面上传:
# openstack image create "Centos-7"
--public
--disk-format qcow2 --container-format bare
--file ./Centos7.1.qcow2
--property hw_qemu_guest_agent=yes
创建虚拟机
#nova boot --image $Image_id --flavor $flavor_id --nic net-id=$network_id $vm_name
二、Linux虚拟机修改密码方法
上面,我们把Linux镜像制作好了,假如我们有天忘记了密码(也丢失了Keypair密钥对),或者说,作为产品界面功能的一部分,你不能让客户去后台敲cmd命令或在虚拟机内部修改密码吧(前端可调用后台API接口实现),那有哪些方法可以重新设置密码呢。Linux虚拟机密码修改方法有。
• Qemu-guest-agent
• libguestfs-tools
• Cloud init
Cloud-Init
基于Cloud-init服务,创建VM虚拟机时可以通过密码注入的方式将新密码注入(如使用nova boot时可以使用--admin-pass参数来指定admin密码),这样VM创建起来后就可以用新密码打开了;此实现方式要求镜像中安装cloud init程序,VM起来后通过cloudinit程序获取到metadata数据并修改密码,它修改的是VM的密码,其实镜像中的密码并没有改变。
使用libvirt管理的Hypervisor(诸如KVM,QEMU,以及LXC),管理员密码注入默认是禁用的。要启用它,则在Compute节点上编辑文件/etc/nova/nova.conf
# vim /etc/nova/nova-compute.conf
[libvirt]
virt_type=kvm
inject_password = true
inject_partition = -1
然后重启计算服务。当启用后,计算服务就会修改虚拟机操作系统的管理员账户密码,通过编辑虚拟机内部的文件/etc/shadow来实现。
修改horizon的配置文件,添加设置密码的界面:
# vim /etc/openstack-dashboard/local_settings
OPENSTACK_HYPERVISOR_FEATURES = {
'can_set_mount_point': False,
'can_set_password': True,
}
# systemctl restart httpd
使用刚刚创建的镜像,在Dashboard界面上创建一台云主机(如果使用nova CLI命令,需要传--admin-pass参数指定密码),如图可输入指定的密码:
创建成功后进入vnc界面,使用root账号以及设置的新密码,如果登录成功,说明注入密码成功。
Qemu-Guest-Agent
Qemu-Guest-Agent就是运行在虚拟机系统里面的一个小服务。这个服务负责hypervisor和Guest之间进行通信。Hypervisor使用这个通道去获取guest OS的信息或执行命令。这个通道的协议叫做Qemu Machine Protocol. 比如,libvirt使用agent去获取网络和文件系统的详细信息。它们是通过virtio-serial或者通过isa-serial通道,又叫做org.qemu.guest_agent.0。 在hypervisior服务器这边也会创建一个文件,在/var/lib/libvirt/qemu/channel/target/.
OpenStack Nova是通过判断镜像元数据hw_qemu_guest_agent是否为yes决定是否支持qemu-guest-agent,代码如下:
# vim nova/virt/libvirt/driver.py
由此可知,我们必须添加镜像property hw_qemu_guest_agent=yes,否则libvert启动虚拟机时不会创建qemu-guest-agent设备,虚拟机的qemu-guest-agent由于找不到对应的串行设备而导致修改密码失败。同时在实测中发现,如果未添加该属性,虚拟机中的qemu-guest-agent服务同样会因为找不到设备而无法启动。
添加该属性命令:
# glance image-update --property hw_qemu_guest_agent=yes $IMAGE_ID
在计算节点上执行查询信息,进行检验:
# virsh qemu-agent-command $VM_ID --pretty '{"execute":"guest-info"}'
nova通过set-password子命令修改虚拟机管理员密码:
nova set-password $VM_UUID
或通过virsh命令设置虚拟机用户密码
# virsh set-user-password <domain> <user> <password>
Libguestfs-tools
libguestfs 是一组 Linux 下的 C 语言的 API ,用来访问虚拟机的磁盘映像文件。该工具包内包含的工具有virt-cat、virt-df、virt-ls、virt-copy-in、virt-copy-out、virt-edit、guestfs、guestmount、virt-list-filesystems、virt-list-partitions等工具,具体用法可以参看官网。该工具可以在虚拟机关闭的情况下,直接编辑查看系统内的文件内容,也可以直接写入文件或复制文件到外面的物理机,当然也可以像mount一样,支持挂载操作。
安装libguestfs-tools工具
yum -y install libguestfs-tools
在计算节点上通过命令或API接口找到实例编号
# virsh list --all
Id Name State
----------------------------------------------------
1 instance-00001035 running
对实例关机(必须关机,否则无法修改密码)
生成新密码
# openssl passwd -1 "openstack"
$1$/20Vnod9$vBvUgodH2qMVTB1EiEs30.
linux系统的加密密码通常存储在/etc/shadow 文件中,共分9列,用“:”分隔,其中第一列是用户名,第二列是密码。密码通常用MD5加密,这里我们用openssl加密工具,-1 即是普通MD5加密。
root:$6$H.RTQF71$7u2Y9YBJPB5.76jbhlTUVdoI/aea2x6mR2yvZx0VukGzaCAWhb.kO9doDaoB9l33IweoL.GvzzksJfQzw.Ntse1:17494:0:99999:7:::
bin:*:17110:0:99999:7:::
daemon:*:17110:0:99999:7:::
adm:*:17110:0:99999:7:::
lp:*:17110:0:99999:7:::
sync:*:17110:0:99999:7:::
shutdown:*:17110:0:99999:7:::
halt:*:17110:0:99999:7:::
mail:*:17110:0:99999:7:::
operator:*:17110:0:99999:7:::
games:*:17110:0:99999:7:::
ftp:*:17110:0:99999:7:::
nobody:*:17110:0:99999:7:::
systemd-network:!!:17494::::::
dbus:!!:17494::::::
polkitd:!!:17494::::::
postfix:!!:17494::::::
chrony:!!:17494::::::
sshd:!!:17494::::::
修改root密码
复制上面得到的密码,执行下面命令(instance-id不是openstack里面的id,而是virsh list 命令查看得到的instance-**那个)。
# virt-edit -d ***instance-id*** /etc/shadow
待打开后修改替换root账户第二栏密码
root:$6$H.RTQF71$7u2Y9YBJPB5.76jbhlTUVdoI/aea2x6mR2yvZx0VukGzaCAWhb.kO9doDaoB9l3IweoL.GvzzksJfQzw.Ntse1:17494:0:99999:7:::
修改为
root:$1$/20Vnod9$vBvUgodH2qMVTB1EiEs30.:17494:0:99999:7:::
保存退出,然后重启实例,就可以用新密码“openstack”登录了。
Qemu-Guest-Agent最大的优势在于他可以在任何时候去修改虚机系统密码,而不像其他两种方式,只能在初始化阶段或关机状态下做。
未免遗忘,特此小记。
徐超,就职于中电科华云,热爱开源技术、云计算、CI/CD。
↓↓ 点击"阅读原文" 【加入云技术社区】
相关阅读:
更多文章请关注