【Azure】Bicepを用いてテンプレートをモジュール化してみる

# 1. はじめに
### 1-1 ご挨拶
初めまして、井村と申します。
今更ですが Azure リソースをデプロイするドメイン固有言語 (DSL) であるBicepが使いやすいそうです。その為、mslearnを用いて勉強をしてみました。Bicepはテンプレートを分割してモジュール化し、管理することができます。実際に分割してテンプレートを作成します。

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

### 1-3 成果物
Bicepテンプレートを作成し、成果物としては下図の通り App Service を作成します。勤怠管理システム、財務会計システムをそれぞれ PaaSのwebサービスとして作成するイメージです。
※App Service plan とは App Service を動かすための実行基盤です。

ポイントは２点です。
・Bicep テンプレートはモジュール化し作成
・なるべくシンプルに作成



<img width="400" alt="システム構成図.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/254f69b8-a57d-eeaa-e0ff-e1ded563637e.png">

**図1 システム構成**

※事前にAzureアカウントは作成済みです。Azure CLI、Bicepはインストール済みです。

# 2. テンプレートの構成について
何をモジュール化するかについては色々と考え方はあると思いますが、私は App Service と App Service plan のデプロイ部分を共通化します。パラメータ部分を勤怠管理システム、財務会計システムそれぞれ作成します。
ローカル端末にBicepテンプレートを作成する際のディレクトリ構成は以下の通りです。


<img width="400" alt="directry2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/8f4355eb-2d1c-d898-6b2e-952c47f6ba39.png">

**図2 ディレクトリ構成**

各サービスの名前やスペックはシステム毎に違う場合がありますのでパラメータ化し、パラメータ化した情報を共通化したテンプレートの引数として利用します。

# 3. 構築
それでは、構築始めます。リソースグループはAzure CLIで作成します。
### 3-1 リソースグループの作成

```bash:bash
# Azureへログイン
az login

#変数宣言
myResourceGroupKintai=kintai-rg
myResourceGroupZaimu=zaimu-rg
location=japaneast

# 勤怠管理システム用リソースグループの作成
az group create -l $location -n $myResourceGroupKintai

# 財務会計システム用リソースグループの作成
az group create -l $location -n $myResourceGroupZaimu
```
図1 システム構成の黄緑色枠であるリソースグループを作成しました。

### 3-2 Bicep テンプレートの作成(モジュール化)
最初にデプロイ部分を共通化したBicepテンプレートになります。
図2 ディレクトリ構成で表した通り、modulesディレクトリ内に 共通化したBicepテンプレートである "common_app.bicep" を作成します。 
Bicepテンプレートを作成するときは、Visual Studio CodeにBicep拡張機能をインストールして作成するのが便利です。

![bicep_template_common_app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/4b1fad90-aa39-a20e-ce9e-60e53e1b4975.png)

**図3 common_app.bicep**

上記Bicepテンプレート少し解説します。
2 - 11行目は後にAzureサービスをデプロイする為に必要なパラメータ名を定義しています。
14 - 20行目は App Service plan をデプロイする記述です。
15行目は App Service plan の名前です。★commonAppServicePlanName
16行目は App Service plan をデプロイするリージョンです。★location
18行目は App Service plan のsku（簡単にいうと実行基盤のスペック）です。★commonAppServicePlanSkuName
23 - 30行目は App Service をデプロイする記述です。
24行目は App Service の名前です。★commonAppServiceAppName
25行目は App Service をデプロイするリージョンです。★location
27行目は App Service の実行基盤である App Service plan の情報を取得しています。

上記にわざとらしく記載した★達に具体的な値を入れる必要があります。★達は勤怠管理システム、財務会計システムを構築する際に同じ値にはならないと思いますし、そもそもAzureの仕様で世界で一意にすべき値だったりします。
★達は勤怠管理システム、財務会計システムのメインテンプレートで後述記載いたします。

※今回リージョンは東日本リージョンで同様の値にしていますが、災対を考慮して西日本リージョンに作成したり、世界中に支社がある場合はその拠点に作成することもあります。

### 3-3 Bicep テンプレートの作成(メインテンプレート)
それでは勤怠管理システム、財務会計システムのメインテンプレートを以下に記載いたします。
勤怠管理システムは "kintai_main.bicep"、財務会計システムは "zaimu_main.bicep"とし "Templates"ディレクトリ配下に格納しています。

![main_template.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/7f0dd272-2d97-94bb-342f-f147ad5781ce.png)

**図4 main.bicep**

上記Bicepテンプレート少し解説します。
左のテンプレートが勤怠管理システム、右のテンプレートが財務会計システムになります。差異としては3行目のシステムコード、12行目の App Service plan のskuです。

2 - 15行目は後にAzureサービスをデプロイする為に必要なパラメータ名を定義しています。具体的な値が入力されていますね。
18 - 26行目は共通化したテンプレートへパラメータを引き渡すしています。
21行目は 上記で定義した具体的な値を ★commonAppServiceAppName へ引き渡しています。
22行目は 上記で定義した具体的な値を ★commonAppServicePlanName へ引き渡しています。
23行目は 上記で定義した具体的な値を ★commonAppServicePlanSkuName へ引き渡しています。
24行目は 上記で定義した具体的な値を ★location へ引き渡しています。

これにて App Service および App Service plan のデプロイ準備が整いました。それではデプロイしましょう。

### 3-4 App Service および App Service plan の作成
以下コマンドをbashで実行します。

```bash:bash
# Azureへログイン
az login

#変数宣言
myResourceGroupKintai=kintai-rg
myResourceGroupZaimu=zaimu-rg
location=japaneast

# bicepファイルがあるディレクトリへ移動
cd templates

# 勤怠管理システム用の app service および app service plan 作成
az deployment group create --resource-group $myResourceGroupKintai --template-file kintai_main.bicep

# 財務会計システム用の app service および app service plan 作成
az deployment group create --resource-group $myResourceGroupZaimu --template-file zaimu_main.bicep

```

# 4. 確認

### 4-1 勤怠管理システム用のリソースグループ

![kintai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/2fe10430-dad9-5baa-d3e3-e3eb0144586a.png)

リージョンはリソースグループと同様の東日本リージョンです。
App Service の名前は "app-kintai"です。
App Service plan の名前は "plan-kintai"です。
想定通りですね。

### 4-2 勤怠管理システム用の App Service plan の sku

![F1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/c0a12ee9-c488-00b6-2459-4e59d17c0009.png)

App Service plan のskuは "F1"です。
想定通りですね。

### 4-3 財務会計システム用のリソースグループ

![zaimu-rg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/6fdeb493-09f0-843f-eacf-97ec730476d1.png)

リージョンはリソースグループと同様の東日本リージョンです。
App Service の名前は "app-zaimu"です。
App Service plan の名前は "plan-zaimu"です。
想定通りですね。

### 4-4 財務会計システム用の App Service plan の sku

![D1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/0fec119f-977a-3674-d30a-de4d3ebe816d.png)

App Service plan のskuは "D1"です。
想定通りですね。

# 5. その他

### 5-1 具体的な値の流れ
時間経つと私が忘れてしまう為、備忘録として載せます。

![5-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/1329fea3-7f44-ef98-d4f8-02394b52d83d.png)

### 5-2 各Bicepテンプレート
サンプルコードを以下に記述します。

<details><summary>common_app.bicep</summary>

```bicep:bicep
@description('リソースをデプロイする Azure リージョン')
param location string

@description('App Service アプリの名前')
param commonAppServiceAppName string

@description('App Service プランの名前')
param commonAppServicePlanName string

@description('App Service プラン SKU の名前')
param commonAppServicePlanSkuName string

@description('App Service プラン のデプロイ')
resource appServicePlan 'Microsoft.Web/serverfarms@2021-01-15' = {
  name: commonAppServicePlanName
  location: location
  sku: {
    name: commonAppServicePlanSkuName
  }
}

@description('App Service のデプロイ')
resource appServiceApp 'Microsoft.Web/sites@2021-01-15' = {
  name: commonAppServiceAppName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
  }
}

```
</details>


<details><summary>kintai_main.bicep</summary>

```bicep:bicep
// 勤怠管理システム
@description('システムコード')
param systemCode string = 'kintai'

@description('リソースをデプロイする Azure リージョン')
param location string = resourceGroup().location

@description('App Service アプリの名前')
param appServiceAppName string = 'app-${systemCode}'

@description('App Service プラン SKU の名前')
param appServicePlanSkuName string = 'F1'

@description('App Service プラン SKU の名前')
param appServicePlanName string = 'plan-${systemCode}'

@description('「common_app.bicep」ファイルへモジュール宣言')
module app 'modules/common_app.bicep' = {
  name: 'hogehoge-app'
  params: {
    commonAppServiceAppName: appServiceAppName
    commonAppServicePlanName: appServicePlanName
    commonAppServicePlanSkuName: appServicePlanSkuName
    location: location
  }
}

```
</details>

<details><summary>zaimu_main.bicep</summary>

```bicep:bicep
// 財務会計システム
@description('システムコード')
param systemCode string = 'zaimu'

@description('リソースをデプロイする Azure リージョン')
param location string = resourceGroup().location

@description('App Service アプリの名前')
param appServiceAppName string = 'app-${systemCode}'

@description('App Service プラン SKU の名前')
param appServicePlanSkuName string = 'D1'

@description('App Service プラン SKU の名前')
param appServicePlanName string = 'plan-${systemCode}'

@description('「common_app.bicep」ファイルへモジュール宣言')
module app 'modules/common_app.bicep' = {
  name: 'hogehoge-app'
  params: {
    commonAppServiceAppName: appServiceAppName
    commonAppServicePlanName: appServicePlanName
    commonAppServicePlanSkuName: appServicePlanSkuName
    location: location
  }
}

```
</details>


### 5-3 required-propertiesについて
以下にスクショを並べているのですが、見てわかる通り、予測変換でサクサク作成することができます。
そして、"required-properties"を選択すると、、、

![kintai_1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/ce4baa5c-dfe7-33ac-2c3f-4b388a4e78db.png)

![kintai_1_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/a6cc628a-8ffd-21d5-fca9-6d3cadf7b314.png)

![kintai_1_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/09061149-1276-20be-7aa4-27e3af7ad46c.png)

![kintai_1_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/2de156b6-c326-7154-f008-adc0841a8f55.png)

![kintai_1_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/ca4685a8-6fe7-6cb2-7f73-192352221574.png)

なんと、共通化テンプレート側を読み込んで、値入力が必須となる★達が表示されました。
正直今回記事を書いた目的は、この機能にすげーって思ったので書きました 笑


# 6. おわりに
本記事を最後まで読んで頂きましてありがとうございます。
モジュール化のメリットは先駆者様の記事を拝見し、可読性の向上だなと思いました。
可読性が向上するとバクの調査がしやすいことでしょうかね。


# 7. 参考記事
-  [演習 - モジュールの作成と使用](https://learn.microsoft.com/en-us/training/modules/create-composable-bicep-files-using-modules/4-exercise-create-use-module?pivots=cli)