クラウド同上

Terraform Google Provier 3.0.0 アップグレードの注意事項

Author
Shohei Abe
Lv:19 Exp:27299

2017年10月より入社しました。これまでの技術分野は主にインフラ関係です。
今後はGCPでフルスタック対応できるエンジニアを目指し日々いろいろと活動しています。

12/4に、TerraformでGCPのリソースを扱うGoogle Provierが 3.0.0 にメジャーバージョンアップしました。(ちなみにその翌日、 v3.1.0 もリリースされております。)
1.xx 系から2.0にバージョンアップしたときは、 Beta Provierが新たに新設され、GAになっていない機能はBeta Providerでリソース定義するようになりましたが、2.xx系から3.0.0にアップグレードするには、どういった点に注意するのかを書いていこうと思います。

対象読者

  • TerraformでGCPリソースを管理している人、または、管理した経験がある人
  • Terraformが大好きな人

アップグレードの概要

公式ドキュメントとして Terraform Google Provider 3.0.0 Upgrade Guide がありますので、まずはこちらをご一読頂くとよいと思います。
大きな変更点について書いていきますと、

  1. Terraform 0.11 以前は動作対象外となった (Terraform 0.12以降を使用する必要がある)
  2. Terraformのリソース管理IDが SelfLink ベースに統一された
  3. 2.xxで、廃止予定(Depricated)になっていたリソースやリソース属性が廃止され使用不能になった
  4. 一部のリソースにおいて、省略可能(Optional)な属性が必須(Required)になった

細かい変更点が非常に多く全てを説明していくことは難しいため、個人的に気になった点について書いていこうと思います。

Terraform 0.11 以前は動作対象外となった

これはそのままですね。まずは Terraformを 0.12 以降に移行しましょう。
たとえTerraform CLI 0.11.14 を使って terraform init すると、Google Provider は 2.20.0 がダウンロードされます。
このとき、provider の version 指定に "= 3.0.0" を指定して terraform init すると、以下のようなエラーになります。

No available provider "google" plugins are compatible with this Terraform version.

From time to time, new Terraform major releases can change the requirements for
plugins such that older plugins become incompatible.

Terraform checked all of the plugin versions matching the given constraint:
    = 3.0.0

Unfortunately, none of the suitable versions are compatible with this version
of Terraform. If you have recently upgraded Terraform, it may be necessary to
move to a newer major release of this provider. Alternatively, if you are
attempting to upgrade the provider to a new major version you may need to
also upgrade Terraform to support the new version.

Consult the documentation for this provider for more information on
compatibility between provider versions and Terraform versions.

Terraform 0.11系(またはそれ以前のバージョン)を使用している方は、まずはTerraformのバージョンを 0.12 以降に上げましょう。Terraform 0.12 に上げるときは以前のエントリをご参考にして頂ければと思います。

Terraformを0.11から0.12に移行するときの注意点とは

Terraformのリソース管理IDが SelfLink ベースに統一された

Terraformのリソース参照において id という、Stateファイルの管理ID属性を参照することができます。この id 属性の形式が SelfLink の形式に統一されるため、既存コードで id 属性を参照しているコードが非互換となる可能性があります。
例えば、VPC Networkを管理する google_compute_network リソースのIDは、 2.20.0 ではネットワークの name が使われていましたが、 3.0.0 では "projects/{PROJECT_ID}/global/networks/{NETWORK_NAME}" と、self_link と同じ形式になっていました。リソースの id 属性をリソース参照に使っている人は形式の変更に注意しましょう。
※個人的には、 id はあくまでState管理上の内部IDなので、リソース間の参照は self_link 等のドキュメント記載の属性を使用する方が好ましいと思います。

google_cloudfunctions_function の runtime 属性

Cloud Functionsは2019/4/18に、 gcloud functions deploy コマンドの --runtime パラメータが必須になり、 Node.js 6 ランタイムはDepricatedになりました。 (参考)
同様に、Terraformの google_cloudfunctions_functionruntime 属性はRequiredになり、 nodejs6 はデフォルト値ではなくなりました。(runtime 属性を省略してデフォルト値を期待するコードを記述している場合は、明示する必要があります。)

google_compute_instance_group_manager と google_compute_region_instance_group_manager の template 属性

マネージドインスタンスグループを設定するときに使用するインスタンステンプレートを指定する template 属性が廃止されました。代わりに version.instance_template を使用します。
version ブロックは v2.19.0 から追加されており、template 属性の廃止予告はありましたが、正式に廃止されたものになります。

google_compute_instance_group_manager と google_compute_region_instance_group_manager の update_strategy 属性

マネージドインスタンスグループのインスタンス更新を制御する update_strategy 属性が廃止されました。代わりに update_policyブロックを使用します。
update_policy ブロックは v2.19.0 から追加されており、update_strategy 属性の廃止予告はありましたが、正式に廃止されたものになります。

google_compute_subnetwork の enable_flow_logs 属性

サブネットワークのフローログ(トラフィックのログ)を取得する設定である、 enable_flow_logs 属性が削除されました。代わりに、 log_config ブロックを使用します。
log_config ブロックは v2.19.0 から追加されており、enable_flow_logs 属性の廃止予告はありましたが、正式に廃止されたものになります。

google_container_cluster の ip_allocation_policy ブロック属性

ip_allocation_policy ブロック属性は、主にVPC Native Clusterの設定で使います。このブロック属性の仕様に幾つかの非互換があります。

use_ip_aliases 属性が削除されました

今まではVPC Native Cluster設定の有効/無効を use_ip_aliases のブール値で制御することができましたが、 3.0.0 からは ip_allocation_policy の有無自体がVPC Native Clusterの有効/無効を制御するようになります。
もし、 use_ip_aliases 属性を記述している場合は、記述を削除しましょう。
また、 VPC Native Cluster を使わない場合(無効にしたい場合)は、 ip_allocation_policy ブロック自体を削除することで無効にできます。

GKEサブネットワークを暗黙で作成できなくなりました

今までは、 create_subnetwork を有効にしたり、 node_ipv4_cidr_block でCIDRを設定することで、GKEクラスタリソース作成とサブネットワーク作成を同時に行うことができましたが、この2つの属性は削除され、クラスタとサブネットワークを1つのリソースで作成することはできなくなりました。
代わりに、 google_compute_subnetwork リソースを使って明示的にサブネットワークを作成し、その nameself_linkgoogle_container_clustersubnetwork 属性で関連付けて設定します。
※余談ですが、個人的は Cluster CIDRやService CIDR用のセカンダリIP範囲についても、 ip_allocation_policy.cluster_ipv4_cidr_blockip_allocation_policy.services_ipv4_cidr_blockではなく google_compute_subnetwork で定義し、 ip_allocation_policy.cluster_secondary_range_nameip_allocation_policy.services_secondary_range_name で関連付けた方がよいと思います。

LoggingとMonitoringのデフォルト設定

GKEでは v1.14 から Stackdriver Kubernetes Monitoring が標準になります。
これに合わせて、 logging_service 属性と monitoring_service 属性のデフォルト値が、Stackdriver Kubernetes Monitoringになります。 logging_service 属性と monitoring_service 属性の設定を省略している場合は、Providerバージョンアップで変更される可能性があります。 logging_service 属性と monitoring_service 属性は明示した方がよいでしょう。

zone, region, additional_zones 属性の廃止

Provider 2.3.0 から、 GKEクラスタ/ノードプールの zone,regionの代わりにlocationを使うようになり、また、additional_zonesnode_locationsを使うようになりました。(v2.xxまでは、どちらも使うことが可能でした。)
3.0.0 で、zone, region, additional_zones は完全に廃止されました。バージョンアップする場合は、記述の修正が必要になります。
※このセクションは google_container_cluster の説明ですが、 locationnode_locations の変更は google_container_node_pool も同様です。

google_project_service のBigQuery API設定

BigQueryのAPIエンドポイントが bigquery-json.googleapis.com から bigquery.googleapis.com に変更となります。
参考: リリースノート

これに伴い、 3.0.0 から google_project_servicebigquery-json.googleapis.com を設定しようとすると以下のようなエラーが発生します。

Error: expected service to not match any of [dataproc-control.googleapis.com source.googleapis.com stackdriverprovisioning.googleapis.com bigquery-json.googleapis.com], got bigquery-json.googleapis.com

google_project_service でBigQuery API有効化に bigquery-json.googleapis.com に使っている場合は,
bigquery.googleapis.com に修正する必要があります。

google_project_services リソースの廃止

悪名高き google_project_services が廃止となります。
google_project_services は、 明示的に設定していないサービスはApply時に削除するという動作(Authoritative)があり、Cloud Consoleでとりあえず有効化したような場合、Terraformで再度無効化されたりして、非常に危険でした。
サービスAPI有効化は google_project_service のみを使うことができます。
google_project_services のようにまとめてサービスAPIを有効化したい場合は、 for_each 構文を使って記述するか、 project_services モジュールを使って記述する、ということになりそうです。

余談ですが、アップグレードガイドの設定例ですと、 project_services モジュールを利用する場合モジュールの version に v3.3.0を指定していますが、 このバージョンは内部的に count 属性で実装しているため、サービス設定を変更する際に、余計なサービス無効化処理が入る可能性があり、ちょっと危険です。
project_services モジュールの v4.0.0 以降から、 for_each で実装しているようなので、 project_services モジュールの version は v4.0.0 以降を指定するのがよいと思います。

google_storage_bucket の condition.is_live 属性

Cloud Storageバケットのライフサイクルルールで、オブジェクトのライブ状態の設定である condition.is_live 属性は廃止されました。代わりに、 condition.with_state 属性を使用します。
condition.with_state 属性は v2.4.0 から追加されており、condition.is_live 属性の廃止予告はありましたが、正式に廃止されたものになります。

バージョンアップでトラブルにならないために

アップグレードガイドのProvider Version Configuration にも記載されておりますが、もし 3.0.0 へのアップグレードにすぐ対応できない場合は、 Google Providerのバージョンを固定し、時期をみて 3.0.0 以降へ移行するのも手だと思います。
以下の例は、2.17.0 に固定する場合の設定です。バージョン固定は provider の中で version を設定します。(アップグレードガイドの記述そのままです。)

provider "google" {
  # ... other configuration ...
  version = "~> 2.17.0"
}

バージョン固定は、今回のようなアップグレードの非互換を防ぐためだけではなく、CIツールでTerraformを使う場合に、CIツールで使うバージョンと、手元でPlanするバージョンを一致させる目的でも使用しますので、今回の対応に限らず、provider の version 設定は入れておく方がよいと思います。

まとめ

Google Provider 3.0.0 の変更点は、上記で説明した内容だけでなく非常に多くのリソースにおいて廃止された機能や必須属性の追加等があります。アップグレードを行う前に、アップグレードガイドを読みながら設定を更新していくのがよいと思います。

商用環境等、トラブル影響が大きいシステムですと、こうした非互換に対応するためのバージョンアップは大変ではあります。
しかし、GCPの機能は日々進化しているため、古いProviderを使い続けることはGCPのAPI仕様からの乖離が発生しリスクとなります。計画的にバージョンアップしていけるよう、準備していきましょう。