Terraform管理 · 1 min read · Dec 10, 2025
AWS S3バケットでTerraformステートを管理する方法

この記事では、Terraformステートとは何か、そしてそれをS3バケットでどのように管理するかを見ていきます。また、Terraformにおける「ロック」とは何か、そしてそれをどのように実装するかも見ていきます。これを実装するためには、AWS上にS3バケットとDynamoDBテーブルを作成する必要があります。
進む前に、Terraformステートとロックの基本を理解しましょう。
- Terraformステート (terraform.tstateファイル):
ステートファイルには、terraform設定ファイルで定義されたリソースが存在するかどうかに関する情報が含まれています。たとえば、terraform設定を使用してEC2インスタンスを作成した場合、ステートファイルにはAWS上で作成された実際のリソースに関する情報が含まれています。 - ステートファイルを保存するためのバックエンドとしてのS3:
チームで作業している場合、チームの人々がアクセスできるように、terraformステートファイルをリモートで保存することが良いです。リモートでステートを保存するためには、2つのものが必要です: ステートファイルを保存するためのS3バケットと、terraform S3バックエンドリソースです。 - ロック:
ステートファイルをリモートで保存すると、多くの人が同じファイルに同時に変更を加えようとするリスクがあります。したがって、他のユーザーによって現在使用されている場合にステートを「ロック」するメカニズムが必要です。これを実現するために、terraformが使用するDynamoDBテーブルを作成します。
ここでは、S3バケットを手動で作成し、必要なポリシーを追加し、Terraformを使用してDynamoDBテーブルを作成し、S3をバックエンドとして使用し、ロックを保存するためにDynamoDBを設定するまでのすべての手順を見ていきます。
前提条件
- Terraformの基本的な理解。
- S3バケットの基本的な理解。
- システムにインストールされたTerraform。
- AWSアカウント(持っていない場合は作成してください)。
- AWS IAMユーザーの’access_key’と’secret_key’。(AWSで’access_key’と’secret_key’を持つIAMユーザーを作成する方法については、こちらをクリックしてください。)
何をするか
- S3バケットを作成し、ポリシーを添付します。
- Terraformを使用してDynamoDBテーブルを作成します。
- Terraform設定ファイルを使用してEC2を作成します。
- Terraformを使用して作成したEC2インスタンスを削除します。
S3バケットを作成し、ポリシーを添付します。
AWSアカウントでS3バケットを作成する方法については、こちらをクリックしてください。バケットを作成したら、以下のポリシーを添付します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1560164441598",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:PutObject*",
"s3:List*",
"s3:Get*",
"s3:Delete*"
],
"Resource": [
"arn:aws:s3:::state-lock-rahul",
"arn:aws:s3:::state-lock-rahul/*"
]
}
]
}
「AWS_ACCESS_KEY_ID」と「AWS_SECRET_ACCESS_KEY」を設定して、CLIからアカウントにアクセスできるようにします。
以下のコマンドを使用して、「AWS_ACCESS_KEY_ID」と「AWS_SECRET_ACCESS_KEY」の値をエクスポートします。
export AWS_ACCESS_KEY_ID=AKIAQ6GAIA5XC2XMMM7W
export AWS_SECRET_ACCESS_KEY=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
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY資格情報を設定したら、以下のコマンドを使用してバケットをリストすることで簡単にテストできます。
aws s3 ls

Terraformを使用してDynamoDBテーブルを作成します
必要な変数の宣言を含む‘variables.tf’を作成します。
vim variables.tf
variable "region" {
description = "AWS VPCのリージョン"
}
DynamoDBテーブルを作成する責任を持つ’main.tf’を作成します。このmain.tfは、variables.tfから変数の値を読み取ります。このテーブルはロックを保存するために使用されます。
provider "aws" {
region = "${var.region}"
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "rahul-test-dynamodb-table"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
最初に使用するコマンドは’terraform init’です。このコマンドは、構成内で使用されるプロバイダーのプラグインをダウンロードしてインストールします。この場合はAWSです。
* terraform init*

次に使用するコマンドは’terraform plan’です。このコマンドは、インフラストラクチャで発生する変更を確認するために使用されます。
terraform plan

‘terraform apply’コマンドは、main.tfファイルに記載されたAWS上のリソースを作成します。リソースを作成するために入力を提供するように求められます。
terraform apply

これで、コンソールのDynamoDBダッシュボードに移動して、テーブルが作成されたかどうかを確認できます。

ここまでの時点で、S3コンソールから手動でS3バケットを作成し、Terraformを使用してDynamoDBテーブルを作成しました。S3バケットをステートを保存するためのバックエンドとして設定し、DynamoDBテーブルをロックを保存するために設定していません。
目標を達成するために、Terraformのmain.tfファイルを修正する必要があります。コードを修正して実行すると、既存のローカルステートがS3バックエンドにコピーされます。
既存のmain.tfを以下のコードで更新します。
vim main.tf
provider "aws" {
region = "${var.region}"
}
terraform {
backend "s3" {
bucket = "state-lock-rahul"
key = "test/terraform.tfstate"
region = "eu-west-3"
dynamodb_table = "rahul-test-dynamodb-table"
}
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "rahul-test-dynamodb-table"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
今、「terraform plan」コマンドを試すと、新しいリソースが作成されるかどうかを確認できますが、コマンドは以下のエラーで失敗します。
バックエンドを再初期化するように求められます。

バックエンドを再初期化するには、「terraform init」コマンドを使用します。このステップでは、ローカルステートファイルがS3バケットにコピーされます。
terraform init
「terraform init」コマンドを実行した後、出力を以下のスクリーンショットのように観察できます。TerraformはDynamoDbテーブルを使用してロックを取得するように設定されました。ロックが有効になると、同じリソースに対して同時に同じ操作を実行することはできなくなります。

AWSコンソールのS3ダッシュボードに移動して、terraform.tfstateがコピーされたかどうかを確認できます。

今、再び新しいリソースを作成し、ステートがS3バケットに保存されることを確認できます。新しいDynamoDBテストテーブルを作成するには、main.tfファイルを以下のコードで更新します。
vim main.tf
variable "region" {
description = "AWS VPCのリージョン"
}
Rahuls-MacBook-Pro:terraform rahul$ cat main.tf
provider "aws" {
region = "${var.region}"
}
tf {
backend "s3" {
bucket = "state-lock-rahul"
key = "test/terraform.tfstate"
region = "eu-west-3"
dynamodb_table = "rahul-test-dynamodb-table"
}
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "rahul-test-dynamodb-table"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
resource "aws_dynamodb_table" "test-table" {
name = "rahul-test-table"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
今回は、プロバイダーへのバックエンドの変更がないため、「terraform init」を実行する必要はありません。
「terraform plan」コマンドを使用して、新しいリソースが作成されるかどうかを確認できます。
terraform plan


次に、新しいDynamoDbテストテーブルを作成するために、以下のコマンドを実行します。
terraform apply


上のスクリーンショットでは、ロックが有効になっており、.tfstateファイルがS3にコピーされていることがわかります。
今、コンソールで新しいテーブルが作成されたことが確認できます。

もしTerraformを使用して作成したリソースがもはや必要ない場合は、以下のコマンドを使用してリソースを削除します。
terraform destroy

リソースを削除すると、ロックに使用されていたテーブルも削除されることがわかります。S3バケットも必要ない場合は、コンソールから削除できます。
結論
この記事では、Terraformにおけるリモートステートとロックの使用の必要性について学びました。S3バケットをバックエンドとして使用してTerraformステートを保存し、DynamoDbテーブルを使用してロックを有効にする手順を見ました。
新しい投稿を受信箱で受け取る
スパムはありません。いつでも購読を解除できます。