Terraformを使用した際の環境差分の表現方法

f:id:y-ohgi:20190603224513p:plain

TL;DR

  • プロダクションでは往々にして複数環境を構築する
  • Terraform単体だとworkspaceを使用すると良い感じになる

概要

Terraformのサンプルでは -var-file オプションで環境を切り替えることがあります。
例えば以下のように。

$ terrafrom plan -var-file=stg.tfvars
$ terrafrom plan -var-file=prd.tfvars

これでも問題はないのですが、 -var-file の場合tfstateがうまく扱えないことがあります。
そのtfstateをうまいこと分離してくれるのが、workspaceを用いた環境の切り替え方法です。

サンプル

コードを見たほうがはやいでしょう。
今回はcidrレンジが異なるVPCをステージングと本番環境の構築を例に上げます

GitHub: https://github.com/y-ohgi/terraform-workspace

使い方

How to Use

1. 初期化

$ terraform init

2. workspaceの選択

$ terraform workspace new stg
$ terraform workspace select stg

3.プロビジョニング

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + aws_vpc.main
      id:                               <computed>
      arn:                              <computed>
      assign_generated_ipv6_cidr_block: "false"
      cidr_block:                       "10.0.0.0/16"
      default_network_acl_id:           <computed>
      default_route_table_id:           <computed>
      default_security_group_id:        <computed>
      dhcp_options_id:                  <computed>
      enable_classiclink:               <computed>
      enable_classiclink_dns_support:   <computed>
      enable_dns_hostnames:             <computed>
      enable_dns_support:               "true"
      instance_tenancy:                 "default"
      ipv6_association_id:              <computed>
      ipv6_cidr_block:                  <computed>
      main_route_table_id:              <computed>
      owner_id:                         <computed>
      tags.%:                           "1"
      tags.Name:                        "myapp-stg"


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

ディレクトリ構成

ステージングと本番環境を用意する場合、以下のような切り方を行います。

.
|-- README.md
|-- main.tf
|-- variables.tf
|-- variables_prd.tf
`-- variables_stg.tf

main.tf

providerの定義とVPCの定義を行います。

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_vpc" "main" {
  cidr_block = "${local.workspace["vpc_cidr"]}"

  tags = {
    Name = "${local.name}"
  }
}

ポイントは "${local.workspace["vpc_cidr"]}" です。
それ以外はよく見るTerraformの書き方だとおもいます。

variables.tf

locals {
  workspaces = {
    default = "${local.stg}"
    stg     = "${local.stg}"
    prd     = "${local.prd}"
  }

  workspace = "${local.workspaces[terraform.workspace]}"

  name = "myapp-${terraform.workspace}"
}

variables_stg.tf

locals {
  stg = {
    vpc_cidr = "10.0.0.0/16"
  }
}

variables_prd.tf

locals {
  prd = {
    vpc_cidr = "10.1.0.0/16"
  }
}

まとめ

workspaceを使うとバックエンド側のtfstateをきれいに管理できるので .tfvar より個人的に好きです。