【Azure】TerraformでAzureVMをデプロイしてみた
AzureCLIで実行したコマンドをGitHubで管理しようと思い、調べていたらTerraformという管理ツールが出てきたので使ってみた。
Terraformとは?
Terraform(テラフォーム) は、インフラストラクチャをコード(Infrastructure as Code, IaC)として管理するためのツール です。HashiCorp(ハシコープ)によって開発され、クラウドリソースやオンプレミスのインフラを自動化して管理できます。
Terraformの特徴
-
インフラをコードで管理(IaC: Infrastructure as Code)
- Terraform を使うと、クラウドリソース(仮想マシン、ネットワーク、ストレージなど)を コード(HCL: HashiCorp Configuration Language) で定義し、自動で作成・更新・削除できます。
-
マルチクラウド対応
- Terraform は AWS, Azure, Google Cloud(GCP)などのマルチクラウド環境 で利用できます。
-
宣言的な構成管理
- 「この状態にしたい」 という 最終的な状態 をコードで記述し、Terraform がその状態にするよう自動的に適用。
- 変更が必要な部分のみ適用され、手動設定のミスを防げる。
-
ステート管理
- Terraform は 「どのリソースを作成したか」 を .tfstate というファイルで管理し、変更の差分を適用。
-
プラン・適用の確認
- 変更前に 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コンソールからアプリケーションの登録を行います。
アプリケーションを登録します。
クライアントIDをメモしておきます。
クライアントシークレットを発行します。発行後のクライアントシークレット(値)をメモしておきます。
アプリケーションにAzureロールを付与する
リソースを構築したいサブスクリプションのコンソールの「アクセス制御(IAM)」にアクセスし、サブスクリプションの共同作成者を付与します。
リソース構築
Azureの資格情報をTerraformに設定する
vscodeに下記2つの拡張機能を追加します。
- HashiCorp Terraform
- Azure Terraform
<任意の名前>.tfvars
というファイルを作成します。
provider_credentials = {
subscription_id = "<構築したい先のサブスクリプションID>"
tenant_id = "<Microsoft Entra IDのテナントID>"
sp_client_id = "<クライアントID>"
sp_client_secret = "<クライアントシークレット>"
}
# .tfvars files
*.tfvars
Terraformファイルを作成する
<任意の名前>.tfvars
と同じ階層にmain.tf
とvariables.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"
}
}
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.
構築されたリソースを確認する
デプロイされたリソースをポータルで確認します。
正常にデプロイされていれば完了です!
参考文献
Discussion