Terraform リソースを Cloud Run API v2 に移行する
Google Cloud Japan Team
※この投稿は米国時間 2023 年 11 月 29 日に、Google Cloud blog に投稿されたものの抄訳です。
デプロイ済みのリソースに変更を加える必要のない Terraform のコードに変更を加える場合、Terraform の状態を更新する必要があります。このプロセスでは、Terraform の状態を削除して Terraform のコードを更新した後、既存のリソースから Terraform の状態を再インポートする必要があります。
この操作が必要となるケースの一例は、Google Cloud リソースのデプロイや構成に新しい Terraform リソースを使用する場合です。新たにリリースされた google_cloud_run_v2_service
Terraform リソースを使用する場合もこれに該当します。
このブログ投稿では、この新しい Terraform リソースについてご説明します。また、サンプルの Cloud Run サービスをこの新しいリソースに移行するプロセスもご紹介します。
Terraform リソースの違い
最初にリリースされたときの Cloud Run は Knative と Kubernetes をベースに構築され、v1 API にはこのモデルが反映されました。現在は、他の Google Cloud API に似たスタイルで構築された v2 API が追加されています。v2 によって v1 が廃止されたわけではなく、どちらの API も一般提供されています。
v2 は、Terraform の Google プロバイダが含まれる Cloud クライアント ライブラリで使用します。この 2 つの API は形が異なるため、google_cloud_run_service
リソースと google_cloud_run_v2_service
リソースの属性は異なっています。
スケーリングや Cloud SQL 接続に関する設定を構成するには、metadata.annoations
を宣言する必要があることは皆さんもご存じかもしれません。これらの設定は、直接引数として定義するようになりました。さらに、containers
は template
属性の中の spec
の下にありますが、v2 では spec は必須ではなく、containers
は template
の直接の子になっています。また、名前が少し変更された属性もあります。
template
の下の metadata.annotations
の違いをいくつかご紹介します(1 つ目が v1、2 つ目が v2 です)。
- "autoscaling.knative.dev/minScale" は
scaling.min_instance_count
に変更 - "autoscaling.knative.dev/maxScale" は
scaling.max_instance_count
に変更 - "run.googleapis.com/cpu-throttling" は
containers.resources.cpu_idle
に変更 - "run.googleapis.com/cloudsql-instances" は
volumes.cloud_sql_instance
に変更
名前が変わった属性には、以下のようなものがあります。
spec.containers.timeout_seconds
はcontainers.timeout
に変更spec.containers.container_concurrency
はcontainers.max_instance_request_concurrency
に変更spec.service_account_name
はservice_account
に変更spec.containers.env.value_from.secret_key_ref.key
はcontainers.env.value_source.secret_ref_key.secret
に変更spec.containers.env.value_from.secret_key_ref.value
はcontainers.env.value_source.secret_ref_key.version
に変更
値が変わった属性には、以下のようなものがあります。
containers.resource.limits.cpu
- v1 の値の例:
1000m
- v2 の同等の値:
1
- v1 の値の例:
containers.timeout
- v1 の値の例:
300
- v2 の同等の値:
300s
- v1 の値の例:
両バージョンの全属性のリストは、Terraform リソース ドキュメント(v1 google_cloud_run_service と v2 google_cloud_run_v2_service)で確認できます。
Terraform のコードを更新する
上記の違いを考慮すると、既存の Cloud Run サービスで新しいリソースを使用するには、以下のような変更が必要となります。
Terraform Cloud Run リソースのバージョン 2 への変換例
この例では、整数値 timeout_seconds
が文字列値 timeout
に、container_concurrency
が max_container_request_concurrency
に、service_account
が service_account_name
に変更されています。また、spec レベルが削除され、リソースそのものが google_cloud_run_v2_service
に変更されています。
Terraform の状態を更新する
リテラルの観点から見ると、Terraform のコードに加えた変更は、デプロイ済みの Cloud Run サービスには影響しません。一方、Terraform の観点から見ると、異なるリソースを使用して宣言されるため、terraform apply
を実行すると Cloud Run サービスは破棄され、再作成されます。Cloud Run はステートレスなので、ほとんどの場合は問題ないでしょう。ですが、リビジョンのタイムラインなど、リソースのリビジョンの履歴に関する情報は残しておきたいかもしれません。
デプロイ済みのリソースに変更を加えることなく、Terraform のコードと状態を更新するには:
- 元のコードから始める
- Terraform の状態にサービスが存在することを確認し、リソース名を取得する
- リソース名を使用して、リソース識別子を取得する
- 新しいリソースを使用するように Terraform のコードを更新する
- リソースの Terraform の状態を削除する
- リソースの状態をインポートする
- 保留中の変更が Terraform にないことを確認する
この投稿の残りの部分では、これらの各ステップについて詳しくご説明します。
実例
ここではサービスの例として、サンプルの Hello World イメージを実行する Cloud Run サービスを使用します。この Terraform はすでにプロジェクトに適用され、状態ファイルはローカルに保存されています(状態を Cloud Storage バケットに保存するのと同じくらい簡単に実行できます)。
元のコード
Terraform の状態を確認する
terraform state list
状態は、現在の .tf
ファイル内の構成に基づいて確認されるため、変更を加える前にこのコマンドを実行する必要があります。
この構成には 2 つのリソースと 1 つのデータソースがあるため、それらが状態に反映されています。
リソース識別子を取得する
echo RESOURCE.NAME.id | terraform console
後ほど実行するインポート ステップの import コマンドでは、Terraform のリソース名だけでなくリソースの実際の識別子も必要となります。
この例の hello
サービスの Terraform リソース名は google_cloud_run_service.default
です。このリソースの id 引数を取得するには、console を使って値を表示します。
この識別子は正確なものですが、そのままでは後のステップで機能しません。
この識別子の形式は region/project/name ですが、Cloud Run Admin API v2 に準じて project/region/name の形式にする必要があります。これについては後でご説明します。
Terraform ファイルを更新する
現在の状態の情報を取得したので、構成を更新できます。
リソース名(関連付けられている参照を含む)を変更し、template
ノードの spec 部分を削除(実質的には containers
を左方向に移動)して、アノテーションを新しい名前に変えます。
このステップでさらに変更を加えることもできますが、terraform plan で新たな変更が認識されないようにするため、追加の変更は後で行います。
更新されたファイルは以下のようになります。
以前の状態を削除する
terraform state rm RESOURCE.NAME
これで、以前の状態を削除する準備が整いました。このコマンドは、Terraform がこのリソースを「忘れる」ように状態ファイルを更新します。使用中のリソースには何も影響しません。対象のリソースがさまざまな .tfstate ファイルから削除されるだけです。
新しい状態をインポートする
terraform import RESOURCE.NAME RESOURCE_IDENTIFIER
以前の状態を削除したので、プロジェクトの状態を取得できるようになりました。Terraform の構成でリソースを定義したので、そのリソース名をリソースとして使用し、先ほど値から適用した識別子をリソース識別子として使用します。
リソース識別子の形式が正しくない場合は、Error 403: Permission denied on resource
のようなエラーになります。また、参照しようとしているリソースが存在しない場合は、権限が拒否されます。解析されたリソース識別子の形式を確認し、必要に応じて修正してください。
保留中の変更がないことを確認する
terraform plan
これで、状態が更新され、新しいリソース定義と未変更のままの実際のリソースを、Terraform でアクティブに識別できるようになりました。
terraform plan
を実行すると、リソース定義に沿って Terraform がサービスに対して実行する処理を確認できます。すべてが正しく実行されていれば、何も変更する必要はありません。
terraform apply
を実行し、Terraform と実際の状態の統合がうまく行っていることを確認します。
これで、デプロイ済みのリソースに変更を加えることなく、Terraform で定義した Cloud Run サービスを別のリソースに正常に移行できました。
まとめ
この記事では、Cloud Run API v2 について、そして google_cloud_run_v2_service
を使用するように既存のデプロイ済みの Cloud Run サービスを適応させる方法についてご紹介しました。また、Terraform の状態を削除してインポートし、インフラストラクチャの実際の状態を非破壊的なやり方で反映させる方法もご紹介しました。
その他のリソース
- google_cloud_run_service の Terraform リソース定義
- google_cloud_run_v2_service の Terraform リソース定義
- Cloud Run 用 IAM ポリシーの Terraform リソース定義
ー シニア デベロッパー リレーションズ エンジニア Katie McLaughlin