はじめに
Terraformの概要、Terraformを用いたAzureリソースのデプロイ方法について基本的な流れを解説致します。
Terraformとは
Terraformとは、HashiCorp社が提供するIaC(Infrastructure as Code)*1のためのサービスです。
Terraformでは様々なインフラストラクチャ用のプロバイダーが用意されており、Azureでも使用できます。 registry.terraform.io
認証
TerraformでAzureリソースをデプロイする際に、Azureへ認証を行う必要があります。
Azureでは以下の認証方法があります。
- Azure CLIを使用したAzureへの認証
- マネージドIDを使用したAzureへの認証
- サービスプリンシパルを使用したAzureへの認証
- OpenID Connectを使用したAzureへの認証
今回はサービスプリンシパルを使用したAzureへの認証の認証にて実施致します。
リソースのデプロイ
今回は例として以下リソースのデプロイを実施します。
- Resource Group
- Virtual Network
- Network Security Group
- Virtual Machine
前提
Terraformをインストール済であること
インストールを未実施の場合は以下を参照し、インストール後に後続手順を実施してください。 developer.hashicorp.com
サービスプリンシパルを作成済であること
未作成の場合は以下コマンドにて作成します。
#Sign In az login --tenant <Tenant ID> #Tenant、Subscription情報の取得 az account show --query "{subscriptionId:id, tenantId:tenantId}" #変数に値を格納 $SUBSCRIPTION_ID="<Subscription ID>" #Subscriptioinのセット az account set --subscription $SUBSCRIPTION_ID #Service Principalの作成 az ad sp create-for-rbac --role Contributor --scopes /subscriptions/$SUBSCRIPTION_ID --name "<Service Principal名>"
※Terraform構成ファイル作成時に使用するため出力の結果を控えてください。
状態格納用のストレージアカウントを作成済であること
既定だとローカルにTerraformの状態が格納されますが、ストレージアカウントへの格納が推奨となります。 以下コマンドより作成可能です。
#Sign In az login --tenant <Tenant ID> #Tenant、Subscription情報の取得 az account show --query "{subscriptionId:id, tenantId:tenantId}" #変数に値を格納 $SUBSCRIPTION_ID="<Subscription ID>" $REGION="<作成先Region>" $RG_NAME="<Resource Group名>" $ST_NAME="<Storage Account名>" $BLOB_NAME="<Blob Container名>" #Subscriptionのセット az account set --subscription $SUBSCRIPTION_ID #Resource Groupの作成 az group create --name $RG_NAME --location $REGION #Storage Accountの作成 az storage account create --resource-group $RG_NAME --name $ST_NAME --sku Standard_LRS --encryption-services blob #Blob Containerの作成 az storage container create --name $BLOB_NAME --account-name $ST_NAME
定義ファイルの作成
まず、各リソースの定義ファイルを作成します。
main.tfの作成
provider情報、状態格納先ストレージアカウントを記載します。
# Env info provider "azurerm" { features {} subscription_id = var.subscription_id tenant_id = var.tenant_id client_id = var.client_id client_secret = var.client_secret } # Azure Provider terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "=3.25.0" } } # Store Terraform state in Azure Storage backend "azurerm" { resource_group_name = "<Resource Group名(状態格納用ストレージアカウントが格納されているResource Group)>" storage_account_name = "<Storage Account名>" container_name = "<Blob Container名>" # Statment File Name key = "terraform.tfstate" } }
valiables.tfの作成
各リソースの値を記載します。
#------------------------------- # 基本変数定義 #------------------------------- # Subscription ID variable "subscription_id" { type = string } # Service Principal ID variable "client_id" { type = string } # Service Principal Secret variable "client_secret" { type = string } # TenantID variable "tenant_id" { type = string } # Region variable "location" { default = "<作成先Region>" } #------------------------------- # Resource Group #------------------------------- # Resource Group Name variable "resource_group_name" { default = "<Resource Group名>" } #---------------------------------- # Virtual Network #---------------------------------- # Virtual Network Name variable "virtual_network_name" { default = "<VNET名>" } # Subnet Name variable "subnet_name" { default = "<Subnet名>" } # Vnet Address Space variable "vnet_address_space" { default = ["<VNET IP Prefix>"] } # Subnet Address Space variable "snet_address_space" { default = ["<Subnet IP Prefix>"] } #---------------------------------- # Network Security Group #---------------------------------- # Network Security Group Name variable "network_security_group_name" { default = "<NSG名>" } #---------------------------------- # Virtual Machine #---------------------------------- # VM Name variable "vm_name" { default = "<VM名>" } # VM Size variable "vm_size" { default = "<VM Size>" } # Public IP Name variable "public_ip_name" { default = "<Public IP名>" } # NIC Name variable "nic_name" { default = "<NIC名>" } # OS DIsk Name variable "os_disk_name" { default = "<OS Disk名>" } # OS Disk SKU variable "os_disk_sku" { default = "<OS Disk SKU>" } # IP Config Name variable "ip_config_name" { default = "<IP Config名>" } # Admin PW variable "admin_pw" { type = string } # Admin User Name variable "admin_user_name" { default = "<管理者User名>" }
rg.tfの作成
リソースグループ設定を記載します。
#------------------------------- # Resource Group #------------------------------- # Resource Group resource "azurerm_resource_group" "rg" { name = var.resource_group_name location = var.location }
vnet.tfの作成
仮想ネットワーク設定を記載します。
#------------------------------- # Virtual Network #------------------------------- # Virtual Network resource "azurerm_virtual_network" "vnet" { name = var.virtual_network_name address_space = var.vnet_address_space location = var.location resource_group_name = var.resource_group_name depends_on = [ azurerm_resource_group.rg ] } # Subnet resource "azurerm_subnet" "snet" { name = var.subnet_name resource_group_name = var.resource_group_name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = var.snet_address_space depends_on = [ azurerm_resource_group.rg, azurerm_virtual_network.vnet, azurerm_network_security_group.nsg ] }
nsg.tfの作成
Network Security Group設定を記載します。
#------------------------------- # Network Security Gtoup #------------------------------- # Network Security Group resource "azurerm_network_security_group" "nsg" { name = var.network_security_group_name location = var.location resource_group_name = var.resource_group_name #------------------------------- # 受信規則 #------------------------------- # RDP接続許可 security_rule { name = "AllowRDPInBound" priority = 1000 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "3389" source_address_prefix = "<接続元IP Address>" destination_address_prefix = "*" } #Resource Group作成後にデプロイ depends_on = [ azurerm_resource_group.rg ] } # Subnetへの関連付け resource "azurerm_subnet_network_security_group_association" "nsgSubnet" { subnet_id = azurerm_subnet.snet.id network_security_group_id = azurerm_network_security_group.nsg.id depends_on = [ azurerm_resource_group.rg, azurerm_virtual_network.vnet, azurerm_subnet.snet ] }
vm.tfの作成
仮想マシン設定を記載します。
#------------------------------- # Virtual Machine #------------------------------- # Public IP resource "azurerm_public_ip" "public_ip" { name = var.public_ip_name location = var.location resource_group_name = var.resource_group_name allocation_method = "Static" depends_on = [ azurerm_resource_group.rg, ] } # Network interface resource "azurerm_network_interface" "nic" { name = var.nic_name location = var.location resource_group_name = var.resource_group_name ip_configuration { name = var.ip_config_name subnet_id = azurerm_subnet.snet.id private_ip_address_allocation = "Dynamic" public_ip_address_id = azurerm_public_ip.public_ip.id } depends_on = [ azurerm_resource_group.rg, azurerm_virtual_network.vnet, azurerm_subnet.snet, azurerm_public_ip.public_ip ] } # Virtual Machine resource "azurerm_windows_virtual_machine" "windows_vm" { name = var.vm_name admin_username = var.admin_user_name admin_password = var.admin_pw location = var.location resource_group_name = var.resource_group_name network_interface_ids = [azurerm_network_interface.nic.id] size = var.vm_size os_disk { name = var.os_disk_name caching = "ReadWrite" storage_account_type = var.os_disk_sku } source_image_reference { publisher = "MicrosoftWindowsServer" offer = "WindowsServer" sku = "2022-datacenter-azure-edition" version = "latest" } depends_on = [ azurerm_resource_group.rg, azurerm_virtual_network.vnet, azurerm_subnet.snet, azurerm_public_ip.public_ip, azurerm_network_interface.nic ] }
Terraformコマンドの実行
定義ファイルの作成が完了しましたら、Terraformコマンドを実行していきます。
terraform init
初期化をし、provider pluginsを取得します。
成功すると「Terraform has been successfully initialized!」と表示されます。
terraform fmt
カレントディレクトリのtfファイルをフォーマットします。(必要に応じて実施)
修正されたファイルがあればファイル名が出力されます。
※サブディレクトリも含むフォーマットする場合は「terraform fmt -recursive」を実行してください。
terraform validate
構成の検証をします。
問題がなければ「Success! The configuration is valid.」と表示されます。
terraform plan
tfファイルにて定義された構築リソースを表示します。
※コマンド実行後に環境情報やシークレット情報の入力が必要です。
構築内容や、作成・削除・変更されるリソース数が表示されます。
terraform apply
リソースをデプロイします。
※実行後に環境情報やシークレット情報の入力が必要です。
内容に問題がないことを確認し、「yes」を入力後「Enter」を押下します。
問題なくデプロイを実行できると「Apply complete! Resources: * added, * changed, * destroyed.」と表示されます。
Azure Portalを確認すると、リソースが問題なく構築されていることが確認できます。
作成リソースの削除
Terraformコマンドの実行
デプロイ時同様、Terraformで管理されたリソースはTerraformコマンドで削除可能です。
terraform destroy
Terraformで構築したリソースの削除を実行します。
※「terraform plan -destroy」を実行することで、削除されるリソースを事前に確認することができます。
※ 実行後に環境情報やシークレット情報の入力が必要です。
内容に問題がないことを確認し、「yes」を入力後「Enter」を押下します。
問題なく削除が完了すると「Destroy complete! Resources: * destroyed.」と表示されます。
おわりに
本記事を最後までお読みいただき、ありがとうございます。
Terraformによるリソース管理を行うことで、効率的かつ正確なインフラストラクチャの構築、変更、削除ができるようになるかと思います。
本記事がTerraformを使用する際の参考となれば幸いです。
*1:IaC:サーバーやネットワークをはじめとしたインフラ構成をコード化し、構築や管理を自動化する手法のこと