1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

terraform state fileのマージ

Last updated at Posted at 2024-08-18

state fileをローカルファイルに書き出す

source側

terraform state pull > source.tfstate

destination側

terraform state pull > destination.tfstate

新しいdirectoryにtfstateファイルを移動

mkdir merge-state
mv /path/to/source.tfstate merge-state
mv /path/to/destination.tfstate merge-state
cd merge-state

resourcesのリストファイルを作成

terraform state list -state=destination.tfstate > destination-resources.txt
terraform state list -state=source.tfstate > source-resources.txt

中身はこんな感じ↓

data.aws_ecr_lifecycle_policy_document.foo_policy
data.aws_iam_policy_document.foo_policy
aws_ecr_lifecycle_policy.foo_policy
aws_ecr_repository.foo
aws_route53_record.about
...

一応、SourceとDestinationのResourceの数も数えておきます

wc -l source-resources.txt 
     107 source-resources.txt
wc -l destination-resources.txt 
      22 destination-resources.txt

state を移動

  1. stateには module.aaa.aws_s3_bucket["aaa"]のようにdoublequotesが入っている可能性があるので、escapeする必要あり。

  2. また、以下のコマンドだと、 xargs: command line cannot be assembled, too long というエラーが出たりするのでlineごとにloopで回した (xargsあまり使いこなせていないので :smiley_cat: )

    cat source-resources.txt | xargs -I {} bash -c 'terraform state mv -state=source.tfstate -state-out=destination.tfstate "{}" "source_module.{}"'
    
while IFS= read -r resource; do
    terraform state mv -state=source.tfstate -state-out=destination.tfstate "$resource" "$resource"
done < source-resources.txt
terraform state list -state=source.tfstate | wc -l
       0
terraform state list -state=destination.tfstate | wc -l
     129

107 (source resources before) + 22 (destination resources before) = 0 (source resources after) + 129 (destination resources after) で一致しています :tada:

コードの移動

対象となるsourceのterraformコードをDestination側に移します

destination 側で確認

destinationのterraform codeのあるdirectoryに移動して destination-after.tfstate に変更後のstate fileを移動します。

cp /path/merge-state/destination.tfstate destination-after.tfstate

backendの設定をremoteからlocalに変えます。

-  backend "s3" {
-    bucket = "your-terraform"
-    key    = "aws/naka/terraform.tfstate"
-  }
+  backend "local" {
+    path = "destination-after.tfstate"
+  }

remote stateはいじらずに、initしたいので -reconfigure Optionをつけてinitします。

terraform init -reconfigure

planをしてみます。

terraform plan

No changeになればcodeとstateが一致しています。

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

No changes :tada: これで、 source から destinationへの移行が完了しました!

これで一致しない場合は何がおかしいのかを確認して、もう一度merge-stateに戻ってstateのマージに間違いがないかやり直します。もし状況がわからなくなってしまった場合には、backendの変更をrevertして terraform init -reconfigureすれば、始める前の状態に戻ることができます。

stateをremoteに戻す

無事に、stateのマージができたので、最後にlocal fileにあるstateをremoteに反映します。

今はlocalのbackendになっているので、destination側のbackendを元々のremote backendに戻します。

+  backend "s3" {
+    bucket = "your-terraform"
+    key    = "aws/naka/terraform.tfstate"
+  }
-  backend "local" {
-    path = "destination-after.tfstate"
-  }

terraform init すると以下のように聞かれます。

terraform init
Initializing the backend...
Initializing modules...
╷
│ Error: Backend configuration changed
│ 
│ A change in the backend configuration has been detected, which may require migrating existing state.
│ 
│ If you wish to attempt automatic migration of the state, use "terraform init -migrate-state".
│ If you wish to store the current configuration with no changes to the state, use "terraform init -reconfigure".

automatic migration of the stateをしたいので、-migrate-state をつけて実行します。

terraform init -migrate-state

そうすると以下のように local -> s3 (remote) にコピーするかどうかが聞かれます。

terraform init -migrate-state
Initializing the backend...
Terraform detected that the backend type changed from "local" to "s3".

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"): /var/folders/20/jnrp85t51hd23cjk51_btywh0000gp/T/terraform4131371062/1-local.tfstate
  New      (type "s3"): /var/folders/20/jnrp85t51hd23cjk51_btywh0000gp/T/terraform4131371062/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:

/var/folders/20/jnrp85t51hd23cjk51_btywh0000gp/T/terraform4131371062/1-local.tfstate 一応中身を軽く確認して (行数やversionをチェックする程度) yes と答えます。

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing modules...
Initializing provider plugins...

...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

そうするとlocal stateをs3(remote)のbackendにコピーしてくれます。

最後にこの状態でterraform planを実行して No changes がでればOKです :tada: :tada: 完全に完了です。

No changes. Your infrastructure matches the configuration.

あとは、Source側のコードとCIを削除して、PushしてCI上でもNo changesとなるのをみて、Mergeをして終わりです。

Ref

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?