Google Cloud プロジェクトの既存リソースを Terraform コードに出力&ドキュメントを作成する方法

2022.03.18

こんにちは、みかみです。

やりたいこと

  • Google Cloud のリソースをコード管理したい
  • Google Cloud プロジェクトに作成済みのリソースを Terraform のコードに出力したい
  • ついでに Terraform コードからドキュメントも作っちゃいたい

前提

Google Cloud SDK(gcloud コマンド)の実行環境は準備済みであるものとします。 本エントリでは、Cloud Shell を使用しました。

gcloud コマンドで出力

Google Cloud 公式ドキュメントによると、Google Cloud プロジェクトのリソースをコード出力する gcloud コマンドがあるとのことです。

まずは gcloud beta resource-config bulk-export コマンドで、プロジェクトに作成済みのリソースを Terraform の構成ファイルに出力してみます。

出力対象の Google Cloud プロジェクトには、Cloud Storage バケットが1つと、BigQuery のデータセット&テーブルが1つある状態です。

Cloud Shell から以下のコマンドを実行しました。

gcloud beta resource-config bulk-export --resource-format=terraform --path=./bulk_export/

なお、上記コマンドの初回実行時に、google-cloud-sdk-config-connector のインストールが必要と言われたため、apt-get でインストール済みです。

This command requires the `config-connector` binary to be installed to export GCP resource configurations. Would you like to install the`config-connector` binary to continue
command execution? (Y/n)?  Y

ERROR: (gcloud.beta.resource-config.bulk-export)
You cannot perform this action because the Google Cloud CLI component manager
is disabled for this installation. You can run the following command
to achieve the same result for this installation:

sudo apt-get install google-cloud-sdk-config-connector

3分ほどでコード出力が完了しました。 結果を確認してみます。

Cloud Shell Editor でみてみると、プロジェクトが所属するフォルダ ID のディレクトリと、プロジェクト番号のデイレクトリ、projects という名前のディレクトリと、プロジェクト名のディレクトリが出力されていました。 各ディレクトリの中身も見てみます。

フォルダ ID のディレクトリの下には、請求先アカウントや所属するフォルダ ID などを定義した、プロジェクトの構成ファイルが出力されていました。

また、プロジェクト番号のデイレクトリの下には、Logging のシンク情報と有効化済みの API(サービス)の構成ファイルが出力されています。

続いて projects ディレクトリです。配下には、BigQuery のテーブルや、サービスアカウント、Cloud Storage バケットといった、プロジェクトに属するリソースの構成ファイルがありました。

最後に、プロジェクト名のディレクトリ配下には、BigQuery データセットの構成ファイルが出力されていました。

今回はまだリソースが少ないプロジェクトだったので、どの構成ファイルがどのリソースか分かりますが、サービスアカウントや Logging のシンク情報など、明示的に作成していないリソースの構成ファイルも出力されるので、リソースが多いプロジェクトだとコード管理対象のリソースの切り分けに若干苦労しそうです。

Terraformer で出力

gcloud コマンド以外でも、Terraform の構成ファイルを出力できる Terraformer というツールがあるようなので、こちらも使い方や出力内容を確認してみます。

以下を参考に、インストールしました。

Cloud Shell で、以下のコマンドを実行します。

export PROVIDER=google
curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-linux-amd64
chmod +x terraformer-${PROVIDER}-linux-amd64
sudo mv terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformer

--version コマンドで確認してみると、正常にインストールできたようです。

mikami_yuki@cloudshell:~/terraform (team-da-initiative)$ terraformer --version
version v0.8.19

新しく作業用ディレクトリを作成し、プラグインをインストールします。 README の記載の通り、以下の内容を versions.tf というファイル名で保存してから、terraform init コマンドを実行しました。

terraform {
  required_providers {
    google = {
      source = "hashicorp/google"
    }
  }
  required_version = ">= 0.13"
}

これで準備完了です。以下のコマンドでコード出力を実行してみます。

terraformer import google --resources=gcs,bigQuery --projects=team-da-initiative

出力対象として GCS と BigQuery を指定しています。 指定可能なリソースは下記ドキュメントでご確認ください。

mikami_yuki@cloudshell:~/terraform/export (team-da-initiative)$ terraformer import google --resources=gcs,bigQuery --projects=team-da-initiative
2022/03/18 05:42:08 google importing project team-da-initiative region global
2022/03/18 05:42:09 googleapi: Error 404: The resource 'projects/team-da-initiative/regions/global' was not found, notFound
2022/03/18 05:42:09 googleapi: Error 404: The resource 'projects/team-da-initiative/regions/global' was not found, notFound
2022/03/18 05:42:09 google importing... gcs
2022/03/18 05:42:10 google done importing gcs
2022/03/18 05:42:10 googleapi: Error 404: The resource 'projects/team-da-initiative/regions/global' was not found, notFound
2022/03/18 05:42:10 google importing... bigQuery
2022/03/18 05:42:10 google done importing bigQuery
2022/03/18 05:42:10 Number of resources for service gcs: 6
2022/03/18 05:42:10 Number of resources for service bigQuery: 2
2022/03/18 05:42:10 Refreshing state... google_bigquery_table.tfer--team-da-initiative-003A-sample-002E-orders
2022/03/18 05:42:10 Refreshing state... google_storage_bucket_iam_member.tfer--da-initiative-recruit
2022/03/18 05:42:10 Refreshing state... google_storage_bucket.tfer--da-initiative-recruit
2022/03/18 05:42:10 Refreshing state... google_storage_bucket_acl.tfer--da-initiative-recruit
2022/03/18 05:42:10 Refreshing state... google_storage_bucket_iam_policy.tfer--da-initiative-recruit
2022/03/18 05:42:10 Refreshing state... google_storage_bucket_iam_binding.tfer--da-initiative-recruit
2022/03/18 05:42:10 Refreshing state... google_storage_default_object_acl.tfer--da-initiative-recruit
2022/03/18 05:42:10 Refreshing state... google_bigquery_dataset.tfer--team-da-initiative-003A-sample
2022/03/18 05:42:11 ERROR: Read resource response is null for resource google_storage_bucket_iam_member.tfer--da-initiative-recruit
2022/03/18 05:42:11 ERROR: Unable to refresh resource tfer--da-initiative-recruit
2022/03/18 05:42:11 Filtered number of resources for service gcs: 5
2022/03/18 05:42:11 Filtered number of resources for service bigQuery: 2
2022/03/18 05:42:11 google Connecting....
2022/03/18 05:42:11 google save bigQuery
2022/03/18 05:42:11 google save tfstate for bigQuery
2022/03/18 05:42:11 google save gcs
2022/03/18 05:42:11 google save tfstate for gcs

なにやらエラーも出ていますが、出力完了したようです。

確認してみると

$ ls -la
total 28
drwxr-xr-x 5 mikami_yuki mikami_yuki 4096 Mar 18 05:42 .
drwxr-xr-x 4 mikami_yuki mikami_yuki 4096 Mar 18 05:16 ..
drwxr-xr-x 3 mikami_yuki mikami_yuki 4096 Mar 18 05:42 generated
drwxr-xr-x 3 mikami_yuki mikami_yuki 4096 Mar 18 05:30 .terraform
-rw-r--r-- 1 mikami_yuki mikami_yuki 1080 Mar 18 05:30 .terraform.lock.hcl
-rw-r--r-- 1 mikami_yuki mikami_yuki  127 Mar 18 05:30 versions.tf

generated という名前のディレクトリが新しく作成されていました。 中身を確認してみます。

provider に指定した google ディレクトリが作成され、プロジェクト名のディレクトリが続きます。 プロジェクト名ディレクトリの下に --resources オプションで指定したリソース名のディレクトリが作成され、その下に各リソースの構成ファイルが出力されているようです。

ファイルの中身はこんな感じ。

リソースごとにディレクトリが分かれているので、どの構成ファイルがどのリソースに関するコードなのか直感的に分かりやすい構成です。 コード内のリソース名に、プロジェクト名や 003A などの識別子(?)的な文字列が含まれているので、別のプロジェクトに反映する場合は少しコードに手を加えた方が良さそうですが、これを使えばインフラコード管理の敷居がずいぶん低くなりそうです。

つまずいたところ

さらっと実行できたように書いていますが、実ははじめ、インストール完了後すぐに実行してしまい、以下のエラーになりました。。

$ terraformer import google --resources=gcs,bigQuery --projects=team-da-initiative
2022/03/18 05:21:53 google importing project team-da-initiative region global
2022/03/18 05:22:00 googleapi: Error 403: Compute Engine API has not been used in project 368392819661 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/compute.googleapis.com/overview?project=368392819661 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
Details:
[
  {
    "@type": "type.googleapis.com/google.rpc.Help",
    "links": [
      {
        "description": "Google developers console API activation",
        "url": "https://console.developers.google.com/apis/api/compute.googleapis.com/overview?project=368392819661"
      }
    ]
  },
  {
    "@type": "type.googleapis.com/google.rpc.ErrorInfo",
    "domain": "googleapis.com",
    "metadata": {
      "consumer": "projects/368392819661",
      "service": "compute.googleapis.com"
    },
    "reason": "SERVICE_DISABLED"
  }
]
, accessNotConfigured
2022/03/18 05:22:00 open /home/mikami_yuki/.terraform.d/plugins/linux_amd64: no such file or directory

エラーメッセージの通りです。。 Compute Engine API が有効になっていないことと、プラグインがインストールされていないことが原因でした。。。

terraform init コマンドでプラグインをインストールしたら、実行できるようになりました。。 なお、Compute Engine API を有効にしなくても、GCS と BigQuery の構成ファイルは出力することができました。(エラーメッセージがうるさいので API も有効化しましたが。

Terraform のコードからドキュメントを作成

Terraform コードを管理する場合、コード内にどんなリソースが含まれるかなど、README 的なドキュメントもあるとより親切です。

ドキュメント自動作成するツールもありそうだなーと思ったら、やはりありました。

どんな準備が必要で、どんなドキュメントが出力できるのか、試してみます。

以下のコマンドを実行して terraform-docs をインストールしました。

curl -Lo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-$(uname)-amd64.tar.gz
tar -xzf terraform-docs.tar.gz
chmod +x terraform-docs
mv terraform-docs /usr/local/bin/terraform-docs

無事インストールできたようです。

$ terraform-docs --version
terraform-docs version v0.16.0 1f686b1 linux/amd64

先ほど Terraformer で出力した GCS と BigQuery のコードに対して terraform-docs を実行して、どんな感じでドキュメント出力できるのか確認してみます。

以下のコマンドを実行しました。

terraform-docs markdown table --output-file bigQuery.md ./export/generated/google/team-da-initiative/bigQuery/global/
terraform-docs markdown table --output-file gcs.md ./export/generated/google/team-da-initiative/gcs/global/

出力結果を確認してみます。

自動出力されたコードを使ったので、リソース名がちょっとあれだったり、モジュールがないので若干さみしい感じですが、簡単にマークダウン出力することができました。 これで README も一瞬で作成できそうです。

まとめ(所感)

Terraform のコードを0から書くのは大変ですが、gcloud コマンドや Terraformer を使えば、既存のリソースを簡単にコード出力できて便利でした。 特に Terraformer ならコード出力対象のリソースを指定できるので、検証環境のリソースに手動で変更を加えた後にコード出力して、本番環境にはコードから変更を反映するなど、リソースのコード管理が非常に楽になりそうです。

また、terraform-docs を使えば Terraform コードから簡単にマークダウンを出力することができるので、README も簡単に作成できます。

インフラのコード管理はシステム処理に直接影響するわけではないのでついつい後回しにしてしまいがちでしたが、Terraformer や terraform-docs を使えば簡単にコードやドキュメントが出力できることが分かったので、これからはありがたく利用させていただこうと思います。

参考