Terraformでのリソース管理の最適化: tfstateファイルの分割と移動手順
はじめに
こんにちは、Shunです。
Terraformを運用する上で、tfファイルが増えたことによる管理工数の増加やAPI実行制限などにより、tfstateファイルの分割を検討されたことはないでしょうか?
この記事では、Terraformを用いたインフラのコード管理で直面することがあるtfstateファイルの分割が必要なケースを想定して、tfstateファイル内のリソースの移動方法と、必要となるTerraformコマンドについて解説します。
想定読者
- Terraformの運用を行っている方
- tfstateファイルの分割を考えている方
本記事で紹介する内容
- tfstateで管理しているリソースをどのように移行するか
- 移行時に使用するTerraformコマンド
本記事で取り扱わない内容
- Terraformの基本的な概念解説
- Terraformの一般的なコマンド説明
実施すること
前提
- Terraformがセットアップ済みであること
- tfstateファイルをローカルで管理していること(リモート管理の場合も、手順の追加により対応可能です。)
手順
今回実施する手順は以下です。
- 必要なファイルの準備
- リソース作成
- tfstateファイルから移行対象を切り出す
- tfstateファイルへ移行対象を追加する
- tfファイルの変更
実際の作業
1. 必要なファイルの準備
ディレクトリ構造は以下の通りです。
terraform ├── from │ └── from.tf └── to └── to.tf
/from/from.tf
resource "terraform_data" "from1" {} resource "terraform_data" "from2" {}
/to/to.tf
resource "terraform_data" "to1" {}
今回の移行では、バックエンドやプロバイダの指定は行いません。
また、terraform_data
は、terraform1.4.0以降で使用できるリソースブロックです。
terraform1.4.0より前は、null_resource
として用いられていました。
詳細は以下のドキュメントを参照してください。
2. リソース作成
それぞれのディレクトリでterraform_data
リソースを作成します。
# リソースを作成します。 $ terraform init $ terraform apply -auto-approve # 管理対象を確認します。 $ terraform state list terraform_data.from1 terraform_data.from2
toディレクトリでも同様の作業を行います。
applyが成功すると、以下のようにtfstateファイルが作成されます。
terraform ├── from │ ├── from.tf │ └── terraform.tfstate └── to ├── to.tf └── terraform.tfstate
3. tfstateファイルから移行対象を切り出す
fromディレクトリで管理されているterraform_data.from2
を切り出します。
現在の/from/terraform.tfstate
は以下の状態です。
{ "version": 4, "terraform_version": "1.7.0", "serial": 3, "lineage": "77ad1c22-6635-1bba-09ce-98227d5b6287", "outputs": {}, "resources": [ { "mode": "managed", "type": "terraform_data", "name": "from1", "provider": "provider[\"terraform.io/builtin/terraform\"]", "instances": [ { "schema_version": 0, "attributes": { "id": "6d642543-2a09-f4dd-d379-64d6ea0acc80", "input": null, "output": null, "triggers_replace": null }, "sensitive_attributes": [] } ] }, { "mode": "managed", "type": "terraform_data", "name": "from2", "provider": "provider[\"terraform.io/builtin/terraform\"]", "instances": [ { "schema_version": 0, "attributes": { "id": "36e3de90-4adc-35d2-57a9-ef83362cb06d", "input": null, "output": null, "triggers_replace": null }, "sensitive_attributes": [] } ] } ], "check_results": null }
以下のコマンドを実行してterraform_data.from2
を切り出します。
$ terraform state mv -state-out=from.tfstate terraform_data.from2 terraform_data.from2 Move "terraform_data.from2" to "terraform_data.from2" Successfully moved 1 object(s).
terraform state mv
コマンドの詳細を知りたい方は以下をご覧ください。
これにより、/from/terraform.tfstate
からterraform_data.from2
が管理対象から外れます。
$ terraform state list terraform_data.from1
4. tfstateファイルへ移行対象を追加する
次に、toディレクトリで/from/from.tfstate
に格納されたterraform_data.from2
を/to/terraform.tfstate
へ移行します。
まず、現在のバックエンドの状態をローカルにコピーします。
$ terraform state pull > to.tfstate
terraform state pull
コマンドの詳細を知りたい方は以下をご覧ください。
続いて、/from/from.tfstate
のリソースを/to/to.tfstate
へマージします。
# リソースの識別子をfrom2→to2へ変更します。 $ terraform state mv -state=../from/from.tfstate -state-out=to.tfstate terraform_data.from2 terraform_data.to2 Move "terraform_data.from2" to "terraform_data.to2" Successfully moved 1 object(s).
これだけでは、先ほどローカルへコピーした/to/to.tfstate
へ移行対象が移動しただけです。
$ terraform state list terraform_data.to1
現在の/to/to.tfstate
は以下の状態です。
{ "version": 4, "terraform_version": "1.7.0", "serial": 1, "lineage": "a0c59a83-dfd9-d9e1-d2d9-d6083494c06e", "outputs": {}, "resources": [ { "mode": "managed", "type": "terraform_data", "name": "to1", "provider": "provider[\"terraform.io/builtin/terraform\"]", "instances": [ { "schema_version": 0, "attributes": { "id": "ced38e32-7f20-4456-2758-7091fd424aac", "input": null, "output": null, "triggers_replace": null }, "sensitive_attributes": [] } ] } ], "check_results": null }
terraform state pull
でバックエンドの状態をローカルにコピーし、terraform state push
で変更をバックエンドに適用します。
$ terraform state push to.tfstate
terraform state push
コマンドの詳細を知りたい方は以下をご覧ください。
これで、to/to.tfstate
で追加されたterraform_data.to2
が/to/terraform.tfstate
にプッシュされます。
$ terraform state list terraform_data.to1 terraform_data.to2
/to/terraform.tfstate
でも管理対象に追加されていることが確認できます。
{ "version": 4, "terraform_version": "1.7.0", "serial": 2, "lineage": "a0c59a83-dfd9-d9e1-d2d9-d6083494c06e", "outputs": {}, "resources": [ { "mode": "managed", "type": "terraform_data", "name": "to1", "provider": "provider[\"terraform.io/builtin/terraform\"]", "instances": [ { "schema_version": 0, "attributes": { "id": "ced38e32-7f20-4456-2758-7091fd424aac", "input": null, "output": null, "triggers_replace": null }, "sensitive_attributes": [] } ] }, { "mode": "managed", "type": "terraform_data", "name": "to2", "provider": "provider[\"terraform.io/builtin/terraform\"]", "instances": [ { "schema_version": 0, "attributes": { "id": "dfb49bcd-3694-e2eb-7e77-3144712ef403", "input": null, "output": null, "triggers_replace": null }, "sensitive_attributes": [] } ] } ], "check_results": null }
5. tfファイルの変更
最後に、管理対象の移動に伴って、tfファイル内のresource
ブロックを更新します。
これにより、terraform plan
を実行した際に差分が生じないようにします。
/from/from.tf
と /to/to.tf
を以下のように更新します。
/from/from.tf
resource "terraform_data" "from1" {} # resource "terraform_data" "from2" {}
/to/to.tf
resource "terraform_data" "to1" {} resource "terraform_data" "to2" {}
まとめ
この記事では、tfstateファイルのリソース移動方法について解説しました。
初めは単一のディレクトリでの管理の方が簡単ですが、ファイル数の増加やAPI制限などにより、分割が必要となる場合があります。
その際は、本記事で紹介した手順を参考にしてください。
ただし、不適切な操作によりファイルが破損した場合、復旧が困難になることやインフラの状態と実際のリソースの状態が不一致になる可能性があるため、tfstateファイルの取り扱いには細心の注意を払い、十分な検証を行った上で実施することを推奨します。
最後まで読んでいただきありがとうございます!
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitter週8バスケしたいです。Google Cloud11冠、2024 AWS All Cert
Recommends
こちらもおすすめ
-
Terraform import ブロックの実活用
2023.12.16
-
Terraform を運用するについて考える ~第2回 Terraformを始める~
2022.10.26
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 8 %割引になる!
『AWSの請求代行リセールサービス』
2023.01.15