[Terraform] 既存のリソースをimportするにはimport blockが有用
副業で携わっている案件で、Terraform で管理されていないインフラストラクチャのリソースを Terraform で管理する(state
ファイルに反映する)ことになり、下記の2つの方法について調査をしました。
-
terraform import
コマンドを使う -
import block
を使う
チームでの運用を考慮すると、terraform import
コマンドにはいくつかの課題があることがわかりました。また、v1.5 から使用可能となった import block
はこの課題を解消しており、import block
の方が有用ではないか、と考えたのでこの点について紹介します。
前提
下記の運用を前提にしています。
-
terraform apply
コマンドは、CI/CD のワークフローによって、PR がマージされたタイミングで自動で実行される -
state
ファイルの変更を伴うコマンドの実行はローカルで行わない
逆に、開発者がローカル上で定常的に state
ファイルを書き換えるような操作を行うことは前提としていません。
terraform import
コマンドについて
terraform import
コマンドを使うことで、state
ファイルに目的のリソースを反映することができます。
作業フローは下記のとおりです。
しかし、下記に上げる 2 点の問題点から基本的に使用は控えるべきだと考えました。
state
ファイルと configuration
ファイルに差分が生じる
1. コマンド実行後に一時的に terraform import
コマンドを実行すると、state
ファイルに目的のリソースは反映されているのですが、この時点ではまだ configuration
ファイル (.tf
ファイル) の resource block
として定義されているわけではありません。
そのため、resource block
を定義するまでに、terraform plan
コマンドを実行すると差分が出てしまいます。
チームでの運用を考えると、ある開発者が terraform import
を実行し、別の開発者が terraform plan
を実行すると意図しない差分が出るなどの問題が生じてしまう可能性が存在します。
2. コマンド実行前にレビューしづらい
terraform import
コマンドを実行する場合、実行前にこのコマンドの内容を第三者にどのようにレビューしてもらうか、という問題があります。ワンショットのシェルスクリプトを作成し、これをレビューしてもらうという方法もありますが、state
ファイルにリソースがどのように反映されるかイメージしづらく、決してわかりやすい方法ではありません。
また、基本的に state
ファイルの更新を伴う操作はローカルでは行うべきではなく、CI/CD パイプラインによって行うべきです。terraform plan
や terraform apply
を行う CI/CD があったとしても、さらに terraform import
を対応するためのコストは低くはないでしょう。
import block
について
次は、Terraform v1.5 から利用できるようになった import block
についてです。この方法がチームでの運用に適していると考えられます。
作業フローは下記のとおりです。
import block
使用時と異なり、resource block
を定義してから terraform apply
した後に state
ファイルが更新されます。
そのため、import block
の課題であったタイムラグやレビューのしづらさの問題が解消されているのです。
-
terraform apply
前に、import block
とresource block
のレビューが可能 -
terraform apply
によってstate
ファイルが更新される
import block
使用例
import block
の使用例を紹介します。
UI から作成した GCS Bucket を Terraform 管理にする場合について考えてみます。まず、import block
を使ってリソースを追加します。
import {
id = "mybucket-import-test"
to = google_storage_bucket.mybucket_import_test
}
次に、terraform plan -generate-config-out
コマンドを使って、import block
を使用したリソースの定義を生成します。-generate-config-out
オプションは Experimental ですので使用する際は一定の検討が必要ですが、私は PoC を経た上で有用だと判断し導入を決断しました。
terraform plan -generate-config-out=gen_google_storage_bucket.tf
生成されたファイルを見てみます。注目すべきなのは、この時点では state
ファイルは変更されていない点です。
# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.
# __generated__ by Terraform from "mybucket-import-test"
resource "google_storage_bucket" "mybucket_import_test" {
default_event_based_hold = false
enable_object_retention = false
force_destroy = false
labels = {}
location = "ASIA-NORTHEAST1"
name = "mybucket-import-test"
project = "myproject"
public_access_prevention = "enforced"
requester_pays = false
rpo = null
storage_class = "STANDARD"
uniform_bucket_level_access = true
timeouts {
create = null
read = null
update = null
}
}
上記の import block
と resource block
を反映した PR を作成することで新たに追加されるリソースを第三者がレビューすることが可能です。レビューを経た PR をマージし、CI/CD によって terraform apply
を実行することで、このリソースが state
ファイルに追加されます。
チームでの運用を考えた場合、追加でいくつか作業をするのがベターです。
まず、import block
は apply
後に state
ファイルに反映後は不要になるため削除します。
次に、任意ですが、自動生成した resource block
の定義は引数が冗長であるため、必要な引数のみを残し、不要な引数を削除します。
resource "google_storage_bucket" "mybucket_import_test" {
location = "ASIA-NORTHEAST1"
name = "mybucket-import-test"
}
だいぶスッキリしたのではないでしょうか?
まとめ
terraform import
コマンドは手軽に利用できるメリットはあるものの、チームでの運用を考えると、import block
を利用したほうが良いのではないかと考えました。
より良い方法などありましたら、コメントお願いします 🙇♂️
Discussion