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


はじめに

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

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

ARM(AzureResourceManager)とは

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

例. ARM

{
  "$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に似てるなと感じます。

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

Terraformとは

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

Azure Providerについて

Terraform Registry

例. 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

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

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

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

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

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

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

  • AWS
  • Azure
  • GCP
  • kubenertes

対応言語

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

書き方の例(一部抜粋)

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

Review the New Project | Azure

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
});

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

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