初めに
terraformで書いたクラウドリソースファイルのapplyをgithub Repositoryと連携、 正確には、github Actionsを利用して行えることがわかりました。 (TerraformとGitHub Actions(CI/CD)を用いたGitHub repositoryの管理) 今回は、「Terraform Cloud」をgithubと連携してより簡単に、CI/CDを実現して行きたいと思います。 Terraform CloudはほぼノーコードでCI/CDを実現できるのでかなり便利です。
以下のような方を想定読者として考えています。
- terraformのActionsを試した方。
- terraformの他のCI/CDを検討されてる方。
Terraform Cloud
HachiCorp社が提供する、TerraformのCI/CDに特化したサービス。プロジェクトの状態と履歴などを追跡して、変更の承認プロセスなどを自動化できます。 Terraform Couldは、AWS・Azure・GCP・Cloudflare・herokuなどのクラウドプロバイダーなどをサポートしています。
価格について
terraformのプレミアムサポートはつかないのと、「5ユーザー」までOrganizationで無料利用可能ぐらいで、 ほぼそれ以外の必要機能は利用できます。詳細はこちらよりご覧ください。
本記事で構築するアーキテクチャと技術
まず、github repositoryとterraform cloudのprojectを作成して監視するブランチを決めて連携します。 次に、開発者がtfファイルをgithub repositoryにpushしてTerraformがファイルの変更を検知し クラウドリソースに変更を加えます。今回は、クラウドプロバイダーにGCPを使用して、GCPのVMインスタンスをterraform Cloudから deployしていこうと思います。
開発ブランチ設計
ブランチと対応させる環境名について明示しておきます。branch:mainは本番環境(production)と対応させます。 branch:developは開発環境(development)と対応させます。
branch | 環境名 |
---|---|
main | 本番環境(production) |
develop | 開発環境(development) |
Let’s try
今回はprodとdevの環境作成は繰り返しなのでproduction環境で記述します。
Terraformディレクトリ設計について
terraformの管理方法には、各開発環境のディレクトリの中に、クラウドプロバイダーが提供するサービスごとに分けて各リソース事をDRYにして管理するやり方など ありますが、その分tf.stateのfile数が増えたりするデメリットもあったりします。
.
└── dev
└── gcp
├── gar
│ ├── main.tf
│ └── variable.tf
└── sql
├── main.tf
└── variable.tf
私は以下のディレクトリ構成が一番、開発者が一瞬でプロジェクトでどこに何がapplyされてるかを 把握できやすく、tfstateは各環境1ファイルのみの管理で運用しやすいかなと思っています。。
.
└── terraform
├── entrypoint #terraformを実際にapplyする対象ディレクトリ
│ └── gcp #terraform applyするクラウドプロバイダーごとに分ける
│ ├── dev #環境別に分ける
│ │ ├── main.tf
│ │ └── variable.tf
│ └── prod
│ ├── main.tf
│ └── variable.tf
└── modules #entrypointから呼び出す、terraformリソースのmoduleを定義する
└── gcp #クラウドプロバイダーごとに分けて上げる
└── compute_instance
├── main.tf
└── variable.tf
/entrypoint
実際にterraform apply
を行うディレクトリで、Terraform Cloudで参照するディレクトリです。 entrypoint/<クラウドプロバイダ>/<環境名>/main.tf
として定義します。
terraform/gcp/prod/main.tf
terraform {
backend "remote" {
organization = "mamushi" #自身で作成するOrganization名を記述
workspaces {
name = "terraform_cloud_exer_prod" #Organizationの中で作成するWorkSpace名を記述
}
}
required_providers {
google = {
source = "hashicorp/google"
version = "4.50.0"
}
}
}
provider "google" {
credentials = var.gcp_credentials # terraform cloudの環境変数で入力する
project = var.gcp_project
region = var.region
zone = var.zone
}
module "instance" {
source = "../../../modules/gcp/compute_instance"
machine_type = var.machine_type
name = var.gcp_project
}
terraform/gcp/prod/variable.tf
variable "gcp_credentials" {
description = "gcp credential"
}
variable "gcp_project" {
type = string
}
variable "region" {
type = string
}
variable "zone" {
type = string
}
variable "machine_type" {
type = string
description = "vm instance of machine type"
}
/module
実際にGCPなどのCloudプロバイダのリソースを定義する場所です。module/<クラウドプロバイダ>/<クラウドプロバイダで提供されるリソース>/main.tf
と定義します。 今回はGCPのVMインスタンスを立ち上げるので、こちらを参考にしてリソースを定義します。
terraform/gcp/compute_instance/main.tf
resource google_compute_instance default {
name = var.name //moduleの中で変数化しておき、entrypointのmain.tfから変数を入れる
machine_type = var.machine_type
zone = var.zone
boot_disk {
initialize_params {
image = "debian-cloud/debian-11"
labels = {
my_label = "value"
}
}
}
network_interface {
network = "default"
}
}
/gcp/compute_instance/variable.tf
variable "name" {
type = string
}
variable "machine_type" {
type = string
}
variable "zone" {
type = string
default = "asia-northeast1-a"
}
これらを記述したらgithubでディレクトリを作成してコードをpushします。
作成したリポジトリ
terraform cloudの設定
workspaceを立ち上げ&githubとリポジトリ接続
上記で作成したgithubのリポジトリとterraform Cloudのworkspaceをリンクさせます。
- New→workspaceを選択
- github連携
- workspace名を決定しworkspaceを作成
github repositoryの監視branchの設定
左バーからworkspace→settings→version control
で設定を行います。 今回production環境を適応するのでmainブランチを監視対象とします。
github repositoryの監視ディレクトリの設定
左バーからworkspace→settings→General
で設定を行います。Terraform Working Directory
で監視するgithubリポジトリのパスを入力します。 Apply Method
はいつのタイミングでterraform applyするか、Auto apply
のブランチに変更が入ったタイミングで動く方が 管理がしやすいです。設定したら保存するのをお忘れずに。
variable(変数)の設定
左バーからworkspace→variables
でterraform/gcp/prod/variable.tf
の変数の中身を定義してあげます。
- 実際の環境変数の追加
gcp_project
はGCPのProjectIDを入力、gcp_credentials
は、GCPのサービスアカウントから作成する秘密鍵のjsonをそのままコピペします。
- サービスアカウント及び、credential(json)
※この時、IAMアカウントも作成して、サービスアカウントと紐付けて下さい。この時、権限不足だとterraform apply
した時に、権限不足でapplyできなくなります。
- サービスアカウントからcredential(json)の作成
ダウンロードされたjsonをそのまま、環境変数のgcp_credentials
にコピペする
workspaceを跨いでtfstateを共有したい場合
左バーのworkspace→settings→General
のRemote state sharing
から別のworkspaceのtfstateを指定できます。 VPCなどをdevelopmentとproduction共通にしたい場合などに使用します。
実際にterraform applyをする
※この時、GCP側で、VMインスタンスのAPIを有効化しておかないとエラーがでます。 branch:mainにpushすると、リソースが作成され始めます。
実際に作成されたVMインスタンス
developmentは上記のworkspaceをdevelopment用に作り直して接続すればokです。
まとめ
今回、Terraform Cloudでの紹介をしました。Terraform Cloudを使用すれば、 コードを書く事なく、簡単にterraformで定義したコードをクラウドプロバイダーに適応できることがわかりました。 実際にはdeployに関することはTerraform Cloudに任せて、terraformのlintや、テストケース、ドキュメント作成に関してはgithub Actionsで動かしています。 ActionsとTerraform Cloudの使い分けは、terraformの純機能(terraform apply,terraform plan
など)のものは、Terraform Cloudで行い、サードパーティ製のものは、Actionsで行うといった形を取っています。
サービス | 環境名 |
---|---|
Terraform Cloud | terraformの純機能 |
Github Actions | terraformのサードパーティ製品のモジュール |
今回テストでGCPをターゲットにapplyをしました。AWSとGCPなどのクラウドプロバイダを選ぶ選定基準はこちらをご覧ください。
参考リンク
- tfsec:静的セキュリティスキャンとして使う
- terratest:terraformのテストケースをかける。kubernetesのテストケースもかける。
- terraform-docs:設定したterraform moduleのドキュメントを自動生成してくれる。