🗂

tfstateファイルを安全に分割・マージする方法

2023/06/11に公開

はじめに

Terraformは、インフラストラクチャの状態をtfstateファイルに保存します。
このファイルは、Terraformが管理するリソースの情報を含んでおり、Terraformの実行に必要です。
しかし、tfstateファイルが大きくなりすぎると、以下のような問題が発生する可能性があります。

  • tfstateファイルの読み書きに時間がかかる
  • tfstateファイルのバックアップや復元が困難になる
  • tfstateファイルの差分が見づらくなる
  • tfstateファイルの競合が発生しやすくなる

これらの問題を回避するために、tfstateファイルを分割できます。分割する方法は、主に以下の2つです。

  • モジュールごとにtfstateファイルを分割する
  • ワークスペースごとにtfstateファイルを分割する

モジュールごとにtfstateファイルを分割する場合は、terraform_remote_stateデータソースを使って、他のモジュールのtfstateファイルを参照できます。例えば、以下のような構成になっているとします。

├── main.tf
├── modules
│ ├── app
│ │ ├── main.tf
│ │ └── outputs.tf
│ └── db
│ ├── main.tf
│ └── outputs.tf
└── outputs.tf

ここで、appモジュールとdbモジュールはそれぞれ別のtfstateファイルを持っており、appモジュールはdbモジュールの情報を必要とします。この場合、appモジュールのmain.tfに以下のように記述します。

data "terraform_remote_state" "db" {
  backend = "s3"
  config = {
    bucket = "my-bucket"
    key = "db/terraform.tfstate"
    region = "ap-northeast-1"
  }
}

resource "aws_instance" "app" {
  ami = "ami-0c3fd0f5d33134a76"
  instance_type = "t2.micro"

  # dbモジュールのtfstateファイルからDBサーバーのIPアドレスを取得する
  user_data = <<-EOF
#!/bin/bash
echo "${data.terraform_remote_state.db.outputs.db_ip}" > /tmp/db_ip.txt
EOF

  tags = {
    Name = "app-server"
  }
}

ワークスペースごとにtfstateファイルを分割する場合は、terraform workspaceコマンドを使って、複数の環境(例えば開発環境や本番環境)を切り替えられます。例えば、以下のような構成になっているとします。

├── main.tf
├── terraform.tfvars
└── variables.tf

ここで、開発環境と本番環境はそれぞれ別のtfstateファイルを持っており、terraform.tfvarsファイルで環境ごとに異なる変数を設定しています。この場合、以下のようにコマンドを実行します。

# 開発環境用のワークスペースを作成する
$ terraform workspace new dev

# 開発環境用のワークスペースに切り替える
$ terraform workspace select dev

# 開発環境用のtfstateファイルを作成する
$ terraform apply

# 本番環境用のワークスペースを作成する
$ terraform workspace new prod

# 本番環境用のワークスペースに切り替える
$ terraform workspace select prod

# 本番環境用のtfstateファイルを作成する
$ terraform apply

tfstateファイルを分割した後、逆にマージする必要がある場合は、terraform stateコマンドを使って、tfstateファイルの内容を移動や削除できます。例えば、以下のようにコマンドを実行します。

# appモジュールのtfstateファイルからappサーバーの情報をルートのtfstateファイルに移動する
$ terraform state mv -state=modules/app/terraform.tfstate module.app aws_instance.app

# dbモジュールのtfstateファイルからdbサーバーの情報をルートのtfstateファイルに移動する
$ terraform state mv -state=modules/db/terraform.tfstate module.db aws_instance.db

# appモジュールとdbモジュールのtfstateファイルを削除する
$ rm modules/app/terraform.tfstate
$ rm modules/db/terraform.tfstate

以上が、tfstateファイルを安全に分割・マージする方法です。tfstateファイルはTerraformの重要なコンポーネントなので、適切に管理することが必要です。
分割・マージする際には、バックアップやテストを行うことをおすすめします。

Discussion