A Complete Guide to Terraform State (tfstate) | Mechanisms You Must Know for Team Development
The first thing that people who start using Terraform find confusing is State (state management) .
However, if you don't understand this, terrible accidents will happen in team development. Conversely, if you do understand it, your anxiety about Terraform will almost disappear. Let's grasp it firmly.
What is State?
Terraform manages the "current state" of infrastructure in a file. This is the tfstate (terraform.tfstate) file.
// terraform.tfstate の中身(例)
{
"version": 4,
"terraform_version": "1.9.8",
"resources": [
{
"type": "aws_s3_bucket",
"name": "my_bucket",
"instances": [
{
"attributes": {
"id": "my-example-bucket",
"bucket": "my-example-bucket",
"region": "ap-northeast-1",
...
}
}
]
}
]
}Every time Terraform executes terraform apply, it compares this "previous state (tfstate)" with the "code definition" and executes only the differences.
コード(.tf) tfstate(前回の状態)
↓ ↓
差分を計算
↓
実際のAWSに適用Why is State necessary?
You might think, "Why not just query AWS directly?"
However, there are problems.
1. Complex resource mapping Terraform code IDs and AWS resource IDs do not match. State serves as the mapping table for them.
2. Performance If you query all AWS resources every time, it would take minutes to execute in environments with hundreds or thousands of resources.
3. Dependency tracking State records which resources depend on which other resources.
Problems with local State
When you execute terraform apply, terraform.tfstate is created locally by default.
This has major problems.
【ローカルStateの問題】
開発者A: terraform apply → tfstateがAのPCに保存
開発者B: terraform apply → BのPCにあるtfstateは古い!
↓
二重実行で環境が壊れるAlso, since tfstate contains information about AWS resources (and in some cases, sensitive information like passwords), it cannot be committed to Git.
Remote State: Managing State with S3
In team development, we use Remote State. This is a method of saving tfstate to S3 and sharing it among everyone.
Creating an S3 bucket and DynamoDB table
First, create an S3 bucket (for saving tfstate) and a DynamoDB table (for locking).
# bootstrap/main.tf
# このリソース自体はコンソールで作るか、一度だけ別途applyする
resource "aws_s3_bucket" "tfstate" {
bucket = "my-tfstate-bucket-xxxxxxx" # 世界でユニークな名前
}
resource "aws_s3_bucket_versioning" "tfstate" {
bucket = aws_s3_bucket.tfstate.id
versioning_configuration {
status = "Enabled" # バージョニングは必須!
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "tfstate" {
bucket = aws_s3_bucket.tfstate.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# 状態ロック用のDynamoDBテーブル
resource "aws_dynamodb_table" "tfstate_lock" {
name = "terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}Backend configuration
Add backend "s3" to the terraform {} block.
terraform {
required_version = ">= 1.9.0"
backend "s3" {
bucket = "my-tfstate-bucket-xxxxxxx"
key = "production/terraform.tfstate" # 保存先のパス
region = "ap-northeast-1"
dynamodb_table = "terraform-state-lock" # ロック用テーブル
encrypt = true
}
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}Running terraform init will switch to S3.
What is State Lock?
Using DynamoDB for State Lock is a very important mechanism.
If multiple people run terraform apply at the same time, the tfstate will be corrupted. State Lock prevents this.
開発者A: terraform apply開始 → DynamoDBにロック取得
開発者B: terraform apply開始 → ロック中!待機 or エラー
開発者A: apply完了 → ロック解除
開発者B: ロック取得 → apply開始Commands related to State
state list: List of resources under management
terraform state list
# 出力例
aws_instance.web
aws_s3_bucket.my_bucket
aws_vpc.mainstate show: Check details of a resource
terraform state show aws_s3_bucket.my_bucketstate mv: Rename a resource
When you change a resource name in the code, it will be "deleted and recreated" by default. Using state mv allows you to change only the name without recreating it.
# コード上で aws_s3_bucket.old → aws_s3_bucket.new に変えた場合
terraform state mv aws_s3_bucket.old aws_s3_bucket.newstate rm: Remove from management
When there is a resource you want to remove from Terraform management (without deleting it):
terraform state rm aws_s3_bucket.my_bucketterraform import: Bring existing resources under State management
Use import when you want to start managing resources created via the console with Terraform.
# Terraform 1.5以降はimportブロックで書ける
import {
to = aws_s3_bucket.existing
id = "existing-bucket-name"
}Or the old method:
terraform import aws_s3_bucket.existing existing-bucket-nameSummary of points to note about tfstate
✅ DO
- S3 + DynamoDBでRemote State管理する
- S3バケットのバージョニングを有効にする(誤操作からの復元用)
- S3バケットの暗号化を有効にする
❌ DON'T
- tfstateをGitにコミットしない(機密情報が含まれる)
- tfstateを手動で編集しない
- ローカルのtfstateをチームで使わないSummary
tfstate is a file where Terraform records the "current state" of the infrastructure
Local storage cannot be used for team development
Remote State management with S3 + DynamoDB is the best practice
Prevent concurrent execution with State Lock
You can manipulate State using the terraform state command
In the next article, I will explain the best practices for Terraform directory structure. We will look specifically at how to organize them, from small-scale projects to large-scale ones.
いいなと思ったら応援しよう!
応援をぜひよろしくお願いします🔥
いただいたチップでより素晴らしい記事を発信していけるよう精進してまいります!