【Azure】Bicepを用いてApp Service planの自動スケールアウト、スケールイン設定を作成する。

# 1. はじめに
### 1-1 ご挨拶
初めまして、井村と申します。
AzureのBicepを用いてApp Service plan、web APPを作成後、スケールアウト、スケールインの動作確認を行いました。

Bicepの練習がてら丁度いいなと思いテンプレートファイル作成を試行錯誤していたのですが、[公式ドキュメント](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/scenarios-monitoring#autoscale-rules)にほぼほぼやりたいことがありました。ので、こちら参考にして作成しました。
※試行錯誤した過程が大事だと信じたい。。

### 1-2 対象読者
- Azureに興味がある
- Bicepに興味がある

# 2. 構築
### 2-1 フォルダ構成
今回作成したBicepファイルは階層型にしています。「main.bicep」ファイルにパラメーターを記述し「module」フォルダ配下にあるAzureリソースを作成するモジュールファイルへパラメーターを渡します。

```
.
├── main.bicep
└── modules
    └── asp.bicep
```

### 2-2 main.bicep構成
利用するBicepテンプレートは以下になります。
[Github](https://github.com/hawk0722/Azure_Bicep_05_Webapp-windows)にあげてます。

<details><summary>main.bicep</summary>

```bicep:bicep

     1  targetScope = 'subscription'
     2
     3  // Parameters for common
     4  param location string = 'japaneast'
     5  param systemCode string = 'imura3'
     6  param env string = 'dev'
     7
     8  // Parameters for resorce group
     9  param resourceGroupName string = 'rg-${systemCode}-${env}'     
    10
    11  // Parameters for app service plan
    12  param sku string = 'S1'
    13
    14  // deploy resource groups.
    15  resource rg 'Microsoft.Resources/resourceGroups@2022-09-01' = {
    16    name: resourceGroupName
    17    location: location
    18  }
    19
    20  // deploy app service plan.
    21  module asp 'modules/asp.bicep' = {
    22    scope: rg
    23    name: 'Deploy_app_service_plan'
    24    params: {
    25      location: location
    26      systemCode: systemCode
    27      env: env
    28      sku: sku
    29    }
    30  }

```
</details>

補足は以下の通りです。
- 1行目の「target.scope」について今回のファイルはリソースグループを作成するため変更しています。
- 4行目から12行目の「param」でパラメーターを定義します。
- 15行目の「resource」でリソースグループを作成します。
- 21行目の「module」で「modules」フォルダのファイルへパラメーターを渡します。
- 12行目の”S1”はweb appの標準プランになります。標準以下の無料プラン、共有プランでは自動スケール機能は利用できないプランとなります。詳細は[こちら](https://azure.microsoft.com/ja-jp/pricing/details/app-service/windows/)


### 2-3 asp.bicep構成
利用するBicepテンプレートは以下になります。
「asp.bicep」ファイルはApp Service plan、web app、スケール設定を作成するファイルになります。

<details><summary>asp.bicep</summary>

```bicep:bicep
     1  @description('Location for all resources.')
     2  param location string
     3
     4  @description('System code')
     5  param systemCode string
     6
     7  @description('Environment')
     8  param env string
     9
    10  @description('Name of app service plan')
    11  param aspName string = 'asp-${systemCode}-${env}'
    12
    13  @description('Usage tiers of app service plan')
    14  @allowed([
    15    'F1'
    16    'D1'
    17    'B1'
    18    'B2'
    19    'B3'
    20    'S1'
    21    'S2'
    22    'S3'
    23    'P1'
    24    'P2'
    25    'P3'
    26    'P4'
    27  ])
    28  param sku string
    29
    30  @description('Name of web apps')
    31  param appName string = 'app-${systemCode}-${env}'
    32
    33  @description('arrangement of Scale out condition')
    34  param args array = [
    35    {
    36      direction: 'Increase'
    37      operator: 'GreaterThan'
    38      threshold: 70
    39    }
    40    {
    41      direction: 'Decrease'
    42      operator: 'LessThan'
    43      threshold: 30
    44    }
    45  ]
    46
    47  var rules = [for arg in args: {
    48    scaleAction: {
    49      cooldown: 'PT5M' // 5 minutes
    50      direction: arg.direction
    51      type: 'ChangeCount'
    52      value: '1'
    53    }
    54    metricTrigger: {
    55      metricName: 'CpuPercentage'
    56      metricResourceUri: asp.id
    57      operator: arg.operator
    58      statistic: 'Average'
    59      threshold: arg.threshold
    60      timeAggregation: 'Average'
    61      timeGrain: 'PT1M'
    62      timeWindow: 'PT10M'
    63    }
    64  }]
    65
    66  @description('Deploy app service plan.')
    67  resource asp 'Microsoft.Web/serverfarms@2022-03-01' = {
    68    name: aspName
    69    location: location
    70    sku: {
    71      name: sku
    72      capacity: 1
    73    }
    74  }
    75
    76  @description('Deploy web app.')
    77  resource app 'Microsoft.Web/sites@2022-03-01' = {
    78    name: appName
    79    location: location
    80    properties: {
    81      serverFarmId: asp.id
    82      httpsOnly: true
    83      siteConfig: {
    84        windowsFxVersion: 'DOTNET|4.7'
    85      }
    86    }
    87  }
    88
    89  resource ass 'Microsoft.Insights/autoscalesettings@2022-10-01' = {
    90    name: asp.name
    91    location: location
    92    properties: {
    93      enabled: true
    94      profiles: [
    95        {
    96          name: 'Scale out condition'
    97          capacity: {
    98            default: '1'
    99            maximum: '2'
   100            minimum: '1'
   101
   102          }
   103          rules: rules
   104        }
   105      ]
   106      targetResourceLocation: location
   107      targetResourceUri: asp.id
   108    }
   109  }
```
</details>

補足は以下の通りです。
- 2行目から64行目の「param」でパラメーター、「var」で変数を定義します。
- 67行目の「resource」でApp Service planを作成します。
- 77行目の「resource」でWeb appを作成します。
- 90行目の「resource」でスケール設定を作成します。

スケールアウト・インの設定値は同じ値を利用する箇所が多い為、差分を配列に格納しています。ループ処理を変数に代入し、デプロイ処理はスッキリ見やすくしています。
- 配列処理：34行目から45行目。
- ループ処理：47行目から64行目。
- デプロイ処理：103行目。

# 3. 検証
### 3-1 リソースの構築
ロケーションを変更し下記コマンドを実行すると構築完了です。

```cmd:cmd (Azure CLI)
$ ls
main.bicep  modules

$ az login

$ az deployment sub create --template-file main.bicep --location <Your location>
```

今回デプロイしたスケールアウト、スケールインの条件は以下になります。
- スケールアウト：10 分間で平均 CPU 消費量の 70% を超えた場合、自動スケール エンジンは 1 つのインスタンスを追加します。
- スケールイン：10 分間で平均 CPU 消費量の 30% を下回った場合、自動スケール エンジンは 1 つのインスタンスを削除します。

デプロイ直後はCPU消費量が低いため１つのインスタンスになります。下記画像の「観察されたリソースのインスタンス数」が1です。

|![1.a_instance.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/b6150d05-7486-2ef6-b675-d3feb0ad7a1a.png)|
|:-:|

### 3-2 スケールの検証
それでは検証を実施します。web appの開発ツールであるKudoを利用します。KudoからPowershellを起動し、以下の無限ループを実行してCPU負荷をあげます。
[Kudoの使い方](https://learn.microsoft.com/ja-jp/training/modules/azure-diagnose-application-startup-errors-with-kudu-console/)

```Powershell:Powershell
while ($true) {}
```
しばらくすると下記画像のようにCPUが100%ではりつきます。

|![asp-100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/3fe3152e-bca2-2fca-d2ae-ef1f25fea9b0.png)|
|:-:|

スケールアウトの条件を満たすと以下画像のように「観察されたリソースのインスタンス数」が2に変更されます。

|![asp-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/09b03b32-ae53-d3dc-9b3b-342a06f89353.png)|
|:-:|

無限ループを解除し、しばらくすると「観察されたリソースのインスタンス数」が1に戻ります。

|![asp-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/15d1c741-50b7-11fa-2a73-9f545aa1d7f0.png)|
|:-:|

上記とは別日ですが検証結果を以下画像にまとめています。項目は時間、CPU数、while文の起動・停止、インスタンス数です。while文の起動・停止後、大体10分経つとスケールアウト・インしているのがわかります。

![table.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/ddef8420-fbae-4a22-44be-6f0d883b90b9.png)

# 4. 終わりに
本記事を最後まで読んで頂きましてありがとうございます。
PaaSサービスのweb appは他にも様々な機能があります。ぜひ試してみてください。

# 5. 参考記事
- [自動スケール ルール](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/scenarios-monitoring#autoscale-rules)
- [Microsoft.Web sites](https://learn.microsoft.com/en-us/azure/templates/microsoft.web/sites?pivots=deployment-language-bicep)
- [webapp-basic-windows](https://github.com/Azure/azure-quickstart-templates/blob/master/quickstarts/microsoft.web/webapp-basic-windows/main.bicep)
- [Bicep を使用して App Service アプリを作成する](https://learn.microsoft.com/ja-jp/azure/app-service/provision-resource-bicep)
- [whileを使って無限ループ](https://win.just4fun.biz/?PowerShell/PowerShell%E3%81%A7%E7%84%A1%E9%99%90%E3%83%AB%E3%83%BC%E3%83%97%E3%83%BBwhile#eeaccc48)
- [Microsoft.Insights autoscalesettings](https://learn.microsoft.com/en-us/azure/templates/microsoft.insights/autoscalesettings?pivots=deployment-language-bicep)