Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

Terraform S3上のRemote Stateのリソースを別階層にお引越しする

f:id:modokkin:20211209114523p:plain

ヤプリSREチームの羽渕です。
すっかり冬ですね。最近、象印の定番加湿器を購入したのですがエアコンつけっぱなしで寝ても喉が痛くならないし、手入れも簡単なので重宝しています。
さて、今回はInfrastructure as Codeを実現する定番ツールである Terraform のちょっとしたTipsをお届けしたいと思います。
この記事は ヤプリ Advent Calendar 2021 15日目 に捧げる記事となります。


はじめに

Terraformを長年運用していると、後からやっぱりこのリソースはこっちの階層に移動したいよな、というシーンがあると思います。ローカルでtfstateを管理しているなら、単純に terraform state mv すれば良いのですがS3などに保管するRemote Stateを利用している場合はそうもいきません。
そこで最短ルートでS3上のStateを引っ越しする手順を記してみたいと思います。

事前準備

次の2点を事前に行っておくことをおすすめします。

  • S3のバージョニング機能を有効化することで手違いがあったときにロールバックできるようにしておく。
    →terraformの機能だけで安全に引っ越ししたい場合は、一時的にbackend設定をローカルに切り替える手順を紹介している記事があるのでググってみてください。
  • 事前に移行元、移行先のterraform planの差分がない状態にしておく。

手順

本手順では次のようなディレクトリ構成を元に解説します。

.
├── fuga #移行元
│   └── fuga.tf
└── hoge #移行先
    └── hoge.tf

tfファイルのソースを移植する

移行元のtfファイルから移行先のtfファイルに必要なリソースブロックを移植します。

移植するリソースブロックのイメージ

resource "aws_s3_bucket" "example" {
  bucket = "example"
  acl        = "private"

  tags = {
    Name  = "example"
  }
}

f:id:modokkin:20211208183107p:plain

作業用tfstateを生成する

terraform state pullでS3上のtfstateファイルをローカルに保存します。

参考 Command: state pull - Terraform by HashiCorp

cd hoge/
terraform state pull > tmp_hoge.tfstate
cd fuga/
terraform state pull > tmp_fuga.tfstate

f:id:modokkin:20211208183109p:plain

移行先ディレクトリーに作業用tfstateをまとめる

同じディレクトリにあった方が作業しやすいのでmvなど1箇所に集めましょう。

mv tmp_fuga.tfstate ../hoge/

f:id:modokkin:20211208183111p:plain

作業用tfstateの移行元から移行先にstateを移動する

terraform state mv でtmp_hoge.tfstateからtmp_fuga.tfstate移行先に対象リソースのstateを移動します。

参考 Command: state mv - Terraform by HashiCorp

# terraform state mv -state=[移行元tfstate] --state-out=[移行先tfstate] [移行元リソースアドレス] [移行先リソースアドレス]
terraform state mv -state=tmp_fuga.tfstate --state-out=tmp_hoge.tfstate aws_s3_bucket.example aws_s3_bucket.example

f:id:modokkin:20211208183114p:plain

作業用tfstateの確認する

移行先のtfstateの内容が意図した状態になっているか確認します。不備がある場合は次の手順に進む前に見直しましょう。 参考 Command: show - Terraform by HashiCorp

terraform show tmp_hoge.tfstate
resource "aws_s3_bucket" "example" {
    acl               = "private"
...
}

作業用tfstateの内容をS3上のtfstateに反映する

terraform state push の引数に移行先tfstateを指定し、S3上のtfstateを更新します。 参考 Command: state push - Terraform by HashiCorp

terraform state push tmp_hoge.tfstate

移行先RemoteStateでplanしてみる

terraform plan で移行先の差分がないことを確認します。 ※もし意図しない状態になっている場合はS3のバージョニング機能で1世代前のtfstateを復元すればロールバックできます。 参考 以前のバージョンの復元 - Amazon Simple Storage Service

terraform plan
aws_s3_bucket.example: Refreshing state... [id=example]
...
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.

移行元RemoteStateから対象リソースを削除して、planする

移行元のtfstateから対象リソースのstateを削除します。 参考 Command: state rm - Terraform by HashiCorp

cd ../fuga
terraform state rm aws_s3_bucket.example

terraform planで移行元の差分がないことを確認します。

terraform plan
aws_s3_bucket.example: Refreshing state... [id=example]
...
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.

作業用tfstateを削除する

最後にいらなくなった作業用ファイルを削除します。

cd ..
rm hoge/tmp_hoge.tfstate fuga/tmp_fuga.tfstate

まとめ

RemoteState間でのstateの移動は面倒なイメージがあったのですが、実際にやってみると意外と簡単にできることが分かりました。
最初からstateを移動しなくても良い構成に仕上げられれば良いのですが、運用上リソースを整理したくなるケースは珍しくないと思います。
この記事がどこかのTerraformerの参考になれば幸いです。

追記 2021/12/23

この記事を書いた後に気づいたのですが、Terraform v1.1でmovedリソースというものが追加されたようです。 まだ試せていませんが、もし最新のTerraformが使えるなら活用してみても良いかもしれません。

learn.hashicorp.com