Infrastructure as Code を Azure で実現してみた

# 1.はじめに
最近クラウドサービスが普及して、 Infrastructure as Codeという考え方が当たり前になりつつあるようです。
AWS では CloudFormation というサービスで インフラをコード化、デプロイすることができます。
私もAWSではCloudFormationを使用していました。

一方、Azure においてのインフラコード化サービスは使用したことがなかったので、
今回諸々と触ってみました。

# 2.Infrastructure as Code とは

Infrastructure as Code とは、インフラ構成をコード化しておこうという考え方のことです。
インフラ構成をコード化しておくことにより、以下のようなメリットがあります。

・複数環境(開発/検証/本番環境など)がすぐに構築できる
・手入力によるミスがなくなる
・各サービスの詳細のパラメータが知れる(仕組みに着目できる)
・詳細設計書と同等のドキュメントとして扱える

ただこのメリットを受容するためには、インフラ構築をするメンバー全員がコードを書く必要があります。
そのため、学習コストがかかります。

# 3.Azure Resource Manager テンプレート

公式ドキュメントを参照すると以下がテンプレートの形式です。

~~~JSON
{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "",
  "apiProfile": "",
  "parameters": {  },
  "variables": {  },
  "functions": [  ],
  "resources": [  ],
  "outputs": {  }
}
~~~

こちらの"$schema"と"contentVersion"にそれぞれのバージョンの値を記載し、
"resources"内に各リソースのパラメータを指定し、テンプレートを流すとAzureのリソースができます。

"parameters"に環境情報の入力をさせると1つのテンプレートで複数環境構築が可能となり、"variables"には変数を入力することができます。

実際にどのようになるのかweb apps で試してみます。

# 4.web appsで実践してみた

今回は、開発環境・検証環境・本番環境の3環境向けに Web Apps の構築が可能なテンプレートを作成していきます。

実際のコードを以下に記載します。
テストコードのため、web apps は全環境でFreeサイズになっています。

~~~JSON
{
   "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
   "contentVersion": "1.0.0.0",
   "parameters": {
       "ENV": {
           "type": "string",
           "allowedValues": ["dev","stg", "pro"],
           "metadata": {
             "description": "環境設定 dev:開発用 stg:検証用 pro:本番用"
           
       
   },
   "variables": {
       "settings": {
           "dev": {
             "name": "dev",
             "location": "Japan East",
             "description": "開発環境",
             "appservice_plan": {
               "name": "F1",
               "tier": "Free",
               "size": "F1",
               "family": "F",
               "capacity": 0
             
           },
           "stg": {
               "name": "stg",
               "location": "Japan East",
               "description": "検証環境",
               "appservice_plan": {
                 "name": "F1",
                 "tier": "Free",
                 "size": "F1",
                 "family": "F",
                 "capacity": 0
               
             },
           "pro": {
             "name": "pro",
             "location": "Japan East",
             "description": "本番環境",
             "appservice_plan": {
               "name": "F1",
               "tier": "Free",
               "size": "F1",
               "family": "F",
               "capacity": 0
             
           
   },
   "sites_server_name": "[concat('webapp-jw-', variables('settings')[parameters('ENV')].name, '-1')]",
   "appservice_plan_name": "[concat('appserviceplan-jw-', variables('settings')[parameters('ENV')].name, '-1')]"
},
   "resources": [
       
           "comments": "共通のAppServiceプラン",
           "type": "Microsoft.Web/serverfarms",
           "apiVersion": "2018-02-01",
           "name": "[variables('appservice_plan_name')]",
           "location": "[variables('settings')[parameters('ENV')].location]",
           "sku": "[variables('settings')[parameters('ENV')].appservice_plan]",
           "kind": "app",
           "properties": {
               "name": "[variables('appservice_plan_name')]",
               "perSiteScaling": false,
               "reserved": false,
               "targetWorkerCount": 0,
               "targetWorkerSizeId": 0
           
       },
       
           "comments": "Web Server",
           "type": "Microsoft.Web/sites",
           "apiVersion": "2018-02-01",
           "name": "[variables('sites_server_name')]",
           "location": "[variables('settings')[parameters('ENV')].location]",
           "kind": "app",
           "properties": {
               "enabled": true,
               "hostNameSslStates": [
                 
                   "name": "[concat(variables('sites_server_name'),'.azurewebsites.net')]",
                   "sslState": "Disabled",
                   "virtualIP": null,
                   "thumbprint": null,
                   "toUpdate": null,
                   "hostType": "Standard"
                 },
                 
                   "name": "[concat(variables('sites_server_name'),'.scm.azurewebsites.net')]",
                   "sslState": "Disabled",
                   "virtualIP": null,
                   "thumbprint": null,
                   "toUpdate": null,
                   "hostType": "Repository"
                 
                 ],
               "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appservice_plan_name'))]",
               "reserved": false,
               "scmSiteAlsoStopped": false,
               "hostingEnvironmentProfile": null,
               "clientAffinityEnabled": true,
               "clientCertEnabled": false,
               "hostNamesDisabled": false,
               "containerSize": 0,
               "dailyMemoryTimeQuota": 0,
               "cloningInfo": null,
           "dependsOn": [
               "[resourceId('Microsoft.Web/serverfarms',variables('appservice_plan_name'))]"
               
           
       
   
}

~~~

このテンプレートを Azure powershell を使用してデプロイします。
以下のドキュメント内のコードを使用してデプロイをしています。
https://docs.microsoft.com/ja-jp/azure/azure-resource-manager/resource-group-template-deploy

~~~
New-AzResourceGroupDeployment -ResourceGroupName <Resource Group Name> -TemplateFile <Template File Path> -Mode "Incremental"
~~~
(*)リソースグループ名とテンプレートファイルは任意のものを指定してください。

デプロイが完了したあと、実際にコンソールをみてみるとweb apps とApp Service Plan 完成しています！
以下画像が実行結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329544/3707a06b-e8ee-3ba8-1e17-0cf0a8dc7b59.png)


# 5.まとめ
Infrastructure as Code について記載しました。
実際にコードをかくとやはり時間がかかってしまいましたが、一度使い始めるとやめられなくなってしまいます。

便利な機能ですのでおすすめです！


## 参考資料
・Microsoft.Web serverfarms template reference
https://docs.microsoft.com/ja-jp/azure/templates/microsoft.web/2018-02-01/serverfarms

・Microsoft.Web sites template reference
https://docs.microsoft.com/ja-jp/azure/templates/microsoft.web/2018-11-01/sites