App Serviceの基本をまとめた

# はじめに
AZ-204対策の一環で、以下のMS Learnに含まれる4つのモジュールの内容を自分の勉強用としてまとめました。

https://learn.microsoft.com/ja-jp/training/paths/create-azure-app-service-web-apps/

# App Service
以下をホストするHTTPベースのサービスです。
- Webアプリケーション
- REST API
- モバイルバックエンド

また、以下に関するお気に入りの環境で開発することができます。
- プログラミング言語
- フレームワーク
- OS(Windows or Linux)

## App Service on Linux
App Serviceでは、WebアプリをLinuxでネイティブにホストすることもできます。App Service on Linuxではさまざまな言語とフレームワークがサポートされています。
- Node.js
- Java(JRE 8 & JRE 11)
- PHP
- Python
- .NET
- Ruby

## App Serviceプラン
App Serviceプランで、Webアプリを実行するための一連のコンピューティングリソースを定義します。

:::note info
同じApp Serviceプランで、1つまたは複数のアプリを同じコンピューティングリソースで実行することができます。
:::

App Serviceプランは以下を定義します。
- オペレーティングシステム
    - Windows, Linux
- リージョン
    - 米国西部、米国東部、など
- VMインスタンスの数
- VMインスタンスのサイズ
    - 小、中、大
- 価格レベル
    - Free, Shared
        - 共有コンピューティング
        - 共有のCPU時間を提供
        - リソースのスケールアウトは不可
    - Basic, Standard, Premium, PremiumV2, PremiumV3
        - 専用のコンピューティング(Azure VM)
        - レベルが高いほど、スケールアウトに使用できるVMインスタンス数が多い
    - Isolated, IsolatedV2
        - 専用のコンピューティングと専用のネットワーク(Azure VMとAzure Network)
        - 最大のスケールアウト機能

:::note info
FreeとSharedのApp Serviceプランは、開発とテストのみでの使用を対象としています。
:::

App Serviceプランはいつでもスケールアップまたはスケールダウンできます。

## App Serviceにデプロイ
App Serviceでは、自動デプロイと手動デプロイの両方がサポートされています。

:::note info
運用ビルドをデプロイする際は、可能な限りデプロイスロットの利用が推奨されます。
:::

### 自動デプロイ
自動デプロイは継続的デプロイとも呼ばれます。このデプロイは、以下の利点が得られるプロセスです。
- エンドユーザーへの影響を最小限に抑える
- 短期間かつ反復的に新機能とバグ修正を提供

自動デプロイでは、次のオプションを使用できます。
- Azure DevOps Services
- GitHub
- Bitbucket

#### Azure DevOps Services
自動デプロイの流れは以下になります。
- Azure DevOps Servicesにコードをプッシュ
- クラウドでコードをビルド&テストの実行
- コードからリリースの生成
- Azure Webアプリにプッシュ

#### GitHub
GitHubリポジトリをAzureに接続すると、GitHub上の運用ブランチにプッシュするすべての変更が自動的にデプロイされます。

### 手動デプロイ
手動デプロイでは、次のようなオプションがあります。
- Git
- CLI
- Zip
- FTP/FTPS

## App Serviceの認証と認可
App Serviceでは、組み込みの認証と認可がサポートされているため、ユーザーのサインインとデータのアクセスが容易です。認証と認可にApp Serviceを必ず使う必要はなく、バンドルされているWebフレームワークの認証・認可機能を使うこともできます。

### IDプロバイダーの利用
App Serviceが使用するフェデレーションIDでは、サードパーティのIDプロバイダーが代わりにユーザーIDと認証フローを管理し、次のIDプロバイダーを規定で利用できます。
- Microsoft ID プラットフォーム
- Facebook
- Google
- Twitter
- OpenID Connect プロバイダー
- GitHub

:::note info
**IDフェデレーションとは**
複数のセキュリティドメイン間で、それぞれのユーザーIDをリンクさせる技術です。
:::

### 認証・認可モジュール
認証と認可のモジュールは、アプリのコードと同じサンドボックスで実行されます。有効になっている場合は、すべてのHTTP要求がアプリのコードによって処理される前に、認証と認可のモジュールを通過し、以下のようないくつかの処理を行います。
- 指定されたIDプロバーダーによる、ユーザーとクライアントの認証
- 指定されたIDプロバイダーによって発行された、OAuthトークンの検証と格納と更新
- 認証されたセッションの管理
- HTTP要求ヘッダーにID情報を挿入

:::note info
認証・認可モジュールは、アプリのコードとは別に実行され、ARMの設定や構成ファイルを使用して構成されます。
:::

### 認証フロー
認証フローには、サーバーフローとクライアントフローの2種類があります。

#### サーバーフロー
プロバイダーのSDKを使わない場合は、サーバーのコードがサインインプロセスを管理するため、サーバーフローとも呼ばれます。ブラウザーアプリで使われるケースで、サインインをApp Serviceに委任します。

#### クライアントフロー
プロバイダーのSDKを使う場合は、アプリのコードがサインインプロセスを管理するため、クライアントフローとも呼ばれます。ブラウザーレスアプリで使われるケースで、ユーザーを手動でプロバイダーにサインインさせてから、検証のためにApp Serviceに認証トークンを送信します。

:::note info
**トークンストアとは**
App Serviceが提供する組み込みのトークンリポジトリです。
:::

## App Serviceのネットワーク機能
App Serviceには主に以下の2種類のデプロイ方法があります。
- マルチテナント型
    - パブリックサービス
    - Free, Sharedプラン
- シングルテナント型
    - ASE(App Service Environment)を使用
    - Azure Virtual Networkで直接ホスト可能
    - Basic以上のプラン

### マルチテナント型
App Serviceは分散システムであり、ロールごとに以下のように呼ばれます。
- フロントエンド
    - HTTPやHTTPSを要求するロール
- ワーカー
    - ワークロードをホストするロール

:::note warn
同じApp Serviceスケールユニット内に多くのお客様が存在するため、App Serviceネットワークを別のネットワークに直接接続することはできません。
:::

ネットワークを接続する代わりに、App Serviceでは以下のようなアプリ通信の様々な機能が実装されています。
- 受信時の機能
    - アプリに割り当てられたアドレス
    - アクセスの制限
    - サービスエンドポイント
    - プライベートエンドポイント
- 送信時の機能
    - ハイブリッド接続
    - ゲートウェイが必要な仮想ネットワーク統合
    - 仮想ネットワークの統合

## Webアプリの作成
Azure CLIで`az webapp up`コマンドを使用した以下のコマンドにより、基本的なHTML+CSSサイトをAzure App Serviceにデプロイ及び再デプロイをすることができます。
```bash:Bash
az webapp up -g $resourceGroup -n $appName --html
```
デプロイが完了したら、`https://<myAppName>.azurewebsites.net`のURLでアプリが実行していることを確認できます。

## アプリ設定
App Serviceにおけるアプリ設定とは、環境変数としてアプリコードに渡される変数です。

:::note info
アプリの設定は、格納されるときに常に暗号化されます。
:::

アプリの設定は、次のようなjsonファイルを使って一括で追加・編集することができます。
```json:JSON
[
  {
    "name": "<key-1>",
    "value": "<value-1>",
    "slotSetting": false
  },
  {
    "name": "<key-2>",
    "value": "<value-2>",
    "slotSetting": false
  },
  ...
]
```

:::note info
`value`にはデータベースへの接続時など、接続文字列が格納される場合があります。
:::

また、Azureポータルを使ってアプリの一般的な設定を構成できます。
- スタックの設定
    - 言語
    - 言語バージョン
    - SDKバージョン
- プラットフォームの設定
    - ビット
    - WebSocketプロトコル
    - Always On
    - マネージドパイプラインバージョン
    - HTTPバージョン
    - ARR affinity
- デバッグ
    - リモートデバッグの有効化
- 受信クライアント証明書
    - 相互認証

## パスマッピング
パスのマッピングでは、以下を構成することができます。
- ハンドラーマッピング
- 仮想アプリケーションのマッピング
- ディレクトリのマッピング

また、マッピングはOSの種類に基づいて、いくつかのオプションがあります。

:::note info
**ハンドラーマッピングとは**
拡張子で示されるファイルに要求があった時、どのプログラムに処理を任せるかというマッピングのこと。
:::

### Windowsアプリ(非コンテナー)
Windowsアプリは、以下のカスタマイズが可能です。
- IIS ハンドラーマッピング
- 仮想アプリケーション
- ディレクトリ

ハンドラーマッピングにより、特定のファイル拡張子への要求の処理を追加できます。
以下のハンドラーがあります。
- 拡張子
    - *.phpやhandler.fcgi
- スクリプトプロセッサ
    - 絶対パス
    - ルートディレクトリ
        - `D:/home/site/wwwroot`
- 引数
    - 省略可能なコマンドライン引数

:::note info
**IISとは**
Microsoft社が提供しているWindowsのWebサーバーソフトウェアです。IISはWindows Serverに標準で搭載されており、以下をホスティングする機能があります。
- Webサイト
- Webアプリ
- FTPサーバー
- SMTPサーバー
:::

### Linuxアプリとコンテナーアプリ
コンテナー化されたアプリは、以下のカスタムストレージを構成することができます。
- 名前
    - 表示名
- 構成オプション
    - Basic, Advanced
- ストレージアカウント
- ストレージの種類
    - Azure BLOB or Azure Files
    - (WindowsコンテナーアプリはFilesのみサポート)
- ストレージコンテナー
- 共有名
    - ファイル共有名
- アクセスキー
- マウントパス
    - カスタムストレージをマウントするためのコンテナー内の絶対パス

:::note info
コンテナー化されたアプリには、Windowsコンテナーアプリも含まれます。
:::

## 診断ログ
App Serviceには、アプリのデバッグを支援する仕組みの診断機能が用意されています。以下はログの種類です。
- アプリケーションのログ記録
    - アプリのコードによって生成されたメッセージ
    - 各メッセージには次のカテゴリが割り当てられます
        - 重大、エラー、警告、情報、デバッグ、トレース
- Webサーバーのログ記録
    - HTTP要求データ
    - 以下のデータが含まれています
        - HTTPメソッド
        - リソースURI
        - クライアントIP
        - クライアントポート
        - ユーザーエージェント
        - 応答コード
- 詳細なエラーログ記録
    - クライアントのブラウザーに送信された.htmlエラーページのコピー
    - HTTPコード400以上のアプリケーションエラーの発生時に、エラーページの保存が可能
- 失敗した要求トレース
    - 以下のようなトレース情報が含まれています
        - IISコンポーネントのトレース
        - 各コンポーネントにかかった時間
- デプロイログ
    - 自動的にログの記録が行われる
    - ログの構成可能な設定はない

### Windowsアプリケーションのログ
アプリのログを有効にできます。以下の2つのオプションがあります。
- ファイルシステムオプション
    - 一時的なデバッグ用
    - 12時間で自動的にオフ
- Blobオプション
    - 長期的なログ記録用

:::note info
Blobオプションには、ログを書き込むBLOBストレージコンテナーが必要になります。
:::

### Linux/コンテナーアプリのログ
アプリケーションログのディスククォータを指定することで、アプリのログを保持する日数を設定することができます。

### Webサーバーのログ
Webサーバーのログは以下の2か所で選択的に保存ができます。
- Blob Storage
- App Serviceファイルシステム

### コードによるログメッセージ
ASP.NETアプリでは、`System.Diagnostics.Trace`クラスを利用してアプリ診断ログに情報を記録できます。
```c#:C#
System.Diagnostics.Trace.TraceError("If you're seeing this, something bad happened");
```

## ログのストリーミング
`/LogFiles`ディレクトリ(`d:/home/logfiles`)に格納されている.txt, .log, .htmで終わるファイルに書き込まれた情報は、App Serviceによってストリーミングされます。ストリーミング手段は以下になります。
- Azure portal
- Azure CLI
- ローカルコンソール

Azure CLIでログをライブストリーミングするコマンドは以下になります。
```bash:Bash
az webapp log tail --name appname --resource-group myResourceGroup
```

## アクセスログファイル
App Serviceファイルシステムに格納されているログ次の場所にあるZIPファイルをダウンロードできます。

- Windowsアプリ
    - `https://<app-name>.scm.azurewebsites.net/api/dump`
    - DockerホストとDockerコンテナーのコンソール出力ログ
- Linux/コンテナーアプリ
    - `https://<app-name>.scm.azurewebsites.net/api/logs/docker/zip`

## セキュリティ証明書
App Serviceでは以下の証明書を作成、アップロード、インポートできます。
- プライベート証明書
- パブリック証明書

以下は証明書を追加するためのオプションです。
- App Serviceマネージド証明書を作成
    - 無料のプライベート証明書
    - カスタムドメインをセキュリティで保護
- App Service証明書を購入
    - Azureで管理されるプライベート証明書
- Key Vaultから証明書をインポート
    - 証明書の管理
- プライベート証明書のアップロード
    - サードパーティプロバイダーからのプライベート証明書
- パブリック証明書のアップロード
    - カスタムドメインのセキュリティ保護には使用されない
    - リモートリソースのアクセスに使用

### プライベート証明書の要件
以下、App Serviceでプライベート証明書を使用する場合の要件の一部です。
- Triple DESを使用して暗号化
- パスワードで保護されたPFXファイル
- 2048ビット長の中間証明書

### 無料のマネージド証明書の作成
App Serviceアプリに対して、クライアント証明書を有効にするのに必要なプランは以下です。
- Basic
- Standard
- Premium
- Isolated

また、無料の証明書には以下の制限が伴います。
- ワイルドカード証明書はサポート非対応
- プライベートDNSはサポート非対応
- エクスポート不可能
- App Service Environment(ASE)ではサポート非対応
- 英数字、ダッシュ、ピリオドのみサポート

:::note info
**無料App Serviceマネージド証明書とは**
有効期限の45日前に6か月単位で継続して自動的に更新されるTLS/SSLサーバー証明書です。
:::

## 自動スケーリング
自動スケーリングとは、現在の需要に基づいて使用可能なリソースを調整するクラウドのシステムまたはプロセスです。自動スケーリングにより、以下のメリットが得られます。
- 可用性の向上
- フォールトトレランスの向上

自動スケーリングはWebアプリで使用されるApp Seriveの機能に含まれます。

:::note warn
すべてのプランで自動スケーリングがサポートされているわけではありません。
:::

### スケーリング方法
- スケールイン
- スケールアウト

以下のスケーリング方法は行われません。
- スケールアップ
- スケールダウン

:::note info
スケールインではインスタンスの数が減らされ、スケールアウトではインスタンスの数が増やされます。
:::

### スケーリングの要因
自動スケーリングは、以下の要因でトリガーされます。
- スケジュール
- CPU使用率の増加
- メモリ占有率の増加
- 受信要求数の増加
- 以上複数の要因の組み合わせ

### 自動スケーリングルール
自動スケーリングは、ユーザーが定義するルールに基づいて行われます。
閾値の指定を行うことで、以下を行えます。
- 自動スケーリングイベントのトリガー
- リソースの割り当てを解除
:::note warn
**自動スケーリングルールの定義は慎重に行いましょう**
Dos攻撃により受信トラフィックが大幅に増加する可能性があります。増加した要求を処理しようとすると大きな被害を被ります。本物ではない要求に対しては処理しないために、要求の破棄を行うフィルタリングの実装をしましょう。
:::

### 自動スケーリング条件
Azureで提供される自動スケジュールオプションは次の2つです。
- メトリックに基づくスケーリング
    - CPU使用率
    - メモリ使用率
    - ディスクキューの長さ
        - 未処理のI/O要求数
    - HTTPキューの長さ
        - 未処理のHTTP要求数
    - 受信データ
        - 受信バイト数
    - 送信データ
        - 送信バイト数
    - 他のAzureサービス
        - Azure Service Busキューのアイテム数
- インスタンス数へのスケーリング
    - 特定の時刻
    - 特定の日付
    - 特定の曜日

:::note info
**メトリックとは**
対象の属性や状態を数値化したものを指します。
:::

### メトリックの分析
メトリック値は、時間グレインで集計された値です。使用できるオプションは、以下の6つです。
- 平均
- 最小
- 最大
- 合計
- 最終
- カウント

時間グレインは、メトリック値の変化の判断には短い時間です。そのため、時間グレインで集計した値をさらに集計することでメトリック値が計算されます。例えば、10分の期間のメトリック値を計算する場合、10個の値が集計されます。

:::note info
時間グレインとは、メトリック値を取得する期間のことです。ほとんどの場合、時間グレインは1分です。
:::

### 自動スケーリングアクション
自動スケーリングアクションでは閾値との比較で、以下の演算子が使用されます。
- より小さい
- より大きい
- 等しい

また、アクションの内容としてインスタンスの数を以下のように変化させることができます。
- 増やす
- 減らす
- 指定の数にする

### クールダウン期間
クールダウン期間とは、自動スケーリングアクション後に適応される、スケジューリングルールがトリガーされない期間です。期間は分単位で、最小は5分です。

### 自動スケーリングルールのペアリング
スケールアウトの設定をする場合、スケールインの設定も行い、システムを元に戻す方法を定義する必要があります。
例えば、以下の条件を定義することができます。
- HTTPキューの長さ
    - 10を超えたら1だけスケールアウト
    - 0になったら1だけスケールイン
- CPU使用率
    - 70%を超えたら1だけスケールアウト
    - 50%未満になったら1だけスケールイン

:::note warn
スケールアウトはルールの**いずれか**が満たされ場合に実行され、スケールインはルールの**すべて**が満たされた場合のみに実行されます。
:::

### 自動スケーリングのアクティビティ監視
Azureポータルにて、以下のメトリック値を監視することができます。
- HTTPサーバーエラー数
- 受信データ量
- 送信データ量
- 要求数
- 平均応答時間

:::note info
自動スケーリングの成功と失敗は、すべてアクティビティログに記録されます。また、アクティビティをメール、SMS、Webhookで通知することもできます。
:::

:::note info
**Webhookとは**
アプリの更新情報を他のアプリに即時提供する仕組みのことです。
:::

### 自動スケーリングの上限
自動スケーリングの暴走を防ぐため、App Service にはインスタンスの上限があり、料金の高い価格レベルのプランほど、上限が高くなります。

### 自動スケーリングが適さないケース
自動スケーリングには以下のようなオーバヘッドがあります。
- リソースの監視
- スケーリングイベントをトリガーするための判断

そのため、以下の場合においては手動によるスケーリングの方がコスト効果を高める可能性があります。
- 長期的な処理の増加

### 自動スケーリング利用時の考慮事項
閾値のメトリック値はすべてのインスタンスで計算されることに注意する必要があります。例えば、以下のような閾値の設定はよくありません。
- スレッド数が600以上でスケールアウト
- スレッド数が600以下でスケールイン

この設定でインスタンス3つの平均スレッドが575だった場合、仮にスケールインすると862.5スレッドになり、再度スケールアウトを実行する必要があります。これはフラッピングと呼ばれるプロセス全体が繰り返される無限ループに繋がるので、それを避けるためにApp Serviceではこのような状況下で自動スケーリングは一切行われない仕様になっています。この場合、自動スケーリングが機能していないように見えるため、ユーザーを混乱させる恐れがあります。

ですから、閾値の設定は以下の設定のように、十分に差をつけておきましょう。
- CPU利用率が80%以上でスケールアウト
- CPU利用率が60%以下でスケールイン

## デプロイスロット
デプロイスロットは、固有のホスト名を持つライブアプリであり、様々な開発環境において以下のことができる強力なツールです。
- プレビュー
- 管理
- テスト
- デプロイ

デプロイスロットにより、運用スロットを含む2つのデプロイスロット間でスワップすることができます。
- アプリのコンテンツ
- アプリの構成要素

:::note info
デプロイスロットは、Windows上のWebアプリ、Linux上のWebアプリ、モバイルバックエンドアプリ、APIアプリの全てで使用することができます。
:::

### 非運用スロット
非運用スロットにアプリをデプロイすることは、以下のようなメリットがあります。
- アプリの変更を検証できる
- デプロイ時のダウンタイムがなくなる
- 元のサイトに戻せる

:::note info
デプロイスロットの使用には追加料金はかかりません。
:::

スロットは、以下からデプロイできます。
- リポジトリブランチ
- リポジトリ

:::note warn
サポートされるデプロイスロット数は、App Serviceプランごとに異なります。
:::

### スロットのスワップ内容
構成要素には、以下の2種類があります。
- スロット固有のもの
- スロット固有ではないもの

:::note info
スロット固有のものとは、スワップを経ても同じスロットに残されるものです。
:::

#### スロット固有のもの
スロット固有のものには、以下のものがあります。
- 発行エンドポイント
- カスタムドメイン名
- パブリックでない証明書
- TLS/SSL設定
- スケールの設定
- Webジョブスケジューラ
- IP制限
- 常時接続
- 診断ログの設定
- CORS
- 仮想ネットワークの統合
- マネージドID
- `_EXTENSION_VERSION`で終わる設定

#### スロット固有ではないもの
スロット固有ではないものには以下のものがあります。
- 一般設定(フレームワークバージョン)
- 一般設定(32/64ビット)
- 一般設定(Webソケット)
- アプリ設定(スロット固有としても構成可能)
- 接続文字列(スロット固有としても構成可能)
- ハンドラーマッピング
- パブリック証明書
- Webジョブコンテンツ
- ハイブリッド接続
- Azure Content Delivery Network
- サービスエンドポイント
- パスのマッピング

:::note info
Azureポータルの[デプロイスロットの設定]でチェックボックスの選択をすることで、設定がスワップ可能ではないことを指示することができます。
:::

### スワップの手法
デプロイスロットのスワップには以下の2つの手法があります。
- 手動スワップ
- 自動スワップ

#### 手動スワップ
手動スワップが行われる前には、プレビューでのスワップを行うことで、運用環境にスワップする前に、スワップ後の設定でアプリの実行を検証することができます。

#### 自動スワップ
自動スワップを使用すると、以下の理由からアプリを連続的にデプロイする効率的なAzure DevOps Servicesを実現できます。
- コールドスタートが不要
- ダウンタイムがない

また、あるスロットから運用環境への自動スワップが有効になっている場合、コードの変更をそのスロットにプッシュする度に、ソーススロットでウォームアップされた後、自動的にスワップされます。

## トラフィックのルーティング
既定では、アプリの運用環境のURLである`https://<app_name>.azurewebsites.net`に対する全てのクライアント要求は運用スロットにルーティングされますが、トラフィックの一部を別のスロットにルーティングすることも可能です。

### 自動的にルーティング
運用トラフィックを自動的にルーティングするには、ルーティング先のスロットの"トラフィック%"を0~100の割合で指定することで、指定された割合のクライアントが非運用スロットにランダムにルーティングされます。

:::note info
別のデプロイスロットに適用される既定のルーティング割合は0%です。
:::

自動的なルーティング後、クライアントセッションの有効期間中はそのスロットに"固定"されます。固定されているスロットを確認するには、HTTPヘッダー内の`x-ms-routing-name`クッキーを調べることでわかります。

#### ルーティング要求
`x-ms-routing-name=`のクッキーの設定により、以下のスロットにルーティング要求されます。
- `staging`の場合、ステージングスロット
- `self`の場合、運用スロット

### 手動でルーティング
`x-ms-routing-name`クエリパラメーターを使用することで、特定のスロットに要求をルーティングすることができます。
```HTML:HTML
<a href="<webappname>.azurewebsites.net/?x-ms-routing-name=self">Go back to production app</a>
```
:::note info
手動ルーティングを使用することで、内部チームにスロットでの変更テストを許可する一方で、ステージングスロットをパブリックから非表示にすることができます。
:::

# おわりに
App Serviceを勉強するほど、良さがわかってきて楽しく学べました。AZ-204の試験ではApp Serviceは重要な項目なので、細かいところまで理解しようと思います。