復原 OpenStack 中被刪除的 instance
上週五在測試 puppet 全自動安裝 Openstack compute,大概是 class dependency 沒有設好的原因,總之 puppet 在安裝 compute 時總是會漏掉許多設定值。因此,我不斷地做 install/uninstall 來做測試。
Unstall 時已經很習慣用 apt-get –purge install nova-* quantum-* 。原本這行指令並沒有甚麼問題,但在於實驗的cloud環境,將 /var/lib/nova/instance
用 ceph 分享給所有 compute。
所以…悲劇發生了,所有 running 中 VM 的 instance 都被我刪除了。這個問題整個周末都沒有發現,是昨天上班時,我問效維新安裝的伺服器是否有發生狀況,這時我們才發現了這個大問題。
所幸,Linux 有個保護機制,當一個 file 被某些 process 佔用時,如果將該檔案刪除,此時系統只會將檔案 mark 為 (deleted)。 這樣一來其他 process、user 是讀取不到該檔案,但是該檔案還是繼續存在於 file system 中,直到那些所佔用 process 都結束了,這些 file 才會消失。
回到正題,cloud 上的 VM instance 被刪除會發生甚麼狀況呢?
- VM 沒有關機,但是他也不能做 clone (在 Openstack Dashbard 上是 snaphost 功能)
- VM 一旦關機,instance 就會被刪掉 => user 的資料消失(除非 user 放在 volume 裡面,而我們系統將 volume 獨立開來)
萬一整個 cloud 上所有 user 的資料都消失了,那我想我應該會被罵到死吧= =
萬幸的是我終於找到方法了
Solution
第一步
先登入到 physical machine 中,使用 virsh 指令查看還有哪些 VM 是 running :
root@local# virsh list --all
Id Name State
----------------------------------------------------
16 instance-000002d3 running
38 instance-0000006c running
39 instance-00000008 running
- instance-0000029d shut off
- instance-000002a6 shut off
- instance-000002c6 shut off
以上述為例,目前還有3個 VM 是 running 中,此時我們必須要先將 VM 暫停:
root@local# virsh suspend 16
root@local# virsh suspend 38
root@local# virsh suspend 39
之後 VM 的狀態就會從 running 變成 paused :
root@local# virsh list --all
Id Name State
----------------------------------------------------
16 instance-000002d3 paused
38 instance-0000006c paused
39 instance-00000008 paused
- instance-0000029d shut off
- instance-000002a6 shut off
- instance-000002c6 shut off
第二步
找到 VM 的 process id:
root@local# ps aux |grep 'instance-000002d3'
root 22430 0.0 0.0 9388 940 pts/1 S+ 09:12 0:00 grep --color=auto 2d3
107 25534 12.9 5.9 13075024 1474148 ? Sl Sep17 6469:57 /usr/bin/kvm -name instance-000002d3 -S ...(以下省略)...
從上述中的例子我們可以看到,instance-000002d3
的 process id 為 25534。根據 process id,切換當前目錄到 /proc/$processid/fd
,此時就可以看到此 process 佔用了那些檔案:
root@local# cd /proc/25534/fd
root@local# ls -l
total 0
dr-x------ 2 libvirt-qemu kvm 0 Oct 21 21:08 .
dr-xr-xr-x 9 libvirt-qemu kvm 0 Sep 17 16:30 ..
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 0 -> /dev/null
l-wx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 1 -> /var/log/libvirt/qemu/instance-000002d3.log
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 10 -> anon_inode:[eventfd]
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 11 -> /var/lib/nova/instances/19664c67-5831-4ebe-a1e5-1cb808ec2d81/disk (deleted)
lr-x------ 1 libvirt-qemu kvm 64 Oct 21 21:08 12 -> pipe:[73026899]
l-wx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 13 -> pipe:[73026899]
lr-x------ 1 libvirt-qemu kvm 64 Oct 21 21:08 14 -> /var/lib/nova/instances/_base/05a559eb870ea8c8e3142a7269f2c1dd8bd69321 (deleted)
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 15 -> anon_inode:kvm-vcpu
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 16 -> anon_inode:kvm-vcpu
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 17 -> anon_inode:kvm-vcpu
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 18 -> anon_inode:kvm-vcpu
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 19 -> socket:[73019779]
l-wx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 2 -> /var/log/libvirt/qemu/instance-000002d3.log
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 20 -> anon_inode:[eventfd]
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 21 -> socket:[73019780]
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 24 -> /dev/net/tun
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 29 -> /dev/vhost-net
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 3 -> socket:[72970876]
l-wx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 4 -> /var/lib/nova/instances/19664c67-5831-4ebe-a1e5-1cb808ec2d81/console.log (deleted)
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 5 -> /dev/ptmx
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 6 -> /dev/kvm
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 7 -> anon_inode:kvm-vm
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 8 -> anon_inode:[signalfd]
lrwx------ 1 libvirt-qemu kvm 64 Oct 21 21:08 9 -> anon_inode:[eventfd]
第三步
在以上的範例中,<font color="red">11</font>
這個檔案是 link 到 VM 的 instance (/var/lib/nova/instances/19664c67-5831-4ebe-a1e5-1cb808ec2d81/disk
),而 <font color="red">14</font>
則是 link 到此 instance 的 backing_file (在 Openstack 上稱為 VM image)。此時,將 11、14、4 三個檔案複製到其他位置保存:
root@local# mkdir ~/backup/19664c67-5831-4ebe-a1e5-1cb808ec2d81 ~/backup/_base
root@local# cp 11 ~/backup/19664c67-5831-4ebe-a1e5-1cb808ec2d81/disk
root@local# cp 4 ~/backup/19664c67-5831-4ebe-a1e5-1cb808ec2d81/console.log
root@local# cp 14 ~/backup/_base/05a559eb870ea8c8e3142a7269f2c1dd8bd69321
重複以上的步驟直到所有 VM 的 instances、base image 都備份完成
一般來說,一個 base image 會開出很多的 VM instance。因此相同的 base image 只要 copy 一份即可
第四步
完成備份之後,將所有的 VM 關機 (這個步驟一定要用 virsh 指令,不可以使用 openstack dashboard):
root@local# virsh list --all
Id Name State
----------------------------------------------------
16 instance-000002d3 paused
38 instance-0000006c paused
39 instance-00000008 paused
- instance-0000029d shut off
- instance-000002a6 shut off
- instance-000002c6 shut off
root@local# virsh destroy 16
Domain 16 destroyed
root@local# virsh destroy 38
Domain 38 destroyed
root@local# virsh destroy 39
Domain 39 destroyed
root@local# virsh list --all
Id Name State
----------------------------------------------------
- instance-0000029d shut off
- instance-000002a6 shut off
- instance-000002c6 shut off
- instance-000002d3 shut off
- instance-0000006c shut off
- instance-00000008 shut off
第五步
將每一台 VM 關機之後,再將備份好的檔案全部寫回去:
root@local# cp -R ~/backup/* /var/lib/nova/instances/
確認一下 base image 與 VM instance 都否都存在:
/var/lib/nova/instances/_base/$(Base image)
/var/lib/nova/instances/$(VM UUID)/disk
/var/lib/nova/instances/$(VM UUID)/console.log
修改檔案的擁有者、群組以及存取權限:
-
/var/lib/nova/instances/_base
的 ownwer/group 必須要是 nova:nova,目錄下內的所有 base image:- Owner/Group => nova:kvm
- Mode => 0644
-
/var/lib/nova/instances/$(VM UUID)
的 owner/group 必須要是 nova:nova,目錄下的所有檔案分別為:disk
- Owner/Group => libvirt-qemu:kvm
- Mode => 0644
console.log
- Owner/Group => nova:nova
- Mode => 0660
完成之後,就可以在 Openstack Dashboard 上 hardware reboot VM 。