Azureの小ネタ (改)

~Azureネタを中心に、色々とその他の技術的なことなどを~

Azure Drive に格納されたWebアプリを実行する

某所でオウンゴールを決めてしまったみたいなので、Azure Driveに格納されたWebアプリケーションを、仮想アプリとして実行する方法についての考察です。仮想サイトとして構成してもよかったのですが、その場合は、InputEndpointを構成しておく必要がありそうなので、仮想アプリで実施しています。


基本的に技術屋なので、与えられた課題に対して実現できることが確認できるまでは燃え上がりますが、実現の見通しがつくと鎮火してしまう性質があります。

Driveの準備

Webアプリを格納するVHDファイルを用意します。以下を参考に固定長のVHDファイルを用意します。

Webアプリの格納

適当にWebアプリを作成して、上記で作成したVHDファイルに格納します。Webアプリの発行から、ローカルPCにマウントしたVHDファイルにWebアプリを格納。


それぞれ、WebApplication1/2/3を格納してみたのが、下図です。

Blobに格納

CloudXplorerあたりで、BlobにPageBlobとして格納します。

WebRole

ポイントは以下。

  • Runtime要素で管理者権限
  • OnStartメソッドでドライブマウント。OnStopでUnmountすべきですが、手抜きしてます。
  • マウントしたDriveのWebアプリを、仮想アプリとして構成。


ServiceDefinitison.csdefには、Runtime要素を追加して、管理者権限で実行させます。












WebRole.csのOnStartメソッドには、以下のコードを追加します。
今回は、以下を実施。

  • Microsoft.Web.Administrationの参照追加。%windir%\system32\inetsrvあたりにあります。
  • Driveをマウントする。
  • ServerManagerクラスを利用して、Driveの直下のフォルダを仮想アプリとして構成する。アプリケーションプールは、Webロールのを利用。

Driveの中身をどう解釈するかは、アプリの設計依存なのでご自由に。

        public override bool OnStart()
        {
            try
            {
                var conn = RoleEnvironment.GetConfigurationSettingValue("connection");
                var account = CloudStorageAccount.Parse(conn);
                var blobClient = account.CreateCloudBlobClient();
                var ls = RoleEnvironment.GetLocalResource("ls");
                CloudDrive.InitializeCache(ls.RootPath + "cache", ls.MaximumSizeInMegabytes);

                var drive = account.CreateCloudDrive("disk/a.vhd");
                string letter = drive.Mount(64, DriveMountOptions.None);

                using (ServerManager serverManager = new ServerManager())
                {
                    string siteName = RoleEnvironment.CurrentRoleInstance.Id + "_Web";
                    var site = serverManager.Sites[siteName];
                    var application = serverManager.Sites[siteName].Applications.First();
                    var applicationPoolName = application.ApplicationPoolName;
                    //var applicationPool = serverManager.ApplicationPools[applicationPoolName];

                    foreach (var webapp in new DirectoryInfo(letter).GetDirectories())
                    {
                        if(webapp.Name.ToLower().Contains("recycle")) continue;
                        var path = "/" + webapp.Name;
                        var physicalPath = letter + webapp.Name;
                        var newapp = site.Applications.Add(path, physicalPath);
                        newapp.ApplicationPoolName = applicationPoolName;
                    }

                    // コミット
                    serverManager.CommitChanges();
                }
            }
            catch (Exception e)
            {
               // 適宜例外処理を
            }
        }

実行

デプロイした後、RDPで乗り込んで構成確認。WebApplication1/2/3が構成されているのが確認できます。


ブラウザで各々のURLをアクセスしたところ。

考察

  • 管理者権限とフルIISの組み合わせで実現できることは検証済。あとは、要件にどのように応えていくか、細かい実装の話になっていくと思われる。
  • このままではスケールアウトしません。Snapshot Blobにすれば、複数インスタンスからマウントも可能かも。
  • サービスの継続性、メンテナンス、アプリの入れ替え等々は未検討です。もっと違う冴えたやり方があるんじゃないですか?的なことは一切考えておりません。