以下の環境をterraformで管理していると仮定する
- develop:開発環境
- staging:試験環境
- main:本番環境
develop環境向け
- terraform-dev-dryrun : dryrunプロジェクト
- terraform-dev : releaseプロジェクト
staging環境向け
- terraform-stg-dryrun : dryrunプロジェクト
- terraform-stg : releaseプロジェクト
main環境向け
- terraform-prd-dryrun : dryrunプロジェクト
- terraform-prd : releaseプロジェクト
.
├── backend.tf
├── builder
│ ├── build.yml
│ └── dryrun.yml
├── config
│ ├── dev
│ │ ├── ap-northeast-1.backend
│ │ └── ap-northeast-1.tfvars
│ ├── prd
│ │ ├── ap-northeast-1.backend
│ │ └── ap-northeast-1.tfvars
│ └── stg
│ ├── ap-northeast-1.backend
│ └── ap-northeast-1.tfvars
├── iam_user.tf
├── locals.tf
├── provider.tf
└── variable.tf
- builder/dryrun.yml : dryrunプロジェクト用yml
- builder/build.yml : releaseプロジェクト用yml
version: 0.2
phases:
install:
on-failure: ABORT | CONTINUE
commands:
- echo $CODEBUILD_INITIATOR
- echo $CODEBUILD_BUILD_ID
- echo $CODEBUILD_WEBHOOK_TRIGGER
- echo $CODEBUILD_SOURCE_VERSION
- export job_name=(${CODEBUILD_BUILD_ID//:/ })
- export split_build_name=(${job_name//-/ })
- export DEPLOY_ENV=${split_build_name[1]}
- export TFVARS_PATH=./config/${DEPLOY_ENV}/ap-northeast-1.tfvars
- wget -q https://releases.hashicorp.com/terraform/0.14.9/terraform_0.14.9_linux_amd64.zip
- unzip terraform_0.14.9_linux_amd64.zip
- mv terraform /bin
- terraform init -backend-config=./config/${DEPLOY_ENV}/ap-northeast-1.backend -no-color
pre_build:
on-failure: ABORT | CONTINUE
commands:
- echo pre_build phases
- terraform plan ${DESTROY_MODE} -var-file=${TFVARS_PATH} -no-color
version: 0.2
phases:
install:
on-failure: ABORT | CONTINUE
commands:
- echo $CODEBUILD_INITIATOR
- echo $CODEBUILD_BUILD_ID
- echo $CODEBUILD_WEBHOOK_TRIGGER
- echo $CODEBUILD_SOURCE_VERSION
- export job_name=(${CODEBUILD_BUILD_ID//:/ })
- export split_build_name=(${job_name//-/ })
- export DEPLOY_ENV=${split_build_name[1]}
- export TFVARS_PATH=./config/${DEPLOY_ENV}/ap-northeast-1.tfvars
- wget -q https://releases.hashicorp.com/terraform/0.14.9/terraform_0.14.9_linux_amd64.zip
- unzip terraform_0.14.9_linux_amd64.zip
- mv terraform /bin
- terraform init -backend-config=./config/${DEPLOY_ENV}/ap-northeast-1.backend -no-color
pre_build:
on-failure: ABORT | CONTINUE
commands:
- echo pre_build phases
- terraform plan ${DESTROY_MODE} -var-file=${TFVARS_PATH} -no-color -out plan.out
build:
on-failure: ABORT | CONTINUE
commands:
- echo build phases
- terraform apply plan.out
バージョンとtfstate置き場
terraform {
required_version = "~> 0.14.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.74.1"
}
}
backend "s3" {
}
}
bucket = "terraform-codebuild-tfstate"
key = "terraform/develop/ap-northeast-1.tfstate"
region = "ap-northeast-1"
terraform実行権限はcodebuildのロールで管理
マルチアカウントで環境を分ける場合はassumeroleを使用
provider "aws" {
region = "ap-northeast-1"
#assume_role {
# role_arn = "arn:aws:iam::${var.aws.account_id}:role/StsAdminRole"
#}
}
試しに作成するもの
variable "aws" { type = map(any) }
variable "stage" { type = map(any) }
variable "project" { type = map(any) }
variable "iam_users" { type = map(any) }
resource "aws_iam_user" "iam_user" {
for_each = var.iam_users
name = "${each.value.name}-${var.stage.short_name}"
path = "/"
tags = merge(local.tags, map("Name", "${local.system_name}-user"))
}
locals {
system_name = "${var.project.name}-${var.stage.short_name}"
tags = {
Env = var.stage.name
Project = var.project.name
}
}
tfvars develop用
aws = {
account_id = "064944057077"
}
stage = {
name = "develop"
short_name = "dev"
}
project = {
name = "terraform-codebuild"
}
iam_users = {
test1 = {
key = "test1"
name = "test1@terraform"
}
test2 = {
key = "test2"
name = "test2@terraform"
}
test3 = {
key = "test3"
name = "test3@terraform"
}
}
staging用
aws = {
account_id = "064944057077"
}
stage = {
name = "staging"
short_name = "stg"
}
project = {
name = "terraform-codebuild"
}
iam_users = {
test1 = {
key = "test1"
name = "test1@terraform"
}
test2 = {
key = "test2"
name = "test2@terraform"
}
test3 = {
key = "test3"
name = "test3@terraform"
}
}
production用
aws = {
account_id = "064944057077"
}
stage = {
name = "production"
short_name = "prd"
}
project = {
name = "terraform-codebuild"
}
iam_users = {
#(for_each)
# = each.value
test1 = {
# = each.value.key
key = "test1"
# = each.value.name
name = "test1@terraform"
}
test2 = {
key = "test2"
name = "test2@terraform"
}
test3 = {
key = "test3"
name = "test3@terraform"
}
}
以下も可
resource "aws_iam_user" "iam_user" {
for_each = var.iam_users
name = "${each.value}-${var.stage.short_name}"
path = "/"
tags = merge(local.tags, map("Name", "${local.system_name}-user"))
}
.
.
.
iam_users = {
#(for_each)
#each.key = each.value
name1 = "test1@terraform"
name2 = "test2@terraform"
name3 = "test3@terraform"
}
Codebuildは任意の場所で処理を停止するような分岐を設けることができない(?)ため、 (sourceコマンドで外部シェルスクリプトを利用することはできるのでシェルで書けばできそうだが可読性が落ちてしまう) terraform planで異常に気付けても強制的にビルトを停止するしか無い点。 Jenkinsなら簡単に分岐を書けるため、その点ではJenkinsの方が優れている。