Terraform Backend変更ガイド: -reconfigureの使用方法
はじめに
こんにちは、Shunです。
今回は、Backendの変更や更新の際に使用するterraform init -reconfigure
コマンドについてご紹介します。
公式ドキュメントでは、以下のように定義されています。
すでに初期化されたバックエンドで init を再実行すると、新しいバックエンド設定を使用するように作業ディレクトリが更新されます。バックエンド構成を更新するには、-migrate-stateか-reconfigureを指定する必要があります。この-reconfigureオプションは既存の構成を無視し、既存の状態の移行を防ぎます。
関連コマンドのterraform init -migrate-state
については、以下の記事で解説をしています。
この記事では、terraform init -reconfigure
コマンドの挙動について、具体例を交えながら解説します。
想定読者
- TerraformのBackend更新を検討している方
terraform init -reconfigure
コマンドの使用経験はあるが、詳細な挙動が気になる方
本記事で取り扱う内容
- TerraformのBackendの切り替え方
terraform init -reconfigure
の挙動- 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" "sapporo" {} resource "terraform_data" "yebisu" {}
※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": "sapporo", "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": [] } ] }, { "mode": "managed", "type": "terraform_data", "name": "yebisu", "provider": "provider[\"terraform.io/builtin/terraform\"]", "instances": [ { "schema_version": 0, "attributes": { "id": "622dced0-b35d-a01c-8a32-4b14d928dd5d", "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 -reconfigureを用いて、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" "sapporo" {} resource "terraform_data" "yebisu" {}
そして、以下のコマンドを実行します。
$ terraform init -reconfigure
/.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": [] } ] }
現在のディレクトリ構造は、以下のようになっています。
blog ├─ .terraform │ └ terraform.tfstate # Backendの情報が記述されたファイル └─ main.tf
ここで、terraform plan
を実行します。
すると、以下のように新規リソースの作成が実行結果として表示されます。
$ terraform plan Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # terraform_data.sapporo will be created + resource "terraform_data" "sapporo" { + id = (known after apply) } # terraform_data.yebisu will be created + resource "terraform_data" "yebisu" { + id = (known after apply) } Plan: 2 to add, 0 to change, 0 to destroy.
これはS3で作成したterraform_data
がローカルの状態ファイルへ移行されていないことを示しています。
terraform apply
を実行することで、ローカルへ/terraform.tfstate
が作成されます。
blog ├─ .terraform │ └ terraform.tfstate # Backendの情報が記述されたファイル ├─ main.tf └─ terraform.tfstate
ローカルでterraform_dataを削除
続いて、S3とローカルで差分を作るために、main.tfファイルから"terraform_data" "sapporo"
リソースの定義をコメントアウトし、
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" "sapporo" {} resource "terraform_data" "yebisu" {}
リソースを削除します。
この変更を適用することで、ローカルの/terraform.tfstate
ファイルが更新されます。
ローカルの/terraform.tfstate
ファイルが更新されたことにより、バックアップとして/terraform.tfstate.backup
ファイルが作成されます。
/terraform.tfstate.backup
は最終更新の一つ前の状態がバックアップとして、保存されます。
現在のディレクトリ構造は、以下のようになっています。
blog ├─ .terraform │ └ terraform.tfstate # Backendの情報が記述されたファイル ├─ main.tf ├─ terraform.tfstate # 現在のリソース状態が記述されたファイル └─ terraform.tfstate.backup # 現在のリソース状態へ変更する前の状態ファイルのバックアップ
terraform init -reconfigureを用いて、BackendをローカルからS3へ変更
次に、main.tfファイルを編集して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" "sapporo" {} resource "terraform_data" "yebisu" {}
再びterraform init -reconfigure
を実行すると、「既にファイルが存在するが、上書きをするかどうか」を問われますので、「yes」を選択します。
$ terraform init -reconfigure Initializing the backend... Do you want to copy existing state to the new backend? Pre-existing state was found while migrating the previous "local" backend to the newly configured "s3" backend. An existing non-empty state already exists in the new backend. The two states have been saved to temporary files that will be removed after responding to this query. Previous (type "local"): xxxx/1-local.tfstate New (type "s3"): xxxx/2-s3.tfstate Do you want to overwrite the state in the new backend with the previous state? Enter "yes" to copy and "no" to start with the existing state in the newly configured "s3" backend. Enter a value:yes
この操作により、.terraform/terraform.tfstate
ファイル内のBackend設定がS3に更新されます。
terraform plan
を実行すると、terraform_data
リソースの削除に関する差分が発生しません。
これはterraform init -reconfigure
によって、既存のtfstateファイルを上書きされるためです。
ローカルのtfstateファイルの中身は空っぽになっており、/terraform.tfstate.backup
ファイルには、ローカルからS3に移した際の状態が記録されております。
terraform init -reconfigureを用いて、BackendをS3からS3へ変更
最後に、新しいS3のkeyへBackendを変更します。
以下のように新しいkeyを指定して、terraform init -reconfigure
を実行します。
terraform { required_version = "~> 1.7.0" backend "s3" { bucket = "[bucket_name]" region = "ap-northeast-1" key = "reconfigure/terraform.tfstate" } # backend "local" { # path = "terraform.tfstate" # } } # resource "terraform_data" "sapporo" {} resource "terraform_data" "yebisu" {}
移行後にterraform plan
を実行すると、新しいリソースの作成が表示されます。
これにより、tfstateファイルが再構成されていることがわかります。
terraform apply
すると、新しいリソースの作成に成功します。
terraform apply -auto-approve Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # terraform_data.yebisu will be created + resource "terraform_data" "yebisu" { + id = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. terraform_data.yebisu: Creating... terraform_data.yebisu: Creation complete after 0s [id=ab9d0a01-afc6-b2bc-b9cc-2ca32cd10fb5] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
ローカルでBackendをterraform init -reconfigure
した際は、バックアップファイルが作成されましたが、S3で行なった場合は作成されませんでした。
注意点
一つだけterraform init -reconfigure
を実施するときに注意が必要です。
以下のように、Backendを明示的に記述しなかった場合、デフォルトのBackendであるローカルが設定されます。
terraform { required_version = "~> 1.7.0" # backend "s3" { # bucket = "eto-test-tfstate" # region = "ap-northeast-1" # key = "main/terraform.tfstate" # } # backend "local" { # path = "terraform.tfstate" # } } resource "terraform_data" "sapporo" {} resource "terraform_data" "yebisu" {}
しかし、terraform init -reconfigure
を上記のコードで実行すると、Backendが記述されている/.terraform/terraform.tfstate
内が書き替わらず、Backendの不整合が生じてしまいます。
$ terraform plan ╷ │ Error: Backend initialization required, please run "terraform init" │ │ Reason: Unsetting the previously set backend "s3" │ │ The "backend" is the interface that Terraform uses to store state, │ perform operations, etc. If this message is showing up, it means that the │ Terraform configuration you're using is using a custom configuration for │ the Terraform backend. │ │ Changes to backend configurations require reinitialization. This allows │ Terraform to set up the new configuration, copy existing state, etc. Please run │ "terraform init" with either the "-reconfigure" or "-migrate-state" flags to │ use the current configuration. │ │ If the change reason above is incorrect, please verify your configuration │ hasn't changed and try again. At this point, no changes to your existing │ configuration or state have been made.
そのため、S3からローカルへterraform init -reconfigure
する際は、以下のように明示的にBackendを記述する必要があります。
terraform { required_version = "~> 1.7.0" # backend "s3" { # bucket = "eto-test-tfstate" # region = "ap-northeast-1" # key = "main/terraform.tfstate" # } backend "local" { path = "terraform.tfstate" } } resource "terraform_data" "sapporo" {} resource "terraform_data" "yebisu" {}
ただ、S3からローカルへterraform init -migrate-state
を行う際は、明示的に記述を行わなくても、自動で/.terraform/terraform.tfstate
ファイルは更新されます。
まとめ
terraform init -reconfigure
を検証して分かったことは以下です。
- Backend設定の
.terraform/terraform.tfstate
ファイルは自動的に更新される - ローカルへの
terraform init -reconfigure
実行時には、ローカルにterraform.tfstate.backup
ファイルが作成されるが、S3への実行時には作成されない /terraform.tfstate
ファイルは既存のBackendから新しいBackendへコピーされるが、既にtfstateファイルが存在する場合には、上書きされるかどうかを問われる- S3からローカルへ
terraform init -reconfigure
する際は、ローカルのBackendを明示的に記述する必要がある
既存のtfstateファイルが存在する場所に、terraform init -reconfigure
を実行すると、tfstateファイルが上書きされてしまうので、この点にも注意が必要です。
最後まで読んでいただきありがとうございます!
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitterGoogle Cloud Partner Top Engineer 2025、2024 AWS All Cert、ビール検定1冠
Recommends
こちらもおすすめ
-
AWS Glueの「AmazonS3イベント通知を使用した加速クロール」とは何か
2022.12.22
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16