本文以製做CentOS7.2鏡像爲例,詳細介紹手動製做OpenStack鏡像詳細步驟,解釋每一步這麼作的緣由。鏡像上傳到OpenStack glance,支持如下幾個功能:php
手動製做鏡像很是麻煩和耗時,本文後面會介紹一個專門用於自動化構建鏡像的項目DIB,經過DIB只須要在命令行上指定elements便可製做鏡像,省去了重複下載鏡像、啓動虛擬機配置鏡像的繁雜步驟。html
鏡像的宿主機操做系統爲Ubuntu 14.04,開啓了VT功能(使用kvm-ok命令驗證)並安裝了libvirt系列工具,包括virsh、virt-manager、libguestfs-tools等。python
1.1 下載鏡像linux
訪問官方鏡像地址下載,注意選擇中國的鏡像源,相對國外鏡像下載速度更快,進入後選擇版本爲7.2.1511,在isos目錄下下載x86_64的Minimal鏡像,若是網速不給力,最好不要選擇下載Netinstall鏡像,由於這會在安裝時聯網下載大量的軟件包,從新安裝時須要從新下載這些軟件包。nginx
1.2 建立虛擬機git
首先建立一個qcow2格式鏡像文件,用於虛擬機的根磁盤,大小10G就夠了。github
qemu-img create -f qcow2 centos.qcow2 10G # create disk image
使用如下腳本建立並啓動虛擬機:sql
NAME=centos ROOT_DISK=centos.qcow2 CDROM=`pwd`/CentOS-7-x86_64-Minimal-1511.iso sudo 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鏈接。json
1.3 安裝OSubuntu
進入虛擬機控制檯能夠看到CentOS的啓動菜單,選擇Install Centos 7,繼續選擇語言後將進入INSTALLION SUMMARY,其中大多數配置默認便可,SOFTWARE SELECTION選擇Minimal Install,INSTALLATION DESTINATION須要選擇手動配置分區,咱們只須要一個根分區便可,不須要swap分區,文件系統選擇ext4或者xfs,存儲驅動選擇Virtio Block Device,如圖:
配置完成後就能夠開始安裝了,在CONFIGURATION中設置root臨時密碼,只須要暫時記住這個臨時密碼,製做完後cloud-init會從新設置root初始密碼。
大約幾分鐘後,便可自動完成安裝配置工做,最後點擊右下角的reboot重啓退出虛擬機。
1.4 配置OS
安裝好系統後,須要進行配置才能做爲glance鏡像使用。首先啓動虛擬機(雖然上一步執行的是reboot,但貌似並不會自動啓動):
sudo virsh start centos
若是雲主機須要支持root ssh遠程登陸,須要開啓root遠程ssh登陸功能,修改配置文件/etc/ssh/sshd_config並修改PermitRootLogin值爲yes,重啓ssh服務生效:
sudo systemctl restart sshd
注意:
爲了加快安裝速度,能夠配置爲本地軟件源倉庫,若沒有本地鏡像倉庫,則選擇國內的軟件源,相對官網的速度下載要快。
mv my_repo.repo /etc/yum.repos.d/
acpid
acpid是一個用戶空間的服務進程, 用來處理電源相關事件,好比將kernel中的電源事件轉發給應用程序,告訴應用程序安全的退出,防止應用程序異常退出致使數據損壞。libvirt能夠經過向guest虛擬機發送acpid事件觸發電源操做,使虛擬機安全關機、重啓等操做,相對於強制執行關閉電源操做更安全。經過acpid事件發送開關機信號即咱們常常所說的軟重啓或者軟關機。
爲了支持軟操做,虛擬機須要安裝acpid服務,並設置開機自啓動:
yum install -y acpid systemctl enable acpid
提示:
console log
當操做系統內核崩潰時會報出內核系統crash出錯信息,一般啓動的時候一閃而過, 而此時系統尚未起來,不能經過遠程工具(好比ssh)進入系統查看,咱們能夠經過配置grub,把這些日誌重定向到Serial Console中,這樣咱們就能夠經過Serial console來訪問錯誤信息,以供分析和排錯使用。
修改配置文件/etc/default/grub,設置GRUB_CMDLINE_LINUX
:
GRUB_CMDLINE_LINUX="crashkernel=auto console=tty0 console=ttyS0,115200n8"
經過這個配置,內核信息會以115200的波特率同時發送到tty0和ttyS0串行端口設備。libvirt能夠經過一個普通文件模擬這個串行端口:
<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網絡,實現方式簡單方便。
<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:
yum install -y qemu-guest-agent
修改/etc/sysconfig/qemu-ga配置文件:
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支持的指令:
$ 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是一種古老的自動網絡配置技術,在沒有DHCP服務的年代,全部服務器都須要網管手動配置IP、hostname等,很是麻煩,zeroconf正好解決了這個問題,不過目前一般都經過DHCP獲取地址了。不過一些操做系統仍然會開啓這個服務,當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服務,關於該問題的更詳細討論可參考bug#983611:
echo "NOZEROCONF=yes" >> /etc/sysconfig/network
cloud-init
接下來安裝cloud-init,cloud-init是虛擬機第一次啓動時執行的腳本,主要負責從metadata服務中拉取配置信息,完成虛擬機的初始化工做,好比設置主機名、初始化密碼以及注入密鑰等。
# yum install -y cloud-init-0.7.6-bzr1.el7.centos.noarch.rpm yum install -y cloud-init
growpart
虛擬機制做鏡像時指定了根分區大小(好比咱們設置爲10GB),爲了使虛擬機可以自動調整爲flavor disk指定的根磁盤大小,即自動擴容, 咱們須要安裝glowpart(老版本叫growroot)並完成如下配置:
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命令後執行關機:
/sbin/shutdown -h now
1.5 移除本地信息
在宿主機上運行如下命名,移除宿主機信息,好比mac地址等。
virt-sysprep -d centos # cleanup tasks such as removing the MAC address references
刪除虛擬機,鏡像製做完成。
virsh undefine centos # 刪除虛擬機
2.1 使用glance命令上傳鏡像
鏡像製做完成,上傳centos.qcow2到glance服務中。
glance image-create --file ./centos.qcow2 --disk-format qcow2 \ --container-format bare --name CentOS-7.2 --progress
2.2 經過rbd直接導入鏡像
因爲鏡像一般比較大,上傳時若是使用glance API,則經過HTTP上傳,因爲HTTP協議的限制,致使上傳很是慢,很是耗時。 若是Glance使用Ceph做爲存儲後端,能夠經過rbd直接導入(import)方式上傳到Ceph中,速度會大幅度提升。
首先須要把鏡像轉爲raw格式:
qemu-img convert -f qcow2 -O raw centos.qcow2 centos.raw
經過glance create建立一個空鏡像,並記錄uuid(不須要指定文件路徑以及其它字段,只是佔個坑):
glance image-create
使用rbd命令直接導入鏡像並建立快照:
rbd -p glance import centos.raw --image=$IMAGE_ID --new-format --order 24 rbd -p glance snap create $IMAGE_ID@snap rbd -p glance snap protect $IMAGE_ID@snap
設置glance鏡像location url:
FS_ID=`ceph -s | grep cluster | awk '{print $2}'` glance location-add --url rbd://${FS_ID}/glance/${IMAGE_ID}/snap $IMAGE_ID
設置glance鏡像其它屬性:
glance image-update --name="CentOS-7.2-64bit" \ --disk-format=raw --container-format=bare
2.3 添加qemu-guest-agent屬性
OpenStack Nova是經過判斷鏡像元數據hw_qemu_guest_agent是否爲yes決定是否支持qemu-guest-agent,代碼以下:
# nova/virt/libvirt/driver.py def _add_qga_device(self, guest, instance): qga = vconfig.LibvirtConfigGuestChannel() qga.type = "unix" qga.target_name = "org.qemu.guest_agent.0" qga.source_path = ("/var/lib/libvirt/qemu/%s.%s.sock" % ("org.qemu.guest_agent.0", instance.name)) guest.add_device(qga) def _set_qemu_guest_agent(self, guest, flavor, instance, image_meta): # Enable qga only if the 'hw_qemu_guest_agent' is equal to yes if image_meta.properties.get('hw_qemu_guest_agent', False): LOG.debug("Qemu guest agent is enabled through image " "metadata", instance=instance) self._add_qga_device(guest, instance) ...
由此可知,咱們必須添加鏡像property hw_qemu_guest_agent=yes
,不然libvert啓動虛擬機時不會建立qemu-guest-agent設備,虛擬機的qemu-guest-agent因爲找不到對應的串行設備而致使修改密碼失敗。
glance image-update --property hw_qemu_guest_agent=yes $IMAGE_ID
前面介紹了手動製做鏡像的過程,從鏡像下載到啓動虛擬機安裝操做系統,而後在虛擬機中完成配置,最後清除本地信息,整個過程很是繁雜、耗時,而且一旦製做鏡像的鏡像有點問題,就須要啓動虛擬機從新再來一遍,重複工做多,效率很是低。
假設製做鏡像時某個配置項錯了,能不能不經過啓動虛擬機進入系統去更改呢?答案是確定的!咱們只須要把製做好的鏡像經過loop設備掛載到本地(若是是qcow2格式,則須要經過nbd掛載),而後chroot到掛載目錄中修改配置文件便可,相對於啓動虛擬機進入系統去更改方便高效不少。
由此咱們天然想到,咱們能夠把最初啓動虛擬機時安裝操做系統完成後的鏡像保存爲base鏡像,之後再作鏡像時,只須要基於該base鏡像調整便可,省去了下載鏡像以及安裝操做系統這兩大耗時步驟。修改鏡像也再也不須要啓動虛擬機,只須要根據前面介紹的方法,把鏡像掛載到本地,而後chroot到根分區修改便可。
OpenStack社區正是基於該思路,開發了DIB(disk image builder),它目前是OpenStack TripleO項目的子項目,專門用於構建OpenStack鏡像:
diskimage-builder is a flexible suite of components for building a
wide-range of disk images, filesystem images and ramdisk images for
use with OpenStack.
DIB把一些操做封裝成腳本,好比建立用戶(devuser)、安裝cloud-init(cloud-init)、配置yum源(yum)、部署tgtadm(deploy-tgtadm)等,這些腳本稱爲elements,位於目錄diskimage-builder/diskimage_builder/elements
,你能夠根據本身的需求本身定製elements,elements之間會有依賴,依賴經過element-deps文件指定,好比elements centos7的element-deps爲:
DIB會首先下載一個base鏡像,而後經過用戶指定的elements,一個一個chroot進去執行,從而完成了鏡像的製做,整個過程不須要啓動虛擬機。這有點相似Dockerfile的構建過程,Dockerfile的每一個指令都會生成一個臨時的容器,而後在容器裏面執行命令。DIB則每一個elements都會chroot到鏡像中,執行elements中的腳本。
好比製做ubuntu 14.04鏡像:
export DIB_RELEASE=trusty disk-image-create -o ubuntu-trusty.qcow2 vm ubuntu
建立Trove percona鏡像:
disk-image-create -a amd64 \ -o ubuntu-trusty-percona-5.6.33-guest-image \ -x ubuntu vm cloud-init-datasources ubuntu-trusty-guest \ ubuntu-trusty-percona
其中ubuntu-trustry-guest會安裝trove-guest-agent,ubuntu-trusty-percona會安裝percona組件。
製做鏡像時能夠經過環境變量進行配置,好比建立ironic鏡像:
# 生成用戶鏡像 # ubuntu.qcow2:用戶最終使用的鏡像 # ubuntu.vmlinuz:"Virtual Memory"的縮寫,具備引導的壓縮內核 # ubuntu.initrd: "initial ramdisk"的縮寫 # Linux系統引導過程當中使用的臨時根文件系統,包含基本linux命令, # 如ls,cd,tftp等 export DIB_DEV_USER_USERNAME=cloud-user export DIB_DEV_USER_PASSWORD=secret export DIB_DEV_USER_PWDLESS_SUDO=YES DIB_CLOUD_INIT_DATASOURCES="ConfigDrive, OpenStack" disk-image-create -o centos7 centos7 baremetal dhcp-all-interfaces grub2 cloud-init-datasources devuser
以上製做鏡像時會建立cloud-user用戶,密碼爲secret,支持免密碼sudo,cloud-init的datasources爲ConfigDriver和OpenStack。
經過DIB製做鏡像可以更方便地管理和維護,實現自動化構建鏡像,建議OpenStack鏡像都直接使用DIB構建。
4.1 注入密碼和密鑰
使用剛剛建立的鏡像啓動一臺雲主機,若是使用nova CLI工具,須要傳–admin-pass參數指定root密碼,並指定disk大小爲20G的flavor。若是使用OpenStack Dashborad建立,須要簡單配置下dashborad使其支持配置雲主機密碼,如圖:
建立成功後進入vnc界面,使用root帳號以及設置的新密碼,若是登陸成功,說明注入密碼成功。
在建立一個一樣配額的虛擬機,指定keypair,建立完後,使用密鑰登陸,若是可以登陸,說明密鑰注入成功。
4.2 動態調整根磁盤分區大小
運行如下命令檢查根磁盤是否自動調整分區和文件系統大小:
lsblk
df -h
如圖:
鏡像原始根分區大小爲10GB,若是lsblk顯示vda大小爲20GB,說明操做系統識別出根磁盤大小。若是df顯示/dev/sda1size爲20GB,說明根磁盤的分區和文件系統均自動完成了擴容操做,growpart運行正常。
4.3 動態修改密碼
nova經過set-password子命令修改虛擬機管理員密碼:
nova set-password ${server_uuid}
重複輸入兩次密碼,若是執行成功,不會有任何輸出。
回到終端,退出以前的登陸,而後使用新的密碼從新登陸,若是登陸成功,則說明動態修改密碼成功!
本文首先介紹了手動製做的OpenStack的鏡像步驟,而後提出一種更快捷的鏡像上傳方法,該方法只能適用於Ceph後端,最後引入OpenStack鏡像製做項目DIB,介紹了DIB的優點。