第3章: Terraformの専門技術
7. モジュールの定義
TerraformのDRYな構築
Terraformでインフラストラクチャを管理する際、コードの重複を避け、再利用可能なコンポーネントを作成することは非常に重要です。これは「DRY(Don’t Repeat Yourself)」原則とも呼ばれ、Terraformではモジュールを使用して実現します。
モジュールを使用する主なメリットは以下の通りです:
- コードの再利用性: 同じリソース構成を複数の環境で使用できる
- 抽象化: 複雑なインフラを論理的なコンポーネントに分割できる
- バージョン管理: モジュールにバージョンを付けて、安定した状態で共有できる
- 一貫性: 組織全体で標準化されたインフラパターンを適用できる
例えば、標準的なVPC設定を複数のプロジェクトで再利用したい場合、以下のようなモジュール構造を作成できます:
modules/
vpc/
main.tf
variables.tf
outputs.tf
README.md
main.tf
ではVPCリソースを定義し、variables.tf
で設定可能なパラメータを定義します。outputs.tf
では、モジュールから出力する値(VPC ID、サブネットIDなど)を定義します。
module の使い方
モジュールを使用するには、以下の構文を使用します:
module "vpc" {
source = "./modules/vpc"
vpc_cidr = "10.0.0.0/16"
region = "ap-northeast-1"
environment = "production"
}
モジュールのソースは以下のような様々な場所から指定できます:
- ローカルパス:
./modules/vpc
- GitHubリポジトリ:
github.com/username/terraform-aws-vpc
- Terraform Registry:
terraform-aws-modules/vpc/aws
実践的な例として、AWSでのウェブアプリケーション用のモジュール構成を考えてみましょう:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "3.14.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
tags = {
Environment = "production"
Project = "MyApp"
}
}
module "web_server" {
source = "./modules/web_server"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
instance_type = "t3.medium"
environment = "production"
}
このように、モジュールを組み合わせることで、複雑なインフラを論理的な単位に分解し、管理しやすくすることができます。
8. TerraformのCI/CD適用
GitHub ActionsでTerraformを自動適用
Terraformを継続的インテグレーション/継続的デプロイメント(CI/CD)パイプラインに統合することで、インフラ変更の自動化と品質保証が可能になります。GitHub Actionsは、このプロセスを簡単に設定できるツールの一つです。
GitHub Actionsでのワークフロー例:
name: "Terraform CI/CD"
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
terraform:
name: "Terraform"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.3.0
- name: Terraform Format
id: fmt
run: terraform fmt -check
- name: Terraform Init
id: init
run: terraform init
- name: Terraform Validate
id: validate
run: terraform validate
- name: Terraform Plan
id: plan
if: github.event_name == 'pull_request'
run: terraform plan -no-color
continue-on-error: true
- name: Update Pull Request
uses: actions/github-script@v6
if: github.event_name == 'pull_request'
env:
PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
#### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
#### Terraform Validation 🤖\`${{ steps.validate.outcome }}\`
#### Terraform Plan 📖\`${{ steps.plan.outcome }}\`
<details><summary>Show Plan</summary>
\`\`\`\n
${process.env.PLAN}
\`\`\`
</details>`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve
このワークフローでは:
- プルリクエスト時に
terraform plan
を実行し、変更内容をコメントとして表示 - メインブランチへのプッシュ時に
terraform apply
を自動実行 - コード品質チェック(フォーマット、検証)を各ステップで実施
より安全な運用のためには、以下のようなプラクティスも検討すべきです:
- 環境分離: 開発、ステージング、本番環境ごとに異なるワークフローを設定
- 承認プロセス: 重要な環境(本番など)への適用前に手動承認ステップを追加
- 状態ファイルのリモート保存: S3やTerraform Cloudなどでステートを安全に管理
AWS CodePipelineとTerraformの組み合わせ
AWS内でインフラを管理している場合、AWS CodePipelineとTerraformを組み合わせることで、AWSネイティブのCI/CDパイプラインを構築できます。
典型的なAWS CodePipelineの構成は以下のようになります:
- Source Stage: AWS CodeCommitやGitHubからTerraformコードを取得
- Build Stage: AWS CodeBuildでTerraform初期化、検証、プラン生成
- Approval Stage: 必要に応じて手動承認ステップを追加
- Deploy Stage: CodeBuildでTerraform適用を実行
AWS CodeBuildのbuildspec.yml
例:
version: 0.2
phases:
install:
runtime-versions:
python: 3.9
commands:
- wget https://releases.hashicorp.com/terraform/1.3.0/terraform_1.3.0_linux_amd64.zip
- unzip terraform_1.3.0_linux_amd64.zip
- mv terraform /usr/local/bin/
pre_build:
commands:
- echo "Initializing Terraform..."
- terraform init
- terraform validate
build:
commands:
- echo "Planning Terraform changes..."
- terraform plan -out=tfplan
- terraform show -json tfplan > tfplan.json
post_build:
commands:
- if [ "$CODEBUILD_WEBHOOK_EVENT" = "PULL_REQUEST_MERGED" ] || [ "$CODEBUILD_WEBHOOK_EVENT" = "" ]; then
echo "Applying Terraform changes...";
terraform apply -auto-approve tfplan;
else
echo "Skipping apply for non-merged PR events";
fi
artifacts:
files:
- tfplan.json
- terraform.tfstate
AWS CodePipelineをさらに強化するためのベストプラクティス:
- 環境変数の管理: AWS Systems Manager Parameter StoreやAWS Secrets Managerを利用
- クロスアカウントデプロイ: 異なるAWSアカウントへのデプロイを安全に管理
- ドリフト検出: 定期的にインフラのドリフト(手動変更)を検出するジョブを追加
AWSのインフラ運用におけるCodePipelineとTerraformの組み合わせは、特に以下のような場合に効果的です:
- AWS内のリソースが多い環境
- セキュリティ要件が厳しく、AWSのIAM統合が必要な場合
- 複数のAWSアカウントやリージョンにまたがる環境
この組み合わせにより、AWSネイティブのセキュリティ機能とモニタリング機能を活用しながら、Terraformによるインフラストラクチャのコード化のメリットを享受できます。
コメント