Ruby on Rails on Windows Azure (3)

(1)(2)のエントリーで、どのいう経緯でホワイトペーパーNougakuDo Companionが出来上がってきたかを説明しました(まあ、前置きが長い気がしなくもありませんが...)。今回は、NougakuDo Companionを説明します。最初に、NougakuDo Companionの概要図を示します。

NougakuDoCompanion

NougakuDo Companionは、図に示すように大きな機能は4つに分類することができます。それぞれの機能は、以下のような役割を持っています。

  • AdminWeb:管理サイト(ポート8080)で、能楽堂で作成したRailsアプリケーションの運用管理や、NougakuDo Comapnionのログ情報などを参照できる、ASP.NET MVC 3による Web アプリケーションです。マルチインスタンスで起動したRailsアプリケーションへの操作(再起動など)は、該当するインスタンスに対してメッセージをQueueストレージへ送信します。
  • Web Role:Windows Azureによって起動されるロールで、NougakuDoControllerを動作させるための準備作業とNougakuDoControllerを起動します。また、マルチインスタンスで起動した場合のRailsアプリケーションに対する操作(再起動など)メッセージをQueueストレージから取得します。また、マルチインスタンスの管理用にインスタンス情報をTableストレージに格納します。
  • NougakuDoController:NougakuDoCompanionの中核機能を実装した実行ファイル(exe)で、能楽堂で作成したRailsアプリケーションに対する様々な操作を行います。
    1)インストール:Blobストレージから、能楽堂ランタイム(実行ファイル)やRailsアプリケーションのzipファイルを取得して、ローカルリソースに展開します。
    2)設定:能楽堂のローンチャで行う設定情報をAdminWebで設定した情報を使って設定します。
    3)運用管理:NougakudoLauncherを使って起動したRailsアプリケーションに対する停止や起動、再起動などの操作を行います。
  • NougakudoLauncher:能楽堂を使ったRailsアプリケーションの起動を行う実行ファイル(exe)で、停止操作ではruby.exeにCTRL+Cを送る機能を持っています。

最初のプレビューは、NougakuDoControllerとNougakudoLauncherです。この2つが動き出せば、能楽堂を使ったRailsアプリケーションを動かせますので、このプレビューを使ってローカル環境でのテストとAzureを使ったテストを行っていたのは、いうまでもありません。唯、このプレビューでの失敗もありました。それは、当初からAzureを前提としていたために SDK のStrage Emulatorを想定していなかったことです。このプレビューに、応急処置的にASP.NETのUIを付けたものを artonさんにお渡しして、SDK 環境で試せないの?と質問された時に、慌てて対応したのが、7月後半のシアトル出張の真っ最中だったのは内緒です。NougakuDoControllerやNougakudoLauncherを単独で実行できるように実装したのは、明確な理由があります。その理由は、以下のような考えを前提としたからです。

  • シンプルであるべき(Simple is best)
  • やり易い環境であるべき

ご存じのようにAzureはクラウド環境ですから、インテリトレースが使えると言ってもデバッグを考えると難しいのも事実でしょう。だからこそ、シンプルで実装し易い環境へ持ってくるべきだと考えたのです。この考えから、NougakuDoControllerは、Azure SDKで提供されるAPIからストレージサービスAPIしか使用していません。では、Azure特有のインスタンス情報などをどうしたかといえば、azure.xmlという設定ファイルから情報を取得するようにしています。つまり、ロールインスタンスのコードでazure.xmlを作成することで、Azureのサービスランタイム APIに依存しないようにしたことになります。この特徴が、Azure以外の環境に持っていく場合に効果を発揮できるでしょうし、NougakuDoController単体でのデバッグを容易にするという効果を発揮しました。利点ばかりではなく、もちろん欠点もあります。それは、管理サイトやWeb ロールとの連携をどのように行うかということです。基本的に、別プロセスとして動作していますから、プロセス間連携をどのように実装するかという課題です。
この課題に対して採用した方法が、ファイルを介して連携するという方法です。共有メモリなどを使うよりも、シンプルで、実装コストもかかりません。ファイルを使った連携で注意しないといけないのが、ファイルの排他ロックの問題です。この理由から、FileSystemWatcherクラスを使ったCreatedイベントを多用しています。一般的に、FileSystemWatcherクラスのイベントは、次のように発生します。

  • Created:空の新規ファイルを作成(Windows エクスプローラーで新しいテキストファイルを作成)
  • Changed:内容を出力した場合(メモ帳で内容を書き換え、上書き保存した場合など)
  • Renamed:ファイル名を変更(Windows エクスプローラーで新しいテキストファイルを作成して、直後にファイル名を変更など)

という順序で、イベントが発生します。この理由から、ファイル名に意味を持たせて空のファイルを作成することでプロセス間連携に利用しています。もちろん、連携ミスなどを考慮して空のファイルを作成する前に、既存のファイルを削除してから作成するようにして目的のファイル システム イベントを発生させるようにしています。ローカル環境ではスムーズに動作しましたが、実際にAzure上で動作させた場合に問題も発生しました。それは、ファイルロックが発生して例外が発生したことです。この原因は、可能性として仮想マシンであるがためにファイル システム イベントの発生タイミングに遅れがあることではないかと考えて、リトライロジックを組み込んで回避しています。

NougakuDoControllerがRailsアプリケーションを管理する上で重要なものは、アプリケーションの設定ファイル(configuration.xml)です。この設定ファイルは、管理サイトの「NougakuDo Runtime & Apps」でも設定することができます。NougakuDoControllerでは、この設定ファイルを使って以下のようなことを行っています。

  • バージョンチェック(シンプルに、バージョンが一致するかしないかの判断です)
    標準で5分間隔でBlobストレージに対してチェックを行います。
  • バージョンが一致しなければ、以下の作業を実施。
  • zip ファイルをBlobストレージからダウンロード
  • Rails アプリケーションであれば、アプリケーションの停止
    NougakuDoそのものであれば、全てのRails アプリケーションの停止
  • zip ファイルの展開を含めたインストール作業
  • Rails アプリケーションの起動

それとNougakudoLauncherをRailsアプリケーションの起動用に独立した実行ファイルにしたのには、明確な理由があります。それは、GenerateConsoleCtrlEvent というWin 32 APIになります。このAPIを使用すると、アプリケーションに「CTRL+C」というブレークシグナルを通知することができるのですが、このAPIを呼び出すと呼び出したプログラムを含めてブレーク シグナルを受取ってしまうために、ruby.exeだけでなく呼び出した自分自身も終了してしまうのです。この理由から、非常に軽いEnnnouの起動用にNougakudoLauncherを別プロセスとして実装したのです。

管理サイトは、Windows Azure Companion をモチーフにしてシンプルな作りにしています。管理機能自体は、次のような機能を提供します。

  • NougakuDo Runtime & Apps:設定ファイルの内容を確認したり、更新します。更新した場合は、Blobストレージへアップロードします。
  • Controller Logs:NougakuDoControllerのログファイルを日付の降順に出力します。リフレッシュ間隔を20秒に設定しています。
  • NougakuDo Status:NougakudoLauncherを使って起動したRailsアプリケーションの稼働状況を表示します。また、停止、再起動などの操作を行うことができます。操作を選択すると、操作内容をQueueストレージへメッセージ登録します。リフレッシュ間隔を1分に設定しています。
  • Cleanup:設定ファイルをBlobストレージから削除します。こうすることで、NougakuDoControllerが次のバージョンチェック時に設定ファイルが削除されているのを検知して、起動済みのRailsアプリケーションの停止作業を行い、設定ファイルなどの削除を行います。

それから図に記載していないものとして、ヘルパーツールの「NougakudSetupTool」があります。このツールは、WPFを使ったデスクトップ アプリケーションで、能楽堂やRailsアプリケーションのzipファイルの作成と設定ファイル(configuration.xml)の作成を行うためのものです。出来上がった、zip ファイルやconfiguration.xmlをBlobストレージへアップロードすれば、後はNougakuDoCompanionがconfiguration.xmlをチェックした時点でアプリケーションの展開と起動が行われることになります。

NougakuDo Companionは、内部的にプロセス連携をファイルを使用して行っていることうを既に説明しました。このような構造にしている関係からも、内部的には以下のようなログファイルを用意しています(ログに記録される内容は、リリースとデバッグでは異なります)。

  • NougakuDoRole.txt:ロール インスタンスが出力するログファイルです。
  • NougakuDoController.txt:NougakuDoControllerが出力するログファイルで、管理サイトのContoller Logsで確認ができます。
  • running.txt:NougakudoLauncherを使って起動したRailsアプリケーションに対する情報で、管理サイトのNougakuDo Statusで確認ができます。
  • NougakudoLauncher.txt:NougakudoLauncherが出力するログファイルです。

何か問題があれば、リモートデスクトップなどで接続して上記のログファイルを検討すれば、問題点を明らかにすることができることでしょう。また、マルチ インスタンスを管理するために使用している手法は、以下のようなものになります。

  • ロール インスタンスの起動時に、Tableストレージへインスタンス情報を追加。
  • NougakuDoControllerが、NougakuDoController.txt と running.txt を定期的にBlogストレージへインスタンス名を付与したファイル名でアップロード。
  • 管理サイトは、Tableストレージからインスタンス情報を取得して、Blobストレージからログファイルをダウンロードして表示。
  • ロール インスタンスの停止時に、Tableストレージからインスタンス情報を削除。

マルチインスタンス管理をシンプルにするために、Azureの管理APIではなく、TableストレージとBlobストレージを組み合わせて実現しています。もちろん、ログファイルに関しては、管理サイトが接続されているインスタンスに関する情報はそのインスタンス内から取得することでネットワーク リクエストを削減しています。

それから、能楽堂1.1以降が提供する仮想ホストへの対応方法について説明します。仮想ホストへの対応は、それなりに悩ましくもあったところなので、Azureのコンピュート サービス上で様々な組み合わせを検証しました。能楽堂では、起動時に「o ホスト名」オプションを付けるだけなのですが、その正常に動作する検証結果を以下に示します。

  • 仮想マシンが持つIPアドレス
  • コンピュートサービスに割り当てるDNS名

Azureのコンピュートサービスを作成すると、仮想IPアドレス(VIP)が割り当てられて、指定したDNS名でサービスが出来上がります。仮想IPアドレスはロードバランサが公開するアドレスになっており、APIで簡単に取得することができません(DNSを使って名前を検索すれば、取得することは可能ですが)。また、DNSに対して利用者が独自のCNAMEなどを割り当てることはできません。それから、仮想マシンのIPアドレスはDHCPで割り当てられており、このIPアドレスを設定するとIPアドレスが変更するごとにRailsアプリケーションの再起動が必要になってしまいます。この理由から、DNS名をServiceConfigurationに手動で設定する方法を採用することで、仮想ホスト機能に対応しています。

最後に、NougakuDo ComapnionがWorkerロールではなくWebロールを採用した理由を説明します。NougakuDoController自体は、どちらのロールでも動作するようになっていますが、管理サイトを起動するための手間を削減したかったことが理由です。結果として、権限という問題がありました。というのは、管理サイトはIISで動作しており、Network Serviceがその実態となります。これに対してWebロールは、System権限で動作しています。それぞれが、異なるユーザー権限で動作していることから、ファイルを使ったプロセス連携では、最初にACLの設定を行うことで共有ができるようにしています。この権限の問題は、Workerロールで行う限りは発生することはありません。なぜなら、IISが必要であれば自分でIISの設定コードなども作成する必要があるからです。

NougakuDo Companionにおいて不足すると思われるものを考えると、Railsのログファイル参照機能かなとも思っています。が、ログの管理自体は環境に応じて、色々な対応が考えらることから、特に何の機能も用意していません。この点は、使われる方が考えていただければと考えています。現在、NougakuDo CompanionのWindows Azure SDK 1.5対応を行っているところであり、今朝に公開された能楽堂 1.1.9 での動作確認ができれば、1.0として公開しようかと考えています。このシリーズは、次の4回目で1.0リリース完了を持って終了する予定です。