AzureのBicepが便利な件について

Azureで***Bicep***という用語を聞いたことがあるでしょうか？

*Bicep*はARMテンプレート(リソースをJson形式で記述しているファイル)が生成される前のファイルです。

テンプレートのエクスポートはBicep → コンパイル　→　ARMの処理がAzureでは行われています。以前までpreviewでしたが正式にリリースされました。

Bicepは***ARMテンプレート***や***Terraform***よりコードの可視性、依存関係が圧倒的に分かりやすいです。自分はインフラのアーキ検討で自動生成させたり、DevOpsのパイプライン処理で重宝しています。



# ①インストール手順
まずAzure CLI のバージョン 2.20.0 以降が必要になります。
インストール手順は下記参照です。
https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli-windows?tabs=azure-cli

Azure CLIのバージョンを確認します。
`az --version`
![スクリーンショット 2022-08-14 113739.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/df63f781-a647-923c-4c73-0f68ab4c9922.png)


Bicepをインストールします。
`az bicep install`
![スクリーンショット 2022-08-14 114119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/2197b431-fee1-8b88-da15-3eef4af4d83d.png)


Bicepのバージョンを確認します。
`az bicep version`
![スクリーンショット 2022-08-14 114309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/0c225489-87e8-f8a4-697f-3856b2e2f068.png)


# ②文法
例としてストレージアカウントを生成するbicepファイルです。
詳細なパラメーターは以下参照してください。
https://docs.microsoft.com/en-us/azure/templates/microsoft.storage/storageaccounts?pivots=deployment-language-bicep

```
//----------パラメーター設定 開始--------------

//param storageSccountType変数の説明するアノテーションになります
@description('Storage Account type')

//param storageSccountType変数に入れられる値を制限します。
@allowed([
  'Premium_LRS'
  'Premium_ZRS'
  'Standard_GRS'
  'Standard_GZRS'
  'Standard_LRS'
  'Standard_RAGRS'
  'Standard_RAGZRS'
  'Standard_ZRS'
])

//パラメーターを変数として定義してます。
//param 変数名 オブジェクト型
param storageAccountType string = 'Standard_LRS'

//resurceGroup().locationはコマンド実行時に指定するリソースグループと同じリージョンを取得する関数になります。
@description('Location for the storage account.')
param location string = resourceGroup().location

//uniqueStringはハッシュ文字列を生成します。
@description('The name of the Storage Account')
param storageAccountName string = 'store${uniqueString(resourceGroup().id)}'

//----------パラメーター設定　終了--------------


//ストレージアカウントのリソース生成を指定します。
//resource リソース生成後の変数名　'Microsoftが提供しているサービス名'
resource stg 'Microsoft.Storage/storageAccounts@2021-06-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: storageAccountType
  }
    kind: 'StorageV2'
    properties: {}
　　　　}
```



上記ファイルをVisual Stadio Codeでbicepファイルを生成します。
拡張機能でBicepを検索してインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/66bdd3a5-44a3-1bae-ac8b-76fa45e1b301.png)


使用されていない変数が存在する、指定パラメーターに誤りがあると警告してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/a65895ad-f3e5-da53-8712-08c2181dcd68.png)


名前を付けて任意フォルダに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/264c899a-c431-9ef3-3e5f-d924df4f6dd9.png)


PowerShellを起動して、main.bicepを保存したフォルダに移動します。そしてbicepファイルからデプロイするコマンドを実行します。
`cd "C:\Users\*****\OneDrive\ドキュメント\qiita材料\main.bicepがあるフォルダ"`

リソースグループは生成したい場所を指定します。
`az deployment group create --resource-group test_group --template-file main.bicep`

デプロイが完了するとJsonが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/83572357-d3b0-131f-2c40-428d5c7a2cb8.png)


生成されていることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/19682eaa-8083-7173-fd34-869b956c0dad.png)

VScode上で右クリックして、メニューから「Deploy Bicep File」からでもデプロイが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/053fcc50-e4f7-487e-7755-bc63b221064e.png)



# ③便利コマンド・その他機能

#### ・デプロイ前のチェック

他の機能として***Trraform***の***plan***のようにデプロイ前にチェックすることが出来ます。
`az deployment group what-if --resource-group (デプロイするリソースグループ) --template-file (bicepファイル)`


![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323735323238382f62316164663566322d616662632d393330342d303638642d3330373961383536.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/47f41495-e0c9-5191-30a5-8e4e93398a44.png)
上記画像では4つのリソースが新たに作成され、既存の２つのリソースは無視することを示しています。

#### ・デプロイ中や詳細のチェック
リソースグループの設定にあるデプロイからBicepファイルのデプロイ状況が分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/ac0e3a3b-ebbc-3c46-32de-1b2782a0f382.png)


#### ・ARMテンプレートからのデコンパイル
ARMテンプレートからBicepファイルに変換が出来ます。

テンプレートのエクスポートでJsonファイルをダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/07c5744e-c567-dcec-1cd7-bd7dc9ba8e67.png)

template.json
``` 
{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "storageAccounts_storeii74qbr62sx4u_name": {
            "defaultValue": "storeii74qbr62sx4u",
            "type": "String"
        }
    },
    "variables": {},
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2021-09-01",
            "name": "[parameters('storageAccounts_storeii74qbr62sx4u_name')]",
            "location": "japanwest",
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "kind": "StorageV2",
            "properties": {
                "minimumTlsVersion": "TLS1_0",
                "allowBlobPublicAccess": true,
                "networkAcls": {
                    "bypass": "AzureServices",
                    "virtualNetworkRules": [],
                    "ipRules": [],
                    "defaultAction": "Allow"
                },
                "supportsHttpsTrafficOnly": true,
                "encryption": {
                    "services": {
                        "file": {
                            "keyType": "Account",
                            "enabled": true
                        },
                        "blob": {
                            "keyType": "Account",
                            "enabled": true
                        }
                    },
                    "keySource": "Microsoft.Storage"
                },
                "accessTier": "Hot"
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/blobServices",
            "apiVersion": "2021-09-01",
            "name": "[concat(parameters('storageAccounts_storeii74qbr62sx4u_name'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccounts_storeii74qbr62sx4u_name'))]"
            ],
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "properties": {
                "cors": {
                    "corsRules": []
                },
                "deleteRetentionPolicy": {
                    "allowPermanentDelete": false,
                    "enabled": false
                }
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/fileServices",
            "apiVersion": "2021-09-01",
            "name": "[concat(parameters('storageAccounts_storeii74qbr62sx4u_name'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccounts_storeii74qbr62sx4u_name'))]"
            ],
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "properties": {
                "protocolSettings": {
                    "smb": {}
                },
                "cors": {
                    "corsRules": []
                },
                "shareDeleteRetentionPolicy": {
                    "enabled": true,
                    "days": 7
                }
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/queueServices",
            "apiVersion": "2021-09-01",
            "name": "[concat(parameters('storageAccounts_storeii74qbr62sx4u_name'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccounts_storeii74qbr62sx4u_name'))]"
            ],
            "properties": {
                "cors": {
                    "corsRules": []
                }
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/tableServices",
            "apiVersion": "2021-09-01",
            "name": "[concat(parameters('storageAccounts_storeii74qbr62sx4u_name'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccounts_storeii74qbr62sx4u_name'))]"
            ],
            "properties": {
                "cors": {
                    "corsRules": []
                }
            }
        }
    ]
}
``` 

下記コマンドを実行すると、今参照しているディレクトリにbicepファイルが生成されます。
読み取り専用パラメータも含まれているので、またBicepでデプロイする際は注意です。
`az bicep decompile --file (ARMテンプレートのJsonファイル)`

template.bicep
``` 
param storageAccounts_storeii74qbr62sx4u_name string = 'storeii74qbr62sx4u'

resource storageAccounts_storeii74qbr62sx4u_name_resource 'Microsoft.Storage/storageAccounts@2021-09-01' = {
  name: storageAccounts_storeii74qbr62sx4u_name
  location: 'japanwest'
  sku: {
    name: 'Standard_LRS'
    tier: 'Standard'
  }
  kind: 'StorageV2'
  properties: {
    minimumTlsVersion: 'TLS1_0'
    allowBlobPublicAccess: true
    networkAcls: {
      bypass: 'AzureServices'
      virtualNetworkRules: []
      ipRules: []
      defaultAction: 'Allow'
    }
    supportsHttpsTrafficOnly: true
    encryption: {
      services: {
        file: {
          keyType: 'Account'
          enabled: true
        }
        blob: {
          keyType: 'Account'
          enabled: true
        }
      }
      keySource: 'Microsoft.Storage'
    }
    accessTier: 'Hot'
  }
}

resource storageAccounts_storeii74qbr62sx4u_name_default 'Microsoft.Storage/storageAccounts/blobServices@2021-09-01' = {
  parent: storageAccounts_storeii74qbr62sx4u_name_resource
  name: 'default'
  sku: {
    name: 'Standard_LRS'
    tier: 'Standard'
  }
  properties: {
    cors: {
      corsRules: []
    }
    deleteRetentionPolicy: {
      allowPermanentDelete: false
      enabled: false
    }
  }
}

resource Microsoft_Storage_storageAccounts_fileServices_storageAccounts_storeii74qbr62sx4u_name_default 'Microsoft.Storage/storageAccounts/fileServices@2021-09-01' = {
  parent: storageAccounts_storeii74qbr62sx4u_name_resource
  name: 'default'
  sku: {
    name: 'Standard_LRS'
    tier: 'Standard'
  }
  properties: {
    protocolSettings: {
      smb: {
      }
    }
    cors: {
      corsRules: []
    }
    shareDeleteRetentionPolicy: {
      enabled: true
      days: 7
    }
  }
}

resource Microsoft_Storage_storageAccounts_queueServices_storageAccounts_storeii74qbr62sx4u_name_default 'Microsoft.Storage/storageAccounts/queueServices@2021-09-01' = {
  parent: storageAccounts_storeii74qbr62sx4u_name_resource
  name: 'default'
  properties: {
    cors: {
      corsRules: []
    }
  }
}

resource Microsoft_Storage_storageAccounts_tableServices_storageAccounts_storeii74qbr62sx4u_name_default 'Microsoft.Storage/storageAccounts/tableServices@2021-09-01' = {
  parent: storageAccounts_storeii74qbr62sx4u_name_resource
  name: 'default'
  properties: {
    cors: {
      corsRules: []
    }
  }
}
``` 

今回はストレージアカウントを例にしていますが、
```` 
parent: storageAccounts_storeii74qbr62sx4u_name_resource
````
とあります。

これはストレージアカウントとBlobコンテナー等の作成が親子関係にあることを明示しています。
他の例としてVNET、Subnetも親子関係となります。

bicepではこのparentを明示することで依存関係を解決してデプロイを行います。

また生成されたリソースのデプロイ名.idを他リソースに指定することでも自動的に依存関係を解消出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/6d292bc3-b1b6-268a-b288-5702e0f774fb.png)

#### ・既存リソースの指定
既にデプロイされているリソースを指定したい場合、`existing`を使用します。
以下はデプロイされているSynapseのサービスプリンシパルをKeyVaultのアクセスポリシーに指定している例になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2752288/50079777-6274-f08b-1b82-fdbe42e289aa.png)



#### ・モジュール化
メインファイルを作成して、それぞれのモジュールからリソースをデプロイすることも出来ます。

main.bicep
``` 
// module デプロイ後の変数名 '参照するbicepファイルパス'
module storage_d 'storage.bicep' = {

// name: はデプロイ名
// paramsは参照先のモジュール内の変数に渡したい値を指定します。

  name: 'myStorageDeployment'
  params: {
    storageAccountName: 'stcontoso'
　　storageAccountType: 'Standard_LRS'
  }
}

//storage_d.output.stgIdで下記storage.bicepファイルのoutputで指定した変数が使用出来ます。

``` 

storage.bicep
``` 

//main.bicepから受け取るパラメーターの変数
param storageAccountType string
param storageAccountName string
param location string = resourceGroup().location

resource stg 'Microsoft.Storage/storageAccounts@2021-06-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: storageAccountType
  }
    kind: 'StorageV2'
    properties: {}
　　　　}

//デプロイ後のリソースIdをstgIdにセットすることでmain.bicepから参照できます。
output stgId string = stg.id
``` 

#### ・パラメータシートの使用
--parametersを追記して以下の形式のjsonファイルを作成して使用します。

`az deployment group what-if --resource-group (デプロイするリソースグループ) --template-file (bicepファイル) --parameters (json形式のファイル)`

parameter.json
````
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "bicepパラメーター変数名": {
            "value": "変数値"
        },
        "location": {
            "value": "japanwest"
        }
    }
}
````

main.bicep
````
param location string
````

bicep内のparam location string = 'japaneast'にして、パラメーターシートで'japanwest'でデプロイしてオーバーライドするような使用方法も可能です。

#### ・代替コマンド
azコマンドで実行すると文字コードエラーが発生する場合があります(azはPython言語で構成されている)。その際には以下のコマンドレットで実行できることがあります(以下はPowerShell言語で構成)。

実行前確認コマンド
`New-AzResourceGroupDeployment -WhatIf -ResourceGroupName リソースグループ名 -TemplateFile bicepファイルパス -TemplateParameterFile パラメーターjsonファイル`

デプロイコマンド
`New-AzResourceGroupDeployment -ResourceGroupName リソースグループ名 -TemplateFile bicepファイルパス -TemplateParameterFile パラメーターjsonファイル`

# ④リファレンス
MicrosoftのBicepドキュメントです。
ARMで使用されている関数も利用できます。
https://docs.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/

クイックスタートを公開されているgithubになります。Bicep記述が非常に参考になります。
https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts


これで以上となります。
見て頂きありがとうございました。