Terraformはtfstateファイルで構成情報を管理しているが、 単純にtfstateファイルをgit等で共有すると他の人が構成変更 (terrafrom apply)している最中に別に作業を実行したり出来る。
そういうときに良く競合してあるべきリソースが削除されたりするが Terraform Backend S3 + DynamoDB Lockを利用することで、自動的に ロックしながら最新状態を共有することが可能となる。
以下、その辺の必要なS3バケットやDynamoDBを用意するためのCloudFormation YAMLファイル。
# terraform_backend_s3.yaml
---
AWSTemplateFormatVersion: 2010-09-09
Description: S3 Bucket and DynamoDB for Terraform state files.
Parameters:
S3BucketName: # tfstateファイルを保持するためのS3バケット名
Type: String
Description: Bucket name
MinLength: 3
MaxLength: 63
AllowedPattern: "[a-z0-9][a-zA-Z0-9.-]+"
DynamoDBTableName: # ロック管理用のDynamoDBテーブル名
Type: String
Description: Table name
MinLength: 3
MaxLength: 63
AllowedPattern: "[a-zA-Z0-9][a-zA-Z0-9.-]+"
Default: TerraformStateLockTable
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName:
Ref: S3BucketName
VersioningConfiguration: # 過去のtfstateファイルをVersioningで保持する
Status: Enabled
Tags:
- Key: Name
Value: !Sub |-
Terraform backend S3 bucket for ${AWS::AccountId} by ${AWS::StackName}.
DynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName:
Ref: DynamoDBTableName
ProvisionedThroughput: # Terraformが利用するだけであれば読み書きパフォーマンスは最小で十分
ReadCapacityUnits: 1
WriteCapacityUnits: 1
AttributeDefinitions: # ロック用列名(Terraformで決まっているので変更不可)
-
AttributeName: "LockID"
AttributeType: "S"
KeySchema:
-
AttributeName: "LockID"
KeyType: "HASH"
上記S3バケット + DynamoDBを利用するためのTerraform側の設定。
terraform {
backend "s3" {
bucket = "S3バケット名"
key = "terraform.tfstate"
region = "us-west-2"
lock_table = "DynamoDBテーブル名"
}
}