自動化クラウド

【後編】IaCの標準化を支えるTerraform Stacks:概要と活用法を解説

前編では、Terraform Stacksの概要や構成について解説しました。本記事では、Terraform StacksをHCP Terraformで利用する方法を解説します。

前編はこちら>>【前編】IaCの標準化を支えるTerraform Stacks:概要と活用法を解説

ComponentsとDeploymentsの設定構成

最初にTerraform Stacksの設定がどのように構成されているかを、下記の構成で説明します。


|-- database
|   |-- main.tf
|   |-- outputs.tf
|   |-- terraform.tf
|   `-- variables.tf
|-- network
|   |-- main.tf
|   |-- outputs.tf
|   |-- terraform.tf
|   `-- variables.tf
|-- setup
|   |-- main.tf
|   |-- outputs.tf
|   |-- terraform.tf
|   `-- variables.tf
|-- vm
|   |-- main.tf
|   |-- outputs.tf
|   |-- terraform.tf
|   `-- variables.tf
|-- LICENSE
|-- README.md
|-- components.tfstack.hcl
|-- deployments.tfdeploy.hcl
|-- providers.tfstack.hcl
`-- variables.tfstack.hcl

Terraform Stacksは、1つ以上のComponentsで構成されており、各コンポーネントはTerraformモジュールで提供します。HCP Terraformは、Stack内の各Deploymentsに対してComponentsをすべてデプロイします。今回使用するComponentsは以下の通りで、Azure上に作成します。

Components 構成
network リソースグループ、仮想ネットワーク、サブネット
vm 仮想マシン
database Azure Database for MySQLフレキシブルサーバー

設定の説明

Componets設定には、providers.tfstack.hclとcomponents.tfstack.hclを使います。Deployments設定には、deployments.tfdeploy.hclを使います。

providers.tfstack.hcl
このファイルに、Terraform Providerを設定します。


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

provider "azurerm" "this" {
  config {
    features {}

    use_cli = false

    use_oidc = true
    oidc_token = var.identity_token
    client_id = var.client_id
    subscription_id = var.subscription_id
    tenant_id = var.tenant_id
  }
}

provider "tls" "this" {}
provider "random" "this" {}
provider "modtm" "this" {}

components.tfstack.hcl
このファイルに、各Componentsを設定します。network、vm、database用の各モジュールを呼び出します。


component "network" {
    source = "./network"

    inputs = {
        location = var.location
        prefix = var.prefix
        suffix = var.suffix
        cidr_range = var.cidr_range
        subnets = var.subnets
        tags = var.tags
    }

    providers = {
        azurerm = provider.azurerm.this
    }
}

component "vm" {
    source = "./vm"

    inputs = {
        location = var.location
        prefix = var.prefix
        suffix = var.suffix
        vm_subnet_id = try(component.network.subnet_ids[0], null)
        tags = var.tags
    }

    providers = {
        azurerm = provider.azurerm.this
        tls = provider.tls.this
        random = provider.random.this
        modtm = provider.modtm.this
    }
}

component "database" {
    source = "./database"

    inputs = {
        location = var.location
        prefix = var.prefix
        suffix = var.suffix
        tags = var.tags
    }

    providers = {
        azurerm = provider.azurerm.this
        random = provider.random.this
        modtm = provider.modtm.this
    }

    depends_on = [component.vm]
}

deployments.tfdeploy.hcl
このファイルに、デプロイ対象の環境を設定します。ここでは、devとprodの2つの環境に対してデプロイを行います。


locals {
  location = "japaneast"
  project = "tfstack-testing"
}

identity_token "azurerm" {
  audience = ["api://AzureADTokenExchange"]
}

deployment "dev" {
    inputs = {
        identity_token = identity_token.azurerm.jwt
        client_id = var.client_id
        subscription_id = var.subscription_id
        tenant_id = var.tenant_id

        location = local.location
        prefix = "tf-stack-dev"
        suffix = "202501"
        cidr_range = "10.0.0.0/16"
        subnets = {
            subnet1 = ["10.0.0.0/24"]
        }
        tags = {
            environment = "dev"
            project = local.project
        }
    }
}

deployment "prod" {
    inputs = {
        identity_token = identity_token.azurerm.jwt
        client_id = var.client_id
        subscription_id = var.subscription_id
        tenant_id = var.tenant_id

        location = local.location
        prefix = "tf-stack-prod"
        suffix = "202412"
        cidr_range = "10.1.0.0/16"
        subnets = {
            subnet1 = ["10.1.0.0/24"]
        }
        tags = {
            environment = "prod"
            project = local.project
        }
    }
}

Stackの設定

Project配下にStackを作成します。NewボタンをクリックしてStackをクリックすると、VCSとの接続画面が表示されます。

コードを管理しているリポジトリを選択して次に進みます。

Stack名を設定し、その他の設定はそのままにしてCreate Stackボタンをクリックします。

VCSとの接続が開始します。完了するとStackのページに移り、最初の設定(Configuration)がRolling outの状態になります。Deploymentsのdevとprodが承認待ちになります。

デプロイの実行

ここから、dev環境のデプロイを実行します。DeploymetsにあるdevのView planをクリックして、Planを表示します。

devがPlannedと表示されており、Planが実行されたことが分かります。Planの画面はWorkspaceで行うPlanの画面と似ていますね。

問題がなければ、Approve planボタンをクリックして承認します。これにより、Applyが実行されdevのPlanでApplyingと表示されます。

devのApplyが完了すると、自動的にもう1度Planが実行されます。

これは、遅延計画(Deferred Plan)と呼ばれ、デプロイ後にコンポーネント間の依存関係のチェックを行うのと同時に、要求したすべてのリソースが完全に作成できているかを検証します。2回目のPlanでは要求したリソースと実際の環境で差異がない場合、この図のようにNo changesと表示されApplyは実行されていません。
Azureの管理コンソールでもリソースが作成されたことが確認できました。

Deferred Planが特に有効なケースとして、Kubernetesクラスターとデプロイメントを作成する場合が挙げられます。この場合、クラスターが作成されるまで Kubernetes APIサーバーが利用できないため、初回のApplyで全てのリソースを作成することができません。クラスター作成後にPodやサービスをデプロイする必要があるため、このような段階的なリソース構築が必要となる状況で効果を発揮します。
prodはまだ承認待ちになっていますので、devと同様の手順でデプロイを実行します。

環境の削除

不要になった環境をそのままにすると、無駄な費用が発生するので削除しておきます。devを削除する場合は、Deploymentからdevをクリックして、左のペインからDestruction and deletionをクリックします。

次にCreate destroy planをクリックします。

その後、削除のPlanが実行されます。

問題がなければ、Approve planボタンをクリックします。

 

いかがでしたでしょうか。Terraform Stacks を利用することで、設定の重複を減らし、複数環境の構築を効率的に行える点や、シンプルな管理画面を通じてインフラのセットアップを容易に行える点をご理解いただけたかと思います。本記事執筆時点(2025年1月現在)ではベータ機能として提供されており、今後IaCの標準化をさらに高度に実現するための有力な機能として期待されています。

 

この記事に関連する製品・サービス

この記事に関連する記事