Windows Azure

Windows Azure Blogの「Alerting and Notifications Support for Windows Azure Applications」を一部抜粋して、ざっくり意訳した投稿です。

コンピュートサービス(クラウドサービス、仮想マシン、Webサイト、モバイルサービス)用の監視メトリックをベースにしたアラートを設定できるようになりました。
アプリケーションでアクティブに、もしくは緊急事態をメール通知できるようになりました。

この機能は、監視メトリックス上でアラートルールを作成できます。重大事態のルールを定義し、アラートを作成します。アラートルールを作成すると、サービス管理者か共同管理者のメールにEメール通知するかどうかを選択することができます。

仮想マシンの監視メトリックスは、ホストOSから収集した性能情報(CPU使用率、ネットワークI/O、ディスクRead bytes/sec、ディスクWrite bytes/sec)や設定した監視WebエンドポイントURLのレスポンス時間やアップタイムを対象とします。

クラウドサービスの監視メトリックスは、ホストOS、ゲストOSから収集した性能カウンターと設定した監視WebエンドポイントURLのレスポンス時間やアップタイムを対象とします。

アラートルールの作成

Windows Azure管理ポータルの左サイドメニューから「設定」を選択し、画面中央の「アラート」タブを選択します。アラートルールを作成するには「Add Rule」ボタンをクリックします。

たとえば、5分間CPU使用率が50%を超えていた場合にアラートとするルールを作成できます。
アラートルールを作成すると最初は「Not Activated」状態になります。
閾値を超過すると「Active」になり、アラート状態が解決すると「Not Active」状態に戻ります。

CPU使用率の値は、過去5分間の平均値で判例されます。値が閾値を境に、問題が発生したり解決したりして状態が変更するたびにアラートされます。

アラート状態は次のように一覧表示されます。

詳細を見たいときは、アラーとルールをクリックするとアラーと詳細ページに遷移します。

最近Activeになったアラートの履歴を参照することができます。

アラート通知

アラートがActiveになったときに、Windows Azure Alerts(alerts-noreply@mail.windowsazure.com)からメールでアラートを管理者から共同管理者のアドレスに通知されることができます。

メール通知はアラートの状態が変化した際(ActiveやNot Activeになったタイミング)に送信されます。

サブスクリプション毎に最大10個のアラートルールを作成できます。

まとめ

今回のアップデートにより、監視メトリックスをベースにしたアラートルールを簡単に作成でき、アプリケーションで注意が必要な状況が発生したり解決した際に通知できるようになりました。
プレビューの間は、サブスクリプションのアラートルールの作成制限数は10となっています。この上限に達した場合、新しいルールを作成するには1つ以上のルールを削除する必要があります。

ちなみに・・・

まだ、自分のサブスクリプションには表示されていない。。

image

Windows Azure

概要

スタートアップスクリプトはたいていの場合、ServiceDefinition.csdefで定義されます。
もしIISの設定を変更する必要があるなら、ロールのOnStartメソッドからスクリプトを実行する必要があります。この投稿は、configuration-driven定義を使用して設定するためのいくつかのサンプルを提供します。

本題

Windows Azureクラウドサービスで、ServiceDefinition.csdefで<Startup>エレメントを使用してロールスタート時に実行すべきスクリプトを指定します。
しかし、IISの設定に対して変更したりクエリを発行する場合には使用することができません。

Kevin Williamsが投稿したブログWindows Azure Roleアーキテクチャ)で説明されています。
スタートアップタスクが完了した後(Step7)まで、IISConfiguratorはIISウェブサイトを作成(Step8)しません。
IISに対して何か設定したくても、ServiceDefinition.csdefでは定義を設定することができません。IISConfiguratorが動作した後で処理する必要があります。

ロールのOnStartメソッド(Step9がトリガーで動作します)で処理します。通常、Process.Startコールを経由して処理します。

OnStartメソッドからプロセスとスクリプトを開始する定義を使用した単純なソリューションを書きました。フルコードは、ここからダウンロードできます。一部を抜粋して説明します。

このソリューションでは、ServiceConfiguration.cscfgで設定の定義をするためにスクリプトを指定しています。

<ConfigurationSettings>
  <Setting name="RoleStartupScripts" value="startup\test1.cmd!;startup\test2.cmd;Powershell.exe startup\test3.ps1" />
    ....
</ConfigurationSettings>

この例では、一つ目のファイル名の後ろに「!」マークを書いています。

これは次のスクリプトを実行する前に、一つ目のファイルのプロセスが完全に終了するのを待つ必要があることを定義しています。「!」マークが無い場合は、処理が完了するのを待たずに次のスクリプトを実行することができます。

これらのスクリプトは権限の昇格が必要ありません。権限の昇格が必要な場合、ServiceDefinition.csdefファイルで<Runtime executionContext="elevated" />を設定します。

次に、プロセスを自動実行させるためにRoleEntriPointを拡張する抽象クラスStartupScriptEntryPointクラスを書きました。

public abstract class StartupScriptRoleEntryPoint : RoleEntryPoint
{
    public override bool OnStart()
    {
        var startupScripts = CloudConfigurationManager.GetSetting("RoleStartupScripts");
        if (!String.IsNullOrEmpty(startupScripts))
        {
            var scriptList = startupScripts.Split(';');
            foreach (var script in scriptList)
            {
                bool waitForExit = false;

                string scriptCommandLine = script;
                if (script.EndsWith("!"))
                {
                    scriptCommandLine = script.Substring(0, script.Length - 1);
                    waitForExit = true;
                }

                var args = CmdLineToArgvW.SplitArgs(scriptCommandLine);

                var processStartInfo = new ProcessStartInfo()
                {
                    FileName = args[0],
                    Arguments = string.Join(" ", args.Skip(1).ToArray()),
                    WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory,
                    UseShellExecute = true,
                };
                var process = Process.Start(processStartInfo);
                if (waitForExit)
                {
                    process.WaitForExit();
                }
            }
        }
        return base.OnStart();
    }
}

デフォルトのRoleEntryPointの代わりにStartupScriptRoleEntryPointからWebRoleクラスを更新します。ほかにはコードの変更をする必要はありません。

public class WebRole : StartupScriptRoleEntryPoint
{
    public override bool OnStart()
    {
        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.

        return base.OnStart();
    }
}

意訳元のBlog

Running scripts from a Windows Azure role’s OnStart method

Windows Azure

Windows Azureにデプロイしたアプリに、特定のIPからのみ接続できるようにアクセス制限をする必要がある場合、Windowsファイヤーウォールの設定をプログラム的に変更することて対応できます。スタートアップ時と(Windows Azureゲストエージェントがファイヤーウォールの設定を戻してしまうので)ロールの変更時に設定する必要があります。

アクセス制限をしたい理由

Windows AzureにPaaSクラウドサースをデプロイすると、インターネット上にデプロイされます。
これは、インターネット上で誰でもアクセスできることを意味します(アプリケーションの認証ロジックがあるかもしれませんが)。
通常は、これは問題にはなりません。アプリを構築しデプロイすれば使用できるようになるからです。
しかし、特定マシンからのみ接続できるようにアクセス制限をしたいことがあります。

  • 未リリースで、準備が整うまでは非公開にしたいアプリケーション。
  • 複数の異なる環境のデプロイ(開発、テスト用など)があって、アプリケーションの認証ロジックを変更せずに許可された人だけがアクセスできるようにしたい
  • アプリケーションがインターナルユーザーのみ使用することを想定して設計されており、リモートから接続を許可したくない。この場合は、個別ユーザー認証のためアイデンティティソリューションを使用すべきです。
  • RDPや別のポートで運用している管理画面のような管理サービスに追加のセキュリティを施したい場合。

IISの「IPアドレスおよびドメインの制限」では不十分?

IIS干すテッドサービスへのトラフィックのみをブロックすることに興味がある場合、
IISの「IPアドレスおよびドメインの制限」機能が選択肢の一つになります
(詳細は、Liam CavanaghのBlog参照)。デフォルトではインストールされていないので、「IPアドレスおよびドメインの制限(IP and Domain Restrictions)」昨日をセットアップスクリプトをでインストールする必要があります。

この解決策では、RDPなどのIIS以外の接続も制限したい場合不十分です。

Windows Firewallでのアクセス制限

この場合、Windows Azure VMのローカルで動作しているWindows Firewallの設定を変更してあげる必要があります。通常、特定IPアドレスとポートからのみアクセスを許可するように設定するのは簡単です。

ここでは、Windows Server 2012、Windows Azure osFamilyの3で動作する、Netowork Security PowerShellコマンドレットを使用して、80と3389の2つのポートへの接続を特定IPからのみ許可する設定例を提示します。

# SetFirewallRestrictions.ps1
$date = Get-Date
Write-Host "Updating firewall rule restrictions at " $date "`r`n"
$allowedRanges = ('3.2.1.0/24', '1.2.3.4') 
Get-NetFirewallPortFilter | ? LocalPort -eq '80' | Get-NetFirewallRule | Set-NetFirewallRule -RemoteAddress $allowedRanges
Get-NetFirewallPortFilter | ? LocalPort -eq '3389' | Get-NetFirewallRule | Set-NetFirewallRule -RemoteAddress $allowedRanges

このスクリプトが呼び出されてたときログを出力するように.cmdファイルでラップします。

rem SetFirewallRestrictions.cmd
cd /d %~dp0
Powershell set-executionpolicy remotesigned -force
Powershell .\SetFirewallRestrictions.ps1 >> SetFirewallRestrictions.out.log 2>> SetFirewallRestrictions.err.log

スタートアップタスクで呼び出されるように、ServiceDefinition.csdefファイルを設定します。セキュリティ設定を昇格するように<Runtime>エレメントで設定します。

<ServiceDefinition name="FirewallTest" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2013-03.2.0">
  <WebRole name="WebRole1" vmsize="Small">
   ...  
    <Startup>
      <Task commandLine="Startup\SetFirewallRestrictions.cmd" executionContext="elevated" taskType="simple" />
    </Startup>
    <Runtime executionContext="elevated" />
  </WebRole>
</ServiceDefinition>

スタートアップタスクを設定すると、Windows Azureは自動的にファイヤーウォールの設定を更新し、IP制限を設定しインスタンスを起動します。ロースをスケールさせると、Windows Azure Gesut Agentは、Windows Firewallの設定を再作成します。IP制限を継続するには、ロールのトポロジーが変わった際に、スクリプトを再適用する必要があります。

アプリケーションがスケールしたときに、ファイヤーウォールルールを再適用するために、RoleEntryPointクラスで、RoleEnvironment.Changedイベントを使用します。

public class WebRole : RoleEntryPoint
{
    public override bool OnStart()
    {
        RoleEnvironment.Changed += RoleEnvironment_Changed;
        return base.OnStart();
    }

    void RoleEnvironment_Changed(object sender, RoleEnvironmentChangedEventArgs e)
    {
        if (e.Changes.Any(ch => ch is RoleEnvironmentTopologyChange))
        {
            var processStartInfo = new ProcessStartInfo(@"Startup\SetFirewallRestrictions.cmd");
            var process = Process.Start(processStartInfo);
        }
    }
}

元記事

MSDNブログ:Using Windows Firewall to restrict access to Windows Azure instances

Windows Azure

A6又はA7の仮想マシンサイズを使おうとしたときに、「Failed to configure virtual machine <machine name>.」や「Failed to create virtual machine <machine name>.」というエラーに遭遇するかもしれません。主に次の3つの場合に、エラーが発生します。

  1. A6やA7以外の既存の仮想マシンをサイズ変更してA6やA7にする
  2. 2013/4/16以前に作成した仮想ネットワークに新しいA6又はA7サイズの仮想マシンを作成する
  3. 既存のクラウドサービスに新しいA6又はA7サイズの仮想マシンを追加する

この問題に遭遇した場合には、シナリオケースごとに次の対応をする必要があります。

1. A6/A7に仮想マシンサイズを変更しようとすると失敗する

既存の仮想マシンを削除し、ディスクは維持します。既存のOSディスクか、オリジナルの仮想マシンディスクを使用して、新たにA6/A7サイズの加増マシンを作成します。

もしサイズ変更しようとしている仮想マシンと同じクラウドサービスに別の仮想マシンがデプロイされている場合、それらの仮想マシンも削除し、新しいクラウドサービスに再デプロイする必要があります。

2. A6/A7仮想マシンを既存の仮想ネットワークに追加しようとすると失敗する

新しい仮想ネットワークを作成し、その仮想ネットワークにA6/A7サイズの仮想マシンをデプロイします。

2013/4/15以降に作成された全ての仮想ネットワークは、全てのリージョンで高メモリの仮想マシンが提供された場合、A6/A7サイズの仮想マシンをサポートします。

3. 既存のクラウドサービスにA6/A7仮想マシンを追加する

既存のクラウドサービスを削除し、新たに作成したクラウドサービスにA6/A7をデプロイします。

一次ソース

MSDNフォーラム:「Error: “Failed to configure virtual machine” with new A6 or A7 size

Windows Azure

Windows Azure Virtual Machineで提供されているOpenlogicのCentOS 6.3イメージにはカーネルヘッダー(kernel-headers)が含まれていません。
その為、開発ツールをインストールしようとすると、インストールできずに途方にくれてしまいます。
開発ツールを入れないとソースからビルドして、ミドルウェアをインストールできないので、
結構いや~んな感じです。

そんな問題に対して、OpenLogic Azure Support Teamが、対応方法を回答していました。
(参考:Openlogic Centos 6.3 image: no kernel-headers

sudo yum –disableexcludes=main install kernel-headers-2.6.32-279.14.1.el6.openlogic.x86_64

カーネルヘッダーをインストールしなさいということですね。

ちなみに、自動スクリプトで対応したいなら、gccなどのパッケージをインストールする前に、次のようなコードを使えばいいよっとアドバイスしている人もいました。

sudo yum -y -q –disableexcludes=main install kernel-headers-*.el6.openlogic.x86_64