Linux の正常なシャットダウン (Graceful Shutdowns)
このポストは、5 月 6 日に投稿された Linux and Graceful Shutdowns の翻訳です。
Azure の IaaS 仮想マシンをシャットダウンする方法はいくつかあり、Azure 管理ポータル経由でシャットダウンしたり、Azure Powershell コマンドレットや CLI ツールを使用したり、あるいはログインしたユーザーが対話的にシャットダウンすることもできます。プラットフォームのメンテナンスのために、Azure プラットフォーム自らがシャットダウンを実行することもあります。オンプレミスのベア メタルで実行されている Linux システムのシャットダウンのプロセスはよく知られていますが、クラウドではどのように行われるのでしょうか?
Azure で正常なシャットダウンを実行する
Azure で Linux 仮想マシンをシャットダウンするプロセスは、オンプレミスの場合とほぼ同じです。ユーザーがログインして ‘/sbin/shutdown now’ を実行すると、システムはすぐにサービスの実行を停止し、電源がオフになります。もちろん、実際のしくみは使用しているディストリビューションや init システム (たとえば SysV、Upstart、systemd) により異なりますが、同じ結果が得られます。
では、Azure 管理ポータルや Azure プラットフォームによってシャットダウンが開始された場合はどうでしょうか? 簡潔に言うと、この場合もほぼ同じ結果が得られます。Azure はホストと通信してゲストの Linux システムの正常なシャットダウンを開始します。Hyper-V と Azure の環境では、ハイパーバイザーが正常なシャットダウンを実行するシグナルを送信し、Linux カーネルに含まれる Linux Integration Services の一部である hv_utils (英語) ドライバーが処理を行います。これが「統合シャットダウン」と呼ばれる機能です。
ハイパーバイザーからシグナルを受信した hv_utils ドライバーは Linux ゲストの正常なシャットダウンを開始します。ユーザーが ‘/sbin/shutdown now’ を手動で実行したのと実質的に同じしくみです。hv_utils がハイパーバイザーからシグナルを受信すると、ハイパーバイザーにより Linux システムがシャットダウンされたことを示す次のメッセージがログ (Ubuntu システムでは通常 /var/log/messages または /var/log/syslog) に送信されます。
ここで小さな問題があり、Azure プラットフォームは正常なシャットダウンを開始した後、永久に待機するわけではなく、5 分間以上仮想マシンの実行状態が続くとこのマシンの電源をオフにします。このため、仮想マシンがこの時間内にすべてのスクリプトを実行してクリーン シャットダウンできるようにする必要があります。
シャットダウン プロセスの管理
Azure に対する Linux ユーザー共通の要求は、Azure によって仮想マシンの正常なシャットダウンが開始される場合にアプリケーションが正しくシャットダウンされるようにすることです。手動によるシャットダウンとハイパーバイザーによるシャットダウンのしくみが同じであることがわかったので、既存の Linux init システムを利用すればアプリケーションを正常にシャットダウンできます。
多くの場合は、既存の SysV、systemd、または upstart スクリプトでアプリケーションを正しくシャットダウンできますが、それでは不十分な場合や、アプリケーションの「クリーンアップ」を実行するプロセスが追加で必要な場合は、他にもいくつかの方法があります。
- 最も簡単なのは、アプリケーションの init スクリプトを書き換えてタスクを追加する方法ですが、これにはいくつか欠点があり、スクリプト編集の際にタイポなどのミスが発生したり、こうしたスクリプトは通常 RPM や Deb パッケージで管理されているためアップグレードできなくなったりする可能性があります。逆にメリットを挙げると、「統合シャットダウン」はハイパーバイザーの一機能なので、Azure にデプロイする前にローカルの Hyper-V で検証を行うことができます。
- 次の選択肢としては、init スクリプトを独自に作成する方法があります。Linux の init システムの種類は多岐にわたるので、その方法もさまざまです。ほとんどのシステムは少なくとも SysV 対応でネイティブな init システムが備わっているので、SysV 対応スクリプトを作成して runlevel 0 から実行されるようにするのが最も簡単です。
- これよりもさらに若干手のかかるアプローチがこちら (英語) で、私は先日 Azure Gallery の CentOS イメージを使って実際にテストしました。このスクリプトをお手本にして、シャットダウン前に必要な処理を実行する独自の init スクリプトを作成することができそうです。なお、電源がオフになるまでに、仮想マシンをクリーン シャットダウンするのに 5 分間の余裕があることを頭の片隅に置いておいてください。
いずれにしても Linux ですので、どんなディストリビューションやワークロードでも有効な万能なアプローチというものはありません。最大のポイントは、「解決方法はいくつもあり、Hyper-V や Azure で特別なことをしなくても仮想マシンをクリーン シャットダウンできる」ということです。ご使用中の Linux ディストリビューションに用意されている標準的な手法やしくみを利用しながらも、Azure でこれらのシステムをホスティングできるというのは大きなメリットです。