クラウドコンピューティングにおいて、重要な機能の1つは、実行中のVMインスタンスを同じクラスターの他のノードに移動させることです。これにより、ハードウェア/ソフトウェアのアップグレードやメンテナンス操作(電源オフを含む)をサービスの中断なしに実行できます。OpenStackとNovaを活用しているユーザーは、計算ノードがダウンしている場合、1つ以上のインスタンスが停止状態にある場合、またはインスタンスがまだ実行中の場合に仮想マシンをさまざまな状態で移行する細かい制御能力を持つことができます。詳細な説明は、Novaのマニュアルページで確認できます:
- host-evacuate
- host-evacuate-live
- host-server-migrate
- live-migration
- migrate
タイトルが示すように、私たちは主に host-evacuate-live に関心があります。これは、すべての実行中のインスタンスを他の計算ノードに移行します。この操作はより要求が高いため、これが正常に動作すれば、他の類似の操作も問題なく動作するはずです。では、移行が失敗した例とその修正方法を見てみましょう。
私たちは、3つのコントロール統合ノードで構成されたクラスタ、cc1、cc2、cc3で始めました。すべてのVMインスタンスはアクティブで実行中でした。
画像出典:Bigstack CubeCOS
そして、cc2上で実行中のすべてのインスタンスをcc3に移動しようとしました。
# nova host-evacuate-live cc2
ステータスがACTIVEからMIGRATINGに変わったことに注目してください。
画像出典:Bigstack CubeCOS
数秒後、cc3に2つのインスタンスが正常に移動されたという良いニュースがありました。
画像出典:Bigstack CubeCOS
しばらく待っていると、最終的にインスタンスがERROR状態になったことがわかりました。ほとんどの場合、すべてのインスタンスは正常に移行されることに注意してください。
画像出典:Bigstack CubeCOS
このようなエラーはHorizon UIで確認できます。
画像出典:Bigstack CubeCOS
何が間違ったのかを診断するために、ログを確認することから始めました。移行元のノードcc2のnova-compute.logを確認したところ、次のようなエラーが見つかりました。
Live migration failed.: libvirt.libvirtError: Timed out during operation: cannot acquire state change lock (held by monitor=remoteDispatchDomainGetobStats)
また、宛先ノードcc3のlibvirtdログも確認しました。同様のエラーがログに記録されていました。
cc3 libvirtd[39220]: Timed out during operation: cannot acquire state change lock (held by monitor=remoteDispatchDomainMigratePrepare3Params)
CubeCOSはLinuxベースで、基盤となる完全仮想化技術はKVMハイパーバイザーであるため、さらに詳しく調査するにはqemuプロセスを調べる必要があります。cc2ノードには、エラーが発生したインスタンスと一致するqemuプロセスが実行されていました。
# ps awx | grep qemu
635175 ? Sl 51:20 /usr/libexec/qemu-kvm -name guest=instance-00000007,debug-threads=on -S
# virsh list
Id Name State
----------------------------------
2 instance-00000007 paused
一時停止状態は予期しない状態だったので、qemuモニターに接続してさらに調査したいと考えました。
# virsh qemu-monitor-command --hmp 2 info status
興味深いことに、このコマンドはハングしましたが、ログがタイムアウトした理由を説明しました。VNCコンソールも応答しませんでした。プロセスは実行中のように見えましたが、何らかの理由で停止した状態でした。インターネット上の古い投稿では、qemuスレッド間の競合状態が示唆されていました。gdb/gstackのダンプは、他の人々が観察したものと一致しているようでした。libvirtとその仲間であるvirshのおかげで、VMの設定はxmlファイルでしっかりと追跡されているため、応答しないプロセスを安全に終了し、同じセットアップで新しいプロセスを起動することができます。
# virsh destroy 2
Domain '2' destroyed
# virsh list --all
Id Name State
------------------------------------
- instance-00000007 shut off
そして、確かに古いqemuプロセスは終了しました。
# ps awx | grep qemu
3633296 pts/2 S+ 0:00 grep --color=auto qemu
# virsh start instance-00000007
Domain 'instance-00000007' started
# virsh list
Id Name State
-----------------------------------
4 instance-00000007 running
# virsh qemu-monitor-command --hmp 4 info status
VM status: running
# virsh console 4
Connected to domain 'instance-00000007'
Escape character is ^] (Ctrl + ])
login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
cirros-hotstorage-1a0e login: cirros
cirros
Password:
$ hostname
hostname
cirros-hotstorage-1a0e
$ uptime
uptime
19:25:08 up 12:03, 1 users, load average: 0.00, 0.00, 0.00
$
これでほぼ終わりですが、1つの追加ステップとして、OpenStackにインスタンスの状態が実際には正常であることを通知する必要がありました。
# openstack server set --state active 198e7b81-8267-44dc-a061-0cf63a970e57
画像出典:Bigstack CubeCOS
すべてが再び正常に戻りましたが、復旧したインスタンスがまだcc2に残っていたため、そのインスタンスをcc3に移動するために、もう一度evacuationコマンドを実行する必要がありました。
# nova host-evacuate-live cc2
その後、ユーザーフレンドリーなUIコンソールに接続して、新しく移行されたVMとやり取りすることができました。
画像出典:Bigstack CubeCOS
これらすべてが終わった後、cc2ノードは空になり(VMインスタンスはなし)、メンテナンス作業の準備が整いました。