広告

Terraform-Azureリソース作成

Azure

以前の記事で、Terraform の基本的な概念をご紹介しました。
今回は Azure のリソースを Terraform でデプロイする基本的なサンプルを公開しようと思います。
個人的な注釈も入れているので、理解するための何等かの助けになると嬉しいです。

前提条件

本サンプルを使用するには、以下の前提条件をまず確認してください。

クリックスタート 記事に、Terraform のインストール方法が載っています。

Azure リソース のデプロイ

上記条件が揃ったら、サンプルを使って、リソースを作成してみましょう。

サンプルコード

下記のサンプルコードをテキストファイルで保存し、".tf" 拡張子で名前を変更してください。

# チュートリアル:https://docs.microsoft.com/ja-jp/azure/developer/terraform/get-started-cloud-shell

# 使用するプロバイダーを指定する:Azure は azurerm を指定する。また、GCPだったら google を指定する
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "~>2.0"
    }
  }
}

# プロバイダーに関する設定を定義する:例えば認証情報とか (自動化したい場合、環境変数での認証も可能なので、明文で書くことをは推奨しない)
provider "azurerm" {
  # The "feature" block is required for AzureRM provider 2.x.
  # If you're using version 1.x, the "features" block is not allowed.
  features {}

  # 認証情報をここに書くことも可能
  # subscription_id             = "00000000-0000-0000-0000-000000000000"
  # client_id                   = "00000000-0000-0000-0000-000000000000"
  # client_certificate_path     = "xxxxx"
  # client_certificate_password = "xxxxx"
  # tenant_id                   = "00000000-0000-0000-0000-000000000000"
}

# 第一 Block laber "azurerm_resource_group" は 作成するリソースの種類を指定する
# 第二 Block laber "myrg01" は tf ファイル内のリソースの識別 ID のようなもの
# 上記の二つの要素を組み合わせすることで、tf ファイル内でリソースを特定できる。Terraform の管理下であるリソースかどうかを識別するために、ステータスファイルとこの識別子で判断する仕組みになっている
resource "azurerm_resource_group" "myrg01" {
  name = "terraform-test-rg01"  # Azure のリソース名
  location = "japaneast"
}

# 仮想ネットワーク作成
resource "azurerm_virtual_network" "myvnet01" {
    name                = "myVnet"
    address_space       = ["10.0.0.0/16"]
    location            = azurerm_resource_group.myrg01.location  # myrg01 の location 属性を使う。他のリソースの情報を使うことで DepandsOn 関係が自動的になる
    resource_group_name = azurerm_resource_group.myrg01.name  # 上記 myrg01 の name 属性を使う

    tags = {
        environment = "Terraform Demo"
    }
}

# サブネット作成
resource "azurerm_subnet" "mysubnet01" {
    name                 = "subnet01"
    resource_group_name  = azurerm_resource_group.myrg01.name
    virtual_network_name = azurerm_virtual_network.myvnet01.name
    address_prefixes       = ["10.0.2.0/24"]
}

# パブリック IP 作成
resource "azurerm_public_ip" "mypublicip01" {
    name                         = "myPublicIP01"
    location                     = azurerm_resource_group.myrg01.location
    resource_group_name          = azurerm_resource_group.myrg01.name
    allocation_method            = "Dynamic"

    tags = {
        environment = "Terraform Demo"
    }
}

# NSG 作成
resource "azurerm_network_security_group" "mynsg01" {
    name                = "myNSG01"
    location            = azurerm_resource_group.myrg01.location
    resource_group_name = azurerm_resource_group.myrg01.name

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

    tags = {
        environment = "Terraform Demo"
    }
}

# VM の NIC 作成 (Azure では NIC は独立したリソースです)
resource "azurerm_network_interface" "mynic01" {
    name                        = "myNIC01"
    location                    = azurerm_resource_group.myrg01.location
    resource_group_name         = azurerm_resource_group.myrg01.name

    # NIC の設定値の定義
    ip_configuration {
        name                          = "myNicConfiguration"
        subnet_id                     = azurerm_subnet.mysubnet01.id
        private_ip_address_allocation = "Dynamic"
        public_ip_address_id          = azurerm_public_ip.mypublicip01.id
    }

    tags = {
        environment = "Terraform Demo"
    }
}

# NIC と NSG の紐づけ
resource "azurerm_network_interface_security_group_association" "mynic01_mynsg01" {
    network_interface_id      = azurerm_network_interface.mynic01.id
    network_security_group_id = azurerm_network_security_group.mynsg01.id
}

# リソースグループ名に依存するランダム文字列を生成する(リソースグループ名が変わらない限り、この文字列も変わらない)
# ストレージアカウントは世界中に一意である必要があるため、ランダムな値を使用する
resource "random_id" "myrandomId01" {
    keepers = {
        # Generate a new ID only when a new resource group is defined
        resource_group = azurerm_resource_group.myrg01.name
    }

    byte_length = 8  # 長さ定義
}

# ストレージアカウント作成
resource "azurerm_storage_account" "mystorageaccount01" {
    name                        = "diag${random_id.myrandomId01.hex}"  # 上記で定義したランダム文字列を使う
    resource_group_name         = azurerm_resource_group.myrg01.name
    location                    = azurerm_resource_group.myrg01.location
    account_replication_type    = "LRS"
    account_tier                = "Standard"

    tags = {
        environment = "Terraform Demo"
    }
}

# SSH の 秘密キーを作成 (VM ログイン用)
resource "tls_private_key" "myssh01" {
  algorithm = "RSA"
  rsa_bits = 4096
}

# "tls_private_key" は出力名、{...} は値
# 秘密キー を出力するのに使用する
output "tls_private_key" { value = tls_private_key.myssh01.private_key_pem }

# 仮想マシン作成
resource "azurerm_linux_virtual_machine" "myvm01" {
    name                  = "myVM01"
    location              = azurerm_resource_group.myrg01.location
    resource_group_name   = azurerm_resource_group.myrg01.name
    network_interface_ids = [azurerm_network_interface.mynic01.id]
    size                  = "Standard_A2_v2"

    # OS ディスクのリソース定義
    os_disk {
        name              = "myOsDisk"
        caching           = "ReadWrite"
        #Choose between Standard_LRS, StandardSSD_LRS and Premium_LRS based on your scenario
        storage_account_type = "Standard_LRS"
    }

    # イメージ指定
    source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
    }

    # OS 情報を指定
    computer_name  = "myvm"  # OS の PC名
    admin_username = "azureuser"  # ローカル管理者名
    disable_password_authentication = true  # パスワード認証を無効にする (秘密キー認証のみが使えるようになる)

    # 公開キー情報の定義
    admin_ssh_key {
        username       = "azureuser"  # 認証のユーザーを指定
        public_key     = tls_private_key.myssh01.public_key_openssh  # 上記で定義した myssh01 の公開キーを使う
    }

    boot_diagnostics {
        storage_account_uri = azurerm_storage_account.mystorageaccount01.primary_blob_endpoint  # ストレージアカウントの URL
    }

    tags = {
        environment = "Terraform Demo"
    }
}

デプロイ手順

  • コマンドプロンプトを起動する(Linux でしたら、このステップをスキップしてください)
  • cd コマンドで、サンプルコードの tf ファイルのディレクトリに移動
  • 以下のコマンドで Azure 環境へログインする
    1. ログインコマンド:az login
    2. サブスクリプション選択コマンド:az account set --subscription="<SUBSCRIPTION_ID>"
    3. ログイン結果確認:az account show --query "{subscriptionId:id, tenantId:tenantId}"
  • Terraform コマンドでデプロイ実行
    1. 初期化(プロバイダーダウンロードなど):terraform init
    2. デプロイ内容の確認(plan run):terraform plan
    3. デプロイ実施:terraform apply

Terraform の Azure 認証について

上記の手順で、 az login コマンドを使って、Azure へログインしていますが、自動化のために認証を省けたい要件はよくあります。その場合、Azure サービスプリンシパルを使うことを推奨します。

サービスプリンシパルがよくわからない方は、以前の記事をご参考をいただければと思います。

また、Terraform では環境変数にサービスプリンシパルの情報を設定することで、az loginを使わなくても、自動的に認証してくれるので、自動化する時に結構役に立ちます。

設定する環境変数名は以下となります:

  • ARM_SUBSCRIPTION_ID
  • ARM_CLIENT_ID
  • ARM_CLIENT_SECRET
  • ARM_TENANT_ID
  • ARM_ENVIRONMENT

最後に

今回は実際に Azure でデプロイできるサンプルコードとデプロイの流れを簡単にご紹介しました。
Terraform はコードを再利用するためにモジュールの仕組みもありますが、いきなりモジュールを分けて説明すると、理解が難しくなりますので、今回はすべてのデプロイ内容を一つの tf ファイルに記載しています。
モジュールに関しては、terraform-module記事で整理していたので、実際の運用で使いたい方は、ぜひ参考にしていただければと思います。

参考サイト

コメント

タイトルとURLをコピーしました