Windows AzureでPerlやPython、Ruby、Git、SSH、MySQLを利用しよう 2ページ

アプリケーションが使用するローカルストレージの用意

 前回解説したとおり、Windows Azureのローカルストレージはインスタンスの停止や再起動によって初期化されてしまう。そのため、動的なデータの保存には永続化される「Azure Drive」を使用する。ただし、Azure Driveにはネットワーク経由でアクセスするため、データアクセスの際にネットワークI/Oが発生する。そのため、永続化が不要なアプリケーションのインストール先にはローカルストレージを使用するのが好ましい。今回は「ApplicationDir」という名称で5GBのローカルストレージを確保して使用する(図2)。

図2 「ApplicationDir」という名前で5GBのローカルストレージを確保する
図2 「ApplicationDir」という名前で5GBのローカルストレージを確保する

 ローカルストレージは通常「C:\Resources\Directory」ディレクトリ以下に「<デプロイID>.<ロール名>.<ローカルストレージ名>」という名前のフォルダとして確保される(図3)。このフォルダは一般的なフォルダと同様、すべてのプログラムから制限なしにアクセスできる。

図3 ローカルストレージは通常C:ドライブ以下に確保される
図3 ローカルストレージは通常C:ドライブ以下に確保される

 なお、「DiagnosticStore」という名称のローカルストレージが自動的に作成されるが、こちらはログやクラッシュダンプなどの診断情報が格納される領域となっている。

Webロール内で「unzip」や「wget」を利用できるようにする

 インストールや設定作業において、ZIPファイルを展開したり、インターネットからファイルをダウンロードする、といった作業が必要だ。しかし、WindowsにはZIPファイルを展開したり、URLを指定してファイルをダウンロードするためのコマンドラインユーティリティが標準では用意されていない。そのため、Windows向けの「unzip」や「wget」といったツールをプロジェクトに追加しておき、あらかじめデプロイ時にWindows Azure環境下にアップロードされるよう設定しておく。

 Windows向けのunzipおよびwgetのバイナリはGnuWinプロジェクトによって公開されている。まずunzipだが、ダウンロードページ内の「unzip」以下からバイナリが入手できる。たとえばバージョン5.51-1の場合、「unzip-5.51-1-bin.zip」をダウンロードすれば良い。

 ZIPファイル内には多くのファイルが含まれているが、必要なのは「bin」フォルダ内に含まれている「unzip.exe」のみだ。これをプロジェクトのWebロール内に追加すれば良い(図4、5)。

図4 必要なのは配布パッケージ内の「unzip.exe」のみだ
図4 必要なのは配布パッケージ内の「unzip.exe」のみだ
図5 Webロールにunzip.exeを追加する
図5 Webロールにunzip.exeを追加する

 また、wgetについては同じくダウンロードページ内の「wget」以下からダウンロードできる。wgetについては本体に加え、「libintl」や「libiconv」、「openssl」などのDLLファイルも必要となる。これらDLLファイルも一緒に配布されており、たとえばバージョン1.9-1なら「wget-1.9-1-bin.zip」と「wget-1.9-1-dep.zip」をダウンロードすれば良い。

 ダウンロード後、Webロール内に「wget」フォルダを作成してそこにそれぞれの「bin」フォルダ内に含まれている実行ファイルおよびDLLファイルをすべてコピーしておく(図6)。

図6 Webロール内にwgetフォルダを作成し、そこに必要な実行ファイルとDLLファイルを追加する
図6 Webロール内にwgetフォルダを作成し、そこに必要な実行ファイルとDLLファイルを追加する

 これらのファイルについてもバッチファイルと同様、プロパティの「出力ディレクトリにコピー」を「新しい場合はコピーする」に変更しておく。

 そのほか、パッケージのインストールなどに必要なアーカイバなどがあれば同様にインストールしておく。たとえば.7z形式の展開が必要であれば、7-Zipを同様にWebロール内にコピーしておけば良い(図7)。

図7 7-zipの場合、アーカイブに含まれる「7z.dll」および「7z.exe」をWebロール内に追加すれば良い
図7 7-zipの場合、アーカイブに含まれる「7z.dll」および「7z.exe」をWebロール内に追加すれば良い

 なお、今回これ以外のソフトウェアはロールの実行時にダウンロードするようにしているが、unzipやwgetと同様にWebロール内にあらかじめプログラムやパッケージを追加しておくことも可能だ。ただしその場合ロールのサイズが大きくなるため、デプロイに時間がかかることがあるので注意したい。

バッチファイルから利用できる環境変数

 Windows Azure環境ではあらかじめいくつかの環境変数が用意されており、これらを使ってさまざまな情報を取得できる(表1)。

表1 Windows Azure環境内で定義されている主要な環境変数
変数名 説明
ROLEROOT ロール格納先のルートパス
ROLEDEPLOYMENTID ロールのデプロイID
ROLENAME ロール名
ROLEINSTANCEID ロールのインスタンスID
@ACCOUNTUSERNAME リモートデスクトップ接続用のユーザー名

 これらを組み合わせることで、バッチファイル中からさまざまな情報を参照できる。たとえば「ApplicationDir」という名前で確保したローカルストレージのルートパスは次のようになる。

C:\Resources\Directory\%ROLEDEPLOYMENTID%.%ROLENAME%.ApplicationDir

 また、IISにおけるデフォルトのサイト名は次のようになる。

%ROLEINSTANCEID%_<ServiceDefinition.csdef内で指定したサイト名>

 「<ServiceDefinition.csdef内で指定したサイト名>」は、ServiceDefinition.csdef設定ファイル内で「<Site>」要素内の「name」属性で指定した値となる。デフォルトでは「Web」となっているはずだ。

 プロパティの「出力ディレクトリにコピー」を「新しい場合はコピーする」に変更したファイルが配置されるディレクトリは、次のようにして取得できる。

%ROLEROOT%\approot\bin

 たとえば、先ほどWebロール内に追加したunzipやwgetは次のパスでアクセスできる。

%ROLEROOT%\approot\bin\unzip.exe
%ROLEROOT%\approot\bin\wget\wget.exe

 使用したい環境変数を自分で定義することも可能だ。これは、ServiceConfiguration.cscfgファイル(Visual Web Developer内ではServiceConfiguration.Cloud.cscfgおよびServiceConfiguration.Local.cscfgファイル)で設定できる。このXMLファイル内<WebRole>要素に含まれる<Runtime>要素内に「<Environment>」要素を作成し、「<Variable>」要素の「name」属性で環境変数名、「value」属性で値を指定する。

 たとえば「FTP_SITENAME」という環境変数に「FTP Site」という値を入れたい場合、<WebRole>要素内に次のような内容を追加する。

<Runtime executionContext="elevated">
  <Environment>
    <Variable name="FTP_SITENAME" value="FTP Site" />
  </Environment>
</Runtime>

 また、ロールのプロパティ内の「設定」で指定した値を環境変数として登録することもできる。たとえば「設定」で「SSLCert」という名前で設定した値を同名の環境変数で参照できるようにするには、上記の<Environment>要素内に次のように<Variable>要素を追加すれば良い。

<Variable name="SSLCert">
  <RoleInstanceValue xpath="RoleEnvironment/CurrentInstance/ConfigurationSettings/ConfigurationSetting[@name='SSLCert']/@value" />
</Variable>

 今回はこれらを組み合わせた、次のような要素を<WebRole>要素内に追加している。

<Runtime executionContext="elevated">
  <Environment>
    <Variable name="FTP_SITENAME" value="FTP Site" />
    <Variable name="SSLCert">
      <RoleInstanceValue xpath="RoleEnvironment/CurrentInstance/ConfigurationSettings/ConfigurationSetting[@name='SSLCert']/@value" />
    </Variable>
  </Environment>
</Runtime>

 なお、これらの環境変数はスタートアップタスクやWebRole.csから実行したプロセスでのみ有効となっている。リモートデスクトップ接続で接続したデスクトップ環境では利用できない点には注意したい。

 WebRole.csから呼び出すバッチファイル内でこれら以外に使いたい情報がある場合は、リスト6のようにProcessクラスの「StartInfo.EnvironmentValiables」にその情報を追加することで、環境変数を定義できる。

リスト6 バッチファイルからアクセスしたい情報は環境変数として追加しておく

// onstart.cmdを実行
Process p = new Process();
// 環境変数を定義
string role_root = Environment.GetEnvironmentVariable("ROLEROOT");
p.StartInfo.EnvironmentVariables.Add("INET_IP_ADDR", ip_addr);
p.StartInfo.EnvironmentVariables.Add("APP_DIR", RoleEnvironment.GetLocalResource("ApplicationDir").RootPath);
p.StartInfo.EnvironmentVariables.Add("WGET_EXE", @"""" + role_root + @"\approot\bin\wget\wget.exe"" -q");
p.StartInfo.EnvironmentVariables.Add("UNZIP_EXE", @"""" + role_root + @"\approot\bin\unzip.exe"" -qq -o");
p.StartInfo.EnvironmentVariables.Add("AZUREDRIVE_ROOT", drive_path);
今回はインスタンスに接続されるロードバランサのインターネット側IPアドレス(INET_IP_ADDR)およびソフトウェアのインストール先ディレクトリ(APP_DIR)、wgetのパスおよびオプション(WGET_EXE)、unzipのパスおよびオプション(UNZIP_EXE)、マウントしたAzure Driveのパス(AZUREDRIVE_ROOT)という環境変数を用意している。

 また、ロールの実行環境を判定するプロパティ「RoleEnvironment.IsEmulated」を使い、ローカルのエミュレータ環境とWindows Azureのクラウド環境とで別の値を設定することも可能だ。たとえば次のように条件分岐を行うことで、Azure Driveのルートパスをエミュレータ環境時は「C:\temp」に設定できる。

if (RoleEnvironment.IsEmulated)
{
    // エミュレータ環境の場合
    p.StartInfo.EnvironmentVariables.Add("AZUREDRIVE_ROOT", @"C:¥temp");
}