stefafafan の fa は3つです

"すてにゃん" こと id:stefafafan のブログです

gcloud のコマンドを活用して既存の環境をTerraformに落とし込む

Google Cloudに手でたてたリソースをTerraformに落とし込むときにterraformerみたいなツールを使ってみようと思ってググってたら公式ドキュメントに gcloudを使ったやり方が紹介されていたので試してみました。(ドキュメント曰く、GAになる前の機能なので、いずれ変わる箇所もありそうです)。

この記事ではその使い方や気になった箇所について軽く紹介します。

cloud.google.com

Terraform形式になるように一括でエクスポートする

まずはTerraform形式に既存の環境をエクスポートするコマンドです。詳しくはここに書いてあります。
cloud.google.com

とにかく対応しているリソースを全てエクスポートしてみたい!というときはこれでいけます。

$ gcloud beta resource-config bulk-export \
  --path=OUTPUT_DIRECTORY_NAME \
  --project=PROJECT_ID \
  --resource-format=terraform

一方で本当に大量に出力されるので、自分の場合は特別Terraform 管理下に入れたいわけでないものまで出てきたので、リソースごとにフィルターしてから出力するというのをやりました。

$ gcloud beta resource-config bulk-export \
  --resource-types=ComputeFirewall,ComputeInstance \
  --path=OUTPUT_DIRECTORY_NAME \
  --project=PROJECT_ID \
  --resource-format=terraform

ちなみにこれを実行するとファイル分割やディレクトリ構造などが自動的に決まるので、特にこだわりがない場合はそれにそのまま従えばよくて便利です。

どういう resource-type がフィルターで使えるかは以下のコマンドで一覧を取得できます。

$ gcloud beta resource-config list-resource-types

Terraformにインポートするためのスクリプトを生成する

エクスポートしたファイルを実際に Terraform の State にインポートするためのスクリプトを生成するためのコマンドがあります。
cloud.google.com

エクスポートされたディレクトリを指定しつつ実行すると、 terraform import 文が羅列されたシェルスクリプトが生成されます。

$ gcloud beta resource-config terraform generate-import OUTPUT_DIRECTORY_NAME \
  --output-script-file=IMPORT_SCRIPT_NAME \
  --output-module-file=OUTPUT_MODULE_FILE_NAME

生成されたインポートスクリプトを実行する

あとは生成されたスクリプトを実行します。その前に認証をどうするかという話があるのですが、Terraformプロバイダのドキュメントに詳細に書かれています。ローカルから実行する場合はApplication Default Credentialsを利用するのが簡単そうです。

$ gcloud auth application-default login

あとは terraform init して import して plan します。

$ terraform init
$ ./terraform_import_20220331-19-12-33.sh
$ terraform plan

ハマり所・気になり所

基本の流れは上に書いたのですが(ドキュメントにも書いてあるのと大体同じような感じ)、いくつか気になりポイントはありましたので共有しておきます。(最初にも書きましたがそもそもGA前の機能という前提はあります)。

bulk-exportコマンドで出力されないリソースがある

これは単純に対応していないという話ですが、例えばCloud Runリソースを作っててもこのgcloudコマンドではエクスポートされないです ( gcloud beta resource-config list-resource-types の結果に無いのでこれは想定通り)。

Cloud Runは未対応というのはわかるけど、 ComputeNetworkEndpointGroup というリソースは一見対応しているようにみえて、自分が試したときはエクスポートされないということもありました。もしかしたらCloud Runに紐づくComputeNetworkEndpointGroupを作っていたため未対応という可能性はあったのかもしれません。

ちなみにCertificate Managerという最近めのサービスもgcloudでは未対応な一方プロバイダ側にはリソースの定義がありました。ただし一般利用はできないみたいなことが書かれてあったり、ワイルドカード証明書に対応していないというOpenなissueがあったりしたので、これについてはサービスを利用していても現時点ではこのプロバイダ経由でのTerraform管理は一旦置きという感想になりました。

bulk-exportコマンドでリソース指定でフィルターしたときにエラーが発生するリソースがある

自分が試したとき、ComputeTargetHTTPSProxyComputeURLMap のリソースは --resource-types で指定した場合はエラーが発生して出力できませんでした。

$ gcloud beta resource-config bulk-export \
    --resource-types=ComputeTargetHTTPSProxy,ComputeURLMap \
    --project=PROJECT_ID \
    --resource-format=terraform

ERROR: (gcloud.beta.resource-config.bulk-export) INVALID_ARGUMENT: No CONTENT_TYPE_UNSPECIFIED found that matches asset type compute.googleapis.com/TargetHTTPSProxy for consumer project: XXXX. For a list of supported content types and asset types, see https://cloud.google.com/asset-inventory/docs/supported-asset-types
- '@type': type.googleapis.com/google.rpc.BadRequest
fieldViolations:
- description: 'No CONTENT_TYPE_UNSPECIFIED found that matches asset type compute.googleapis.com/TargetHTTPSProxy
    for consumer project: XXXX. For a list of supported content types and
    asset types, see https://cloud.google.com/asset-inventory/docs/supported-asset-types'
    field: asset_types

上記のように、指定したリソースタイプに対応したtypeはないですよ!と怒られます。このオプション指定なしだとちゃんとComputeTargetHTTPSProxyやComputeURLMapのリソースは出力されていました。以下のURLに誘導されるのでここを眺めるとどうやら TargetHttpsProxyUrlMap っぽい(つまり大文字の具合が違いそう)ということがわかるので今度はそれを指定して実行してみます。
cloud.google.com

$ gcloud beta resource-config bulk-export \
    --resource-types=ComputeTargetHttpsProxy,ComputeUrlMap \
    --project=PROJECT_ID \
    --resource-format=terraform

こうすると一応エラーはでなくなって成功するんですが、該当リソースはありませんということで何も差分がない状態になります。 --resource-types 指定なしの場合は確かにリソースがあるので何かおかしいなと思いつつ結局オプション指定なしのときに出力されたファイルの一部を利用することにしました。

terraform plan したらエラーが発生したり差分が発生することがある

gcloud beta resource-config bulk-export で生成されたTerraformのファイルと、Terraformプロバイダ側の制約が一致していないところがあるようで、 terraform plan を実行したら怒られるというのがありました。

例えば自分の場合は以下のような部分で怒られました。

  • compute_backend_serviceoauth2_client_secret が必須だけど指定されていません
  • google_storage_bucketpublic_access_prevention が指定されている箇所がおかしいです

とはいえ、このへんはエラーの様子をみつつ、Google Provider Configuration Reference | Guides | hashicorp/google | Terraform Registry のドキュメントを見つつ対応していけば問題なかったので、たいしたことではなかったです。

終わり

色々と細かいハマり所みたいなのを書きましたが全体的には便利で満足しました。ドキュメントに従ってやってれば8割方完成してあとは terraform plan で怒られた箇所を調整すれば終わるのでそんなに苦ではなかったです。公式でこういう機能があるのはいいですね。