ブログ
Terraformで複数環境を構築する方法
所要時間:約5分
2021/09/08
ブログ
所要時間:約5分
2021/09/08
こんにちは。アクセンチュアのLiです。
いきなりですが、Terraformによる複数環境の管理は難しい!!!何の話かというと、システム開発では、dev(開発環境)、staging(ステージング環境)、prod(本番環境)など、リソース構成が類似するものの、差分が存在する複数環境を同時に運用しなければならないケースが多いですよね。
そのような複数環境をTerraformを活用してどのように管理すべきかは、非常に悩ましい問題です。ネットで検索すると、様々な会社に所属する方々が、ベストプラクティスを模索されているのがよくわかります。
私は、アクセンチュア転職後にTerraformを使いはじめて、TerraformのようなInfrastructure as Codeの考え方に基づいて、複数環境の管理・運用を経験してきました。
いくつかの案件を経験する中で、時にはTerraformを一生懸命コーディングしたものの思ったとおりに動かない!というような苦労をする時期もありました。最近ようやく「どの案件でも、こういった部分は共通的に実装するとよいな」というポイントのようなものが見えてきました。
本記事では、これまで現場で経験したTerraformでの環境実装や運用経験を振り返りつつ、複数環境の実装・運用時の留意点をシェアしたいと思います。
本記事では、 Terraform workspaceを活用して、複数環境の管理・運用を行う方法をご紹介します。Terraformは複数のクラウドプラットフォームをサポートしていますが、本記事ではGoogle Cloud Platform(以下、GCP)を例にしています。
たとえば、GCP上に「dev」、「staging」、「prod」という3環境があるとします。devとstaging環境には、テスト用のGoogle Cloud Storage(以下、GCS)バケット(例:{環境識別子}-mybucket01、{環境識別子}-mybucket02)を作成するが、prod環境に作成したくない、という要件があるとします。環境ごとに.tfファイルを作成し、terraform applyすることも可能ですが、Terraform workspaceを使えば、複数環境のリソースを同じ.tfファイルにまとめることができます。
実装上のポイントは以下のとおりです。なお、以下のサンプルコードではTerraformモジュールを使っていますが、必須ではありません。
Terraformのディレクトリには、以下のようにファイルを配置します。
├── backend.tf
├── main.tf
├── module
│ ├── gcs.tf
│ └── variables.tf
└── provider.tf
ファイルおよびディレクトリについての説明です。
.tfファイルのうち、複数環境の制御に関わるファイルについて、ファイル単位で解説します。
locals {
gcs_names = {
mybucket01 = "${terraform.workspace}-mybucket01"
mybucket02 = "${terraform.workspace}-mybucket02"
}
enabled = {
dev = true
staging = true
prod = false
}
storage_class = {
dev = "STANDARD"
staging = "STANDARD"
prod = "STANDARD"
}
location = {
dev = "asia1"
staging = "asia1"
prod = "asia1"
}
}
module "gcs_mybucket01" {
source = "./module/"
enabled = local.enabled[terraform.workspace]
name = local.gcs_names["mybucket01"]
location = local.location[terraform.workspace]
storage_class = local.storage_class[terraform.workspace]
}
module "gcs_mybucket01" {
source = "./module/"
enabled = local.enabled[terraform.workspace]
name = local.gcs_names["mybucket02"]
location = local.location[terraform.workspace]
storage_class = local.storage_class[terraform.workspace]
}
resource "google_storage_bucket" "bucket" {
count = var.enabled ? 1 : 0
project = var.project
name = var.name
location = var.location
storage_class = var.storage_class
}
variable enabled {
type = string
default = "false"
description = "リソースを作成するか"
}
variable project {
type = string
default = "xxxxxxxxx"
description = "GCS作成先のGCPプロジェクトID"
}
variable name {
type = string
default = ""
description = "バケット名"
}
variable location {
type = string
default = "asia1"
description = "バケットのロケーション"
}
variable storage_class {
type = string
default = "STANDARD"
description = "ストレージのクラス"
}
上記サンプルコードのように、count、terraform workspaceと条件式を活用することで、同じ.tfファイルで複数環境のリソースを管理できるようになります。 このようなコード設計で環境を行い、メリットと感じた点、および、ソースコードを工夫して修正した場面は以下のとおりです。
以上、Terraformで複数環境の実装・運用方法と留意点を整理してみました。
環境管理のほかの方法として、例えば「Terraform: Up & Running: Writing Infrastructure As Code」( Yevgeniy Brikman (著))では、異なる環境のリソース定義を異なるリソースセット(.tfファイル)として管理する、という方法を紹介しています。
私が参画している案件では、上記のリソース管理する方針を採用するケースが多いですが、ディレクトリを分けたり、環境依存情報を敢えてハードコードしたりするケースもあります。
どのように複数環境を管理するかは、Terraformで管理したいリソースの特徴、チーム構成、リポジトリ構成やCI/CD等を考慮に入れる必要があると思います。ビジネス要件の複雑さは、1つの方法のみで管理できるものではなく、状況に応じて最適解を常に考え続ける必要があります。
Terraformも常に進化しており、未来のバージョンでは、複数環境の管理がさらに容易に管理できるよう、機能追加がなされるものと期待しております。 また、TerraformコミュニティやTerraformのGitリポジトリもウォッチしていきたいと思います。
最後に、Terraformと似ていますが、異なるアプローチであるConfiguration as Dataの考え方についても気になっており、キャッチアップの途中です。また知見が纏まりましたら、ご紹介したいと思います!