Terraformの導入 - 検証環境をコマンドで立ち上げられるようにする その1 - 2020-05-25 - ククログ

ククログ

株式会社クリアコード > ククログ > Terraformの導入 - 検証環境をコマンドで立ち上げられるようにする その1

Terraformの導入 - 検証環境をコマンドで立ち上げられるようにする その1

はじめに

クラウドサービスをコマンドラインで操作した方が楽に目的の環境作成ができると言うことに気づいた畑ケです。 Terraformと言うクラウド上のリソースを作成するツールがあります。TerraformでAWS, Azure, GCPなど各種クラウドのリソースの状態を定義し、作成できます。

AzureでWindowsのインスタンスを作成するには

AzureでWindowsのインスタンスを作成するには、以下のものを定義して作成する必要があります。

  • リソースグループ

  • バーチャルネットワーク

  • サブネット

  • ネットワークインターフェース

  • 仮想マシンの設定

また、Azureに立ち上げた仮想マシンに対して、プロビジョニングやssh, RDPで接続するためには追加で以下の設定も必要です。

  • セキュリティグループ

  • ネットワークインターフェースとセキュリティグループのアソシエーション(関連づけ)

  • パブリックIPアドレス

Azure上のWindows 10のインスタンスについてはボリュームライセンスを用意する必要があります。ライセンス認証については https://docs.microsoft.com/ja-jp/windows/deployment/windows-10-subscription-activation の記事をご覧ください。 この記事ではWindows Server 2019 Datacenterを用いて解説します。

実際に作成してみる

Terraformはディレクトリにある拡張子tfのファイルを読み込みます。また、必要なモジュールはproviderブロックで指定する必要があります。

Terraformを使用する準備

Terraformのインストール

Terraformを使用するには、まずTerraformをインストールする必要があります。 https://www.terraform.io/downloads.html から使用するプラットフォームに応じた実行ファイルをインストールします。

Azureコマンドラインフロントエンドをインストール

Terraformを使用するためには、Azureから認証情報を取得する必要があります。Azureをコマンドラインから操作するコマンドはazです。 https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli?view=azure-cli-latest を参考に使用するプラットフォーム応じた実行ファイルをインストールします。

Terraform用の認証情報の作成

Terraformを使用するには、Terraform用に認証情報を作成する必要があります。

先ほどインストールしたAzure CLIのazを使ってAzureにログインします。

$ az login

Azureへのログインが成功すると、az account listにより、以下の情報をとることができます。

$ az account list
[
  {
    "cloudName": "AzureCloud",
    "id": "00000000-0000-0000-0000-000000000000",
    "isDefault": true,
    "name": "AN USER Subscription",
    "state": "Enabled",
    "tenantId": "00000000-0000-0000-0000-000000000000",
    "user": {
      "name": "user@example.com",
      "type": "user"
    }
  }
]

ここで、idはサブスクリプションのIDです。これを、SUBSCRIPTION_ID環境変数に代入します。

$ export SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000"

続いて、以下のコマンドを実行すると、appIdとpasswordと認証トークンを取得できます。

$ az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/${SUBSCRIPTION_ID}"
{
  "appId": "00000000-0000-0000-0000-000000000000",
  "displayName": "azure-cli-2020-05-18-04-58-43",
  "name": "http://azure-cli-2020-05-18-04-58-43",
  "password": "00000000-0000-0000-0000-000000000000,
  "tenant": "00000000-0000-0000-0000-000000000000
}

idの値をARM_SUBSCRIPTION_IDに設定し、appIDの値をARM_CLIENT_IDに設定し、passwordの値をARM_CLIENT_SECRETに設定し、tenantの値をARM_TENANT_IDに設定します、

export ARM_SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000"
export ARM_CLIENT_ID="00000000-0000-0000-0000-000000000000"
export ARM_CLIENT_SECRET="00000000-0000-0000-0000-000000000000"
export ARM_TENANT_ID="00000000-0000-0000-0000-000000000000"

ここまでの準備で、Terraformが読み取る環境変数にAzureの認証情報を格納することに成功しました。

使用するプロバイダー

この記事ではAzureにWindowsの検証環境を作成する想定でmain.tfへTerraformのスクリプトを書き進めていきます。

そのため、azurerm プロバイダーを使用します。

terraform {
  required_version = ">= 1.1.3"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>2.10"
    }
  }
}

provider "azurerm" {
  features {}
}

(2022年1月14日追記:例を最新のTerraformの仕様に合わせて更新しました)

リソースグループ

Azureでは、リソースを作成する前に、リソースがどのリソースグループに属するかを指定しないといけません。そのため、リソースグループを指定するリソースグループを作成します。

resource "azurerm_resource_group" "clearcode" {
  name     = "ExampleClearCodeResourceGroup"
  location = "Japan East"
}

AzureRMにおけるリソースグループに関して詳しくは https://www.terraform.io/docs/providers/azurerm/r/resource_group.html を参照してください。

バーチャルネットワーク

Azureでは、インスタンスが属するバーチャルネットワークを指定する必要があります。ローカルネットワークのIPアドレスには10.0.0.0/8のクラスAアドレスを使用することができます。1 この例では、10.5.0.0/16(10.5.0.0 ~ 10.5.255.255)を切り出して使用することにします。

# Create a virtual network in the production-resources resource group
resource "azurerm_virtual_network" "clearcode" {
  name                = "clearcode-network"
  resource_group_name = azurerm_resource_group.clearcode.name
  location            = azurerm_resource_group.clearcode.location
  address_space       = ["10.5.0.0/16"]
}

AzureRMにおけるバーチャルネットワークに関して、詳しくは https://www.terraform.io/docs/providers/azurerm/r/virtual_network.html を参照してください。

サブネット

Azureでは、大元のバーチャルネットワークを定義したら、その次はインスタンスが直接属するサブネットを定義する必要があります。 internalサブネットを以下のように定義します。(10.5.2.0 ~ 10.5.2.255の範囲とします。)

resource "azurerm_subnet" "internal" {
  name                 = "internal"
  resource_group_name  = azurerm_resource_group.clearcode.name
  virtual_network_name = azurerm_virtual_network.clearcode.name
  address_prefixes       = ["10.5.2.0/24"]
}

AzureRMのサブネットに関して詳しくは https://www.terraform.io/docs/providers/azurerm/r/subnet.html を参照してください。

ネットワークインターフェース

Azureのインスタンスの設定に行く前にさらに設定が要ります。インスタンスに紐付けるネットワークインターフェースの設定です。 このネットワークインターフェースの設定を行うことで、インスタンスにようやくネットワーク設定が紐付けされます。

resource "azurerm_network_interface" "testing" {
  name                = "clearcode-testing-instance-nic"
  location            = azurerm_resource_group.clearcode.location
  resource_group_name = azurerm_resource_group.clearcode.name

  ip_configuration {
    name                          = "testing-instance-nic"
    subnet_id                     = azurerm_subnet.internal.id
    private_ip_address_allocation = "Static"
    private_ip_address            = "10.5.2.4"
  }
}

AzureRMのネットワークインターフェースに関して詳しくは https://www.terraform.io/docs/providers/azurerm/r/network_interface.html を参照してください。

これで、インスタンスに紐付けるネットワークインターフェースの設定ができました。

Windowsインスタンス

ようやくここで、インスタンスに紐付ける最低限のリソースの作成ができました。

Windows Server 2019 Datacenterのインスタンスの設定を書き下してみます。

resource "azurerm_virtual_machine" "winservtesting" {
  name                             = "clearcode-testing-winserv-vm"
  location                         = azurerm_resource_group.clearcode.location
  resource_group_name              = azurerm_resource_group.clearcode.name
  network_interface_ids            = [azurerm_network_interface.testing.id]
  vm_size                          = "Standard_B2S"
  delete_os_disk_on_termination    = true
  delete_data_disks_on_termination = true

  storage_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2019-Datacenter"
    version   = "latest"
  }

  storage_os_disk {
    name              = "2019-datacenter-disk1"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
    os_type           = "Windows"
  }

  os_profile {
    computer_name  = "cc-winserv"
    admin_username = "clearcode"
    admin_password = "CC/changeme1"
  }

  os_profile_windows_config {
    enable_automatic_upgrades = true
    provision_vm_agent        = true
  }

  tags = {
    CreatedBy = "clearcode"
    Purpose   = "Describe Terraform instruction"
  }
}

AzureRMのバーチャルマシンについて詳しくは https://www.terraform.io/docs/providers/azurerm/r/virtual_machine.html を参照してください。

実際にデプロイしてみる

ここまでの設定が書けたら、実際にデプロイしてみましょう。今回はパブリックIPアドレスを指定していないので、インターネットからのアクセスはできません。

$ terraform init

以下のようなログが出力されれば、Terraformの初期化に成功しています。


Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "azurerm" (hashicorp/azurerm) 2.10.0...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

デプロイする前に、terraformの設定の齟齬がないかをplanサブコマンドで確認してみましょう。

$ terraform plan

# ...

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

どうやらplanの段階ではエラーはないようです。

applyしてリソースを実際に作成してみましょう。

$ terraform apply -auto-approve

ここまでに作成したTerraformのスクリプトは、 https://gitlab.com/clear-code/terraform-example/-/tree/708283aaeeb8f9f389d4cdc45560d6817ce0ac83 に置いてあります。

まとめ

TerraformでAzureのインスタンスを立ち上げる最低限のところまでを解説しました。今回立ち上げたWindows Server 2019 DatacenterのインスタンスはパブリックIPアドレスを持たないため、Azure内部の同じサブネットワークのインスタンスからしか接続することができません。そのため、サンプルのTerraformスクリプトはセキュリティに関する記載がありません。 次回の記事では、セキュリティグループの作成や、公開リポジトリに置く際にtfvarsファイルを使って変数を外出しするテクニックを紹介します。

  1. RFC 1918 https://tools.ietf.org/html/rfc1918 のSection 3にて10/8プレフィックスのアドレスとして例示されている。