[Azure] Azure Resource Manager と Terraform どちらがいいのか調べてみた

# はじめに

現在担当しているプロジェクトでAzureを利用しており、インフラについても次フェーズからはコードで管理することになり、IaCとしてARM(AzureResourceManager)と自分が触ったことのあるTerraformどちらがいいのか調べてみました。

運用経験ベースではなくあくまで調査ベースですので、運用の観点からご意見等あれば是非コメントいただきたいです。

# ARM(AzureResourceManager)とは

Azure謹製のIaCツール。リソースの定義方法については,ARMテンプレート(JSON)とBicepと呼ばれるAzure専用のDSL(ドメイン固有言語)の２つがあります. Bicepについては、デプロイ中に自動で ARM テンプレートに変換されるそうで、ARMテンプレートが完全にお役御免になったわけではないみたいです。

例. ARM

```json
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "storageAccountName": {
      "type": "string",
      "defaultValue": "[format('toylaunch{0}', uniqueString(resourceGroup().id))]"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2021-06-01",
      "name": "[parameters('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "StorageV2",
      "properties": {
        "accessTier": "Hot"
      }
    }
  ]
}
```

例:Bicep
個人的にはすごいterraformに似てるなと感じます。

```json
param location string = resourceGroup().location
param storageAccountName string = 'toylaunch${uniqueString(resourceGroup().id)}'

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
  }
}
```

[Azure Resource Manager の概要 - Azure Resource Manager](https://docs.microsoft.com/ja-jp/azure/azure-resource-manager/management/overview#:~:text=Azure%20Resource%20Manager%20%E3%81%AF%E3%80%81Azure,%E4%BF%9D%E8%AD%B7%E3%81%8A%E3%82%88%E3%81%B3%E6%95%B4%E7%90%86%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

# Terraformとは

こちらはAzureに限らず広く使われているのでご存知の方も多いかと思いますが、HashiCorp社製のIaCツールです。リソースの定義には、HCL(HashiCorp Configuration Language)が使われます。
Azureを利用する場合は、裏側でAzure Resource Manager APIを利用しているみたいです。

Azure Providerについて

[Terraform Registry](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)

例. AzureStorageAccountを定義する場合

```
resource "azurerm_storage_account" "mystorageaccount" {
  name                        = "st${random_id.randomId.hex}"
  resource_group_name         = azurerm_resource_group.rg.name
  location                     = var.resource_group_location
  account_tier                = "Standard"
  account_replication_type    = "LRS"
}
```

# 比較表
|  | ARM | Terraform |
| --- | --- | --- |
| リソース定義の方法 |JSON(ARMテンプレート) or 独自言語(Bicep) | 独自言語(HCL) |
| 独自言語に対するエディタ、IDEのサポート | vscodeにARMテンプレート、bicepともにプラグインあり | vscode,inteliJにプラグインあり。(自分の手元のツールのみ調査しました) |
| 対応クラウドプラットフォーム | Azure | 複数(Azure,AWS,GCP etc) |
| クラウドプラットフォームの最新機能への追従性 | 常に追従 | OSSなので時間がかかる可能性がある |
| 状態管理ファイル(クラウドリソースと手元のIaCコードの状態差異の管理方法) | なし。 | terraform.tfstate |
| 適用前にデプロイ対象を確認できるか | Whatifオプションを使うことで可能[1] | terraform plan or apply時の最終確認で可能 |
| モジュール化できるか | Bicepなら可能 | 可能 |
| リソースのデプロイ順序依存の解決 | Bicepは自動でやってくれる(ARMテンプレートは明記する必要があった) | 自動 |


[1]Whatifオプションについて

[Template deployment what-if - Azure Resource Manager](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/deploy-what-if?tabs=azure-powershell)

# で、結局どちらがいいのか。

運用経験からではなく複数の記事を調べた結果ベースではありますが、やはり**ケースバイケース**かと思いました。

どちらもこれといってこれがすごい！これがダメ！といった特徴はないと感じたからです。以前はBicepがなかったことから、モジュール化ができないこと、JSONでの冗長な定義を理由にARMを敬遠する主張もできたかと思いますが、現在はBicepの登場により両者実現できるのでARMの弱みにならなくなっています。

しかし、それでは悩んでる方の参考にならないかと思いますので以下に３パターンだけ自分が思うおすすめを書いておきますのでよかったら参考にしてください。

## Azureの最新機能をどんどん使う・使いたい人

→ ARM.

ARMが謹製とはいえ、機能リリースからARMへの反映にタイムラグがある可能性はありますが、ARMのRESTAPIができないと追加されないTerraformよりは反映が早いと期待できます。

## 同じプロダクトで他のクラウドプラットフォームのリソースも使う人

→ Terraform.

ARMは,Bicepが導入されより書きやすくなったとはいえあくまでAzure専用のIaCツールなので他のクラウドプラットフォームも包括的に管理したい場合はTerraformを選択すべきかと思います。

## サービスとか作ってるわけじゃないけどとりあえずIaC勉強したい人

→ Terraform.

個人的な意見ではありますが、業務でAzureを使うことが確定してるわけではないのであれば,さまざまなクラウドプラットフォームに対応しているTerraformが良いかなと思います。とりあえず,Terraformを抑えておけば、その後の自分の趣味・仕事でどのクラウドを使うことになっても臨機応変に動けるからです。

# 運用経験を積んだら見方が変わるかもしれない点

- ARMがAzure謹製であること
これは当たり前ですがterraformでazureを運用していくと痒いところに手が届かない！という事態が頻繁に起きたら、上記がARMの大きな強みになりうると思ったからです。
- 状態管理ファイルの有無
ARMには状態管理ファイルがなく、Terraformにはtfstateがありますが、これは素人目には一見管理しなくて済むARMの方がいいじゃん！とも思えますが、逆にファイル管理できないということは状態を切り戻したりする上で不便なこともあるんじゃないかと感じています。また逆に”terraform側のtfstateの管理の手間”があまりにも大きければ”ARMで出来ないこと”は些細なことに思えるかもしれません。これらは今後運用経験を積んだ段階でまた記事を書きたいと思います。

# ARM,Terraform以外の選択肢:Pulumi

Pulumi以外にもIaCツールはありますが、調査時に見かけて気になったので概要を紹介します！

## Pulumiとは

> Build, deploy, and manage modern cloud applications and infrastructure using familiar languages, tools, and engineering practices.
> 

とのことで、なんと自分の好きな言語でインフラ定義が書けるツールになります。

出典:[Pulumi - Modern Infrastructure as Code](https://www.pulumi.com/)

## 対応クラウドプラットフォーム

- AWS
- Azure
- GCP
- kubenertes

## 対応言語

- JavaScript/TypeScript
- Python
- Go
- C#,F#,VB

書き方の例（一部抜粋)

TypeScriptでAzureStorageAccountをデプロイする場合は以下のような書き方をするみたいです。
参考：

[Review the New Project | Azure](https://www.pulumi.com/docs/get-started/azure/review-project/)

```tsx
import * as pulumi from "@pulumi/pulumi";
import * as resources from "@pulumi/azure-native/resources";
import * as storage from "@pulumi/azure-native/storage";

// Create an Azure Resource Group
const resourceGroup = new resources.ResourceGroup("resourceGroup");

// Create an Azure resource (Storage Account)
const storageAccount = new storage.StorageAccount("sa", {
    resourceGroupName: resourceGroup.name,
    sku: {
        name: storage.SkuName.Standard_LRS,
    },
    kind: storage.Kind.StorageV2,
});

// Export the primary key of the Storage Account
const storageAccountKeys = storage.listStorageAccountKeysOutput({
    resourceGroupName: resourceGroup.name,
    accountName: storageAccount.name
});
```

今回はまだ自分も調査し切れてないので軽い紹介に留めますが非常に面白そうなツールだと思うのでまた記事に書こうかと思います。


# わかりやすかった記事まとめ

- ARM vs Terraform系の記事
    
    - [IaC: Azure Resource Manager Templates vs. Terraform](https://www.trendmicro.com/en_us/devops/22/b/iac-azure-resource-manager-templates-terraform.html#:~:text=To%20choose%20between%20the%20two,choose%20ARM%20templates%20over%20Terraform).
    
    - [Compare ARM templates vs. Terraform for infrastructure as code](https://www.techtarget.com/searchitoperations/tip/Compare-ARM-templates-vs-Terraform-for-infrastructure-as-code)
    
    - [Azure の構成管理を ARM templates と Terraform で検討してみた - Qiita](https://qiita.com/nassy20/items/9bf9042da8319bf0ee37)
    
    - [Comparing Azure ARM vs Cloudify vs Terraform | Cloudify](https://cloudify.co/blog/azure-arm-vs-terraform-vs-cloudify/)
    
- Terraform,ARMだけでなくPulumiも比較対象に入れている記事
    
    [ARM Templates vs Terraform vs Pulumi - Infrastructure as Code in 2021](https://julie.io/writing/arm-terraform-pulumi-infra-as-code/)
    
- TerraformをARM(Bicep)で置き換えるべきかについての記事
    
    [Would I replace Terraform with Bicep ? 💪🏽](https://dev.to/ghostinthewire5/would-i-replace-terraform-with-bicep--5gbj)

- Pulumiについて
    
    - [Pulumi - Modern Infrastructure as Code](https://www.pulumi.com/)
    
    - [これが次世代プロビジョニングツールの実力か！？ PulumiでAWSリソースを作成してみた | DevelopersIO](https://dev.classmethod.jp/articles/pulumi-aws/)