Edited at

TerraformでtfstateファイルをS3で管理する


TL;DR

Terraformでのtfstateファイルを管理するためにbackendとしてS3を使用する。


前提条件


  • AWSアカウント


    • CLIから操作できる権限を持つユーザ & AWS-Cliに対するアクセスキーなどの設定



  • Terraform



    • v0.11.0 以上を使用します。




手順


tfstateファイルを格納するS3バケットを作成する


main.tf

terraform {

required_version = ">= 0.11.0"
}

provider "aws" {
region = "us-east-1"
}

resource "aws_s3_bucket" "terraform_state" {
bucket = "example-terraform-state"
versioning {
enabled = true
}
}


実行

$ terraform plan

からの

$ terraform apply


作成したS3バケットでtfstateファイルを管理するよう設定する


main.tf

terraform {

required_version = ">= 0.11.0"
backend "s3" {
bucket = "example-terraform-state" # 作成したS3バケット
region = "us-east-1"
key = "terraform.tfstate"
encrypt = true
}
}

provider "aws" {
region = "us-east-1"
}

resource "aws_s3_bucket" "terraform_state" {
bucket = "example-terraform-state"
versioning {
enabled = true
}
}


terraform ブロック内に backend ブロックを追記する。

backend 設定をいじった後なので、

$ terraform init して、

ローカルの tfstate をS3にコピーするか聞かれるので yes と答えて完了。


(オプショナル)state lockを有効化する

S3によって複数人でtfstateファイルを扱うことが可能になったが、逆にそれによってデータがコンフリクトしてしまう恐れがある。

そこで、TerraformではDynamoDB(S3の場合)を用いてtfstateファイルの一貫性を保つことができる機能を提供している。


DynamoDBを作成する


main.tf

terraform {

required_version = ">= 0.11.0"
backend "s3" {
bucket = "example-terraform-state"
region = "us-east-1"
key = "terraform.tfstate"
encrypt = true
}
}

provider "aws" {
region = "us-east-1"
}

resource "aws_s3_bucket" "terraform_state" {
bucket = "example-terraform-state"
versioning {
enabled = true
}
}

resource "aws_dynamodb_table" "terraform_state_lock" {
name = "terraform_state_lock"
read_capacity = 1
write_capacity = 1
hash_key = "LockID"

attribute {
name = "LockID"
type = "S"
}
}


これで $ terraform apply する。


DynamoDBをbackendに設定する


main.tf

terraform {

required_version = ">= 0.11.0"
backend "s3" {
bucket = "example-terraform-state"
region = "us-east-1"
key = "terraform.tfstate"
encrypt = true
dynamodb_table = "terraform_state_lock"
}
}

provider "aws" {
region = "us-east-1"
}

resource "aws_s3_bucket" "terraform_state" {
bucket = "example-terraform-state"
versioning {
enabled = true
}
}

resource "aws_dynamodb_table" "terraform_state_lock" {
name = "terraform_state_lock"
read_capacity = 1
write_capacity = 1
hash_key = "LockID"

attribute {
name = "LockID"
type = "S"
}
}


backendの設定を変更したので

$ terraform init してあげれば完了。


困ったこと



  • Terraform: Up and Running: Writing Infrastructure as Codeを読みながら学習しているものの、バージョンが古くて参考にならない。

  • S3を作らずにbackend設定しようとすると怒られる。



    • Error loading state: NoSuchBucket: The specified bucket does not existが発生する。

    • 関連するIssueのcomment




参考資料

https://qiita.com/marshmallow911/items/e8c05f580d07451fcf5e

https://qiita.com/sinshutu/items/7d3cc7438871c50ea63c