Terraform を使用して Linux 仮想マシンをプロビジョニングする

完了

Terraform は、そのコンポーネントの目的の状態を記述する構成ファイルを使用して、ターゲット インフラストラクチャを実装して制御します。 ファイルの基本形式と、Hashicorp 構成言語 (HCL) で表される一般的な構文は、クラウドの選択に関係なく同じです。 ただし、個々のコンポーネントの説明は、対応する Terraform プロバイダーで決定されるクラウドによって異なります。

Azure インフラストラクチャ管理をサポートする Terraform プロバイダーはいくつかありますが、特に関連性があるのは AzureRM です。 AzureRM プロバイダーは、仮想マシン、ストレージ アカウント、ネットワーク インターフェイスなどの一般的な Azure IaaS リソースのプロビジョニングと構成を容易にします。 また、クラウド固有ではない追加のプロバイダーもあり、デプロイに組み込むことができます。 これらの中には、疑似ランダム文字列を生成することでリソースの名前付けの競合を回避するのに役立つランダム プロバイダーや、Linux 認証をセキュリティで保護するための非対称キーの管理を簡略化する tls プロバイダーがあります。

Terraform は単一のバイナリとして使用でき、Hashicorp Web サイトからダウンロードできます。 このバイナリによって、Terraform コマンド ライン インターフェイス (CLI) が実装されます。これをシェル セッションから呼び出して、Terraform を初期化し、構成ファイルを処理できます。 Terraform CLI は、Azure CLI をサポートする任意のシェルから使用できます。

Azure Cloud Shell を使用する場合は、「Bash を使用して Azure Cloud Shell で Terraform を構成する」に記載されている手順に従って、Terraform の現在のバージョンを実行していることを確認します。

Terraform を使用して Linux VM をデプロイする

Terraform を使用すると、プロバイダー固有のクラウド インフラストラクチャにリソースを定義、プレビュー、デプロイできます。 プロビジョニング プロセスは、HCL 構文を使用する構成ファイルの作成から始まります。これにより、ターゲットのクラウド環境 (Azure など) と、クラウド インフラストラクチャを構成するリソースを指定できます。 関連する構成ファイルをすべて配置したら (通常は同じファイル システムの場所内)、結果として生じたインフラストラクチャの変更を、実際のデプロイ前にプレビューできる実行プランを生成できます。 これには、Terraform を初期化して、クラウド リソースの実装に必要なプロバイダー モジュールをダウンロードする必要があります。 変更を検証したら、実行プランを適用してインフラストラクチャをデプロイできます。

実行プランの生成は省略可能ですが、実行プランにより、ターゲット環境に影響を与えることなく、計画されたデプロイによる影響を確認できるため、生成することをお勧めします。 Azure リソースを対話形式でデプロイすると、Terraform では、資格情報を再利用してターゲットの Azure サブスクリプションにアクセスすることで Azure CLI 認証が透過的にサポートされます。

Linux を実行する Azure VM を、Terraform を使用してプロビジョニングするプロセスでは、通常、次に大まかに示す一連の手順が含まれます。

  • 適切な VM イメージを特定する。
  • 適切な VM サイズを特定する。
  • Azure VM リソースとその依存関係を定義する構成ファイルを作成する。
  • Terraform を初期化します。
  • Terraform 実行プランを生成する。
  • Terraform デプロイを開始する。

VM の適切なイメージとサイズを特定するには、このモジュールのユニット 4 で説明する手順に従います。 このユニットでは、Terraform 固有のタスクについて重点的に説明します。

構成ファイルを作成する

Terraform ファイル用に選択するファイル名は任意ですが、ファイルの内容または目的を反映する名前を選択することをお勧めします。 ファイル拡張子には .tf を使用する必要があります。

Terraform を使用して Linux VM をデプロイするには、まず、構成ファイルをホストするディレクトリを作成します。 次に、providers.tf という名前のファイルを作成します。これは、Terraform バージョンを適用し、デプロイに含めるリソースを定義するときに使用するプロバイダーを指定します。 このファイルには、次のコード スニペットに表示されるコンテンツが含まれている必要があります。

terraform {
  required_version = ">=0.12"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>2.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~>3.0"
    }
    tls = {
      source = "hashicorp/tls"
      version = "~>4.0"
    }
  }
}

provider "azurerm" {
  features {}
}

同じディレクトリで、次のコードを使用して main.tf という名前のファイルを作成します。これは、Azure VM とその依存関係を定義します。

resource "random_pet" "rg_name" {
  prefix = var.resource_group_name_prefix
}

resource "azurerm_resource_group" "rg" {
  ___location = var.resource_group_location
  name     = random_pet.rg_name.id
}

# Create virtual network
resource "azurerm_virtual_network" "terraform_network" {
  name                = "lnx-tf-vnet"
  address_space       = ["10.1.0.0/16"]
  ___location            = azurerm_resource_group.rg.___location
  resource_group_name = azurerm_resource_group.rg.name
}

# Create subnet
resource "azurerm_subnet" "terraform_subnet" {
  name                 = "subnet0"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.terraform_network.name
  address_prefixes     = ["10.1.0.0/24"]
}

# Create public IPs
resource "azurerm_public_ip" "terraform_public_ip" {
  name                = "lnx-tf-pip"
  ___location            = azurerm_resource_group.rg.___location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Dynamic"
}

# Create Network Security Group and rule
resource "azurerm_network_security_group" "terraform_nsg" {
  name                = "lnx-tf-nsg"
  ___location            = azurerm_resource_group.rg.___location
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "ssh"
    priority                   = 300
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

# Create network interface
resource "azurerm_network_interface" "terraform_nic" {
  name                = "lnx-tf-nic"
  ___location            = azurerm_resource_group.rg.___location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "nic_configuration"
    subnet_id                     = azurerm_subnet.terraform_subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.terraform_public_ip.id
  }
}

# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "lnx-tf-nic-nsg" {
  network_interface_id      = azurerm_network_interface.terraform_nic.id
  network_security_group_id = azurerm_network_security_group.terraform_nsg.id
}

# Generate random text for a unique storage account name
resource "random_id" "random_id" {
  keepers = {
    # Generate a new ID only when a new resource group is defined
    resource_group = azurerm_resource_group.rg.name
  }

  byte_length = 8
}

# Create storage account for boot diagnostics
resource "azurerm_storage_account" "storage_account" {
  name                     = "diag${random_id.random_id.hex}"
  ___location                 = azurerm_resource_group.rg.___location
  resource_group_name      = azurerm_resource_group.rg.name
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

# Create (and display) an SSH key
resource "tls_private_key" "lnx-tf-ssh" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

# Create virtual machine
resource "azurerm_linux_virtual_machine" "lnx-tf-vm" {
  name                  = "lnx-tf-vm"
  ___location              = azurerm_resource_group.rg.___location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.terraform_nic.id]
  size                  = "Standard_F4s"

  os_disk {
    name                 = "lnx-tf-vm-osdisk"
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts-gen2"
    version   = "latest"
  }

  computer_name                   = "lnx-tf-vm"
  admin_username                  = "azureuser"
  disable_password_authentication = true

  admin_ssh_key {
    username   = "azureuser"
    public_key = tls_private_key.lnx-tf-ssh.public_key_openssh
  }

  boot_diagnostics {
    storage_account_uri = azurerm_storage_account.storage_account.primary_blob_endpoint
  }
}

同じディレクトリで、次のコードを使用して variables.tf という名前の別のファイルを作成します。これは、main.tf ファイル内に出現する変数に値を割り当てます。

variable "resource_group_location" {
  default     = "eastus"
  description = "Location of the resource group"
}

variable "resource_group_name_prefix" {
  default     = "rg"
  description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription"
}

最後に、次のコードを使用して outputs.tf という名前のファイルを作成します。これにより、デプロイが成功した後に表示される出力が決まります。

output "resource_group_name" {
  value = azurerm_resource_group.rg.name
}

output "public_ip_address" {
  value = azurerm_linux_virtual_machine.lnx-tf-vm.public_ip_address
}

output "tls_private_key" {
  value     = tls_private_key.lnx-tf-ssh.private_key_pem
  sensitive = true
}

Terraform を初期化する

Terraform デプロイを初期化するには、シェル プロンプトから次のコマンドを実行します。

terraform init

このコマンドは、Azure リソースのプロビジョニングと管理に必要な Azure モジュールをダウンロードします。

実行プランを生成する

初期化したら、terraform plan を実行して実行プランを作成します。 このコマンドは実行プランを作成しますが、実行はしません。 代わりに、構成ファイルで定義したリソースの作成に必要なアクションを決定します。 オプションの -out パラメーターを使用すると、実際のデプロイ時に参照できるプランの出力ファイルを指定できます。 このファイルを使用すると、確認するプランとデプロイ結果が正確に一致することが保証されます。 実行プランを生成するには、次のコマンドを使用します。

terraform plan -out <terraform_plan>.tfplan

デプロイを開始する

Azure 環境に実行プランを適用する準備ができたら、前の手順で生成したファイル名を含む terraform apply を実行します。 予想される結果を確認する機会がもう一度与えられます。 Terraform により、続行の確認を求めるプロンプトが表示されます。ただし、-auto-approve スイッチを追加して、このプロンプトが表示されないようにすることができます。 デプロイを開始するには、次のコマンドを使用します。

terraform apply <terraform_plan>.tfplan

Azure VM はすぐに (通常は数分以内に) 実行を開始します。 terraform apply コマンドの出力には出力のリストが含まれますが、tls_private_key の値は、Terraform によって<機密>ラベルに置き換えられます。

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

出力:

public_ip_address = "74.235.10.136"
resource_group_name = "rg-flexible-shark"
tls_private_key = <sensitive>

自動生成された秘密キーを SSH 接続の認証に使用するには、それをファイルに格納し、他のユーザーがアクセスできないようにファイルのアクセス許可を設定します。 これを行うには、次のコマンドを実行します。

terraform output -raw tls_private_key > id_rsa
chmod 600 id_rsa

これで、(<public_ip_address> プレースホルダーを、terraform apply で生成された出力で識別した IP アドレスに置き換えた後) 次のコマンドを実行して、Azure VM に接続できるようになりました。

ssh -i id_rsa azureuser@<public_ip_address>