1. 概要
- GitLab CI/CDでTerraformのplan/applyを自動化する方法
- GitLab CI/CD Catalog(公式Terraform Component)の活用
- OIDCを使ったAWS認証
- GitLab Environmentsでのデプロイ追跡
GitLabはGitHub Actionsと同様にCI/CDが組み込まれています。特にセルフホスト版GitLabを使っているチームでは、GitLab CI/CDでTerraformを動かすのが自然な選択です。
2. Terraform設定
terraform {
required_version = ">= 1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-company-tfstate"
key = "app/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "terraform-lock"
}
}
provider "aws" {
region = "ap-northeast-1"
}
variable "environment" {
description = "環境名"
type = string
default = "dev"
}
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
root_block_device {
volume_size = 20
volume_type = "gp3"
encrypted = true
}
tags = {
Name = "${var.environment}-web"
Environment = var.environment
ManagedBy = "terraform"
}
}
3. GitLab CI/CD設定(.gitlab-ci.yml)
# .gitlab-ci.yml
image: hashicorp/terraform:1.9.0
variables:
TF_ROOT: ${CI_PROJECT_DIR}/environments/production
AWS_DEFAULT_REGION: ap-northeast-1
# OIDCを使う場合は以下を設定
# AWS_ROLE_ARN: arn:aws:iam::123456789012:role/GitLabCIRole
stages:
- validate
- plan
- apply
# GitLab CI/CDのOIDC認証(ID Tokens)
default:
id_tokens:
AWS_OIDC_TOKEN:
aud: sts.amazonaws.com
.aws_oidc_login: &aws_oidc_login
before_script:
- apk add --no-cache aws-cli jq
- |
CREDS=$(aws sts assume-role-with-web-identity --role-arn "$AWS_ROLE_ARN" --role-session-name "GitLabCI-${CI_JOB_ID}" --web-identity-token "$AWS_OIDC_TOKEN" --duration-seconds 3600 --output json)
export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r '.Credentials.SessionToken')
validate:
stage: validate
script:
- cd $TF_ROOT
- terraform init -backend=false
- terraform validate
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"
plan:
stage: plan
<<: *aws_oidc_login
script:
- cd $TF_ROOT
- terraform init
- terraform plan -no-color -out=tfplan 2>&1 | tee plan_output.txt
artifacts:
name: terraform-plan
paths:
- $TF_ROOT/tfplan
- $TF_ROOT/plan_output.txt
expire_in: 7 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"
apply:
stage: apply
<<: *aws_oidc_login
script:
- cd $TF_ROOT
- terraform init
- terraform apply tfplan
environment:
name: production
url: https://my-app.example.com
dependencies:
- plan
when: manual # 手動実行
rules:
- if: $CI_COMMIT_BRANCH == "main"
4. GitLab OIDC IAMロール設定
resource "aws_iam_openid_connect_provider" "gitlab" {
url = "https://gitlab.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["b3dd7606d2b5a8b4a13771dbecc9ee1cecafa38a"]
tags = {
Name = "gitlab-oidc-provider"
Environment = "dev"
ManagedBy = "terraform"
}
}
resource "aws_iam_role" "gitlab_ci" {
name = "GitLabCIRole"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Federated = aws_iam_openid_connect_provider.gitlab.arn }
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"gitlab.com:aud" = "sts.amazonaws.com"
}
StringLike = {
"gitlab.com:sub" = "project_path:my-group/my-repo:ref_type:branch:ref:main"
}
}
}]
})
tags = {
Name = "GitLabCIRole"
Environment = "dev"
ManagedBy = "terraform"
}
}
resource "aws_iam_role_policy_attachment" "gitlab_ci" {
role = aws_iam_role.gitlab_ci.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
5. 関連記事
- GitHub ActionsでTerraformを実行する方法 — GitHub版との比較
- GitHub Actions vs CircleCI — Terraform CI/CDパイプライン選び方 — CI/CD比較
- Terraform CI/CDのシークレット管理 — 認証情報管理
- GitHub Actions: OIDC認証でAWSクレデンシャルを排除する — OIDC詳解
- Terraform CI/CDのブランチ戦略 — ブランチ設計
- backend — stateファイルの保存場所を設定 — S3バックエンド
6. まとめ
- GitLab CI/CDは
.gitlab-ci.ymlでTerraformのvalidate → plan → applyパイプラインを定義する - GitLab OIDC(ID Tokens)を使うとAWSアクセスキーなしで認証できる
- planのArtifactsをapplyジョブに引き渡すことで、planしたままのtfplanをapplyできる
when: manualでapplyを手動実行にしてPRマージ後の意図しないapplyを防止する
対象バージョン: Terraform >= 1.9 / GitLab CI/CD (2024) 公式ドキュメント: https://docs.gitlab.com/ee/user/infrastructure/iac/