Terraform Backend変更ガイド: -migrate-stateの使用方法
はじめに
こんにちは、Shunです。
Terraformを運用していると、一時的にBackendを変更したり、更新が必要になる場面があると思います。
そんな時に役立つterraform init -migrate-state
コマンドについてご紹介します。
公式ドキュメントでは、以下のように定義されています。
すでに初期化されたバックエンドで init を再実行すると、新しいバックエンド設定を使用するように作業ディレクトリが更新されます。バックエンド構成を更新するには、-migrate-stateか-reconfigureを指定する必要があります。この-migrate-stateオプションは、既存の状態を新しいバックエンドにコピーしようとします。変更内容に応じて、ワークスペース状態の移行を確認する対話型プロンプトが表示される場合があります。
関連コマンドのterraform init -reconfigure
については、以下の記事で解説をしています。
この記事では、terraform init -migrate-state
コマンドの挙動について、具体例を交えながら解説します。
想定読者
- TerraformのBackend更新を検討している方
terraform init -migrate-state
コマンドの使用経験はあるが、詳細な挙動が気になる方
本記事で取り扱う内容
- TerraformのBackendの切り替え方
terraform init -migrate-state
の挙動- tfstateファイルなどの関連ファイルの説明
本記事で取り扱わない内容
- Terraformの基本的な概念解説
- Terraformの一般的なコマンド説明
実施すること
前提
- tfstateファイルをS3で管理していること
- Terraformがセットアップ済みであること
必要ファイルの準備
ディレクトリ構造としては、/blogの下にmain.tfファイルを用意します。
blog └ main.tf
/blog/main.tf
terraform { required_version = "~> 1.7.0" backend "s3" { bucket = "[bucket_name]" region = "ap-northeast-1" key = "main/terraform.tfstate" } # backend "local" { # path = "terraform.tfstate" # } } resource "terraform_data" "main" {}
※terraform_data
はterraform1.4.0以上で使用できます。
BackendをS3に設定した状態で、以下のコマンドを実行してください。
$ terraform init $ terraform apply -auto-approve
tfstateファイルの確認
S3に保存されているtfstateファイルと、/blog/.terraform/terraform.tfstate
のファイルを確認します。
S3に保管されているtfstateファイルでは、先ほど立ち上げたリソースの状態が保管されています。
{ "version": 4, "terraform_version": "1.7.0", "serial": 1, "lineage": "b855417a-5d74-aec3-b503-bfcc1fb5f05a", "outputs": {}, "resources": [ { "mode": "managed", "type": "terraform_data", "name": "main", "provider": "provider[\"terraform.io/builtin/terraform\"]", "instances": [ { "schema_version": 0, "attributes": { "id": "8cf84313-2cb8-16e1-5a91-4565bcd87d13", "input": null, "output": null, "triggers_replace": null }, "sensitive_attributes": [] } ] } ], "check_results": null }
次に、/blog/.terraform/terraform.tfstate
を確認します。
.terraform
配下にあるterraform.tfstate
はリソース状態を定義するtfstateファイルではなく、指定されたBackendの情報が記述されたファイルです。
中身は以下のようにS3がBackendとして指定されています。
{ "version": 3, "serial": 1, "lineage": "e9a0f02a-d1ef-c671-d922-274b44b4991a", "backend": { "type": "s3", "config": { "access_key": null, "acl": null, "allowed_account_ids": null, "assume_role": null, "assume_role_duration_seconds": null, "assume_role_policy": null, "assume_role_policy_arns": null, "assume_role_tags": null, "assume_role_transitive_tag_keys": null, "assume_role_with_web_identity": null, "bucket": "[bucket_name]", "custom_ca_bundle": null, "dynamodb_endpoint": null, "dynamodb_table": null, "ec2_metadata_service_endpoint": null, "ec2_metadata_service_endpoint_mode": null, "encrypt": null, "endpoint": null, "endpoints": null, "external_id": null, "forbidden_account_ids": null, "force_path_style": null, "http_proxy": null, "https_proxy": null, "iam_endpoint": null, "insecure": null, "key": "main/terraform.tfstate", "kms_key_id": null, "max_retries": null, "no_proxy": null, "profile": null, "region": "ap-northeast-1", "retry_mode": null, "role_arn": null, "secret_key": null, "session_name": null, "shared_config_files": null, "shared_credentials_file": null, "shared_credentials_files": null, "skip_credentials_validation": null, "skip_metadata_api_check": null, "skip_region_validation": null, "skip_requesting_account_id": null, "skip_s3_checksum": null, "sse_customer_key": null, "sts_endpoint": null, "sts_region": null, "token": null, "use_dualstack_endpoint": null, "use_fips_endpoint": null, "use_legacy_workflow": null, "use_path_style": null, "workspace_key_prefix": null }, "hash": 226295838 }, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": {}, "depends_on": [] } ] }
実際の作業
terraform init -migrate-stateを用いて、BackendをS3からローカルへ変更
まずは、以下のようにファイルを書き換えます。
terraform { required_version = "~> 1.7.0" # backend "s3" { # bucket = "[bucket_name]" # region = "ap-northeast-1" # key = "main/terraform.tfstate" # } backend "local" { path = "terraform.tfstate" } } resource "terraform_data" "main" {}
そして、以下のコマンドを実行します。
$ terraform init -migrate-state
以下のように、「BackendをS3からローカルへ変更し、S3のtfstateファイルをローカルにコピーしますよ。」との確認が出ますので、「yes」を入力します。
Initializing the backend... Terraform detected that the backend type changed from "s3" to "local". Do you want to copy existing state to the new backend? Pre-existing state was found while migrating the previous "s3" backend to the newly configured "local" backend. No existing state was found in the newly configured "local" backend. Do you want to copy this state to the new "local" backend? Enter "yes" to copy and "no" to start with an empty state. Enter a value:yes
ここでローカルへS3で保管していたtfstateファイルがコピーされます。
また、/.terraform/terraform.tfstate
のBackendの向き先がローカルへ切り替わります。
{ "version": 3, "serial": 2, "lineage": "e9a0f02a-d1ef-c671-d922-274b44b4991a", "backend": { "type": "local", "config": { "path": "terraform.tfstate", "workspace_dir": null }, "hash": 73024536 }, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": {}, "depends_on": [] } ] }
ローカルでterraform_dataを削除
まず、main.tfファイルからterraform_data
リソースの定義をコメントアウトし、
terraform { required_version = "~> 1.7.0" # backend "s3" { # bucket = "[bucket_name]" # region = "ap-northeast-1" # key = "main/terraform.tfstate" # } backend "local" { path = "terraform.tfstate" } } # resource "terraform_data" "main" {}
リソースを削除します。
$ terraform apply -auto-approve
この変更を適用することで、ローカルの/terraform.tfstate
ファイルが更新されます。
またローカルの/terraform.tfstate
ファイルが更新されたことにより、S3からローカルにコピーされたtfstateファイルのバックアップとして/terraform.tfstate.backup
ファイルが作成されます。
現在のディレクトリ構造は、以下のようになっています。
blog ├─ .terraform │ └ terraform.tfstate # Backendの情報が記述されたファイル ├─ main.tf ├─ terraform.tfstate # 現在のリソース状態が記述されたファイル └─ terraform.tfstate.backup # S3からmigrateしたファイルのバックアップ
terraform init -migrate-stateを用いて、BackendをローカルからS3へ変更
次に、main.tfファイルを編集してBackendをS3に設定し、再びterraform init -migrate-state
を実行します。
以下のようにファイルを書き換えます。
terraform { required_version = "~> 1.7.0" backend "s3" { bucket = "[bucket_name]" region = "ap-northeast-1" key = "main/terraform.tfstate" } # backend "local" { # path = "terraform.tfstate" # } } # resource "terraform_data" "main" {}
この操作により、.terraform/terraform.tfstate
ファイル内のBackend設定がS3に更新されます。
terraform plan
を実行すると、terraform_data
リソースの削除に関する差分が発生することが示されます。
これはterraform init -migrate-state
が既存のtfstateファイルを上書きしないためです。
terraform init -migrate-stateを用いて、BackendをS3からS3へ変更
最後に、新しいS3のkeyへBackendを変更します。
以下のように新しいkeyを指定して、terraform init -migrate-state
を実行します。
terraform { required_version = "~> 1.7.0" backend "s3" { bucket = "[bucket_name]" region = "ap-northeast-1" key = "migrate/terraform.tfstate" } # backend "local" { # path = "terraform.tfstate" # } } # resource "terraform_data" "main" {}
この場合、terraform plan
を実行しても差分が発生しないことから、tfstateファイルが新しいBackendに適切に移行されていることがわかります。
まとめ
terraform init -migrate-state
を検証して分かったことは以下です。
- Backend設定の
.terraform/terraform.tfstate
ファイルは自動的に更新される - ローカルへの
terraform init -migrate-state
実行時には、terraform.tfstate.backup
ファイルが作成されるが、S3への実行時には作成されない /terraform.tfstate
ファイルは既存のBackendから新しいBackendへコピーされるが、既にtfstateファイルが存在する場合には上書きされない
Backupファイルを作成してくれることやtfstateファイルが上書きされないことは、tfstateファイルの整合性を保つことに非常に役立ちます。
terraform init
という基本的なコマンドを深掘りすることで、普段から使っているterraformの挙動をコントロールできている感覚になりました。
最後まで読んでいただきありがとうございます!
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitterGoogle Cloud Partner Top Engineer 2025、2024 AWS All Cert、ビール検定1冠
Recommends
こちらもおすすめ
-
AWS Glueの「AmazonS3イベント通知を使用した加速クロール」とは何か
2022.12.22
-
お願い城之内、Amazon S3 のバケットポリシーに Deny を使わないで!
2022.11.28
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16