在線升級glance鏡像技巧
0.背景
我們經(jīng)常需要更新glance鏡像,比如上傳的鏡像可能有配置問題,或者我們需要對已有的鏡像進(jìn)行軟件包升級或者預(yù)裝一些新的軟件包等。當(dāng)時(shí)著手這件事是由于我們對cloud-init進(jìn)行了大量的patch,需要同步到glance鏡像中,如果重新制作鏡像然后傳輸?shù)缴a(chǎn)環(huán)境再上傳,不僅工作非常繁瑣,還非常消耗時(shí)間,我們希望能夠在原來的鏡像基礎(chǔ)之上直接升級cloud-init。
1.通過快照方式更新鏡像
最簡單的方式是通過創(chuàng)建一個(gè)云主機(jī),然后更新cloud-init后創(chuàng)建快照形成新的鏡像(注意刪除/var/lib/cloud下的文件,否則cloud-init下次啟動(dòng)時(shí)不會(huì)重新拉取metadata)??墒俏覀冇龅降膯栴}是,老版本的cloud-init在L版中注入密碼和密鑰都失敗,并且安裝的qemu-guest-agent不支持修改密碼,因此完全沒有辦法登錄云主機(jī)。因此必須另辟蹊徑。
2.glance存儲(chǔ)后端使用本地文件系統(tǒng)
于是我們想到把鏡像掛載到本地文件系統(tǒng)中,然后chroot到鏡像文件系統(tǒng)環(huán)境中進(jìn)行升級配置。如果glance鏡像使用本地文件系統(tǒng)作為存儲(chǔ)后端,鏡像格式為raw,掛載鏡像就非常簡單了:
- losetup /dev/loop0 image.img
- kpartx -a /dev/loop0
- mount /dev/mapper/loop0p1 /mnt/image
如果是qcow2格式,需要安裝qemu-nbd工具包,并且加載nbd內(nèi)核模塊:
- modprobe nbd max_part=63
- qemu-nbd -c /dev/nbd0 image.img
- mount /dev/nbd0p1 /mnt/image
如果鏡像文件系統(tǒng)中使用LVM,可以使用以下方法初始化:
- vgscan
- vgchange -ay
- mount /dev/VolGroupName/LogVolName /mnt/image
chroot進(jìn)行后執(zhí)行相關(guān)操作后,卸載鏡像文件系統(tǒng):
- umount /mnt/image
- vgchange -an VolGroupName
- killall qemu-nbd
- kpartx -d /dev/loop0
- losetup -d /dev/loop0
以上方法參考Mounting-raw-and-qcow2-vm-disk-images。
本文重點(diǎn)不在于基于本地文件系統(tǒng)作為存儲(chǔ)后端的情況,重點(diǎn)介紹基于Ceph存儲(chǔ)后端的操作方法,下文將詳細(xì)介紹過程。
3.基于Ceph存儲(chǔ)后端的更新方法
我們知道使用ceph作為存儲(chǔ)后端時(shí),鏡像首先會(huì)生成一個(gè)以snap命名的快照,比如glance有一個(gè)鏡像id為35fcb79c-43a1-4b59-83d7-f4e46a524419,則在rbd中有對應(yīng)的image,命名與glance鏡像id一致,我們查看其快照:
- rbd snap ls --image openstack-images/35fcb79c-43a1-4b59-83d7-f4e46a524419 2>/dev/null
輸出:
- SNAPID NAME SIZE
- 94604 snap 20480 MB
我們不能直接修改快照snap,因?yàn)樗莗rotect的,只能讀不能寫。直接修改鏡像的話不能同步到快照中,并且出錯(cuò)也不好回滾。
因此我們的做法是先復(fù)制一個(gè)rbd image副本.
首先使用glance命令行工具獲取需要更新的鏡像的id:
- IMAGE_ID=$(glance image-list --name "CentOS 7.1 64bit 2>/dev/null | awk --re-interval '/\w{8}-.*/{print $2}')
使用rbd命令拷貝一份鏡像副本,假設(shè)POOL變量為glance使用的ceph池:
- rbd cp $POOL/${IMAGE_ID} $POOL/${IMAGE_ID}_copy
掛載鏡像到本地文件系統(tǒng)中:
- rbd map $POOL/${IMAGE_ID}_copy
- # /dev/rbd0
- mount /dev/rbd0p1 /mnt
注意由于鏡像是Linux文件系統(tǒng),因此通常只有一個(gè)根分區(qū),如果是windows鏡像,***個(gè)分區(qū)通常是隱藏分區(qū),C盤是第二個(gè)分區(qū),因此掛載時(shí)注意選擇rbd0p2,其中p表示partition。
掛載到本地后,可以拷貝軟件包、配置模板等到鏡像文件系統(tǒng)中,比如/mnt/root/,然后chroot到鏡像文件系統(tǒng)中:
- cd /mnt # /mnt是我們需要chroot的根目錄
- # mount -t proc proc proc/ # 掛載proc
- # To use an internet connection in the chroot environment copy over the DNS details:
- cp /etc/resolv.conf etc/resolv.conf # 覆蓋即可,生成云主機(jī)會(huì)自動(dòng)覆蓋
- # To change root into a bash shell:
- chroot /mnt bash # chroot 到/mnt中,如果提示bash命令找不到,使用絕對路徑試試 chroot /mnt /bin/bash
- # 初始化環(huán)境變量
- source /etc/profile
- source ~/.bashrc
- # 如果提示找不到ls等命令,需要手動(dòng)設(shè)置PATH變量: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/bin
- # Tip: Optionally, create a unique prompt to be able to differentiate your chroot environment:
- export PS1="(chroot) $PS1"
接下來就可以執(zhí)行命令對鏡像進(jìn)行更新了,比如更新cloud-init:
- yum remove cloud-init # Remove the old version package
- rpm -i cloud-init-0.7.6-bzr1.el7.centos.noarch.rpm # Install the pacakge
升級qemu-guest-agent:
- yum install -y qemu-guest-agent
- rpm -aq | grep qemu-guest-agent
- # qemu-guest-agent-2.3.0-4.el7.x86_64
執(zhí)行完所有的更新操作后,完成以下清理工作:
- yum clean all
- rm -rf /root/* # 危險(xiǎn)?。?!刪除根目錄下拷貝的臨時(shí)文件,執(zhí)行前確認(rèn)無有用文件!
- exit # 退出chroot環(huán)境
- cd # 切換到家目錄,工作目錄不能位于/mnt,否則卸載不了
- umount --recursive /mnt/ # 如果busy怎么辦?lsof查看哪個(gè)進(jìn)程占用,如果還是不行試試使用 --lazy 參數(shù)
- rbd unmap /dev/rbd0 # 從rbd中卸載
***需要更新glance,我們的方法是先創(chuàng)建一個(gè)glance空鏡像實(shí)例,不需要指定鏡像文件,只是占個(gè)坑,拿到新鏡像id:
- NEW_IMAGE_ID=`glance image-create | grep id | awk '{print $4}'` || { echo 'Error: glance image-create failed !' ; exit 1; }
接下來更新我們的rbd image,命名為新創(chuàng)建鏡像實(shí)例id并設(shè)置快照:
- rbd mv $POOL/${IMAGE_ID}_copy $POOL/${NEW_IMAGE_ID}
- rbd --pool=$POOL --image=${NEW_IMAGE_ID} --snap=snap snap create
- rbd --pool=$POOL --image=${NEW_IMAGE_ID} --snap=snap snap protect
***更新glance鏡像元數(shù)據(jù):
- glance image-update --name="$DISPLAY_NAME" --disk-format=raw --container-format=bare --is-public=True ${NEW_IMAGE_ID}
- glance image-update --property image_meta="$image_meta" ${NEW_IMAGE_ID}
- glance image-update --property hw_qemu_guest_agent=yes $IMAGE_ID
- # ...
- # update image location
- FSID=`ceph -s | grep cluster | awk '{print $2}'`
- glance image-update --location rbd://$FSID/$POOL/$IMAGE_ID/snap ${NEW_IMAGE_ID}
- if [[ $IMAGE_LABEL == "Windows" || $IMAGE_LABEL == "windows" ]]; then
- glance image-update --property hw_video_model=qxl --property hw_video_ram=64 --property os_admin_user=Administrator $IMAGE_ID
- fi
***對新鏡像進(jìn)行功能驗(yàn)證,如果沒有問題,就可以安全的刪除老的鏡像了。
【本文是51CTO專欄作者“付廣平”的原創(chuàng)文章,如需轉(zhuǎn)載請通過51CTO獲得聯(lián)系】