(仮) ブログ

主にWeb Apps や、Azure PaaS サービス を使う際に役立ちそうなことを書こうと思っています。

従量課金の Function App の制限の話

Azure Functions 人気ですよね。いわゆるサーバーレス アーキテクチャと呼ばれていて、小さな関数コードを書くだけで簡単に実行でき、インフラストラクチャのことを考える必要がありません。

また、Azure Functions では、従量課金プランと呼ばれる実行した分だけ課金されるプランがあるので、とても安価に利用することができます。

実はそんな従量課金プランの Azure Functions ですが、安価な分制限があります。

今日はその Function App に関して簡単に制限を紹介しようと思います。

接続数や、プロセスの数に制限がある

下記のドキュメントは、Azure Web Apps のデプロイエンジンである Kudu の Wiki になりますが、こちらには Azure Web Apps の制限が書かれています。 資料内の表に Consumption と書かれた列があると思いますが、こちらが従量課金プランの制限になります。

例えば、アウトバウンドの接続数は、300 が制限値となりますが、制限はそれぞれのインスタンス上で動作する Function App ごとに適用されるので、インスタンスが動的にスケールアウトされると、増えたインスタンスの台数分だけ接続できる数が増えます。

github.com

インスタンスの割り当ては 10 秒に 1 台

従量課金プランの場合インスタンスは 200 台までスケールすることができますが、10 秒に 1 台ずつしか新たに割り当てられません。 このため、いきなり Function へのリクエストが増加すると、インスタンスの割り当てが間に合わない場合があります。

docs.microsoft.com

Function が実行されないとインスタンスの割り当ては解除される

従量課金プランの場合しばらく Function が実行されないと、インスタンスの割り当てが解除されます。(下記の記事だと大体 20 分程度実行されないと割り当てを解除すると記載されています。) 急激なリクエストの増加が予想される場合には、App Service Plan の利用を検討する方が良さそうです。

blogs.msdn.microsoft.com

もしくは、下記のブログ記事のように頑張って工夫することで、従量課金プランでも大量のイベントを処理することができそうです。

https://blogs.msdn.microsoft.com/jpcie/?p=1905blogs.msdn.microsoft.com

まとめ

  • 従量課金プランの場合は、通常の App Service Plan に加えて別の制限がある
  • インスタンスは急激には増えないので、リクエストの急増には注意が必要
  • しばらく Function が実行されないとインスタンスの割り当ては解除される

意外と知られていない Web Apps の制限

本日は、意外と知られていないけど、よく引っかかる Web Apps の制限についてお話しします。

リクエストの 240 秒制限

Azure Web Apps では、各要求に対して 240 秒のアイドル タイムアウトが設定されています。Web Apps on Linux の場合も同じです。 このため、240 秒以上かかりそうな処理を Azure Web Apps 上で実行したい場合は、Web Apps から Web Job を呼び出すようにしましょう。

docs.microsoft.com

しかし、Azure Web Apps では定期的にメンテナンスによる再起動が発生しますので、Web Job による長時間の処理はあまりオススメできません。 なるべく短く切るように頑張りましょう。

docs.microsoft.com

どのようにメンテナンスが実施されるかは、こちらで紹介されていますので、ぜひ一読してください。

blogs.msdn.microsoft.com

アウトバウンド接続数の制限

Azure Web Apps は、スケールユニットと呼ばれるそれぞれ異なる役割を持つ複数のインスタンス (仮想 VM) で構成されています。 アプリケーションをデプロイすると WebWorker インスタンスと呼ばれるインスタンス上で、アプリケーションが実行されます。 詳しくは下記の記事を参照。

keyomura.hatenablog.com

この WebWorker インスタンスには、アウトバウンド接続の制限があります。実際には下記リンクの通りとなりますが、例えば S1/B1/P1 プランの場合、1920 が制限値となり、インスタンスごとにこの制限が適用されます

github.com

docs.microsoft.com

つまり、S1 プランで、インスタンスを 2 台にスケール アウトしている場合は、アウトバウンドの接続制限は、1920 × 2 となります。 (資料を見ると、実は A シリーズの VM が動作していることがわかります。)

そのほか、上記の Kudu のページには、ローカル ホストにアクセスしようとするとエラーが出ることや、いろんな制限が書いてあるのでオススメです。

自分のアプリケーションの接続数に関しては、Azure ポータルから、自分の Web Apps を選択した後、[問題の診断と解決] から確認することができます。 実はこのブレードから、Web Apps が再起動したかどうかもわかりますので、触ってみてください。

blogs.msdn.microsoft.com

後から制限が発覚すると困りますね。。

Web Apps で FTPS Only が選択できるようになった

先日の Microsoft Build 2018 に合わせて、Web Apps に色々な機能が追加されているのですが、その一つとして Web Apps へ FTP の機能の変更がありました。FTPS のみの接続を許可したり、FTP/FTPS を無効化することができます。

blogs.msdn.microsoft.com

以前は FTP が開きっぱなしだったので、構築するシステムのセキュリティ要件が厳しい場合は敬遠されがちだった Web Apps ですが、この機能が追加されたことでもっと使ってもらえるようになるのではないでしょうか。。と期待しています。

早速触ってみましょう。

Web Apps を作る

Web Apps を作ろうとしたところ、プラン選択の UI が大幅に変わっていますね。

f:id:yoshioblog:20180519192853p:plain

各プランでどんな機能が使えるかがわかりやすくなってます。

今回は、FTP を触りたいだけなので Free プランにしましょう

出来上がったら、[アプリケーション設定] から設定可能です。

f:id:yoshioblog:20180520004259p:plain

[概要] にある、[発行プロファイルの取得] を押してダウンロードされる PublishSettings ファイルに書かれている資格情報を使って認証することができます。

接続を試す

まずは FTP で接続してみます。Azure ポータル上で Web Apps を選択した後表示される概要のところから FTP 用の URL を控えておきます。

先ほど、ダウンロードした発行プロファイルを開いて、ユーザー名($マーク以下)と、パスワードも控えておきます。

コンソールを開いて ftp コマンドを実行しましょう。Mac の場合は、こんな感じで画面が出てきて、パスワードを入力するとログインできます。

$ ftp sitename@waws-prod-dm1-057.ftp.azurewebsites.windows.net
Trying 52.165.149.125...
Connected to waws-prod-dm1-057.drip.azurewebsites.windows.net.
220 Microsoft FTP Service
331 Password required
Password: 
230 User logged in.
Remote system type is Windows_NT.
ftp> 

今度は FTPS Only に変更して試してみましょう。

$ ftp sitename@waws-prod-dm1-057.ftp.azurewebsites.windows.net
Trying 52.165.150.113...
Connected to waws-prod-dm1-057.drip.azurewebsites.windows.net.
220 Microsoft FTP Service
331 Password required
Password: 
421 Service not available, remote server has closed connection.
ftp: Login failed
ftp> 

ちゃんと、FTP だけ遮断できていそうですね。

ためしに FTPS は接続できるか FileZilla で試してみましょう。FileZilla の時は、サイト名の前に $ マークをつけるのを忘れないでください。

f:id:yoshioblog:20180519230450p:plain

うまくできてそうですね。

f:id:yoshioblog:20180519231714p:plain

FTP を使わない場合は "無効にする" 選択肢もできるようになってだんだんと便利になってますね。

デプロイの資格情報について

最後に Azure Web Apps で、ログイン アカウントとは別に FTP や Git のアクセスで利用する資格情報についてご説明します。

Azure Web Apps のデプロイ時に利用する資格情報には、Azure ポータルの、[デプロイ資格情報] から設定できるユーザー資格情報と、先ほどの発行プロファイルから取得できるサイト資格情報の二つがあります。

ユーザー資格情報

Azure ポータル上で Web App を選択した後、[デプロイ資格情報] から設定できる情報がユーザー資格情報です。 この情報は Azure ポータルにログインするときのアカウントに紐づいています。 サブスクリプション上で複数の管理者や共同管理者がいる場合もここのアカウントに紐づいているので、情報が共有されることはありません。

サイトレベル情報

個々のサイトに紐づいた資格情報で、発行プロファイルと呼ばれる XML 形式のファイルの中に記載されています。 サブスクリプション内でこの資格情報は共有となり、"発行プロファイルのリセット" を押すことで新しい情報に更新されます。

詳しくはこちら

github.com

今後も新しい機能が出たらどんどん使って行きたいですね。

君は Batch Shipyard を知っているか

Batch Shipyardって知ってますか?

Batch Shipyard は Azure Batch でコンテナ ベースのジョブを作成する際に利用できる便利なツールです。DcokerSingularity が利用可能で、QuickStart では、CNTK、Caffe、Chainer、Keras、TensorFlow をコンテナ上で実行するチュートリアルが紹介されています。

利用できる VM の種類は、Batch と同じで、Market Place の Linux VM、対応するカスタム VM 、そして Windows VM イメージのようです。

設定が楽

とにかく事前に準備する必要がないから楽! 以前、Azure Batch で Docker コンテナを利用するよう設定をしたことがありましたが、これがだいぶめんどくさかった。。それに比べると、Batch Shipyard は yaml ファイルを書くだけで設定ができるからすごい楽です。 以前の記事はこちら

keyomura.hatenablog.com

例えば、pool VM を設定する時の yaml ファイルはこんな感じ

pool_specification:
  id: tensorflow-cpu
  vm_configuration:
    platform_image:
      offer: UbuntuServer
      publisher: Canonical
      sku: 16.04-LTS
  vm_count:
    dedicated: 1
    low_priority: 0
  vm_size: STANDARD_D1_V2
  ssh:
    username: shipyard

引用: batch-shipyard/pool.yaml at master · Azure/batch-shipyard · GitHub

Job の設定も、ファイルを指定するだけで便利です。

実行が楽

Batch Shipyard は、Azure ポータル上の Cloud Shell から実行が可能です。あらかじめインストールされているので、環境構築の必要がありません。

連携が便利

Batch Shipyard は、Azure Functions との連携が可能です。詳しくは、Azure Functions and Batch Shipyard - Batch Shipyard に書かれていますが、簡単な設定だけで使うことができます。

※ Function App は、App Service Plan 上にホストする必要があります。

使ってください

他にも色々な機能が使えるのですが、書ききれないので是非読んで使ってみてください!

github.com

Traffic Manager の正常性チェックのソース IP が JSON で公開されています

Traffic Manager の FAQ をみると

先日、Traffic Manager の FAQ をみたら今までそこに書いてあった IP のリストが消えて、代わりにこんなことが書いてありました。

docs.microsoft.com

正常性チェックはどの IP アドレスから発信されますか。

ここをクリックして表示される JSON ファイルに、Traffic Manager の正常性チェックの実行元になる IP アドレスが列挙されています。 JSON ファイルに列挙されている IP を確認し、正常性状態をチェックするためにこれらの IP アドレスからの受信接続がエンドポイントで確実に許可されるように設定してください。

今までは、IP のリストが書いてあるだけだったのに、、、

これからは、これを定期的にチェックしてアプリケーションで自動に制御ができそうですね。

他にも、仮想ネットワーク上にデプロイされているサービスであれば、Network Security Group が利用可能です。

NSG なら、何も作業する必要がないから楽そう。

注意点

Traffic Manager を使う時の注意点もせっかくなので紹介しようと思います。

せっかく災害対策を組んだのにうまく動かなかった、、、なんてことになったら悲しいですよね。

Traffic Manager を使う時には下記の点にも注意してください。

正常性チェックは HTTP 200 OK しかダメ

Traffic Manager の正常性チェックでは、対象のエンドポイントが HTTP 200 OK を返した時のみ正常とみなします。

アプリケーション側で 301 などを返して別サイトへリダイレクトさせるように設定している場合は、正常性チェックで失敗するので気をつけてください。

※ 監視プロトコルTCP の場合は接続できれば成功とみなされます。

docs.microsoft.com

連続で正常性チェックが失敗しないとエンドポイントが切り替わらない

Traffic Manager は指定した間隔で正常性チェックを実施しますが、指定回数連続で失敗しないとエンドポイントは切り替わりません。

このため、正常性チェックで成功と失敗を繰り返す不安定なエンドポイントの場合は、ずっと切り替わらずに最初のエンドポイントへアクセスが発生する可能性があります。

なかなか切り替わらないようであれば、手動で切り替えを実行してしまいましょう。

Web Apps (Linux) でログファイルを取得してくる

Web Apps on Linux でコンテナの起動に失敗したときは、ブラウザ上にエラーが出ますが、詳細なエラーはログ ファイルに記録されます。 ウェブ上で見ることもできますが、手元に保存してからの方がより簡単ですよね。 そのやり方がよくわからないという方向けの記事です。 ※ 今回はWeb App for Containers は当てはまりません。

目次

ログ ファイルを有効化する

まずは、stdout、stderr をログに出力するように設定を行いましょう。これができてないと Docker コンテナの起動しか記録されません。

f:id:yoshioblog:20180325092354p:plain

Kudu サイトに行く

Web Apps の管理サイトである Kudu サイトに行きましょう。Azure ポータルから、Web Apps を選択したあと、[高度なツール] から移動することができます。 もしくは、https://yourwebapp.scm.azurewebsites.net からも移動可能です。(yourwebapp は自分の Web Apps 名)

Web Apps (Linux) はコンテナ上で動作するアプリケーションですが、Kudu も別コンテナ上で動作するアプリケーションとなります。 このため、アプリケーションが動作しているコンテナ内のプロセス情報などを見るには、WebSSH で、Kudu からアプリケーションが動作しているコンテナへ接続する必要があります。

なお、Kudu からしSSH 接続はできず、クライアント PC から SSH でコンテナへの接続はできませんので注意してください。

/home/LogFiles へ移動する

画面上部の [Debug console] -> [Bash] から Bash コンソールへ移動しましょう。/home/LogFiles 以下にログ ファイルが保存されています。

f:id:yoshioblog:20180325092722p:plain

cat コマンドでログ ファイルを見ることができるのですが、正直わかりづらい、、

f:id:yoshioblog:20180325092810p:plain

ということで手元にダウンロードしましょう。

ログ ファイルを ZIP でダウンロード

Web Apps の管理サイトである Kudu サイトにはいくつか便利な API が用意されています。 その中でも重宝しているのが、 特定のディレクトリやファイルを ZIP でダウンロードしてくる API

github.com

ログ ファイルが保存されているディレクトリを ZIP でダウンロードする場合はこんな感じ。ブラウザに入力するだけでダウンロードできます。

https://yourwebapp.scm.azurewebsites.net/api/zip/LogFiles

ダウンロードしてきた、ログ ファイルを好きなエディタで読みましょう。

f:id:yoshioblog:20180325093044p:plain

Visual Studio Code の拡張機能である、Log File Highlighter を入れると便利です。

f:id:yoshioblog:20180325101201p:plain

おわりに

Web Apps on Linux では /home/LogFiles 以下にログを出力するようにあらかじめ設定がされています。 一方で、Web App for Containers は自分で Docker イメージを作る必要があるので、今回の方法ではログファイルを出力することはできません。 Web App for Containers の場合は自分で頑張って設定しましょう。

Web Apps on Linux と Web App for Containers の違いはここで説明されています。

azure.microsoft.com

ちなみに、Web Apps on Linux の場合、DockerFile や各言語のスクリプトの中身は実は Azure App Service · GitHub で公開されています。

Azure Batch で Docker コンテナと Python を利用する

先日、Azure Batch で Docker コンテナを利用したのですが、結構大変で気が遠くなったので書いておこうと思います。

目次

Azure Batchとは ?

Azure Batchは仮想マシンと Azure Storage Blob を利用したサービスで、Azure Batch を利用することで大規模な並列計算を行うことができます。 ただ、、設定して使えるようになるまでの道のりがめちゃくちゃ長い、、簡単にコンテナを使いたいなら、Batch Shipyard の方が簡単でした。。。

docs.microsoft.com

Docker コンテナとの連携

この Azure Batch ですが、これまでは動的に作成した VM 上で、必要なパッケージをインストールしたりと、Batch 上で実行するアプリケーションの依存関係を管理する必要がありました。

しかし、下記ドキュメントのように設定を行うことで、Docker コンテナ上で Azure Batch のタスクを実行できるようになります。 Docker コンテナをあらかじめ作っておくことで、VM の環境に左右されずにタスクの実行ができます。

docs.microsoft.com

ドキュメント内にも書いてありますが、Linux ベースの Docker コンテナを利用するためには、あらかじめ下記の設定を行う必要があります。

  • Docker が実行可能な Ubuntu 16.04 LTS または CentOS 7.3 の VM のカスタム イメージを作る
  • Batch のジョブ実行時にAzure Active Directory を使用して認証する

是非、Docker コンテナと Batch を使って欲しいのでそれぞれに関して下記について説明します。

Docker が実行可能な Ubuntu 16.04 LTS または CentOS 7.3 の VM のカスタム イメージを作る

Azure ポータルから VM を作ってカスタム イメージを作る方法が簡単です。 下記のドキュメントから Azure CLI を使ってカスタム イメージを作ってください。

docs.microsoft.com

カスタム イメージを作る前に、OS に Docker CEをインストールしておきましょう。

docs.docker.com

作成が終わったら、カスタム イメージのリソース ID を保存しておきましょう。

Batch のジョブ実行時にAzure Active Directory を使用して認証する

Azure Batch がカスタム イメージの VMを利用するためには、既定の共有キー認証ではなく Azure Active Directory 認証を利用する必要があります。 下記のドキュメントに従って設定しましょう。

docs.microsoft.com

これで準備が整いました。Docker コンテナを利用できるよう Pythonスクリプトを作成します。

Azure Batch × Docker × Python

今回は、下記のドキュメントのチュートリアルの内容を、Docker コンテナ上で同じように動作させるよう設定します。

docs.microsoft.com

Docker コンテナを利用するためには、このチュートリアルのコードを変更する必要があります。 具体的には下記の部分を追加/変更します。

  • Batch サービスの認証に Azure Active Directory を利用する
  • ImageReference クラスで カスタムイメージを利用するように設定する
  • Docker コンテナをプリフェチするよう設定する
  • タスク向けにコンテナの設定を行う

Batch サービスの認証に Azure Active Directory を利用する

通常は、SharedKeyCredentials を利用して認証を行いますが、今回はカスタムイメージを利用するので、ServicePrincipalCredentials による認証を行います。 サンプルスクリプト内の SharedKeyCredentials の部分を ServicePrincipalCredentials へ変更しましょう。

# SharedKeyCredentials

from azure.batch import BatchServiceClient
from azure.batch.batch_auth import SharedKeyCredentials

credentials = SharedKeyCredentials(BATCH_ACCOUNT_NAME, BATCH_ACCOUNT_KEY)
batch_client = BatchServiceClient(
    credentials,
    base_url=BATCH_ACCOUNT_URL
)

↓

# ServicePrincipalCredentials

from azure.batch import BatchServiceClient
from azure.common.credentials import ServicePrincipalCredentials

credentials = ServicePrincipalCredentials(
    client_id=CLIENT_ID,
    secret=SECRET,
    tenant=TENANT_ID,
    resource="https://batch.core.windows.net/"
)
    batch_client = BatchServiceClient(
    credentials,
    base_url=BATCH_ACCOUNT_URL
)

ImageReference クラスで カスタムイメージを利用するように設定する

チュートリアルでは、サンプルコードの 219 行目あたりで、helper 関数を利用して MarketPlace 上のイメージを取ってくるように記述されてます。 これを変更して、ImageReference クラスでカスタムイメージを利用するように変更しましょう。今回は Ubuntu Server 16.04 LTS からカスタムイメージを作ったので、SKU は Ubuntu です。

IMAGE はカスタムイメージのリソース ID になります。仮想マシンのイメージは同リージョン、同サブスクリプション上に配置されている必要があります。

sku_to_use, image_ref_to_use = \
    common.helpers.select_latest_verified_vm_image_with_node_agent_sku(
        batch_service_client, publisher, offer, sku)
user = batchmodels.AutoUserSpecification(
    scope=batchmodels.AutoUserScope.pool,
    elevation_level=batchmodels.ElevationLevel.admin)
new_pool = batch.models.PoolAddParameter(
    id=pool_id,
    virtual_machine_configuration=batchmodels.VirtualMachineConfiguration(
        image_reference=image_ref_to_use,
        node_agent_sku_id=sku_to_use),
    vm_size=_POOL_VM_SIZE,
    target_dedicated_nodes=_POOL_NODE_COUNT,
    start_task=batch.models.StartTask(
        command_line=common.helpers.wrap_commands_in_shell('linux',
                                                               task_commands),
        user_identity=batchmodels.UserIdentity(auto_user=user),
        wait_for_success=True,
        resource_files=resource_files),
)

↓

  
    user = batchmodels.AutoUserSpecification(
        scope=batchmodels.AutoUserScope.pool,
        elevation_level=batchmodels.ElevationLevel.admin)
    new_pool = batch.models.PoolAddParameter(
        id=pool_id,
        virtual_machine_configuration=batchmodels.VirtualMachineConfiguration(
            image_reference=batchmodels.image_reference.ImageReference(
                virtual_machine_image_id=IMAGE
            ),
            node_agent_sku_id="batch.node.ubuntu 16.04",
            container_configuration=CONTAINER_CONFIG),
        vm_size=_POOL_VM_SIZE,
        target_dedicated_nodes=_POOL_NODE_COUNT,
        start_task=batch.models.StartTask(
            command_line=common.helpers.wrap_commands_in_shell('linux',
                                                               task_commands),
            user_identity=batchmodels.UserIdentity(auto_user=user),
            wait_for_success=True,
            resource_files=resource_files,
            container_settings=CONTAINER_TASK),
)

Docker コンテナをプリフェチするよう設定する

上記のコードですでにでていますが、コンテナをプリフェッチするためには、VirtualMachineConfiguration クラスで container_configuration に、ContainerConfiguration クラスを指定する必要があります。

Docker Hub から引っ張ってくる場合はこんな感じ

CONTAINER_IMAGE = "test/image"

CONTAINER_CONFIG = batchmodels.container_configuration.ContainerConfiguration(
    container_image_names=[CONTAINER_IMAGE])

Azure Container Registry から引っ張ってくる場合はこんな感じ

CONTAINER_IMAGE = "yourregistry.azurecr.io/image"
CONTAINER_USER = "yourregistory"
CONTAINER_PASS = "yourpassword"
CONTAINER_HOST = "yourregisty.azurecr.io"

CONTAINER_REGISTRY = batchmodels.container_registry.ContainerRegistry(
    user_name=CONTAINER_USER,
    password=CONTAINER_PASS,
    registry_server=CONTAINER_HOST)

CONTAINER_CONFIG = batchmodels.container_configuration.ContainerConfiguration(
    container_image_names=[CONTAINER_IMAGE],
    container_registries=[CONTAINER_REGISTRY])

この CONTAINER_CONFIG をcontainer_configuration に設定します。

タスク向けのコンテナ設定を行う

最後に各タスク向けのコンテナの設定を行います。スタートタスクには不要ですが上記コードでは一応入れてみました。 チュートリアルだとこのあたりになります。

# 新しく追加するコード

CONTAINER_TASK = batchmodels.task_container_settings.TaskContainerSettings(
    container_run_options="--rm",
    image_name=CONTAINER_IMAGE
)

# チュートリアルの 329 行目あたり

tasks.append(batch.models.TaskAddParameter(
            'topNtask{}'.format(idx),
            common.helpers.wrap_commands_in_shell('linux', command),
            resource_files=[input_file],
            container_settings=CONTAINER_TASK
            )

最後に実行、、!

これでやっと準備完了です。。長い道のりでしたね。あとは、Python がインストールされた適当なコンテナを作ってチュートリアルを試してみてください。 Docker コンテナが使えると、今までスタートタスクで必要なソフトをインストールしていましたが、その手間も省けるので、Batch 利用がもっと簡単になりそうです。