はじめに
前回のPhase1ではIAM・CLI・CloudFormationの基礎を学んだ。
Phase2ではいよいよTerraformに入門し、実際にS3バケットをデプロイしてリモートステートまで設定した記録。
目次
- TerraformとCloudFormationの違い
- Terraformインストール
- ファイル構成と各ファイルの役割
- init / plan / apply の流れ
- tfstateとは
- リモートステート設定
- ハマったポイント
- まとめ
1. TerraformとCloudFormationの違い
| CloudFormation | Terraform | |
|---|---|---|
| 作成元 | AWS | HashiCorp |
| 対応クラウド | AWSのみ | AWS / GCP / Azure など |
| 記法 | YAML / JSON | HCL(独自言語) |
| tfstate管理 | AWSが自動管理 | 自分で管理が必要 |
一番大きな違いはマルチクラウド対応。
AWSとGCPを両方使う場合、CloudFormationはAWSしか管理できないが、Terraformなら同じ書き方でどちらも管理できる。
2. Terraformインストール
Windowsの場合、公式サイトからzipをダウンロードして terraform.exe を C:\Windows\System32\ に置く。
terraform -version
# Terraform v1.x.x
3. ファイル構成と各ファイルの役割
phase2/
├── provider.tf # どのクラウドを使うか
├── main.tf # 何を作るか
└── outputs.tf # 作った後に何を表示するか
provider.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
version = "~> 5.0" は「5.x系を使う(6.0は使わない)」という意味。
main.tf
resource "aws_s3_bucket" "practice" {
bucket = "my-terraform-practice-123456789012"
}
resource "aws_s3_bucket_versioning" "practice" {
bucket = aws_s3_bucket.practice.id
versioning_configuration {
status = "Enabled"
}
}
CloudFormationと違い、TerraformではS3バケット本体とバージョニング設定は別リソースとして書く。
aws_s3_bucket.practice.id のようにリソース同士を参照できるのがTerraformの強み。
outputs.tf
output "bucket_name" {
value = aws_s3_bucket.practice.id
}
output "bucket_arn" {
value = aws_s3_bucket.practice.arn
}
terraform apply 後に自動で表示される。デプロイ直後に情報を確認できて便利。
4. init / plan / apply の流れ
terraform init
terraform init
AWSプロバイダー(AWSを操作するためのプラグイン)をダウンロードする。初回だけ実行すればOK。
npm install に近いイメージ。
terraform plan
terraform plan
実際には何も変わらない。差分のプレビューを確認するためのコマンド。
Plan: 2 to add, 0 to change, 0 to destroy.
↑ ↑ ↑
新規作成 変更なし 削除なし
+ が新規作成、~ が変更、- が削除を意味する。
(known after apply) はデプロイ後にAWSが決める値(ARNなど)。
デプロイ前に必ずplanで差分確認するのが鉄則。本番環境への誤デプロイ事故を防げる。
terraform apply
terraform apply
planの内容を実際に実行する。yes と入力して確定。
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
bucket_arn = "arn:aws:s3:::my-terraform-practice-123456789012"
bucket_name = "my-terraform-practice-123456789012"
outputs.tfで定義した値がここで表示される。
5. tfstateとは
terraform apply を実行すると terraform.tfstate というファイルが自動生成される。
{
"resources": [
{
"type": "aws_s3_bucket",
"name": "practice",
"instances": [
{
"attributes": {
"bucket": "my-terraform-practice-123456789012",
"arn": "arn:aws:s3:::my-terraform-practice-123456789012"
}
}
]
}
]
}
これは**「今AWSに何が存在するか」を記録したファイル**。
terraform plan を実行すると:
tfstate(現状) vs .tfファイル(あるべき姿)
└── 差分だけ実行する
この差分計算のためにtfstateが必要。tfstateがないとTerraformは現状を把握できない。
tfstateは絶対にGitHubにpushしない。AWSの構成情報が全部入っているため、流出すると危険。.gitignore に必ず追加する。
6. リモートステート設定
なぜリモートステートが必要か
デフォルトではtfstateがローカルPCに保存される。
問題点:
└── チームで共有できない
└── PC壊れたら消える
└── 間違えて削除したら管理不能になる
これを解決するのがリモートステート。tfstateをS3で管理する。
手順
1. tfstate用のS3バケットを作成
resource "aws_s3_bucket" "tfstate" {
bucket = "my-tfstate-123456789012"
force_destroy = true
}
resource "aws_s3_bucket_versioning" "tfstate" {
bucket = aws_s3_bucket.tfstate.id
versioning_configuration {
status = "Enabled"
}
}
force_destroy = true をつけておくと terraform destroy 時にバケットの中身ごと削除できる。
2. provider.tf に backend を追加
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-tfstate-123456789012"
key = "phase2/terraform.tfstate"
region = "ap-northeast-1"
}
}
provider "aws" {
region = "ap-northeast-1"
}
backend "s3" ブロックは必ず terraform {} の中に書く。外に書くとエラーになる。
3. terraform init を再実行
バックエンドの設定が変わったので再度initが必要。
terraform init
これでtfstateがS3に保存されるようになる。
my-tfstate-123456789012/
└── phase2/
└── terraform.tfstate
7. ハマったポイント
backend ブロックの位置を間違えた
# NG: terraform {} の外に書いてしまった
terraform {
required_providers { ... }
}
backend "s3" { # ← ここはダメ
...
}
# OK: terraform {} の中に書く
terraform {
required_providers { ... }
backend "s3" { # ← ここが正しい
...
}
}
tfstateバケットをterraform destroyで消せない
バージョニングを有効にしたtfstateバケットをdestroyしようとするとエラーになる。
Error: BucketNotEmpty: The bucket you tried to delete is not empty.
You must delete all versions in the bucket.
対策として force_destroy = true を最初からつけておく。
yes ではなく y と入力してキャンセルになった
Only 'yes' will be accepted to approve.
y だけだと Apply cancelled. になる。必ず yes と全部入力する。誤操作防止のための仕様。
8. まとめ
Phase2で学んだこと:
- Terraformはマルチクラウド対応のIaCツール。実務でのシェアが高い
- init → plan → apply の流れを必ず守る。planで差分確認してからapply
- tfstateはTerraformの記憶。現状とコードの差分計算に使う
- リモートステートでtfstateをS3管理するとチーム開発・バックアップに対応できる
-
force_destroy = trueでバケットの中身ごと削除できる - tfstateは
.gitignoreに追加してGitHubにpushしない
コードはGitHubで公開しています:
https://github.com/Allure2140/aws-iac-learning
次のPhase3ではVPC・EC2をTerraformでコード化し、複数環境(dev/prod)管理に挑戦します。