2021年9月22日 星期三

Terraform - will be read during apply ?

有時候會在 terraform plan / apply 的時候看到這種恐怖的情況...

  # module.foobar.data.google_service_account.this will be read during apply
  # (config refers to values not yet known)
  ...
  # module.foobar.google_pubsub_subscription.this must be replaced
  ...
  # module.foobar.google_pubsub_topic.this must be replaced
  ...
  # module.foobar.google_storage_bucket.this will be destroyed
  ...
  # module.foobar.google_storage_bucket_iam_member.bucket will be destroyed
  ...
  # module.foobar.google_storage_bucket_iam_member.object will be destroyed
  ...
  # module.foobar.google_pubsub_subscription_iam_member.this will be updated in-place
  ...

在同一個層級(module.foobar), 只要有一個 data object 需要被重讀(will be read during apply)更新內容的話, 後面同級的 resource 幾乎都會被當作受到影響, 而被 terraform 進行取代(replaced)或是砍掉(destroyed)的處置, 要是這些 resource 是 pubsub topic / cloud storage bucket 這類會存資料的地方, 那就會掉資料甚至全滅.

如果直接 terraform apply -target='module.foobar' 執行更新下去, 那通常會很慘, 因為 terraform apply 列出來這些就是這次安排執行的處置, 就算 module.foobar.data.google_service_account.this 執行重讀之後內容還是一樣, 後續的取代或砍掉的處置照樣會執行, 造成誤砍誤殺的結果.

正確的手動解法, 是執行 terraform apply -target='module.foobar.data.google_service_account.this' 先把 data read 的動作獨自執行完成, 若是 data read 回來的內容不變, 那再執行 terraform plan / apply 就不會出現後續的取代或砍掉的處置. 若是內容有變, 顯示出來的可能就只是 object 裡面部分更新(will be updated in-place)的處置, 影響太大的才會被取代或是砍掉.

至於為什麼會出現需要重讀的情況, 大都是因為線上環境的設定跟 terraform 的設定不一致, 或是 gke 被更新版本導致 resource 被異動, 或者可能是 data.google_service_account.this 資料過期了, 所以需要先更新資料.