Terraform Modulesで環境を分割・切り替える

2022-04-22

Terraform Modulesはソースコードをモジュール化することでテンプレートとして使うことができるようになる機能です。
この記事では、Terraform Modulesを利用した本番・検証などの環境分割・切り替えの方法についてご紹介します。

Terraform の入門内容については以下の記事を参照してください。

Terraform Modulesとは

Terraform Modules は、ディレクトリなどにまとめた Terraform のコードをテンプレート・モジュールとして呼び出して利用することができる機能です。
以下のように呼び出します。

module "リソースの名前" {
    source = "モジュールを定義したフォルダのパス"
    パラメーター名 = "パラメーター値"
}

また、自身で作成した Module ではなく Terraform Registry で提供されているモジュールは以下のように呼び出すことができます。
AWS VPC Terraform module の例です。

module "vpc" {
  source = "terraform-aws-modules/vpc/aws"
  // 以降、変数へ値を代入する
}

本記事では Terraform Modules を利用した環境分割方法について記載しますが、他にも Workspaces を利用した方法もあります。

命名規則

この記事でご紹介する例は下記の記事の命名規則に従っています。

環境分割方法

あくまで筆者独自の方法なので参考までにお願いします。
ディレクトリ構成は以下の通りです。

.
├── env         # 環境差分用ディレクトリ
│   ├── prd       # prd 環境用ディレクトリ
│   │   └── main.tf # 環境差分に応じたTerraformバージョン、Provider、Backend、変数、Module、Outputsの設定
│   ├── stg       # stg 環境用ディレクトリ
│   │   └── main.tf
└── modules     # 各環境共通で利用する resources をモジュール化
    ├── sample-vpc.tf  # resource(sampleサービスのVPC) の設定を記述
    ├── ...            # resource(その他) の設定を記述
    ├── variables.tf   # Module 内で利用する変数定義
    └── outputs.tf     # outputし、他のリソースから tfstate ファイル経由で参照されるデータを記載

使い方は対応する環境をカレントディレクトリとして、 terraform コマンドを実行するだけです。

# プロジェクトの初期化
$ cd env/[環境]
$ terraform init

# ファイルフォーマット
$ cd env/[環境]
$ terraform fmt ../../modules
$ terraform fmt

# 個別のリソースのterraform 初期化
$ cd env/[環境]
$ terraform init

# 個別のリソースの設定確認
$ cd env/[環境]
$ terraform validate

# 個別のリソースの差分確認
$ cd env/[環境]
$ terraform plan

# 個別のリソースの適用
$ cd env/[環境]
$ terraform apply

# 個別のリソースの削除
$ cd env/[環境]
$ terraform destroy

以降で個々のファイルについて説明していきます。
aws_vpc を 1 つ構築する簡易な例になっています。

env/[環境]/main.tf

modules の呼び出し元です。
../../modules でモジュールを呼び出して modules/variables.tf に定義した変数に値を代入します。
これによって環境差分を実現できます。
modules の他にも必要に応じて変数を定義してください。

また、 output でリソースの設定結果を出力する対象について記載します。
modules/outputs.tf に記載した modulesoutput を実際に出力します。

#####################################
# Terraform Settings
#####################################
terraform {
  required_version = "~> 1.1.0" // Terraform のバージョン
  required_providers {          // Provider の設定
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"        // AWS Provider のバージョン
    }
  }
  backend "s3" {                 // この設定で State ファイルが S3 に保存されます
    bucket = "your-bucket-name"  // State ファイルを配置するバケット
    key    = "terraform.tfstate" // State ファイルを配置するパス・ファイル名
    region = "ap-northeast-1"    // S3のリージョン
  }
}

#####################################
# Provider Settings
#####################################
provider "aws" {
  region  = local.region
  profile = var.profile
  default_tags { // AWS リソースへのデフォルトタグの設定
    tags = {
      System    = local.system
      Env       = local.env
      Terraform = "true"
    }
  }
}

#####################################
# Variables
#####################################
variable "profile" {}
locals {
  region = "ap-northeast-1"
  system = "system"
  env    = "prd"
}

#####################################
# Module
#####################################
module "modules" {
  source = "../../modules"

  #####################################
  # Common Variables
  #####################################
  system    = local.system
  region    = local.region
  env       = local.env
  base_name = "${local.system}-${local.env}"

  #####################################
  # VPC Variables
  #####################################
  vpc_cidr_block = "10.0.0.0/16"
}

#####################################
# Outputs
#####################################
output "sample_vpc" {
  value = module.modules.sample_vpc
}

Provider の設定では default_tags を変数で代入する形で設定しておくと非常に便利です。

modules/variables.tf

modules 内で利用される変数を管理するファイルです。
env/[環境名]/main.tf にて変数に値を代入します。
これによって環境差分を実現できます。

#####################################
# Common Variables
#####################################
variable "region" {}
variable "system" {}
variable "env" {}
variable "base_name" {}

#####################################
# VPC Variables
#####################################
variable "vpc_cidr_block" {}

modules/outputs.tf

output でリソースの設定結果を出力する対象について記載したファイルです。
なお注意しなければならないのは、このファイルはあくまで modules からのアウトプットです。
env/[環境名]/output.tfmodules/outputs.tf からのアウトプットをマッピングする必要があります。

#####################################
# VPC
#####################################
output "sample_vpc" {
  value = aws_vpc.sample
}

modules/sample-vpc.tf

Amazon VPC のリソース定義を記載します。

#####################################
# VPC
#####################################
resource "aws_vpc" "sample" {
  cidr_block = var.vpc_cidr_block
  tags       = merge(tomap({ "Service" = "sample" }), tomap({ "Name" = "${var.base_name}-sample" }))
}

おすすめ書籍

おすすめ記事