Terraform Google Provider 5.0.0 の新機能と変更点について
こんにちは。クラウドエースの阿部です。
この記事ではメジャーアップデートした Terraform Google Provider 5.0.0 の新機能と変更点について説明しようと思います。
概要
2023年10月3日に、Terraform の Google Cloud 向けプラグイン(Provider)である Terraform Google Provider が 5.0.0 にバージョンアップしました。
v4.0.0 のリリースは 2021年11月3日だったため、Provider のメジャーアップグレードは約2年ぶりということになります。
ざっとリリース情報やアップグレードガイドを読むと、変更点が多かったので筆者が気になった点についてまとめていきたいと思います。
対象読者
- Terraform で Google Cloud の構築・運用をしているエンジニア
- メジャーバージョン間の非互換が気になる方
変更点概要
5.0.0 になったことで、バージョン 4 系から以下の点が変更されています。
主な変更点を以下に列挙します。
- 新機能: Provider で設定したデフォルト値が
terraform plan
に表示されるようになった - 新機能: Provider でリソースラベルのデフォルト値(
default_labels
)を設定できるようになった - 新機能: ラベル設定可能なリソースで
terraform_labels
,effective_labels
フィールドが追加された - 新機能: ラベル参照可能なデータリソースで
labels
,terraform_labels
,effective_labels
が追加された - 新機能: アノテーション設定可能なリソースで
effective_annotations
フィールドが追加された - 新機能: アノテーション参照可能なデータリソースで
annotations
,effective_annotations
が追加された - 変更: リソースラベルフィールドが authoritative ではなく non-authoritative な動作に変更された
- 変更: アノテーションフィールドが authoritative ではなく non-authoritative な動作に変更された
- 非互換: Provider 設定において
credentials
,access_token
,impersonate_service_account
,project
,billing_project
,region
,zone
に空文字列が設定できないよう検証する動作が追加された - 非互換:
terraform import
に指定するリソースIDの検証が強化された - 非互換: データリソースで参照先リソースがない場合、404エラーで失敗する動作に変更された
また、上記以外にも多数のリソースにおいて機能追加、非互換、および、機能削除があります。
詳細は後述の参考リンクから、変更点を確認してください。
バージョン 4.x 系からアップグレードする場合の注意点
公式の 5.0.0 Upgrade Guide は原則 4.x 系の最終バージョンからのアップグレードについて説明しているドキュメントです。
そのため、推奨のアップグレード手順としては、まず現在の 4.x 系最終バージョンである 4.84.0
にアップグレードし、 terraform plan
で意図しない差分が発生しないことを確認してから 5.0.0
にアップグレードすることをおすすめします。(4.x 系の Provider をお使いであれば、おそらく直接 5.0.0
にアップグレードしてもそこまで深刻な事態にはならないと思いますが、その場合 4.x のマイナーバージョン間の差分も合わせて考慮した上で作業する必要があります。)
バージョン 5.0.0 から 4.x 系にダウングレード可能かについて
いくつかの条件や作業状態において、ダウングレード可能な手段があります。
- Provider のバージョンを固定しておらず、
terraform init
等で最新の Provider をダウンロードしただけの場合、もしくはterraform plan
を実行しただけの場合
この場合は、 State ファイルは更新されていないはずなので、 Provider バージョンを固定する設定を追加してから改めてterraform init -upgrade
を実行してください。 -
terraform apply
やterraform refresh
といった State ファイルを更新した場合- ローカルステート等、 State ファイルのバージョニングの仕組みがない場合は前述の Provider ダウングレードを行った後、
terraform refresh
を実行して State ファイルだけ更新すると復旧できる可能性があります。 - GCS バックエンドのリモートステートのように、 State ファイルのバックアップがある場合は、ファイルを更新前の状態に戻してから前述の Provider ダウングレードを実行することで元に戻すことが可能です。
- ローカルステート等、 State ファイルのバージョニングの仕組みがない場合は前述の Provider ダウングレードを行った後、
ただ、アップグレードしてから新リソース追加等をしてしまい、State ファイルの状態が進んでいると、戻したときに作成したはずのリソースが未管理扱いになったりします。
ダウングレードはあくまで State の状態が進んでいない前提ですので、普段の運用でも Provider のバージョンを固定する設定は必要だと思います。
参考リンク
新機能
terraform plan
で表示されるようになった
Provider で設定したデフォルト値が Provider ブロックには、これまで project
,region
,zone
の3つのデフォルト値を設定できました。例えば、以下のような Provider ブロック設定があるとします。
provider "google" {
project = "example-project"
region = "asia-northeast1"
zone = "asia-northeast1-b"
}
この設定を使ってリソース設定すると、固定値であるにも関わらず terraform plan
時は (known after apply)
という表示でした。以下は、Compute Engine インスタンス作成の plan ログの一部です。
# google_compute_instance.main will be created
+ resource "google_compute_instance" "main" {
...(snip)...
+ name = "provider-test"
+ project = (known after apply)
+ zone = (known after apply)
...(snip)...
}
これだと、 plan の結果をレビューに使っているとき、設定値の確からしさを plan から確認できないという問題があります。
これが、 5.0.0
から以下のようになります。Provider ブロックに設定した project
と zone
のデフォルト値が plan 実行時に表示されるようになりました。
# google_compute_instance.main will be created
+ resource "google_compute_instance" "main" {
...(snip)...
+ name = "provider-test"
+ project = "example-project"
+ zone = "asia-northeast1-b"
...(snip)...
}
これまでは plan 時に設定値を確認できないことから、私はプロジェクトメンバーに Provider のデフォルト値を極力使わないよう指示していましたが、 5.0.0
のように表示されるなら忌避しなくてもよいかと考えています。
default_labels
)を設定できるようになった
Provider でリソースラベルのデフォルト値(Provider でリソースラベルのデフォルト値を設定できるようになりました。
以下のように設定します。
provider "google" {
project = "example-project"
region = "asia-northeast1"
zone = "asia-northeast1-b"
default_labels = {
tool = "terraform"
}
}
こうすることで、上記 Provider で作成するラベル設定が可能な全てのリソースに、 key が tool
、 value が terraform
のラベルを追加することが可能です。
使いどころとしては、Cloud コンソールや gcloud コマンドで Terraform で作成したリソースかそうでないかを確認するときに便利だと思います。
また、コスト管理等でリソースに漏れなくラベルを設定したい際に、これまではマメにラベルがコーディングされているかをレビューしたり、テストツールでチェックするといったことが必要でしたが、 Provider レベルでデフォルトラベルが設定できれば少なくともコーディングのレビューの負担は減ると思います。
terraform_labels
, effective_labels
フィールドが追加された
ラベル設定可能なリソースで 5.0.0
から、 terraform_labels
, effective_labels
という参照のみ(output-only)のフィールドが追加されました。
このフィールドは、前述の Provider で記述したデフォルトラベル設定と、リソース毎に記述するラベル設定、そして Terraform で設定していない現物リソースに存在するラベルの3つをそれぞれマージしたものになります。
-
terraform_labels
は、Provider デフォルトラベルとリソース毎のラベル設定をマージした設定を表示します。 -
effective_labels
は、前述のterraform_labels
に加え既に現物リソースに設定されている内容も含めた最終的な設定内容を表示します。
これにより、ラベルを別のツールで一括設定した際に Terraform も追従する必要がなく、ラベル設定は Terraform のコードだけ気にすれば良くなっています。
labels
, terraform_labels
, effective_labels
が追加された
ラベル参照可能なデータリソースで これはそのままですね。 Data Resource (data ブロック)で参照するときに、ラベルフィールドも参照できるようになりました。
effective_annotations
フィールドが追加された
アノテーション設定可能なリソースで アノテーション(annotations
)が設定可能なリソース(例えば Cloud Run サービスリソース)に、 effective_annotations
フィールドが追加されました。
このフィールドは、「ラベル設定可能なリソースで terraform_labels
, effective_labels
フィールドが追加された」で説明した effective_labels
の動作に似ています。
4.84.0
以前の動作として、 annotations
フィールドは authoritative であり、Terraform で設定された値を正として完全に置き換える動作でした。
Cloud Run サービスを例に挙げると、Terraform 管理下の Cloud Run サービスに、 Cloud コンソールや gcloud コマンド等で更新すると、これらのツールを使用したときに暗黙で設定されるアノテーション(例えば、run.googleapis.com/client-name
)があるため、 Terraform 実行時に意図しない差分が発生することがありました。
5.0.0
では、実際に設定されている値と Terraform で設定する値をマージした effective_annotations
を計算してから適用するため、意図しない差分の発生がなくなります。
annotations
, effective_annotations
が追加された
アノテーション参照可能なデータリソースで Data Resource (data ブロック)で参照するときに、アノテーションフィールド(annotations
, effective_annotations
)も参照できるようになりました。
変更点
リソースラベルフィールドが authoritative ではなく non-authoritative な動作に変更された
新機能の「ラベル設定可能なリソースで terraform_labels
, effective_labels
フィールドが追加された」に関連しますが、ラベル設定が authoritative ではなく non-authoritative な動作に変更されました。
即ち、 Terraform 設定が現物リソースの設定を全て上書きする動作(authoritative)から、デフォルトラベル、リソースラベル、現物の設定済みラベル全てを加味した上で設定値をマージする動作(non-authoritative)になったということです。
これは、ラベル設定を Terraform 上で厳密に行いたい場合はデメリットですが、ほとんどのケースでは non-authoritative の方がメリットがあると判断され、変更になったと推測しています。(Provider デフォルトラベルとの兼ね合いもあると思います。)
この動作変更により、 terraform plan
等で意図しない差分が発生する可能性がありますので、公式ドキュメントの Provider-level Labels Rework に記載されている注意事項を確認しながら必要に応じてコード修正を行いましょう。
アノテーションフィールドが authoritative ではなく non-authoritative な動作に変更された
新機能の「アノテーション設定可能なリソースで effective_annotations
フィールドが追加された」に関連しますが、アノテーション設定が authoritative ではなく non-authoritative な動作に変更されました。
これにより、Terraform 以外のツールで設定されたアノテーション設定を残したまま Terraform で設定できるようになりました。
この動作による副作用はあまりないと思いますが、これまで annotaions
設定で意図しない差分を抑止するために lifecycle.ignore_changes
を設定している場合は、様子を見ながら外してもよいのではないかと思います。
非互換
credentials
, access_token
, impersonate_service_account
, project
, billing_project
, region
, zone
に空文字列が設定できないよう検証する動作が追加された
Provider 設定において これは掲題の通りで、4.84.0
以前は空文字列も設定可能でした。(筆者は空文字列を設定したことがないので気付きませんでしたが……)
そのため、明らかに apply が失敗するような設定でも plan でも成功してしまうケースがありました。
5.0.0
では、 plan 実行時に以下のようなエラーメッセージを出力します。
provider "google" {
project = ""
}
│ Error: expected a non-empty string
│
│ with provider["registry.terraform.io/hashicorp/google"],
│ on versions.tf line 11, in provider "google":
│ 11: provider "google" {
│
│ project was set to ``
╵
terraform import
に指定するリソースIDの検証が強化された
この動作変更は内部ロジックの正規表現で ^
と $
を追加し リソース ID 形式の文字列検証を少しだけ厳密化しただけです。
実際の修正はこちらの Pull Request が該当します。
実運用上はそこまで影響しないのではないかと思いますが、もし 5.0.0
で import するときにうまく実行できない場合は、リソース ID 文字列の形式を見直すとよいと思います。
データリソースで参照先リソースがない場合、404エラーで失敗する動作に変更した
Data Resource を使用する際に存在しないリソースを参照したとき、 4.84.0
以前は plan を実行してもエラーが発生しませんでした。
5.0.0
では、存在しないリソースを参照した場合、 以下のようなエラーが発生し plan に失敗します。( defaulte
という存在しない VPC ネットワークを参照したときの例です。)
Planning failed. Terraform encountered an error while generating this plan.
╷
│ Error: projects/example-project/global/networks/defaulte not found
│
│ with data.google_compute_network.default,
│ on data.tf line 1, in data "google_compute_network" "default":
│ 1: data "google_compute_network" "default" {
│
╵
リソース単位での機能変更や廃止について
メジャーバージョンアップしたことで、これまで破壊的な変更として保留されていたリソース毎の変更や廃止がまとめて行われています。
この記事で全てを紹介しませんが、筆者が気になったところについてピックアップして紹介します。
変更点の全量を確認したい場合は、5.0.0 リリース情報 と 5.0.0 Upgrade Guide を確認してください。
Game Servers リソースと Cloud IoT リソースを廃止
Google Cloud で廃止された Game Servers と Cloud IoT ですが、 5.0.0
で Provider としても廃止されました。
具体的には以下のリソースです。
Game Servers リソース
- google_game_services_game_server_cluster
- google_game_services_game_server_deployment
- google_game_services_game_server_config
- google_game_services_realm
- google_game_services_game_server_deployment_rollout
Cloud IoT リソース
- google_cloudiot_device
- google_cloudiot_registry
- google_cloudiot_registry_iam_*
- data.google_cloudiot_registry_iam_policy
Access Context Manager リソースの設定順序や重複設定時の動作を改善
google_access_context_manager_service_perimeters
と google_access_context_manager_service_perimeter
において、 Terraform 上の設定順序と実リソースの設定の順序が変わった際に意図しない差分が発生することがありましたが、この動作が改善されています。
また、 内部動作を変更したことにより、重複設定があった場合に plan 時点で検出できるようになりました。
GKE クラスタリソースがデフォルトで削除不可に設定
google_container_cluster
リソースはデフォルトで deletion_protection
フィールドに true
を設定するようになりました。
そのため、誤って削除する動作を防ぐことができます。
Terraform で GKE クラスタを削除したい場合、 deletion_protection
フィールドに false
を明示的に設定し、apply してからリソースのコードを削除する操作が必要です。
作成に中途半端に失敗した GKE クラスタの扱いを変更
google_container_cluster
リソースで作成した GKE クラスタが、何らかの理由で Healthy にならずリソース作成が中途半端に失敗することがありました。
4.84.0
以前は State ファイルから除外され、再度 apply したとき新規作成状態になりますが、 5.0.0
では State ファイルに taint
状態で記録されます。
そのため、 GKE クラスタ側を直接修復して復旧した場合、 apply せず taint
状態を解除するといった操作が必要です。
GKE クラスタのデフォルトを VPC ネイティブクラスタに変更
5.0.0
の google_container_cluster
リソースで作成した GKE クラスタは VPC ネイティブクラスタがデフォルトになります。
4.84.0
以前は、 ip_allocation_policy
ブロックが設定されていない限り、 ルートベースクラスタで作成していました。
GKE ノードプールの自動アップグレードと自動復旧がデフォルト有効に変更
google_container_node_pool
リソースの management.auto_repair
と management.auto_upgrade
がデフォルトで true
に設定されます。
これまで未設定の場合は差分が発生する可能性があります。
Cloud Logging Sink のユニーク書き込み ID がデフォルトで有効に変更
google_logging_project_sink
リソースの unique_writer_identity
がデフォルトで true
に設定されます。
これにより、 unique_writer_identity
フィールド未設定の場合は差分が発生する可能性があります。
unique_writer_identity
フィールドの設定値によって、 アクセス許可設定するべきサービスアカウントも変更されますので、これまでの動作を変更したくない場合は明示的な設定が必要です。
Cloud Monitoring Dashboard の差分検出が改善
4.84.0
以前は、 google_monitoring_dashboard
リソースの dashboard_json
フィールドに設定する値は、厳密に一致していないと差分が多く出るためメンテナンスが非常に煩雑でした。
5.0.0
では、dashboard_json
フィールドのパラメータで明示的に設定していないが、ダッシュボード API でデフォルト値を生成する場合等については差分を抑制する処理に変更されています。
Secret Manager リソースの複製における automatic フィールドを auto ブロックに置き換え
google_secret_manager_secret
リソースの automatic
フィールドが廃止され、代わりに auto
ブロックで設定します。
設定のサンプルはこちらのドキュメントをご確認ください。
Cloud SQL データベースのデータベースフラグが順序性を持たないように変更
google_sql_database
リソースの database_flags
は順序性を持たない内部処理に変更されました。
そのため、意図しない差分が発生しづらくなっています。
まとめ
バージョン 5.0.0
になってより成熟度が高くなった Google Provider の変更点について紹介しました。
リソースラベルのデフォルト設定等、機会があれば活用したい機能追加もありますので、引き続き Google Provider の更新をウォッチしていこうと思います。
この記事が皆様の Google Provider アップグレード作業の一助になれば幸いです。
Discussion