📌

Azureのブート診断の有効化をTerraformだけで完結できないからGUIとの合わせ技でゴリ押しする

2021/08/04に公開

0. はじめに

こんにちは。都内でエンジニアをしている、@gkzvoiceです。

AzureでLinux VMをデプロイする必要に迫られ、Azureのドキュメントを読み漁っていたところ、「ブート診断」なるものを知りました。後述しますが、このブート診断はかゆいところに手が届くサービスだと感じたので、Terraformでブート診断の設定を試みることにしました。

1.本記事における問題意識の共有

しかし、表題のとおり、Terraformだけでブート診断の設定をおこなうことはできませんでした。そこで、本記事にTerraformだけでブート診断を設定するためにおこなったこと、引いたエラー、そして今できる打ち手を書き残しておくこととします。

※ 本記事では、Terraformについては必要以上にフォーカスしません。Terraformの基本的な使い方については、手前味噌ですが、以下の記事をご参照ください。

[Azure]TerraformでWindows Virtual Machineでデプロイするまでにおこなったこと

2. 「Azureのブート診断」を使うとできること

Azureのドキュメントでは、以下のような説明がされています。

ブート診断は、VM ブート エラーの診断を可能にする、Azure の仮想マシン (VM) のデバッグ機能です。 ブート診断を使用すると、ユーザーは、シリアル ログ情報とスクリーンショットを収集して、起動中の VM の状態を確認できます。

参考:Azure のブート診断 - Azure Virtual Machines | Microsoft Docs

ブート診断を使うと、以下のようなログなどが確認できます。

  • VMをデプロイした後に表示されるVMのログイン画面のスクリーンショット(以下の画像の左側)
  • VMをデプロイするまでのシリアルログ(以下の画像の右側)
    • ログの末尾には successfully running と出力されている

2-1.ユースケース(予想)

実務で使ったことがなく、個人の検証環境で使ってみたという前提での予想ですが、以下のようなユースケースは考えられるのではないでしょうか?

  • 起動しているはずだけどVMにリモートアクセスできない といった際にデバッグし、原因の究明に役立てる

2-2.VMのログイン画面のスクリーンショットとデプロイするまでのログの格納場所

VMのログイン画面のスクリーンショットとデプロイするまでのログの格納場所は、Azure Storage アカウントです。

なお、IaaSやオンプレミスでVMをデプロイする際にも聞く「ディスク」はAzure Storage アカウントとは別物です。「ディスク」は以下の画像でいう「管理ディスク」にあたります。

画像の出所: Azure での Windows VM の実行 - Azure Reference Architectures | Microsoft Docs (赤い枠は筆者が編集)

3. 環境情報

- ローカル(Terraform実行環境)
  - Ubuntu 20.04.2 LTS
  - Terraform v1.0.0
  - azure-cli 2.61.0

- TerraformでデプロイするVM
  - Ubuntu 18.04
   - Standard F2

4. TerraformだけでAzureのブート診断を有効化するためにtfファイルに書いたこと

[ポイント1]ブート診断のスクリーンショットやシリアルログを用意するために"azurerm_storage_account"リソースを使う

:::messages

  • ストレージアカウントはオブジェクトストレージなので、名前はユニークとしなければならない。
  • そこで"random_id"リソースを使ってストレージアカウントの名前を生成することとした。(*1)

ストレージ アカウントでは、世界中のどこからでも HTTP または HTTPS 経由でアクセスできる Azure Storage データ用の一意の名前空間が提供されます。

参考:ストレージ アカウントの作成 - Azure Storage | Microsoft Docs
:::

main.tfより抜粋

resource "azurerm_storage_account" "main" {
    ## *1: "random_id"リソースを使ってストレージアカウントの名前を生成
    ## ここでは"boot diagnostics"の"diag"をprefixとしている
    name                        = "diag${random_id.main.hex}"
    location            = azurerm_resource_group.main.location
    resource_group_name         = azurerm_resource_group.main.name
    account_replication_type    = "LRS"
    account_tier                = "Standard"
}

resource "random_id" "main" {
    keepers = {
        # Generate a new ID only when a new resource group is defined
        resource_group = azurerm_resource_group.main.name
    }

    byte_length = 8
}

参考:https://github.com/gkzz/azure-provider-terraform-linux/blob/main/main.tf#L171:#L191

[ポイント2]"azurerm_linux_virtual_machine"リソースのboot_diagnosticsブロックにて、ポイント1で作成したストレージアカウントを指定

main.tfより抜粋

resource "azurerm_linux_virtual_machine" "main" {
  name                = "${var.prefix}-vm"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  size                = "Standard_F2"
  admin_username      = "${var.admin_username}"
  network_interface_ids = [
    azurerm_network_interface.main.id,
  ]

  admin_ssh_key {
    #略
  }

  os_disk {
    #略
  }

  source_image_reference {
    #略
  }

  boot_diagnostics {
        enabled = "true"
        storage_account_uri = azurerm_storage_account.main.primary_blob_endpoint
  }
}

参考:https://github.com/gkzz/azure-provider-terraform-linux/blob/main/main.tf#L66:#L169

それでは、tfファイルが書けているか確認するためにterraform planしてみましょう。

5. terraform planしてみると、、、

エラーとなってしまいました。以下のエラーメッセージを読むと原因は
"azurerm_linux_virtual_machine"リソースのboot_diagnosticsブロックで、enabled = "true" と書いてしまったことと考えてよさそうです。

main.tfより抜粋

resource "azurerm_linux_virtual_machine" "main" {
  name                = "${var.prefix}-vm"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  size                = "Standard_F2"
  admin_username      = "${var.admin_username}"
  network_interface_ids = [
    azurerm_network_interface.main.id,
  ]

  #略

  boot_diagnostics {
        enabled = "true"
        storage_account_uri = azurerm_storage_account.main.primary_blob_endpoint
  }
}

6. "azurerm_linux_virtual_machine"リソースでenabled=trueとすることができないか調べたこと

  • Azureのドキュメントによると、Azure Resource Manager (ARM) テンプレートでは使うことができるみたい
    • ※ 手元で未検証
 "diagnosticsProfile": {
     "bootDiagnostics": {
         "enabled": true
      }
 }

参考:Azure のブート診断 - Azure Virtual Machines | Microsoft Docs

  • Terraformのドキュメントでも、boot_diagnosticsブロックは**enabled**をサポートしていると記載されていた

    • A boot_diagnostics block supports the following:

      ・enabled - (Required) ty

      ・storage_uri - (Required) The Storage Account's Blob Endpoint which should hold the virtual machine's diagnostic files.

参考:azurerm_virtual_machine | Resources | hashicorp/azurerm | Terraform Registry

::: messages

:::

7. TerraformだけでAzureのブート診断を有効化できないからどうしたか

TerraformとGUIの合わせ技でブート診断を有効化としました。Terraformでストレージアカウントを作成し、GUIでブート診断を有効化とするようなかんじです。

7-1.Terraformでストレージアカウントを作成

  • "azurerm_linux_virtual_machine"リソースのboot_diagnosticsブロックから、enabled = "true"を削除
  • "azurerm_storage_account"リソースと"random_id"リソースは上記で書いたものをそのまま使う
main.tfから"azurerm_linux_virtual_machine"リソースと"azurerm_storage_account"リソースと"random_id"リソースを抜粋
略

resource "azurerm_linux_virtual_machine" "main" {
  name                = "${var.prefix}-vm"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  size                = "Standard_F2"
  admin_username      = "${var.admin_username}"
  network_interface_ids = [
    azurerm_network_interface.main.id,
  ]

  admin_ssh_key {
    #略
  }

  os_disk {
    #略
  }

  source_image_reference {
    #略
  }

  boot_diagnostics {
        # enabled = "true"
        storage_account_uri = azurerm_storage_account.main.primary_blob_endpoint
  }
}

resource "azurerm_storage_account" "main" {
    name                        = "diag${random_id.main.hex}"
    location            = azurerm_resource_group.main.location
    resource_group_name         = azurerm_resource_group.main.name
    account_replication_type    = "LRS"
    account_tier                = "Standard"
}

resource "random_id" "main" {
    keepers = {
        # Generate a new ID only when a new resource group is defined
        resource_group = azurerm_resource_group.main.name
    }

    byte_length = 8
}
  • "azurerm_storage_account"のnameのoutputを設定(後続の設定で"azurerm_storage_account"のnameを使うので)
output.tfから抜粋
output "azurerm_storage_account_name" {
  value = azurerm_storage_account.main.name
}

7-2.GUIでブート診断を有効化

  • terraform apply後、出力される「ストレージアカウント」を確認するでデプロイしたVMの画面左のタブを下にスクロールして、「診断設定」をクリック

  • 「ストレージアカウントを選択します」の下のタブから"azurerm_storage_account"のnameを選択
    • prefixが"diag"となっているはず!
  • 「ゲスト レベルの診断を有効にする」をクリック

  • しばらくすると以下のような画面に切り替わるので「ブート診断を表示する」をクリック

    • 画面右上のポップアップにて、ブート診断が有効となったと通知が届く
  • 以下のようにVMのスクリーンショット(画面左)とログ(画面右)が表示され、ブート診断が有効となっていることが確認できる

8. 今後の展望

現時点ではブート診断の設定がTerraformだけで完結することは難しいようですが、ドキュメントが先行している?ことから、Terraformだけでブート診断の有効化ができる日はそう遠くはないのかもしれません。

もっといいブート診断の有効化の設定方法があればコメントなどで教えていただけるとうれしいです。

P.S. AzureでTerraformを使ってLinux VMをデプロイするサンプルコード

https://github.com/gkzz/azure-provider-terraform-linux

P.P.S. Twitterもやってるのでフォローしていただけると泣いて喜びます:)

@gkzvoice

Discussion