Azure Provider に限った話ではないと思うのですが、正直 Azure Provider はリソースの非推奨化が多い気がするので書いています。きっかけとしては直近の Azure Provider の更新で azurerm_static_site
は非推奨になって azurerm_static_web_app
が追加されたことにあります。
追加された時から正直命名をミスっているなと思っていましたが、このバージョンから他の App Service に合わせる形で新しい名前のリソースが追加されました。機能としては変わっていないので、今回の場合は本当に名前が変わっただけです。
これまでにも Azure Provider では同じようなリソース変更があり、代表的かつ影響範囲の広いものとして App Service / Azure Functions があります。v3 のリリースタイミングで OS で別々のリソースが用意されるようになり、これまでのリソースは v4 で削除されるためマイグレーションが必須です。
しかし、そのリソースを移行すると言っても Terraform 側でのサポートがあるわけではなく、単純にリソースを変更すると再作成が走ってしまうため tfstate から削除してインポートし直す必要があります。具体的な手順は以下のマイグレーションのドキュメントにありますが、本番環境の tfstate を CLI から触るというのは危険な作業には変わりありません。
折角 Terraform の運用を GitHub Actions や Terraform Cloud で自動化していても、たまにあるマイグレーションで手動作業になってしまうのは避けたいので、CI/CD を生かしたまま実行したいところです。
そこで最新の Terraform では removed
ブロックと import
ブロックが使えるようになっているので、これを使ってマイグレーションを簡単に行えないか実際のリソースで試しました。Terraform CLI を使った作業であれば tfstate から削除してインポートし直すという 2 つの手順が必要ですが、この removed
と import
を使うと理屈上は 1 回で終わるはずです。
実際に azurerm_static_web_app
へのマイグレーションを行った時の Terraform 定義は以下のようになります。元々あった azurerm_static_site
は削除しつつ同時に removed
を追加して、該当リソースを tfstate から削除します。そして azurerm_static_web_app
と import
を追加することで新しいリソースとしてインポートするようにしています。
この時 removed
には明示的に destroy = false
を追加してリソース自体は削除しないようにします。
#resource "azurerm_static_site" "default" { # name = "stapp-xxxxxx" # location = var.location # resource_group_name = var.resource_group_name #} removed { from = azurerm_static_site.default lifecycle { destroy = false } } resource "azurerm_static_web_app" "default" { name = "stapp-xxxxxx" location = var.location resource_group_name = var.resource_group_name } import { id = "/subscriptions/.../resourceGroups/.../providers/Microsoft.Web/staticSites/..." to = azurerm_static_web_app.default }
本来であれば import
で指定する id
を既存のリソースから取得したいのですが、removed
ブロックを使う場合はリソース定義は削除する必要があるので無理でした。更に import
ブロックはモジュールの中では書けないようなので、ルートで指定する必要があるのも面倒でした。将来的には改善して欲しいです。
このように書くことで古いリソースの tfstate からの削除と、新しいリソースのインポートが 1 回で完了します。実際に稼働しているアプリケーションで移行を行った Pull Request が以下のようになります。
カスタムドメインも移行しているので 2 つ分 removed
と import
を書いて対応しています。現在の Azure Provider バージョンではカスタムドメインのインポートに失敗している気がするので、再作成した方が結果として安定する予感です。
Terraform Cloud で運用しているので plan 結果を確認すると tfstate からの削除とインポートが行われていることが分かります。カスタムドメインは若干この時点でも挙動がおかしいです。
この Pull Request をマージすると apply が走って新しいリソースへのマイグレーションが完了します。Terraform CLI で tfstate を直接触るよりも安全かつ効率的に行えました。
最後に追加した removed
ブロックと import
ブロックを削除する Pull Request を作成します。
この Pull Request の plan を確認すると変更なし扱いとなるので、今回の removed
と import
を使ったマイグレーションが正しく行われていることが確認出来ました。
最新の Terraform を使っておく必要がありますが、Terraform CLI を使って手動で作業するよりも格段に安全なので、今後も Azure Provider でリソースの非推奨化が行われても安心して作業が出来そうです。