上週五在測試 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]
  • 在以上的範例中,11這個檔案是 link 到 VM 的 instance(/var/lib/nova/instances/19664c67-5831-4ebe-a1e5-1cb808ec2d81/disk),而14則是 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 的 instance 、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 都否都存在:

1 /var/lib/nova/instances/_base/$(Base image)
2 /var/lib/nova/instances/$(VM UUID)/disk
3 /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 上將 VM 做 Hardware reboot

Comments

comments powered by Disqus