エクスポート (0) 印刷
すべて展開

Windows Azure の VM ロールのアダプターの開発

更新日: 2011年3月

[Windows Azure の VM ロール機能は 2013 年 5 月 15 日に廃止されます。 廃止日以降、VM ロール展開環境は削除されます。 既存のアプリケーションと共に移行するには、Windows Azure 仮想マシンを使用することができます。 アプリケーションでの仮想マシンの使用方法の詳細については、「Moving from VM Role to Windows Azure Virtual Machines (VM ロールから Windows Azure 仮想マシンへの移行)」を参照してください。

オペレーティング システムが起動されると自動的に開始され、Microsoft.WindowsAzure.ServiceRuntime API を使用して Windows Azure のランタイム情報を使用する Windows サービスとしてアダプターを作成できます。Windows サービスの作成が必要になるのは、現在の VM ロール インスタンス、またはサービスで実行されているその他のロール インスタンスのネットワーク アドレス情報が必要な場合、ローカル ストレージ リソースに書き込む必要がある場合、実行時にサービス構成設定を読み取る必要がある場合、その設定の変更に応答する場合などです。

このセクションでは、VM ロールをサポートするサービスを示すアダプターをビルドする方法について説明します。このセクションで使用する例では、オペレーティング システムの起動時に Windows Azure ドライブをマウントし、ドライブに HTTP ログ ファイルを書き込むようにインターネット インフォメーション サービス (IIS) を構成します。

アダプターを作成するには、次の作業を実行する必要があります。

  1. ストレージ コンテナーの作成

  2. アダプター プロジェクトの作成

  3. ロール インスタンスの構成の変更を追跡する機能の追加

  4. アダプターの起動時の動作の定義

  5. アダプターの停止時の動作の定義

  6. アダプターのインストーラーの作成

  7. アダプターのセットアップ プロジェクトの作成

  8. アセンブリの一貫性エラーを修正するビルド後イベントの追加

  9. クラウド サービス モデルへの構成設定の追加

  10. アダプターのインストール

アダプターでは、BLOB ストレージを使用して Windows Azure ドライブにログ データを格納します。それには Windows Azure のストレージ アカウントにアクセスする必要があり、さらにアダプターで使用するコンテナーを作成する必要があります。Windows Azure ストレージでのコンテナーの作成には任意のツールを使用し、作成するコンテナーに任意の名前を指定することができます。コンテナーの名前は、クラウド サービス モデルを構成するときに使用します。

Visual Studio 2010 には、Windows サービスを作成するためのテンプレートが用意されています。このテンプレートを使用して、VM ロール インスタンスのアダプターを作成できます。

  1. Visual Studio 2010 を開き、[ファイル][新規作成] をポイントし、[プロジェクト] をクリックします。

  2. [インストールされたテンプレート] ウィンドウで [Visual C#][Windows] をクリックし、中央のウィンドウで [Windows サービス] をクリックします。

  3. ソリューションとアダプター プロジェクトの名前を入力し、[OK] をクリックします。

  4. ソリューション エクスプローラーで、ソリューションを右クリックし、[構成マネージャー] をクリックし、プロジェクトに "Any CPU" が選択されていることを確認してから、[閉じる] をクリックします。

  5. ソリューション エクスプローラーで、Service1.cs ファイルの名前をアダプターに使用する名前に変更します。このセクションの例では、指定する名前を表す AdapterName プレースホルダーを使用します。

  6. プロジェクトを右クリックして [プロパティ] をクリックし、アプリケーション ページの [ターゲット フレームワーク][.NET Framework 3.5] が選択されていることを確認します。

  7. プロジェクトのプロパティの [発行] ページで、[必須コンポーネント] をクリックし、[.NET Framework 4 (Client Profile)] が選択されていないことを確認します。

  8. ソリューション エクスプローラーで、次のアセンブリの参照を追加します。

    • Microsoft.WindowsAzure.ServiceRuntime.dll

      note
      このアセンブリの "ローカルにコピー" プロパティが False に設定されていることを確認する必要があります。

    • Microsoft.WindowsAzure.CloudDrive.dll

    • Microsoft.WindowsAzure.StorageClient.dll

    • Microsoft.Web.Administration.dll

  9. ソリューション エクスプローラーで [AdapterName.cs] を右クリックし、[コードの表示] をクリックします。

  10. 次の using ステートメントを追加します。

    
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;
    using Microsoft.WindowsAzure;
    using Microsoft.Web.Administration;
    using System.IO;
    using System.Threading;
    
  11. ソリューション エクスプローラーで [AdapterName.cs] を右クリックし、[デザイナーの表示] をクリックします。

  12. [プロパティ] ウィンドウで次のプロパティを設定します。

    • ServiceName - システムがアダプターを識別する名前を指定できます。

    • (名前) - コードでアダプター オブジェクトを表すために使用する名前を指定できます。

    • CanShutdown – システムがシャットダウンしたらアダプターに通知するようにするには、このプロパティの値を True に指定する必要があります。

Program.cs ファイルには、次のコードが含まれます。


static void Main()
{
   ServiceBase[] ServicesToRun;
   ServicesToRun = new ServiceBase[] 
   { 
      new ServiceName() 
   };  
   ServiceBase.Run(ServicesToRun);
}

ロール インスタンスの構成が変更されたときに実行する操作を定義できます。たとえば、ロール インスタンスの構成を変更することにより、ログ データが格納されるドライブの場所を変更できます。これを行うには、RoleEnvironment イベントを使用します。

  1. ソリューション エクスプローラーで [AdapterName.cs] を右クリックし、[コードの表示] をクリックします。

  2. コンストラクターを編集して、構成を変更するイベントを定義します。コンストラクターに追加するイベント定義のコード例を次に示します。

    
    public AdapterName()
    {
       InitializeComponent();
       RoleEnvironment.Changed += RoleEnvironmentChanged;
       RoleEnvironment.StatusCheck += RoleEnvironmentStatusCheck;
    }
    
  3. Changed イベントが発生すると呼び出される RoleEnvironmentChanged メソッドを追加します。新しい Windows Azure ドライブをマウントし、新しいドライブにログ ファイルを書き込むように IIS を構成する RoleEnvironmentChanged メソッドのコード例を次に示します。

    
    private CloudDrive currentDrive;
     
    private void RoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e)
    {
       if(!e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>().Any(
          c => c.ConfigurationSettingName == "AdapterName.BlobPath"))
          return;
    
       try
       {
          // perform a rolling drive change
          var oldDrive = this.currentDrive;
          var newDrive = MountDrive();
          try
          {
             ConfigureWebServer(newDrive.LocalPath);
          }
          catch (Exception)
          {
             UnmountDrive(newDrive);
             throw;
          }
          this.currentDrive = newDrive;
          UnmountDrive(oldDrive);
       }
       catch (Exception ex)
       {
          this.EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
          throw;
       }
    }
    

    ここで、AdapterName はアダプター プロジェクトに付けた名前です。

  4. Windows Azure ドライブのマウントおよびアンマウントを行うメソッドを追加してから、IIS のログ ファイルの場所を構成するメソッドを追加します。MountDrive メソッドのコード例を次に示します。

    
    private CloudDrive MountDrive()
    {
       // create or mount an instance-specific drive
       var credentials = GetStorageCredentials();
       var driveUri = GetDriveUri();
       var drive = new CloudDrive(driveUri, credentials);
    
       try
       {
          drive.Create(1024);
       }
       catch (Exception ex)
       {
          if (ex.Message != "ERROR_BLOB_ALREADY_EXISTS") throw;
       }
    
       // mount the drive
       string mountPoint = drive.Mount(1024, 
          DriveMountOptions.FixFileSystemErrors | DriveMountOptions.Force);
       this.EventLog.WriteEntry(string.Format("{0} mounted at {1}", drive.Uri, mountPoint));
       return drive;
    }
    
    private Uri GetDriveUri()
    {
       return new Uri(string.Format(
       RoleEnvironment.GetConfigurationSettingValue("AdapterName.BlobPath"),
          RoleEnvironment.CurrentRoleInstance.Id));
    }
    
    private StorageCredentials GetStorageCredentials()
    {
       return new StorageCredentialsAccountAndKey(
       RoleEnvironment.GetConfigurationSettingValue("AdapterName.AccountName"),
       RoleEnvironment.GetConfigurationSettingValue("AdapterName.AccountKey"));
    }
    

    CloudDrive API の使い方の詳細については、「CloudDrive」を参照してください。AdapterName.BlobPath、AdapterName.AccountName、および AdapterName.AccountKey の設定は、クラウド サービス定義ファイルで定義され、サービス構成ファイルで構成されます。これらの設定の定義の詳細については、「クラウド サービス モデルへの構成設定の追加」を参照してください。

    UnmountDrive メソッドのコード例を次に示します。

    
    private void UnmountDrive(CloudDrive drive)
    {
       drive.Unmount();
       this.EventLog.WriteEntry(string.Format("{0} unmounted", drive.Uri));
    }
    
    

    ConfigureWebServer メソッドのコード例を次に示します。

    
    private void ConfigureWebServer(string drivePath)
    {
       using (var config = new ServerManager())
       {
          var logdir = Path.Combine(drivePath, @"inetpub\logs\LogFiles");
          config.SiteDefaults.LogFile.Directory = logdir;
    
          config.CommitChanges();
    
          this.EventLog.WriteEntry(string.Format("IIS log location set to '{0}'", logdir));
       }
    }
    
    
  5. ロール インスタンスの状態を判断する RoleEnvironmentStatusCheck メソッドを追加します。statusCheckWaitHandle オブジェクトは、ロール インスタンスの状態がビジーか準備完了かをロード バランサーに通知するために使用されます。オブジェクトの Set メソッドの呼び出しは、構成の変更が完了したことを示します。RoleEnvironmentStatusCheck メソッドのコード例を次に示します。

    
    private readonly EventWaitHandle statusCheckWaitHandle = new ManualResetEvent(false);
    private volatile bool busy = true;
    
    private void RoleEnvironmentStatusCheck(object sender, RoleInstanceStatusCheckEventArgs e)
    {
       if (this.busy)
       {
          e.SetBusy();
       }
       statusCheckWaitHandle.Set();
    }
    
    

次の例では、アダプターは起動時に次の操作を実行します。

  • ドライブ キャッシュを初期化する

  • ドライブをマウントする

  • マウントしたドライブを使用するように IIS を構成する

  1. ソリューション エクスプローラーで [AdapterName.cs] を右クリックし、[コードの表示] をクリックします。プロジェクトの作成時に自動的にオーバーライドされた OnStart メソッドを見つけ、statusCheckWaitHandle オブジェクトを使用して、ロール インスタンスが実行されていることを確認し、別のスレッドでアダプターの操作を実行し、操作の完了を通知するコードを追加します。

    
    protected override void OnStart(string[] args)
    {
       /// Windows Azure waits for auto-start services to be fully started 
       /// before sending any traffic.  Service Control Manager (SCM) does
       /// not impose a time limit on startup; the service need only 
       /// request additional time.
    
       if (!RoleEnvironment.IsAvailable) return;
          
       var startThread = new Thread(OnStartInternal);
       startThread.Start();
    
       // wait until a status check has occurred, so that Windows Azure 
       // knows we are working on something.
       WaitForHandle(statusCheckWaitHandle);
    }
    

    Windows Azure ドライブをマウントし、ログ データの書き込みに新しいドライブを使用するように IIS 構成を変更する OnStartInternal メソッドのコード例を次に示します。

    
    private void OnStartInternal()
    {
       try
       {
          // initialize the drive cache
          string cachePath = RoleEnvironment.GetLocalResource("Data").RootPath;
          CloudDrive.InitializeCache(cachePath, 4096);
          this.EventLog.WriteEntry("initialization succeeded");
    
          // mount the current drive
          this.currentDrive = MountDrive();
    
          // configure IIS
          ConfigureWebServer(this.currentDrive.LocalPath);
    
          this.busy = false;
       }
       catch (Exception ex)
       {
          this.EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
          throw;
       }
    }
    

    ステータス チェックが行われるまで待機する WaitForHandle メソッドのコード例を次に示します。

    
    private const int ThreadPollTimeInMilliseconds = 1000;
    
    private void WaitForHandle(WaitHandle handle)
    {
       while (!handle.WaitOne(ThreadPollTimeInMilliseconds))
       {
          this.RequestAdditionalTime(ThreadPollTimeInMilliseconds * 2);
       }
    }
    

この例では、アダプターがログ ファイルの場所を再構成し、停止するとドライブをアンマウントします。

  1. ソリューション エクスプローラーで [AdapterName.cs] を右クリックし、[コードの表示] をクリックします。プロジェクトの作成時に自動的にオーバーライドされた OnStop メソッドを見つけ、ログ ファイルの場所を再構成してドライブをアンマウントするコードを追加します。

    
    protected override void OnStop()
    {
       OnStopInternal();
    }
    
  2. OnShutdown メソッドのコード例を次に示します。

    
    protected override void OnShutdown()
    {
       /// Windows Azure stops sending traffic before shutting down.
       /// Note that some requests may still be executing.
       OnStopInternal();
    }
    
  3. 操作を実行する OnStopInternal メソッドを追加します。

    
    private void OnStopInternal()
    {
       try
       {
          ConfigureWebServer(@"%SystemDrive%");
    
          if (this.currentDrive != null)
          {
             UnmountDrive(this.currentDrive);
             this.currentDrive = null;
          }
       }
       catch (Exception ex)
       {
          this.EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
          throw;
       }
    }
    
    

Windows サービスのインストール時にいくつかのカスタム動作が行われるようにするには、インストーラー クラスを使用します。Visual Studio ではこれらのインストーラーを Windows サービス用に作成し、プロジェクトに追加できます。

  1. ソリューション エクスプローラーで [AdapterName.cs] を右クリックし、[デザイナーの表示] をクリックします。

  2. デザイナーの背景をクリックして、アダプターのコンテンツではなくアダプター自体を選択します。

  3. デザイナーにフォーカスがある状態で右クリックし、[インストーラーの追加] をクリックします。

    既定では、2 つのインストーラーを格納するコンポーネント クラスがプロジェクトに追加されます。コンポーネントは、ProjectInstaller という名前で、このコンポーネントに格納されているインストーラーはアダプターのインストーラーとアダプターの関連プロセスのインストーラーです。

  4. ProjectInstaller のデザイン ビューで [serviceInstaller1] をクリックします。

  5. [プロパティ] ウィンドウで、ServiceName プロパティにアダプターの名前を設定します。

  6. StartType プロパティを [自動] に設定します。

  7. デザイナーで [serviceProcessInstaller1] をクリックします。Account プロパティを [LocalService] に設定します。これにより、アダプターがインストールされ、ローカル サービス アカウントで実行されます。

  8. プロジェクトをビルドします。

セットアップ プロジェクトは、コンパイルされたプロジェクト ファイルをインストールし、アダプターの実行に必要なインストーラーを実行します。完全なセットアップ プロジェクトを作成するには、セットアップ プロジェクトにプロジェクト出力を追加し、プログラムをインストールするカスタム動作を追加します。

  1. ソリューション エクスプローラーで、右クリックしてソリューションを選択し、[追加] をポイントして [新しいプロジェクト] をクリックします。

  2. [インストールされたテンプレート] ウィンドウで [その他のプロジェクトの種類][セットアップ/配置プロジェクト] の順に展開し、[Visual Studio インストーラー] をクリックします。

  3. 中央のウィンドウで [セットアップ プロジェクト] をクリックします。

  4. セットアップ プロジェクトの名前を入力し、[OK] をクリックします。

  5. [見つかった依存関係] を展開し、[Microsoft .NET Framework] をダブルクリックして、[プロパティ] ウィンドウで [バージョン] の値が [.NET Framework 3.5] であることを確認します。

  6. 次の各アセンブリについて、[見つかった依存関係] でアセンブリを右クリックし、[除外] をクリックします。

    • Microsoft.Web.Administration.dll

    • Microsoft.WindowsAzure.ServiceRuntime.dll

    • msshrtmi.dll

    • mswacdmi.dll

次に、アダプターのプログラム ファイルをインストールするカスタム動作を追加します。

  1. ソリューション エクスプローラーで、セットアップ プロジェクトを右クリックし、[表示] をポイントして [カスタム動作] をクリックします。

  2. カスタム動作エディターで [カスタム動作] ノードを右クリックし、[カスタム動作の追加] をクリックします。

  3. ボックスの一覧の [アプリケーション フォルダー] をダブルクリックして開き、[出力の追加] を選択します。

  4. [プロジェクト出力グループの追加] ウィンドウで [プライマリ出力] を選択し、構成に対して [(アクティブ)] を選択して [OK] をクリックします。

Visual Studio は 32 ビットのアセンブリを .msi ファイルに追加しますが、Windows Azure は 64 ビットのアセンブリを必要とするので、スクリプトを実行して一貫性エラーのあるアセンブリを修正する必要があります。アセンブリを修正するには、ビルド後イベントとして JavaScript ファイルを使用できます。

  1. セットアップ プロジェクトのルート フォルダーにある FixMSI.js という名前のファイルに次のコードを保存します。

    
    // workaround for "BadImageFormatException" issue - see http://msdn.microsoft.com/ja-jp/library/kz0ke5xt.aspx
    
    var msiOpenDatabaseModeTransact = 1;
    var msiViewModifyInsert = 1
    var msiViewModifyUpdate = 2
    var msiViewModifyAssign = 3
    var msiViewModifyReplace = 4
    var msiViewModifyDelete = 6
    
    var filespec = WScript.Arguments(0);
    var frameworkpath = WScript.Arguments(1);
    var installer = WScript.CreateObject("WindowsInstaller.Installer");
    var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
    
    WScript.Echo("Updating file '" + filespec + "' to use a 64-bit custom action...");
    
    Update64Bit();
    
    database.Commit();
    database = null;
    installer = null;
    
    function Update64Bit() {
        var sql;
        var view;
        var record;
        sql = "SELECT * FROM Binary WHERE `Name`='InstallUtil'";
        view = database.OpenView(sql);
        view.Execute();
        record = view.Fetch();
        if (record != null) {
            var dataCol = 2;
            record.SetStream(dataCol, frameworkpath + "\\InstallUtilLib.dll");
            view.Modify(msiViewModifyUpdate, record);
        }
        record = null;
        view.close();
        view = null;
    }
    
  2. ソリューション エクスプローラーで、前に作成したセットアップ プロジェクトをクリックし、[プロパティ] ウィンドウで次のコマンドを PostBuildEvent プロパティに追加します。

    
    cd $(ProjectDir) 
    CScript //NoLogo FixMSI.js "$(BuiltOutputPath)" "%SystemRoot%\Microsoft.NET\Framework64\v2.0.50727"
    
  3. ソリューション エクスプローラーでセットアップ プロジェクトを右クリックし、[ビルド] をクリックします。

アダプターが Windows Azure と通信するには、クラウド サービス モデルで設定が定義されている必要があります。

  1. VM ロールの ServiceDefinition.csdef ファイルを開きます。

  2. ConfigurationSettings 要素に次の設定を追加します。

    
    <Setting name="AdapterName.BlobPath" />
    <Setting name="AdapterName.AccountName" />
    <Setting name="AdapterName.AccountKey" />
    

    ここで、AdapterName はアダプター プロジェクトの名前です。

  3. LocalResources 要素に次の設定を追加します。

    
    <LocalStorage name="Data" />
    

    サービス モデルで使用できる要素の詳細については、「VirtualMachineRole Schema」を参照してください。

  4. ファイルを保存します。

  1. VM ロールの ServiceConfiguration.cscfg ファイルを開きます。

  2. 次の構成設定をファイルに追加します。

    
    <Setting name="AdapterName.BlobPath" value="http://StorageAccountName.blob.core.windows.net/ContainerName/{0}.vhd" />
    <Setting name="AdapterName.AccountName" value="StorageAccountName" />
    <Setting name="AdapterName.AccountKey" value="StorageAccountKey" />
    

    ここで、AdapterName は、作成したアダプター プロジェクトの名前です。StorageAccountName はストレージ アカウントの名前です。StorageAccountKey は、ストレージ アカウントの主キーです。ContainerName は、前に作成したストレージ コンテナーです。サービス モデルの構成の詳細については、「Windows Azure Service Configuration Schema」を参照してください。設定の定義と構成の詳細については、「VM ロール サービス モデルの作成と配置」を参照してください。

  3. ファイルを保存します。

これで、Windows Azure にアップロードする VHD にアダプターをインストールする準備ができました。

コードを作成し、サービス モデルで設定を定義および構成したら、アダプターをインストールし、サービス モデル パッケージを配置できます。VM ロールの場合、アダプターは Windows Azure 統合コンポーネントのインストール後に仮想マシンにインストールされます。

アダプターが正しく機能するためには、複数のオペレーティング システム機能を有効にする必要があります。Windows Azure にアップロードするイメージで、次のコマンドを実行します。

DISM /Online /Enable-Feature /FeatureName:NetFx3 /FeatureName:IIS-WebServerRole /FeatureName:IIS-WebServer /FeatureName:IIS-CommonHttpFeatures /FeatureName:IIS-HttpErrors /FeatureName:IIS-ApplicationDevelopment /FeatureName:IIS-HealthAndDiagnostics /FeatureName:IIS-HttpLogging /FeatureName:IIS-RequestMonitor /FeatureName:IIS-Security /FeatureName:IIS-RequestFiltering /FeatureName:IIS-Performance /FeatureName:IIS-WebServerManagementTools /FeatureName:IIS-StaticContent /FeatureName:IIS-DefaultDocument /FeatureName:IIS-DirectoryBrowsing /FeatureName:IIS-HttpCompressionStatic /FeatureName:IIS-ManagementConsole

アダプターをインストールするには、.msi ファイルを格納するフォルダーに移動し、ファイルをダブルクリックします。ファイルは、前に作成したセットアップ プロジェクトの Debug フォルダーにあります。

参照

コミュニティの追加

表示:
© 2014 Microsoft