ユースケースクラウド

(連載) HashiCorp活用例3: 動的なDNSレコードの更新

東京エレクトロンデバイスではHashiCorp社製品とその他各社製品とのマルチベンダー連携を通じて、お客様のWebアプリやクラウド、ITインフラなどの展開から運用までを効率化できるソリューション開発に取り組んでいます。さまざまな活用例をご紹介することで、HashiCorp社製品の提供する価値や可能性を発信していきたいと思っております。

はじめに

本記事で取り扱うのは動的なDNSレコードの更新となります。

初回の記事で取り上げたユースケースに基づいて記載しておりますので、ユースケースの詳細につきましては過去の記事も併せてご参照ください。

連載記事一覧:

  1. Webアプリ用マルチベンダーインフラの自動構築
  2. 動的なバックエンドSSL証明書の管理
  3. 動的なDNSレコード管理           ←本記事
  4. 動的なロードバランサの構築
  5. プライベートネットワークでのIaC
  6. 一連のWebアプリ用のマルチベンダーインフラ展開を効率化   

動的なDNSレコード管理

本ユースケースの構成ではInfobloxという製品を用いて、動的なDNSレコードの更新を実現しています。

バックエンドで稼働するアプリケーションVM群は負荷状況に応じて増減(スケールアウト/イン)することを考えなければなりません。前回の記事では増減に伴うバックエンド間のSSL証明書の設置について解説しましたが、同様にDNSレコードの更新も付随して行われるべきです。

クラウド環境においては各ベンダーが用意したDNSサービスを利用することも可能ですが、今回はInfobloxという製品を使用することにより、オンプレミス環境やクローズドな環境でも動的なDNSレコード更新に対応できる構成を実現しています。

参考サイト:Infoblox

公式ページ(Infoblox社)※英語

製品紹介ページ(東京エレクトロンデバイス株式会社)


Infoblox(DNSサーバー)の構築と連携

以下の流れで環境構築を進めていきます

  1. Infobloxの構築
  2. DNSレコードへの登録

Infobloxの構築

今回のデプロイ環境ではクラウド版のイメージが提供されているため、そちらを利用してInfobloxのVMを作成します。
※マーケットプレイスのVMイメージを使用する際、初めて利用するVMイメージの場合、agreementの同意を求められる場合があります。その際はAgreementの設定も記載が必要です。

※Terraform構成ファイルの記述サンプル ◆LinuxVM 構築の宣言 resource "azurerm_linux_virtual_machine" "infoblox" {
  name                  = VM名
  location              = リージョン名
  resource_group_name   = リソースグループ名
  size                  = インスタンスサイズ名
  network_interface_ids = [azurerm_network_interface.infoblox-mgmt.id, azurerm_network_interface.infoblox-lan1.id] ←ネットワークインターフェイス名
  disable_password_authentication = false  ←パスワード認証の無効化(デフォルト:true)
  admin_username        = 初期ユーザー名
  admin_password        = 初期ユーザーパスワード

  source_image_reference {
    publisher = "infoblox"                   ←VMイメージ発行元
    offer     = "infoblox-vm-appliances-862" ←VMイメージのオファー
    sku       = "vsot"                       ←SKUの指定
    version   = "862.49947.0"                ←VMイメージのバージョン
  }
  plan {
      name      = "vsot"                       ←SKUの指定
      product   = "infoblox-vm-appliances-862" ←VMイメージのオファー
      publisher = "infoblox"                   ←VMイメージ発行元
  }
  os_disk {
    name                  = VMのOSディスク名
    storage_account_type  = ストレージタイプ
    caching               = OSディスクに使用するキャッシュタイプ
  }
  boot_diagnostics {
    storage_account_uri = ブート診断を保存するためのストレージアカウントURL
  }
  depends_on = [azurerm_network_interface_security_group_association.infoblox-mgmt-sg-ass]  ←依存関係の明示的宣言

  tags = タグの設定
}

◆ネットワークインターフェイスとセキュリティグループの関連付け 
resource "azurerm_network_interface_security_group_association" "infoblox-mgmt-sg-ass" {
  network_interface_id      = ネットワークインターフェイスID
  network_security_group_id = セキュリティグループID
}

resource "azurerm_network_interface_security_group_association" "infoblox-lan1-sg-ass" {
  network_interface_id      = ネットワークインターフェイスID
  network_security_group_id = セキュリティグループID
}

◆マーケットプレイスイメージ利用の同意
resource "azurerm_marketplace_agreement" "infoblox_agree" {
  publisher = VMイメージの発行元
  offer     = VMイメージのオファー
  plan      = イメージの利用プラン
}

Infoblox VMの起動が完了したら、InfobloxのGUIもしくはCLIで初期設定を行います。
※Infobloxの初期設定につきましては本記事での対象外となりますので、購入元へお問い合わせ下さい

Infoblox VMでDNSサービスの起動が完了した後、次のステップに進みます。

DNSレコードへの登録

DNSへのレコード登録はTerraformでアプリケーションVMを構築した際に行う設定です。また、今回は複数のアプリケーションVMを構築するためにTerraformのモジュールという機能を用いた記述方法となります。モジュールはテンプレートのような使い方ができます。

以下に設定サンプルを記載します。

※Terraform構成ファイルの記述サンプル

◆アプリケーションVM構築用モジュールの宣言
resource "azurerm_linux_virtual_machine" "vm" {
  name                            = "${var.prefix}-${random_id.id.hex}-${var.vm_name}" ←ポータル上のサーバー名
  location                        = リージョン名
  resource_group_name             = リソースグループ名
  size                            = サイズ名
  network_interface_ids           = ネットワークインターフェイス名
  computer_name                   = "${var.prefix}-${random_id.id.hex}-${var.vm_name}" ←サーバーのホスト名
  admin_username                  = var.admin_username ←初期ユーザー名
  disable_password_authentication = var.disable_password_authentication                             ←パスワード認証の許可
  admin_password                  = var.disable_password_authentication ? null : var.admin_password ←初期ユーザーのパスワード
  user_data                       = cloud-initで実行するスクリプト
  source_image_reference {
    publisher = VMイメージ発行元
    offer     = VMイメージのオファー
    sku       = SKUの指定
    version   = VMイメージのバージョン
  }

  os_disk {
    name                 = "${var.prefix}-${random_id.id.hex}-${var.vm_name}-osdisk" ←VMのOSディスク名
    storage_account_type = "Standard_LRS" ←ストレージタイプ
    caching              = "ReadWrite" ←OSディスクに使用するキャッシュタイプ
  }

  dynamic "boot_diagnostics" {
    for_each = var.create_storage_account ? { "sa" : "" } : {}
    content {
      storage_account_uri = azurerm_storage_account.sa[0].primary_blob_endpoint ←ブート診断を保存するストレージアカウントのURI
    }
  }

  dynamic "admin_ssh_key" {
    for_each = var.disable_password_authentication ? { "dpa" : "" } : {}
    content {
      username   = var.admin_username ←初期ユーザー名
      public_key = azurerm_ssh_public_key.sshpublickey[0].public_key ←初期ユーザー用SSH公開鍵
    }
  }
  # Added to allow destroy to work correctly.
  depends_on = [azurerm_network_interface_security_group_association.sgasc] ←関連性の明示。
  tags = var.tags ←タグ
}

上記はVM構築部分の抜粋でしたが、モジュールを利用する場合は関連するストレージアカウント等も併せてモジュールを利用することをお勧めします。
下記は上記モジュールを利用した場合のVM構築サンプルです。

※Terraform構成ファイルのサンプル
◆アプリケーションVM 構築の宣言(モジュール連携版)
module "demovm" {
  source = "./modules/terraform-azurerm-linux-vm" ←利用するモジュールの指定(↑の内容)
  count  = var.demovm_count                       ←カウント変数(作成数)

  resource_group_name    = リソースグループ名
  ssh_pub_key            = 公開鍵の指定
  subnet_name            = サブネット名
  network_name           = ネットワーク名
  tags                   = タグ
  vm_size                = インスタンスサイズ名
  admin_username         = 初期ユーザー名
  prefix                 = "ted-demo${count.index}" ←命名規則用のプリフィックス
  create_storage_account = true ←ストレージアカウント作成許可
  rules = [                     ←セキュリティグループ ルール
    {
      name                       = "https-fake" ←ルール名
      priority                   = "101"        ←優先度
      direction                  = "Inbound"    ←通信方向
      access                     = "Allow"      ←許可設定
      protocol                   = "Tcp"        ←プロトコル
      source_port_range          = "*"          ←アクセス元ポート範囲
      destination_port_range     = "10443"      ←通信先ポート範囲
      source_address_prefix      = "xxx.xxx.xxx.xxx" ←接続元IP範囲
      destination_address_prefix = "*"          ←通信先IP範囲
      description                = ルールの説明
    },
    {
      name                       = "ssh"        ←ルール名
      priority                   = "102"        ←優先度
      direction                  = "Inbound"    ←通信方向
      access                     = "Allow"      ←許可設定
      protocol                   = "Tcp"        ←プロトコル
      source_port_range          = "*"          ←アクセス元ポート範囲
      destination_port_range     = "22"         ←通信先ポート範囲
      source_address_prefix      = "xxx.xxx.xxx.xxx" ←接続元IP範囲
      destination_address_prefix = "*"          ←通信先IP範囲
      description                = ルールの説明
    }
  ]
}

上記に紐づくDNSレコードの登録については下記のように表現できます。

※Terraform構成ファイルの記述サンプル
locals {
  records = { for v in module.demovm : "${v.prefix}.${var.domain}" => v.private_ip_address["nic1"] } ←モジュール設定を通じて作成したVMのドメインとIPアドレスを取得
}

resource "infoblox_a_record" "a_rec" { ←上の処理で取得したFQDNとIPの組み合わせをInfoblox用に宣言
  for_each = local.records
  fqdn     = each.key
  ip_addr  = each.value
}

モジュールはテンプレートのように使うこともできますが、他にも内部的な処理を定義したり、その処理結果を変数(アウトプット)として利用できます。今回は上記のようにdemovmモジュールを使ってFQDNとIPを取得し、Infobloxへのレコード登録に利用しています。


次回案内

今回はアプリケーションVM構築に伴う動的なDNSレコードの登録についてご紹介しました。
すべて静的なパラメータで管理できるシチュエーションであればよいのですが、昨今のアプリケーション構成やデプロイ方法を考えると、クラウド、オンプレミス問わず、動的な変化に対応できることが必要となってくるのではないかと考えます。

次回は動的なロードバランサーの構築についてご紹介します。

ここまで読んでいただきありがとうございました。