プロバイダとState管理
ストーリー
「Terraformの最も重要な概念の1つがStateだ」
木村先輩が
terraform.tfstateファイルを開いた。「Terraformは『コードに書いたあるべき姿』と 『実際のクラウド上の状態』を比較して差分を計算する。 その『実際の状態』を記録しているのがStateファイルだ」
「これを壊したらどうなるんですか?」
「Terraformがリソースを認識できなくなる。 最悪、同じリソースを二重に作ったり、 既存のリソースを消せなくなったりする。 Stateの管理は生命線だ」
プロバイダ(Provider)
プロバイダとは
プロバイダは、TerraformがクラウドサービスのAPIと通信するためのプラグインです。
プロバイダの役割
Terraform コード (.tf)
│
▼
┌──────────────┐
│ Terraform │
│ Core │
└──────┬───────┘
│
┌────┴────┐
▼ ▼
┌──────┐ ┌──────┐
│ AWS │ │ GCP │
│Provider│ │Provider│
└──┬───┘ └──┬───┘
▼ ▼
AWS API GCP API
プロバイダの設定
hcl
# providers.tf
terraform {
required_version = ">= 1.7.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # 5.x 系の最新
}
}
}
# AWSプロバイダの設定
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
ManagedBy = "terraform"
Project = "my-project"
Environment = var.environment
}
}
}バージョン制約
| 制約式 | 意味 | 例 |
|---|---|---|
= 5.0.0 | 完全一致 | 5.0.0 のみ |
>= 5.0 | 以上 | 5.0, 5.1, 6.0 ... |
~> 5.0 | パッチバージョンのみ許容 | 5.0.x |
~> 5.0.0 | マイナーバージョンのみ許容 | 5.0.0 〜 5.0.x |
>= 5.0, < 6.0 | 範囲指定 | 5.x 系 |
複数リージョンの使用(エイリアス)
hcl
# 東京リージョン(デフォルト)
provider "aws" {
region = "ap-northeast-1"
}
# バージニアリージョン
provider "aws" {
alias = "virginia"
region = "us-east-1"
}
# バージニアのリソース
resource "aws_s3_bucket" "logs" {
provider = aws.virginia
bucket = "my-logs-bucket-us"
}State(状態管理)
Stateとは
TerraformのStateは、管理しているリソースの現在の状態を記録するJSONファイルです。
Stateの役割
┌───────────┐ ┌───────────┐ ┌───────────┐
│ .tf ファイル │ │ State │ │ 実際の │
│ (あるべき姿) │ │ (記録状態) │ │ クラウド状態 │
└──────┬────┘ └──────┬────┘ └──────┬────┘
│ │ │
└────────┬─────────┘ │
│ │
▼ │
terraform plan │
(差分計算) ←───────────────────────┘
│
▼
terraform apply
(差分適用)
Stateファイルの中身
json
{
"version": 4,
"terraform_version": "1.7.0",
"resources": [
{
"type": "aws_instance",
"name": "web",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"attributes": {
"id": "i-0abc123def456",
"ami": "ami-0abcdef1234567890",
"instance_type": "t3.micro",
"public_ip": "54.123.45.67"
}
}
]
}
]
}ローカルState vs リモートState
ローカルState(デフォルト)
ローカルState
my-project/
├── main.tf
├── terraform.tfstate ← ローカルファイル
└── terraform.tfstate.backup
問題点:
- チーム開発で共有できない
- 誤って削除するリスク
- 同時実行で競合する可能性
リモートState(推奨)
リモートState (S3 + DynamoDB)
┌──── 開発者A ────┐ ┌──── 開発者B ────┐
│ terraform apply │ │ terraform apply │
└────────┬────────┘ └────────┬────────┘
│ │
└───────────┬───────────┘
▼
┌───── S3 ──────┐
│ tfstate ファイル │
│ (暗号化保存) │
└───────────────┘
│
┌── DynamoDB ──┐
│ 状態ロック │
│ (排他制御) │
└──────────────┘
リモートStateの設定
hcl
# backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "production/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}S3バケットとDynamoDBテーブルの事前作成
hcl
# state-backend/main.tf(Stateバックエンド自体のTerraform)
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-terraform-state-bucket"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_dynamodb_table" "terraform_lock" {
name = "terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}State操作コマンド
| コマンド | 用途 |
|---|---|
terraform state list | 管理中のリソース一覧 |
terraform state show aws_instance.web | リソースの詳細表示 |
terraform state mv | リソースの名前変更/移動 |
terraform state rm | Stateからリソースを削除(実体は残る) |
terraform import | 既存リソースをStateに取り込む |
import の例
bash
# 手動で作成したEC2インスタンスをTerraform管理下に置く
terraform import aws_instance.web i-0abc123def456Stateのベストプラクティス
| プラクティス | 説明 |
|---|---|
| リモートState必須 | チーム開発では必ずS3等のリモートバックエンドを使用 |
| State暗号化 | S3の暗号化を有効にする |
| ロック有効化 | DynamoDBで排他制御を行う |
| バージョニング | S3バージョニングで誤操作に備える |
| 直接編集禁止 | StateファイルをテキストエディタなどでSTATE直接編集しない |
| 環境分離 | staging/production でStateファイルを分ける |
まとめ
| ポイント | 内容 |
|---|---|
| プロバイダ | クラウドAPIとの通信プラグイン、バージョン固定推奨 |
| State | リソースの現在状態を記録するファイル |
| リモートState | S3 + DynamoDB でチーム共有と排他制御 |
| import | 既存リソースをTerraform管理下に取り込む |
チェックリスト
- プロバイダの設定とバージョン制約を書ける
- Stateの役割と重要性を説明できる
- ローカルStateとリモートStateの違いを理解した
- S3 + DynamoDB でリモートStateを設定できる
次のステップへ
次のセクションでは、変数とモジュールについて学びます。 Terraformコードの再利用性と保守性を高める方法をマスターしましょう。
推定読了時間: 30分