🚀

【Azure】TerraformでAzureVMをデプロイしてみた

に公開

AzureCLIで実行したコマンドをGitHubで管理しようと思い、調べていたらTerraformという管理ツールが出てきたので使ってみた。

Terraformとは?

Terraform(テラフォーム) は、インフラストラクチャをコード(Infrastructure as Code, IaC)として管理するためのツール です。HashiCorp(ハシコープ)によって開発され、クラウドリソースやオンプレミスのインフラを自動化して管理できます。

https://www.hashicorp.com/ja/products/terraform

Terraformの特徴

  1. インフラをコードで管理(IaC: Infrastructure as Code)
    • Terraform を使うと、クラウドリソース(仮想マシン、ネットワーク、ストレージなど)を コード(HCL: HashiCorp Configuration Language) で定義し、自動で作成・更新・削除できます。
  2. マルチクラウド対応
    • Terraform は AWS, Azure, Google Cloud(GCP)などのマルチクラウド環境 で利用できます。
  3. 宣言的な構成管理
    • 「この状態にしたい」 という 最終的な状態 をコードで記述し、Terraform がその状態にするよう自動的に適用。
    • 変更が必要な部分のみ適用され、手動設定のミスを防げる。
  4. ステート管理
    • Terraform は 「どのリソースを作成したか」 を .tfstate というファイルで管理し、変更の差分を適用。
  5. プラン・適用の確認
    • 変更前に terraform plan で どのリソースが追加・更新・削除されるか を確認できる。
    • terraform apply で実際にインフラを構築。

目標

Terraformを使ってコードのみでAzureVMリソースをデプロイする。

前提条件

  • ローカル環境はMac
  • AzureCLIを事前にインストールしてください
  • コードエディタはvscodeです
  • TerraformファイルはGitHubで管理しています

環境構築

Terraformをインストールする

Terraformの バージョン管理ツール(tfenv) をインストールします。

brew install tfenv

利用可能なTerraformバージョンを取得します。執筆段階では、1.11.2が最新版でした。

tfenv list-remote

Terraform(1.11.2)をインストールします。

tfenv install 1.11.2

ローカルPC上で使用できるTerraformのバージョンを確認します。

tfenv list

Terraform(1.11.2)を使用するように切り替えます。

tfenv use 1.11.2

tfenv use を実行後、下記のような結果になっていればOKです!

Switching default version to v1.11.2
Default version (when not overridden by .terraform-version or TFENV_TERRAFORM_VERSION) is now: 1.11.2

アプリケーション登録を行う

Azureポータルサイトにアクセスし、Microsoft Entra IDコンソールからアプリケーションの登録を行います。

image.png

アプリケーションを登録します。

image.png

クライアントIDをメモしておきます。

image.png

クライアントシークレットを発行します。発行後のクライアントシークレット(値)をメモしておきます。

image.png

アプリケーションにAzureロールを付与する

リソースを構築したいサブスクリプションのコンソールの「アクセス制御(IAM)」にアクセスし、サブスクリプションの共同作成者を付与します。

image.png

image.png

リソース構築

Azureの資格情報をTerraformに設定する

vscodeに下記2つの拡張機能を追加します。

  • HashiCorp Terraform
  • Azure Terraform

image.png

<任意の名前>.tfvars というファイルを作成します。

param.tfvars
provider_credentials = {
  subscription_id  = "<構築したい先のサブスクリプションID>"
  tenant_id        = "<Microsoft Entra IDのテナントID>"
  sp_client_id     = "<クライアントID>"
  sp_client_secret = "<クライアントシークレット>"
}
.gitignore
# .tfvars files
*.tfvars

Terraformファイルを作成する

<任意の名前>.tfvars と同じ階層にmain.tfvariables.tfを作成します。

main.tf
provider "azurerm" {
  subscription_id = var.provider_credentials.subscription_id
  tenant_id       = var.provider_credentials.tenant_id
  client_id       = var.provider_credentials.sp_client_id
  client_secret   = var.provider_credentials.sp_client_secret
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "rg-tr-001"
  location = var.location
}

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

resource "azurerm_subnet" "subnet" {
  name                 = "snet-tr-001"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

resource "azurerm_public_ip" "public_ip" {
  name                = "pip-tr-001"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Static"
}

resource "azurerm_network_interface" "nic" {
  name                = "nic-tr-001"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "nicconfig-tr-001"
    subnet_id                     = azurerm_subnet.subnet.id
    public_ip_address_id          = azurerm_public_ip.public_ip.id
    private_ip_address_allocation = "Static"
    private_ip_address            = "10.0.1.4"  # 明示的にIPアドレスを指定
  }
}

resource "azurerm_linux_virtual_machine" "vm" {
  name                = "vm-tr-001"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  size                = "Standard_B1s"
  admin_username      = "adminuser"
  admin_password      = "*******" # 任意のパスワードを設定
  disable_password_authentication = false # パスワード認証を有効化

  network_interface_ids = [
    azurerm_network_interface.nic.id
  ]

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

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-focal"
    sku       = "20_04-lts-gen2"
    version   = "latest"
  }
}
variables.tf
variable "provider_credentials" {
  type = object({
    subscription_id  = string
    tenant_id        = string
    sp_client_id     = string
    sp_client_secret = string
  })
}

variable "location" {
  type    = string
  default = "japaneast"
}

Terraformでリソースを作成する

Terraformプロバイダを初期化(init)します。

terraform init

構築するリソース情報の計画(plan)を実行します。

terraform plan -var-file=param.tfvars

リソースを構築(apply)します。

terraform apply -var-file=param.tfvars

planと同じ結果が表示された後、確認を求められます。yesと入力し、実行します。

Plan: 6 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

下記が表示されれば完了です。

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

構築されたリソースを確認する

デプロイされたリソースをポータルで確認します。

image.png

正常にデプロイされていれば完了です!

参考文献

https://zenn.dev/murakami_koki/articles/43d2294d9761be
https://persol-serverworks.co.jp/blog/terraform/terraformpushgitignore.html

GitHubで編集を提案

Discussion