APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

何もしてないのに HCP Terraform の Drift Detection が失敗するんですが(AzureRM Provider 編)

こんにちは、ACS事業部の埜下です。

今回は HCP Terraform を使っていくなかで発生した事象について紹介していきます。

前置き

HCP Terraform(旧称 Terraform Cloud)には Drift Detection という、それはもう便利な機能があります。 どういう機能かと言うと、Terraform で作成したリソースが外部から更新された場合に検知してくれます! 外部からの更新、というのが所謂ドリフトです。 ドリフトを検知してくれるので Drift Detection、わかりやすいですね。

HCP Terraform を使わなくても同じような機能は実現できますが、HCP Terraform の有料プランを契約すれば作り込まなくてもこの Drift Detection が使えるようになるんです! 執筆時点では有料プランの中でも上位の Plus プラン限定の機能ですが、Plus プランの HCP Terraform を使う理由の大半を占めると言っても過言ではありません。

さて、この Drift Detection ですが、あるとき何もしてないのに動かなくなってしまいました。 ドリフトを検知したのではなく Drift Detection の起動に失敗していました。 Terraform 構成を変更したわけでもありませんし、HCP Terraform の設定も変わっていません。 確認のために HCP Terraform の Plan を手動実行してみると、こちらは正常終了します。

では、どうして Drift Detection は何もしてないのに失敗するようになってしまったのでしょうか。

Drift Detection が失敗する原因

Drift Detection で使われている AzureRM Provider のバージョンが古いことが原因でした。

AzureRM Provider とは、Azure リソースを Terraform で管理する際に利用する Terraform の Provider です。 長らくメジャーバージョンが v3 のままでしたが、先日ついに v4 がリリースされました。 が、今回の原因にメジャーバージョンのリリースは関係ありませんでした。

具体的な原因はというと、Azure のリソースプロバイダー「Microsoft.TimeSeriesInsights」が廃止されたことによる影響です。 リソースプロバイダー「Microsoft.TimeSeriesInsights」の廃止は2024年5月末にアナウンスされていました。

azure.microsoft.com

実際にリソースプロバイダーの一覧から「Microsoft.TimeSeriesInsights」が消えたのが2024年9月中旬ごろのようで、このタイミングで AzureRM Provider を使った Terraform Plan が動かない事象が発生しました。 GitHub にも Issue が挙がっており、多くの方が巻き込まれたようです。

github.com

このリソースプロバイダー「Microsoft.TimeSeriesInsights」の廃止にともなう影響は AzureRM Provider の v3.90 未満のバージョンを使っている場合に発生するようで、HCP Terraform の利用に関係なく該当するバージョンの AzureRM Provider を使っていれば発生する事象です。

どのような場合に発生するかと言うと、例えば Terraform 構成ファイルに以下のような required_providers ブロックを設定していたとします。

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.89"
    }
  }
}

注目してほしいのは version = "~> 3.89" のところです。 これは利用する Provider のバージョンに制約を設けるための設定になります。 ~> 3.89 という書き方は「v3.89 より新しいマイナーバージョンがあれば最新のバージョンを利用する」という意味になります。

~> 3.89 のようなバージョン制約であれば Terraform Plan 実行により執筆時点で v3 系最新の v3.116.0 が利用されるはずで、リソースプロバイダー「Microsoft.TimeSeriesInsights」の廃止の影響はありません。 その他にも provider ブロックに skip_provider_registration = "true" を設定することでも回避できます。

余談ですが、もし ~> 3.89.0 と書いていた場合は「v3.89.0 より新しいパッチバージョンがあれば最新のバージョンを利用する」を意味することから、v3.90 がリリースされていても利用されることはありません。 リソースプロバイダー「Microsoft.TimeSeriesInsights」の廃止に巻き込まれていてマイナーバージョンを固定している場合はバージョン制約を見直してみてください。

このように、影響を回避するバージョン制約が設定できていれば Terraform Plan は成功するはずです。 しかし、今回 Drift Detection が失敗していたワークスペースの Terraform 構成もエラーを回避できる ~> 3.89 というバージョン制約になっていました。

では、リソースプロバイダーの廃止に巻き込まれないバージョン制約なのに Drift Detection が失敗しているのはなぜでしょうか?

Drift Detection の仕組み

公式ドキュメントには Drift Detection のアーキテクチャに関する記述がなく、あくまで状況証拠からの推測になりますが、Drift Detection は最後の Apply 実行時に作られた Plan ファイルを元に定期的に Plan を実行していると思われます。 今回の AzureRM Provider に関する事象以外にも、Terraform が管理インフラのアクセスに使う認証情報を更新したときも Drift Detection だけ失敗するという事象がありました。

今回の場合で言うと、最後に Apply された AzureRM Provider のバージョンが v3.90 未満の場合、Drift Detection ではリソースプロバイダーの廃止に巻き込まれる AzureRM Provider バージョンの Plan ファイルが使われてエラーになります。 一方、HCP Terraform で Plan を手動実行した場合はバージョン制約により最新のバージョンが利用されてリソースプロバイダー廃止の影響は受けずに正常終了します。

このように、手動実行では成功するのに Drift Detection だけ失敗する、という状態が生まれてしまいます。

どうすればよいのか

上記の通り、最後に実行された Apply を元に Drift Detection が実行されているとすると、Plan & Apply を再実行して Plan ファイルで使われる AzureRM Provider のバージョンを最新化してあげればよいのです。

また、Apply をするためにリソースの変更が必要かと思われるかもしれませんが、Plan & Apply に差分がなくても Drift Detection で使う Plan ファイルは更新されます。 とは言えいきなり Plan & Apply するのではなく、事前に Plan only を実行して差分の有無を確認してから Apply することが安全です。

おわりに

今回は「何もしてないのに動かなくなってしまった Drift Detection の謎」に迫ってみました。

原因を調べてみると「何もしてないのに Drift Detection が失敗した」のではなく、「古いバージョンの Provider で作ったリソースを放置していたら Drift Detection が失敗した」というのが正しいかと思います。 「放置」という言葉を使ってはいますが、実際はこのような運用は別に問題ないですよね。 Terraform で作成したリソースを変更する要件がないのにわざわざ Terraform Apply を実行すること自体がないと思います。

しかし、HCP Terraform では今回のように作成したリソースを「放置」、つまり古い Plan ファイルのまま Drift Detection を使っていると、せっかく HCP Terraform Plus プランの料金を払っている Drift Detection が動かなくなってしまうことがあります。 HCP Terraform を提供してくれている HashiCorp さんには是非この仕組みを見直してもらいたいなぁ、という思いとともに今回のブログを終わりにします。 ありがとうございました。