[プレビュー]Google CloudリソースをTerraformにエクスポートしてみた。(+Cloud ConsoleからリソースのHCLを確認する小ネタ)

Google Cloud上の既存リソースを一括エクスポートでTerraform形式(HCL)にコード化するためのプレビュー機能を試してみました。 プレビューではありますが、Google Cloud上にデプロイした既存リソースをコード化して新しいプロジェクトに複製するといったニーズに活用できるものとなっています。 また、Cloud ConsoleからリソースのHCLを確認する小ネタも合わせて共有します。Google Cloudにおけるコードによるインフラ運用の手助けになれば幸いです。
2023.10.31

アライアンス事業部 エンジニアの村田です。

Cloud Console(GUI) や Cloud SDK(CLI)によってGoogle Cloud上にデプロイした既存リソースをコード化し、新しいプロジェクトに複製したいケースはありませんでしょうか? Google Cloud上の既存リソースを一括エクスポートでTerraform形式(HCL)にコード化するための機能がプレビューにて利用可能でしたので、本ブログにて試してみました。

※Google Cloud上の既存リソースをHCLに一括エクスポートできる機能はプレビューリリースのためテスト利用にお使いください。

※以下Google Cloudのチュートリアルを参考にしています。 https://cloud.google.com/docs/terraform/resource-management/export?hl=ja

検証環境

以下ローカル環境で検証しています。

OS : Ubuntu 22.04.2 LTS (GNU/Linux 5.15.90.1-microsoft-standard-WSL2 x86_64)
※Windows 11のWSL上に立てています。

ローカル環境で本検証を実行するにはgcloud CLI(Cloud SDK)のインストールと初期化が必要です。手順は以下をご参照ください。(Cloud Shellを利用する場合は以下手順は不要です。)

gcloud CLI をインストールする  |  Google Cloud CLI のドキュメント

準備

Google Cloud の Terraform一括エクスポートツールを利用するために、以下コマンドでConfig Connectorをインストールします。

gcloud components install config-connector

対象プロジェクトのGoogle Cloudリソースをエクスポートするために、Cloud Asset APIを有効化します。

gcloud services enable cloudasset.googleapis.com

Google Cloudのbetaバージョン機能やサービスを利用するためのgcloud betaコマンドをインストールします。

gcloud components install beta

Google Cloudプロジェクト全体のエクスポート

プロジェクトのリソース構成を出力するディレクトリを作成します。

mkdir OUTPUT_DIRECTORY

プロジェクト構成全体を Terraform HCL コードにエクスポートします。

gcloud beta resource-config bulk-export \
  --path=OUTPUT_DIRECTORY \
  --project=<Google CloudプロジェクトID> \
  --resource-format=terraform

resource-config Google Cloudリソースを宣言的に管理するためのコマンド。本コマンドを利用するために、前述のconfig-connectorのインストールが必要。

bulk-export 一括エクスポートのためのコマンド。

--path エクスポート先ディレクトリ。

--project エクスポート対象のプロジェクト。

--resource-format エクスポートするコンフィグレーションのフォーマット。terraform:Terraform HCL または krm: KRM YAML のいずれかを指定可能。

指定したディレクトリ配下に詳細なリソースごと/インスタンスごとに、以下の構成で多数のtfファイルがエクスポートされました。(プロジェクトIDなどの情報はマスクしています)

$ tree
.
├── xxxxxxxx
│   └── Project
│       └── xxxxxxxx.tf
├── xxxxxxxx
│   └── Service
│       ├── artifactregistry-googleapis-com.tf
│       ├── autoscaling-googleapis-com.tf
│       ├── bigquery-googleapis-com.tf
│       ├── bigquerymigration-googleapis-com.tf
│       ├── bigquerystorage-googleapis-com.tf
│       ├── cloudapis-googleapis-com.tf
│       ├── cloudasset-googleapis-com.tf
│       ├── cloudbuild-googleapis-com.tf
│       ├── cloudtrace-googleapis-com.tf
│       ├── compute-googleapis-com.tf
│       ├── container-googleapis-com.tf
│       ├── containerfilesystem-googleapis-com.tf
│       ├── containerregistry-googleapis-com.tf
│       ├── datastore-googleapis-com.tf
│       ├── dns-googleapis-com.tf
│       ├── iam-googleapis-com.tf
│       ├── iamcredentials-googleapis-com.tf
│       ├── logging-googleapis-com.tf
│       ├── monitoring-googleapis-com.tf
│       ├── networkconnectivity-googleapis-com.tf
│       ├── osconfig-googleapis-com.tf
│       ├── oslogin-googleapis-com.tf
│       ├── pubsub-googleapis-com.tf
│       ├── run-googleapis-com.tf
│       ├── servicemanagement-googleapis-com.tf
│       ├── serviceusage-googleapis-com.tf
│       ├── sourcerepo-googleapis-com.tf
│       ├── sql-component-googleapis-com.tf
│       ├── storage-api-googleapis-com.tf
│       ├── storage-component-googleapis-com.tf
│       └── storage-googleapis-com.tf
├── xxxxxxxx
│   └── ComputeDisk
│       └── us-west1-a
│           └── flask-vm.tf
└── projects
    └── xxxxxxxx
        ├── ComputeFirewall
        │   ├── allow-ssh.tf
        │   ├── default-allow-http.tf
        │   ├── default-allow-https.tf
        │   ├── default-allow-icmp.tf
        │   ├── default-allow-internal.tf
        │   ├── default-allow-rdp.tf
        │   ├── default-allow-ssh.tf
        │   └── flask-app-firewall.tf
        ├── ComputeInstance
        │   └── us-west1-a
        │       └── flask-vm.tf
        ├── ComputeNetwork
        │   └── my-custom-mode-network.tf
        ├── ComputeResourcePolicy
        │   └── us-central1
        │       └── test-schedule.tf
        ├── ComputeSubnetwork
        │   └── us-west1
        │       └── my-custom-subnet.tf
        ├── IAMServiceAccount
        │   ├── xxxxxxxx-compute.tf
        │   ├── xxxxxxxx-sa.tf
        │   ├── xxxxxxxx-sa.tf
        │   └── terraform-account.tf
        └── StorageBucket
            └── US
                ├── export-xxxxxxxxxx.tf
                └── xxxxxxxx-cloudbuild.tf

20 directories, 51 files

一部のtfファイルの中身を見てみます。(flask-vmというCompute Engineインスタンスを確認。プロジェクトIDや外部IPなどの情報はマスクしています)

$ cat projects/xxxxxxxx/ComputeInstance/us-west1-a/flask-vm.tf
resource "google_compute_instance" "flask_vm" {
  boot_disk {
    auto_delete = true
    device_name = "persistent-disk-0"

    initialize_params {
      image = "https://www.googleapis.com/compute/beta/projects/debian-cloud/global/images/debian-11-bullseye-v20231010"
      size  = 10
      type  = "pd-standard"
    }

    mode   = "READ_WRITE"
    source = "https://www.googleapis.com/compute/v1/projects/xxxxxx/zones/us-west1-a/disks/flask-vm"
  }

  machine_type = "f1-micro"

  metadata = {
    startup-script = "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask"
  }

  name = "flask-vm"

  network_interface {
    access_config {
      nat_ip       = "xx.xxx.xx.xx"
      network_tier = "PREMIUM"
    }

    network            = "https://www.googleapis.com/compute/v1/projects/xxxxxx/global/networks/my-custom-mode-network"
    network_ip         = "10.0.1.2"
    stack_type         = "IPV4_ONLY"
    subnetwork         = "https://www.googleapis.com/compute/v1/projects/xxxxxx/regions/us-west1/subnetworks/my-custom-subnet"
    subnetwork_project = "xxxxxx"
  }

  project = "xxxxxx"

  scheduling {
    automatic_restart   = true
    on_host_maintenance = "MIGRATE"
    provisioning_model  = "STANDARD"
  }

  shielded_instance_config {
    enable_integrity_monitoring = true
    enable_vtpm                 = true
  }

  tags = ["ssh"]
  zone = "us-west1-a"
}

一部のGoogle Cloudリソースタイプのみエクスポート

--resource-typesでリソースタイプを指定することで、一部のリソースタイプのみをエクスポートすることができます。

gcloud beta resource-config bulk-export \
  --resource-types=<リソースタイプ> \
  --path=OUTPUT_DIRECTORY \
  --project=<Google CloudプロジェクトID> \
  --resource-format=terraform

指定可能なリソースタイプは以下コマンドを入力して確認できます。

$ gcloud beta resource-config list-resource-types
┌──────────────────────────────────────┬──────────────┬─────────┬──────┐
│               KRM KIND               │ BULK EXPORT? │ EXPORT? │ IAM? │
├──────────────────────────────────────┼──────────────┼─────────┼──────┤
│ AccessContextManagerAccessLevel      │              │         │      │
│ AccessContextManagerAccessPolicy     │              │         │ x    │
│ AccessContextManagerServicePerimeter │              │         │      │
│ ArtifactRegistryRepository           │ x            │ x       │ x    │
│ BigQueryDataset                      │ x            │ x       │      │
│ BigQueryJob                          │              │ x       │      │
│ BigQueryTable                        │ x            │ x       │ x    │
│ BigtableAppProfile                   │ x            │ x       │      │
│ BigtableGCPolicy                     │              │         │      │
│ BigtableInstance                     │ x            │ x       │ x    │
│ BigtableTable                        │ x            │ x       │ x    │
│ CloudBuildTrigger                    │              │         │      │
│ CloudIdentityGroup                   │              │         │      │
...

BULK EXPORT?列にxが記載してある行のKRM KINDが指定可能なリソースタイプです。

ComputeInstanceComputeNetworkのみをOUTPUT_DIRECTORY_2にエクスポートしてみます。

gcloud beta resource-config bulk-export \
  --resource-types=ComputeInstance,ComputeNetwork \
  --path=OUTPUT_DIRECTORY_2 \
  --project=<Google CloudプロジェクトID> \
  --resource-format=terraform

以下のようにエクスポートされました。(プロジェクトIDはマスクしています)

$ tree
.
└── projects
    └── xxxxxxxxxx
        ├── ComputeInstance
        │   └── us-west1-a
        │       └── flask-vm.tf
        └── ComputeNetwork
            └── my-custom-mode-network.tf

5 directories, 2 files

[Tips]Cloud ConsoleからTerraformコードを確認する

Cloud Console の GUI画面からリソースのコードを確認する方法もあります。

Compute Enigineなど一部のリソースについては、リソース作成中の画面で[同等のコード]をクリックすることで画面右側に作成中のリソースについてコードをリアルタイム表示してくれます。

なお、Terraform(HCL)以外にもgcloudコマンド等によるコマンドラインでの設定、REST API(JSON)による設定も確認することもできます。

おわりに

今回、TerraformでGoogle Cloudを管理するための小ネタ的機能を試してみましたが、今後はTerraformによるGoogle Cloudのコード管理について様々な運用パターンでのベストプラクティスなど発信していきたいと思っています。