BicepとTerraformでAzure VMをデプロイしてみる

タイトルの通りBicepとTerraformでAzureのVMをデプロイしてみたメモになります。
２つの違いについては簡単にはまとめていますが、詳細については記載をしておりません。
IaC初心者が試しに触ってみた記事になりますのでご承知おき頂ければと思います。

# 事前準備

環境の準備やチュートリアルがMicrosoft公式から出ていますので、そちらを参考に実施しました。

自身のローカル端末にて環境を用意する場合以下のインストールが必要となります。（Visual Studio Code利用前提）
・Visual Studio Codeのインストール
・Azure CLI
・Visual Studio CodeのBicep拡張機能インストール
・Terraformのインストール
・Visual Studio CodeのTerraform拡張機能インストール　

### Bicep事前準備
https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/install

https://learn.microsoft.com/ja-jp/azure/virtual-machines/windows/quick-create-bicep?tabs=PowerShell

### Terraform事前準備
https://learn.microsoft.com/ja-jp/azure/virtual-machines/windows/quick-create-terraform



# Bicepファイルの作成とデプロイ

事前準備が完了したら、まずはBicepでVMをデプロイしてみます。
Bicepファイルの作成方法や構文などについては公式リンクを記載します。

https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/quickstart-create-bicep-use-visual-studio-code?tabs=CLI

https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/file

今回は以下のようなBicepファイルを用意します。

### Bicepファイルの作成
```
@description('リージョンの指定')
param location string = resourceGroup().location

@description('VMの名前')
param vmName string = 'myWinVM'

@description('管理者ユーザー名')
param adminUsername string

@description('管理者パスワード')
@secure()
param adminPassword string

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = {
  name: 'myVNet'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'mySubnet'
        properties: {
          addressPrefix: '10.0.0.0/24'
        }
      }
    ]
  }
}

resource networkInterface 'Microsoft.Network/networkInterfaces@2021-05-01' = {
  name: 'myNIC'
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig1'
        properties: {
          subnet: {
            id: virtualNetwork.properties.subnets[0].id
          }
          privateIPAllocationMethod: 'Dynamic'
        }
      }
    ]
  }
}

resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-11-01' = {
  name: vmName
  location: location
  properties: {
    hardwareProfile: {
      vmSize: 'Standard_D2s_v3'
    }
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      adminPassword: adminPassword
    }
    storageProfile: {
      imageReference: {
        publisher: 'MicrosoftWindowsServer'
        offer: 'WindowsServer'
        sku: '2019-Datacenter'
        version: 'latest'
      }
      osDisk: {
        createOption: 'FromImage'
        managedDisk: {
          storageAccountType: 'Premium_LRS'
        }
      }
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: networkInterface.id
        }
      ]
    }
  }
}
```

このBicepファイルでは以下のリソースを作成します

* 仮想ネットワーク
* ネットワークインターフェース
* 仮想マシン

### Bicepファイルのデプロイ

デプロイ手順：
1 Azure CLIをインストールし、ログインします
```
az login
```

2 リソースグループを作成します（作成済みの場合は省略可）
```
az group create --name myResourceGroup --location eastus
```

3 Bicepファイルをデプロイします
```
az deployment group create --resource-group myResourceGroup --template-file main.bicep --parameters adminUsername=azureuser adminPassword=YourSecurePassword123!
```

ポータルを確認するとBicep上で指定したリソースが作成できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/2ff780f2-cd8f-0871-3f8e-72d3ee453764.png)



# Terraform作成とデプロイ

次にTerraformファイルを作成します。
内容は上記のBicepと同様にします。

```terraform
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "terraformTest"
  location = "japaneast"
  tags = {
    Name = "Naoto_Minagawa"
  }
}

resource "azurerm_virtual_network" "vnet" {
  name                = "myVNet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "subnet" {
  name                 = "mySubnet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.0.0/24"]
}

resource "azurerm_network_interface" "nic" {
  name                = "myNIC"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_windows_virtual_machine" "vm" {
  name                = "myWinVM"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  size                = "Standard_D2s_v3"
  admin_username      = var.admin_username
  admin_password      = var.admin_password
  network_interface_ids = [
    azurerm_network_interface.nic.id,
  ]

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
  }

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2019-Datacenter"
    version   = "latest"
  }
}

variable "admin_username" {
  description = "管理者ユーザー名"
  type        = string
}

variable "admin_password" {
  description = "管理者パスワード"
  type        = string
  sensitive   = true
}
```

上記Terraformファイルでは先に作成したBicepファイル同様に以下のリソースを作成します

* 仮想ネットワーク
* ネットワークインターフェース
* 仮想マシン

### Terraformファイルのデプロイ

デプロイ手順：
1 Azure CLIをインストールし、ログインします
```
az login
```

2 Terraformの初期化を実施します
```
terraform init
```
3 Terraformのplanを確認します
```
terraform plan
```
Terraformを初めて触ったのですが、このplanコマンド実施後にAzure上でどういったリソースが作成されるかをコマンドライン上でリストアップしてくれます。
Bicepではそういったリソースリストアップはなさそうでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/3f428c40-f937-1e65-cfa3-244609494eef.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/b1ccc57d-71e6-5649-5e60-4a1cd67118e7.png)


4 リソースをデプロイします
```
terraform apply
```
作成確認のメッセージが表示されるため「yes」と入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/e74c9b52-0f88-8e66-58a6-8ecdd1b56307.png)


ポータルを確認するとBicep同様にterraformで定義したリソースが作成されていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/abade14d-6ba2-c24e-77bf-d8667a68379e.png)



# デプロイ後の比較

実際に2つを試してみてそれぞれの特徴やメリットデメリットを以下に簡単にまとめてみました。

## Bicep

### 特徴
- Microsoft Azureに特化したIaCツール
- Azure Resource Managerテンプレートをより簡潔に記述可能
- Azureリソースのデプロイに最適化

### メリット
- Azure固有の機能との高い互換性
- ARM JSONテンプレートとの相互変換が可能

### デメリット
- Azure以外のクラウドプロバイダーには使用できない
- コミュニティとエコシステムがTerraformほど成熟していない
- State管理ができない（Azure Resource Manager (ARM) が状態を管理）

## Terraform

### 特徴
- マルチクラウド対応のIaCツール
- HCL（HashiCorp Configuration Language）を使用
- 幅広いプロバイダーとリソースタイプをサポート

### メリット
- クラウドプロバイダー間での移植性が高い
- 大規模で成熟したコミュニティとエコシステム
- 多様なユースケースと豊富な機能

### デメリット
- Azure固有の最新機能のサポートが遅れる場合がある
- 状態管理の複雑さ

## 選択基準
- Azure専用の場合はBicepが適している（最新のリソースも対応する可能性が高い）
- マルチクラウド環境ではTerraformが優位
- チームの既存のスキルセットとプロジェクトの要件を考慮


# おわりに

今回ははじめて２つを比較しながら触ってみましたが、どちらもメリット/デメリットがあるため絶対にこちらのほうがおすすめできるといった感触は得られませんでした。
上記のメリット/デメリットを比較しながら、その時の要件やどちらが会社やチームに合うかを考慮しながら採用を決めたほうが良さそうです。

個人的にはTerraformの構文の方が可読性高く分かりやすい印象があったのと、ネット上での事例が豊富なため完全にゼロベースであればTerraformの方が手が出しやすい印象でした。