ヤプリ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" } }
作業用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
移行先ディレクトリーに作業用tfstateをまとめる
同じディレクトリにあった方が作業しやすいのでmvなど1箇所に集めましょう。
mv tmp_fuga.tfstate ../hoge/
作業用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
作業用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が使えるなら活用してみても良いかもしれません。