コンテンツに移動
DevOps & SRE

Terraform リソースを Cloud Run API v2 に移行する

2023年12月5日
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 を宣言する必要があることは皆さんもご存じかもしれません。これらの設定は、直接引数として定義するようになりました。さらに、containerstemplate 属性の中の specの下にありますが、v2 では spec は必須ではなく、containerstemplate の直接の子になっています。また、名前が少し変更された属性もあります。

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_secondscontainers.timeout に変更
  • spec.containers.container_concurrencycontainers.max_instance_request_concurrency に変更
  • spec.service_account_nameservice_account に変更
  • spec.containers.env.value_from.secret_key_ref.keycontainers.env.value_source.secret_ref_key.secret に変更
  • spec.containers.env.value_from.secret_key_ref.valuecontainers.env.value_source.secret_ref_key.version に変更

値が変わった属性には、以下のようなものがあります。

  • containers.resource.limits.cpu
    • v1 の値の例: 1000m
    • v2 の同等の値: 1
  • containers.timeout
    • v1 の値の例: 300
    • v2 の同等の値: 300s

両バージョンの全属性のリストは、Terraform リソース ドキュメント(v1 google_cloud_run_servicev2 google_cloud_run_v2_service)で確認できます。

Terraform のコードを更新する

上記の違いを考慮すると、既存の Cloud Run サービスで新しいリソースを使用するには、以下のような変更が必要となります。

https://storage.googleapis.com/gweb-cloudblog-publish/images/Cloud_Run_API_v2.max-1000x1000.png

Terraform Cloud Run リソースのバージョン 2 への変換例

この例では、整数値 timeout_seconds が文字列値 timeout に、container_concurrencymax_container_request_concurrency に、service_accountservice_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 の状態を削除してインポートし、インフラストラクチャの実際の状態を非破壊的なやり方で反映させる方法もご紹介しました。

その他のリソース

ー シニア デベロッパー リレーションズ エンジニア Katie McLaughlin

投稿先