Terraformを使っているとリソースの再作成が行われることはよくあると思います。このとき、再作成(replace)の対象となるリソースが他のリソースから依存されている状態だと削除に失敗してしまいます。リソースのreplace時の削除(destroy)と作成(create)の順序を制御するにはlifecycleの機能を使います。
現象
以下がTerraformのコードのイメージです。リソースAとBがあり、BはAに依存しています。
resource "example1" "resource_a" {
name = "A"
}
resource "example2" "resource_b" {
name = "B"
connect_with = example1.resource_a.id
}
ここでリソースAの名前を変更したことでAが再作成されることになったとします。
# example1.resource_a must be replaced
+/- resource "example1" "resource_a" {
~ name = "A" -> "A'" # forces replacement
}
# example2.resource_b will be updated in-place
~ resource "example2" "resource_b" {
name = "B"
~ connect_with = "resource_a_1234567890" -> (known after apply)
}
Plan: 1 to add, 1 to change, 1 to destroy.
リソースAはリソースA’となるだけで一見何も問題無いのですが、これをapplyすると resource_a is in use
のようなエラーが出て削除に失敗してしまいます。つまり、TerraformはまずリソースAを削除しようとするのですがリソースAはリソースBから参照されているため削除できないというエラーです。
普通に考えたらリソースA’を作ってからリソースBの参照先をリソースA’に更新し最後にリソースAを削除すればいいのですが、Terraformはこれを自動で行ってくれるとは限りません。
解決策
どうすればいいのかというと、lifecycleという機能を使います。以下のように create_before_destroy
を指定することで、このリソースをreplaceする場合はまずcreateしてからdestroyするようになります。
resource "example1" "resource_a" {
name = "resource_a"
lifecycle {
create_before_destroy = true
}
}
オプションは create_before_destroy
以外にもあるので、詳しく知りたい方は以下をご参照ください。
余談
2023年11月にTerraformを体系的に学べる書籍がオライリーから発売されました。Terraformを使ってきてそろそろ体系的に学びたいという人におすすめです。