📚

Terraform Google Provider 6.0.0 の新機能と変更点について

2024/09/02に公開

こんにちは、クラウドエース株式会社 SRE 部の阿部です。
この記事ではメジャーアップデートした Terraform Google Provider 6.0.0 の新機能と変更点について紹介します。

概要

2024 年 8 月 27 日に、Terraform の Google Cloud 向けプラグイン(Provider)である Terraform Google Provider が 6.0.0 にバージョンアップしました。
また、同日に 6.0.1 もリリースされております。
このブログ記事では、6.0.1 の内容もあわせて紹介します。

対象読者

  • Terraform で Google Cloud の構築・運用をしているエンジニア
  • メジャーバージョン間の非互換が気になる方

変更点概要

  • プロバイダデフォルトラベル(goog-terraform-provisioned)が自動付与されるようになりました
  • いくつかのリソースの name_prefix の最大長を 37 文字から 54 文字に拡大しました
  • google_project を含むいくつかのリソースで削除防止フィールドが追加されました

また、上記以外にも多数のリソースにおいて機能追加、非互換、および、機能削除があります。
詳細は後述の参考リンクから、変更点を確認してください。

バージョン 5.x 系からアップグレードする場合の注意点

公式の 6.0.0 アップグレードガイドでは、まず 5.x 系の最新バージョン(記事執筆時点では 5.48.1)にアップグレードしてから、アップグレードガイドに記載されている変更内容や廃止項目に応じて修正し、 terraform plan で予期しない変更がないかを確認しながらアップグレードすることを推奨しています。
また、アップグレードガイドには記載されていませんが、念のため terraform state pull コマンドで State ファイルをバックアップしておくことをおすすめします。

バージョン 6.0.0 から 5.x 系へのダウングレードについて

terraform initterraform plan を実行しただけでは State ファイルは更新されないため、もし意図せず 6.0.0 以降になってしまった場合は、 Provider version constraint を使って元々使用していたバージョンに固定してから、再度 terraform init -upgrade を実行しましょう。

terraform refreshterraform apply を実行すると、State ファイルが更新されるため、事前に取得した State ファイルのバックアップを使って戻すか、 Cloud Storage のオブジェクトバージョニングを使って戻すことを検討してください。

参考リンク

新機能

バージョン 6.0.0 で追加された新機能について紹介します。

プロバイダデフォルトラベルの自動付与

プロバイダデフォルトラベル(goog-terraform-provisioned)が自動付与されるようになりました。
これは バージョン 5.16.0 からオプトインすることで使用可能な機能で、 6.0.0 からはデフォルトで有効になりました。
これにより、リソースが Terraform で作成されたのか、 Google Cloud コンソールや gcloud CLI 等別の手段で作成されたのかを識別することができます。

この機能は新規作成リソースのみで有効であり、作成済みリソースには適用されません。

デフォルトラベル適用を無効にする場合は、 provider ブロックで以下のように設定します。

provider "google" {
  # デフォルトラベル適用を無効にする
  add_terraform_attribution_label = false
}

また、デフォルトラベルを既存リソースにも適用する場合は、以下のように設定します。

provider "google" {
  # 既存リソースにもデフォルトラベルを適用する。デフォルトは "CREATION_ONLY"
  terraform_attribution_label_addition_strategy = "PROACTIVE"
}

name_prefix の最大長を 37 文字から 54 文字に拡大

インスタンステンプレート(google_compute_instance_template)等のリソースでは作成時に name_prefix を使う事で名前の重複を防ぐことができました。
インスタンステンプレートはリリース毎に頻繁に入れ替えるリソースのため、 Terraform の式でユニークな name を計算するよりも便利です。
ただ、これまで name_prefix は最大 37 文字までしか入力できない制限がありました。
これが 6.0.0 から 54 文字まで拡大されました。

非互換動作を防ぐため、 name_prefix が 37 文字以下の場合はこれまでと同じネーミング規則が適用され、 37 文字より大きく 54 文字以下の場合に新しいネーミング規則が適用されます。

この変更は以下のリソースが対象です。

  • google_compute_instance_template
  • google_compute_region_instance_template
  • google_compute_ssl_certificate
  • google_compute_region_ssl_certificate

削除防止フィールドの追加

以下のリソースに削除防止フィールドが追加されました。
これによって Terraform の記述ミス等による誤削除を防ぐことができます。

  • google_cloud_run_v2_job
  • google_cloud_run_v2_service
  • google_active_directory_domain
    ※ アップグレードガイドでは google_domain と記載されていますが、リリースノートや該当する PR を見る限りはこちらが正しいと思います。
  • google_folder
  • google_project
  • google_redis_cluster
    ※アップグレードガイドには記載されていませんが、こちらも削除防止フィールドが追加されています。

なお、 google_project は、 deletion_policy フィールドで削除動作を制御しますが、他のリソースとは異なり bool 値ではなく文字列で設定します。

  • deletion_policy = "PREVENT" でリソース削除動作を防止します。 (terraform apply 時にエラーが発生します。)
  • deletion_policy = "ABANDON"terraform apply 時のエラーは発生しませんが、プロジェクトは削除せず State のみ削除します。
  • deletion_policy = "DELETE"terraform apply 時にプロジェクトを削除します。

デフォルトは deletion_policy = "PREVENT" です。

変更点・非互換

広範に変更された非互換について説明します。

ブロック要素の厳格化

バージョン 5.x までは特定のリソースにおいて、過去の設定との互換性のためブロック要素に = [] と設定することを許容していました。(参考)
バージョン 6.0.0 より、以下のリソースについては = [] を設定できなくなりました。
もしこうした設定が残っている場合は、修正が必要です。

google_compute_instance

  • guest_accelerator フィールド

google_compute_subnetwork

  • secondary_ip_ranges フィールド

google_composer_environment

  • ip_allocation_policy フィールド

google_container_cluster

  • guest_accelerator フィールド
  • guest_accelerator.gpu_driver_installation_config フィールド
  • guest_accelerator.gpu_sharing_config フィールド

google_container_node_pool

  • guest_accelerator フィールド
  • guest_accelerator.gpu_driver_installation_config フィールド
  • guest_accelerator.gpu_sharing_config フィールド

google_compute_instance_from_template

  • network_interface.alias_ip_range フィールド
  • network_interface.access_config フィールド
  • attached_disk フィールド
  • guest_accelerator フィールド
  • service_account フィールド
  • scratch_disk フィールド

google_compute_instance_from_machine_image

  • network_interface.alias_ip_range フィールド
  • network_interface.access_config フィールド
  • attached_disk フィールド
  • guest_accelerator フィールド
  • service_account フィールド
  • scratch_disk フィールド

リソース毎の変更点

以下はリソース毎の変更点や非互換について紹介します。

google_alloy_db_cluster

  • network フィールドが削除されました。代わりに network_config.network 使用します。

google_bigquery_table

  • View を含むテーブルを作成する際に、スキーマを指定し、かつ、そのスキーマに REQUIRED モードのフィールドが含まれている場合、プロバイダがエラーを出すようになりました。
  • allow_resource_tags_on_deletion フィールドを削除しました。以降は Resource Tag を含むテーブルでも削除可能です。

google_bigquery_reservation

  • multi_region_auxiliary フィールドを削除しました。

google_billing_project_info

  • id フィールドの形式を変更しました。 (projects/{{project}}/billingInfo から projects/{{project}})

google_cloud_run_v2_service

  • liveness_probe で API のデフォルト値を推論しなくなりました。
  • containers.env は内部データ構造を ARRAY から SET に変更されました。記述順序によらず設定が保持されます。

google_cloud_run_v2_job

  • containers.env は内部データ構造を ARRAY から SET に変更されました。記述順序によらず設定が保持されます。

google_compute_backend_service, google_compute_region_backend_service

  • iap フィールドに enable が追加され、必須属性になりました。
  • connection_draining_timeout_sec, balancing_mode, outlier_detection のデフォルト値が変更されました。
    • balancing_modeUTILIZATION に統一され、その値に従う形でいくつかのフィールドのデフォルト値も変更されました。

google_compute_managed_ssl_certificate

  • certifcate_id (Output only)が正しい動作に修正されました。

google_compute_network_endpoints

  • id フィールドの形式を変更しました。 ({{project}}/{{zone}}/{{network_endpoint_group}}/endpoints から "{{project}}/{{zone}}/{{network_endpoint_group}})

google_container_cluster

  • advanced_datapath_observability_config.enable_relay が必須属性になりました。
  • advanced_datapath_observability_config.relay_mode が削除されました。代わりに advanced_datapath_observability_config.enable_relay を使用します。
  • resource_labels は non-authoritative な動作に変更され、他のリソースと同様に terraform_labelseffective_labels により設定済みラベルとマージされて反映されます。
    • ※この動作は Data Resouce の同名リソースでも同様です。

google_datastore_index

  • google_datastore_index リソースは削除されました。代わりに google_firestore_index リソースを使用してください。

google_edgenetwork_network, google_edgenetwork_subnet

  • labels は non-authoritative な動作に変更され、他のリソースと同様に terraform_labelseffective_labels により設定済みラベルとマージされて反映されます。

google_identity_platform_project_default_config

  • google_identity_platform_project_default_config リソースは削除されました。代わりに google_identity_platform_project_config リソースを使用してください。

google_pubsub_topic

  • schema_settings はデフォルト値を推論しなくなりました。スキーマが不要な場合はブロックを削除してください。

google_integrations_client

  • create_sample_workflowsprovision_gmek フィールドは削除されました。

google_storage_bucket

  • lifecycle_rule.condition フィールドにおける no_age フィールドは削除されました。
    以前は、 age = 0 が暗黙のデフォルト値だったため、 デフォルト値の設定を回避する場合に no_age = true を設定する必要がありました。
    バージョン 6.0.0 からは no_age = true を設定している場合は、代わりに send_age_if_zero = false を設定します。また、暗黙のデフォルト値 age = 0 を前提にする場合は send_age_if_zero = true を設定します。

google_vpc_access_connector

  • max_throughputmin_throughput フィールドにおけるプロバイダ固定のデフォルト値が削除されました。未設定の場合、API が自動設定したデフォルト値を使用します。
    ※リリースノートでは min_throughputmin_instances フィールドと記載されていますが、ソース差分を見る限りは前述のフィールドが正しいと思います。
  • max_instancesmax_throughput フィールドを同時設定するとコンフリクトを検出するように修正されました。同様に、min_instancesmin_throughput フィールドも同時設定時にコンフリクトを検出します。

google_workstations_workstation_config

  • host.gce_instance.disable_ssh フィールドのデフォルト値は True に変更されました。

google_compute_subnetwork

  • reserved_internal_rangesecondary_ip_ranges[].reserved_internal_range フィールドが追加されました。

google_sql_database_instance (バージョン 6.0.1)

  • settings.ip_configuration.require_ssl フィールドは削除されました。代わりに settings.ip_configuration.ssl_mode を使用します。

google_vpc_access_connector の非互換の補足

google_vpc_access_connector リソースの非互換についてはアップグレードガイドで詳しく触れられていないため補足します。
バージョン 5.x 以前において google_vpc_access_connector リソースを作成する場合、 max_instances と min_instances を設定するときに合わせて max_throughput と min_throughput もあわせて設定が必要でした。

例えば以下のような設定があったとします。
VPC Access コネクタで、最大インスタンス数 5、最小インスタンス数 3 で設定するケースです。

resource "google_compute_subnetwork" "test" {
  name          = "vpc-access-test"
  region        = "asia-northeast1"
  network       = google_compute_network.main.self_link
  ip_cidr_range = "10.100.10.0/28"
}

resource "google_vpc_access_connector" "test" {
  name   = "tf-600-test"
  region = google_compute_subnetwork.test.region
  subnet {
    name = google_compute_subnetwork.test.name
  }

  machine_type  = "e2-micro"
  max_instances = 5
  min_instances = 3
}

一見正しそうに見えます。実際、この設定の terraform apply は成功します。
しかし、直後の terraform plan では以下のような差分を検出し、 force replacement となってしまいます。

terraform plan
  # google_vpc_access_connector.test must be replaced
-/+ resource "google_vpc_access_connector" "test" {
      ~ connected_projects = [] -> (known after apply)
      ~ id                 = "projects/example-project/locations/asia-northeast1/connectors/tf-600-test" -> (known after apply)
      ~ max_throughput     = 500 -> 300 # forces replacement
      ~ min_throughput     = 300 -> 200 # forces replacement
        name               = "tf-600-test"
      ~ network            = "tf-600-test" -> (known after apply)
      ~ self_link          = "projects/example-project/locations/asia-northeast1/connectors/tf-600-test" -> (known after apply)
      ~ state              = "READY" -> (known after apply)
        # (6 unchanged attributes hidden)

      ~ subnet {
            name       = "vpc-access-test"
          ~ project_id = "example-project" -> (known after apply)
        }
    }

これは何故発生するかというと、 Terraform Google Provider で max_throughput と min_throughput の暗黙のデフォルト値が設定されているためです。
max_throughput と min_throughput が未設定の場合は max_throughput = 300min_throughput = 200 が設定されます。
そのため、こういった差分を抑制するため、 max_instances と min_instances の値から max_throughput と min_throughput を手計算して明示的に設定するか、 lifecycle.ignore_changes に変更を無視するフィールドにするか、どちらかの設定が必要でした。
例えば、以下のような設定です。

resource "google_compute_subnetwork" "test" {
  name          = "vpc-access-test"
  region        = var.region
  network       = google_compute_network.main.self_link
  ip_cidr_range = "10.100.10.0/28"
}

resource "google_vpc_access_connector" "test" {
  name   = "tf-600-test"
  region = google_compute_subnetwork.test.region
  subnet {
    name = google_compute_subnetwork.test.name
  }

  machine_type   = "e2-micro"
  max_instances  = 5
  min_instances  = 3
  max_throughput = 500 # 本質的には不要な設定
  min_throughput = 300 # 本質的には不要な設定
}

バージョン 6.0.0 からはこうした設定は不要になり、max_throughput と max_instances、 min_instances と min_throughput 同時に設定すると以下のようにエラー停止します。

terraform plan エラーメッセージ
terraform plan エラーメッセージ
╷
│ Error: Conflicting configuration arguments
│
│   with google_vpc_access_connector.test,
│   on vpc_access_connector.tf line 16, in resource "google_vpc_access_connector" "test":
│   16:   max_instances  = 5
│
│ "max_instances": conflicts with max_throughput
╵
╷
│ Error: Conflicting configuration arguments
│
│   with google_vpc_access_connector.test,
│   on vpc_access_connector.tf line 17, in resource "google_vpc_access_connector" "test":
│   17:   min_instances  = 3
│
│ "min_instances": conflicts with min_throughput
╵
╷
│ Error: Conflicting configuration arguments
│
│   with google_vpc_access_connector.test,
│   on vpc_access_connector.tf line 18, in resource "google_vpc_access_connector" "test":
│   18:   max_throughput = 500
│
│ "max_throughput": conflicts with max_instances
╵
╷
│ Error: Conflicting configuration arguments
│
│   with google_vpc_access_connector.test,
│   on vpc_access_connector.tf line 19, in resource "google_vpc_access_connector" "test":
│   19:   min_throughput = 300
│
│ "min_throughput": conflicts with min_instances
╵

バージョン 6.0.0 からは、基本的には max_instances と min_instances のみで設定すれば問題ありません。
lifecycle.ignore_changes で無視している場合は特に問題ありませんが、フィールドを同時設定することで対応している場合は修正が必要です。

ちなみに、この google_vpc_access_connector の動作は以前報告した Issue の修正で、改善されてよかったと思います。

まとめ

Terraform バージョン 6.0.0 (含む 6.0.1) の新機能と変更点について紹介しました。
プロバイダデフォルトラベルは、Terraform で作成したリソースを区別しやすくなり、Terraform 管理外リソースを見つけやすくなったのではないかと思います。
他にも細やかな改善が行われているので、アップグレードを計画していくとよいかと思います。
この記事が皆様の Google Provider アップグレード作業の一助になれば幸いです。

Discussion