🪂

Terraform で入門する Google Cloud【セットアップ編】

2023/12/29に公開

🌟 はじめに

最近 GoogleCloud を使った開発を始めました。今までは AWS×Terraform の開発がメインだったのですが、 GoogleCloud×Terraform の開発は初めてだったため、備忘録的に必要なことをまとめていこうと思います。
本記事は ~セットアップ編~ としていますが、今後様々なリソースを構築して行き、知見を溜めたいと考えています。
説明が不十分である点がある可能性があるため、その際はご指摘いただければと思います。
なお、一部リソースを作成する例を示しますが、リソースを適切に削除しないと課金が発生する可能性があります。課金を意図されていない方はリソースの削除まで行うようにしてください。

📖 対象読者

  • terraform を触ったことはあるが、GoogleCloud の構築はしたことがない方
  • GoogleCloud の勉強がしたい方

✅ ゴールの確認

  • 🔥 これを読めば GoogleCloud×Terraform の構築が始められる
  • terraform コマンドを実行し、GoogleCloud のリソースが作成できる
  • terraform の状態を保存する tf.state を GoogleCloudStorage で管理する

🙋 Google Account / Google Cloud Console の準備

最初に GoogleCloudConsole にアクセスします。
下記から GoogleCloudConsole にアクセスできます。

https://console.cloud.google.com/

GoogleAccount がない場合は Account を用意してください。
GoogleCloudPlatform を初めて使う方は下記やコンソール画面から「無料トライアルに登録」から無料のクレジットを獲得できます。

https://cloud.google.com/free

※インフラ費用の「お支払い方法」として、クレジットカードの登録が必要になります。適切に作業を行えば課金は発生しない想定です。

🏢 Project の確認

コンソール画面を開き、Project の確認を行います。
この Project に対して GoogleCloud のリソースを作成していくので、必ず確認をしてください。
コンソール画面を開くと「プロジェクト番号」「プロジェクトID」が記載してあります。これは後ほど使用するので、参照できるようにしましょう。

🌟 Google Cloud CLI(gcloud)の設定

このセクションでは GoogleCloud を CLI 上から操作できる gcloud コマンドの紹介をします。
gcloud コマンド実行していないと、そもそも terraform コマンドを実行できなくなる可能性があるため、適宜見返してください。
一度スキップしていただき、必要なタイミングで見返していただく形でも大丈夫です。

Google Cloud CLI(gcloud) とは?

GoogleCloudCLI は、GoogleCloud リソースの作成と管理を行うための一連のツールです。これらのツールを使用すると、コマンドラインから、またはスクリプトや他の自動化により、多くの一般的なプラットフォーム タスクを実行できます。

https://cloud.google.com/sdk/gcloud?hl=ja

Google Cloud CLI(gcloud)のインストール

下記を参考に、GoogleCloudCLI のインストールが可能ですので、特定の手順を選択し、インストールしてください。

https://cloud.google.com/sdk/docs/install-sdk?hl=ja#installing_the_latest_version

ここからは早速 gcloud コマンドを使っていきましょう。

gcloud CLI の初期化(gcloud init)

gcloud init コマンドは、gcloud CLI の初期設定を行います。このコマンドを実行すると、ユーザーアカウントの認証情報を使用して GoogleCloud にアクセスできるように gcloud CLI を承認し、デフォルトの構成をセットアップします。

詳細は下記を参考にしてください。
https://cloud.google.com/sdk/docs/install-sdk?hl=ja#initializing_the

gcloud config configurations list

gcloud config configurations list コマンドは、local に保存されているすべての gcloud CLI 構成を一覧表示します。
例えば複数の configuration を登録していた場合下記のように表示されます。
このコマンドを使うことで、どの configuration が有効になっているかを確認できます。

$ gcloud config configurations list
NAME    IS_ACTIVE  ACCOUNT        PROJECT  COMPUTE_DEFAULT_ZONE  COMPUTE_DEFAULT_REGION
default True       xxx@gmail.com  xxx
xxx     False      yyy@gmail.com  yyy
yyy     False      xxx@gmail.com  xxx

gcloud config configurations activate [NAME]

gcloud config configurations activate [NAME] コマンドは、指定したアカウント名の gcloud CLI 構成をアクティブにします。 NAME には configurations list で表示された物で意図したものを指定してください。

gcloud config set

gcloud config set コマンドは、上記の configuration で IS_ACTIVE=True となっているものに対して、指定したプロパティの再設定が可能です。
例えば先の例では xxx という configuration が Active になっているので、下記のコマンドを実行すると、当該の configuration の project フィールドが更新されます。

$ gcloud config set project [project名]

gcloud auth login

gcloud auth login コマンドはユーザーアカウントを認証し、その結果を gcloud CLI の設定に保存します。このコマンドを使用すると、 gcloud CLI を介して GoogleCloud リソースを管理できます。認証が成功すると、ブラウザが開き、 Google アカウントのログインを求められます。ログイン後、そのアカウントは gcloud を操作するデフォルトアカウントとして設定されます。

gcloud auth application-default login

gcloud auth application-default login コマンドは、アプリケーションがGoogleCloudAPIを使用するための認証情報を取得します。これは主にローカル開発環境で使用されます。このコマンドを使用すると、アプリケーションは GoogleCloud リソースに対する API 呼び出しを行うことができます。これにより、GoogleCloud リソースを作成するための Terraform コマンドも打つことができるようになるため、先に実行しましょう。

🛠今回作成する成果物

今回は簡易的に default で用意されている VPC に属する ComputeEngine を構築します。

構成

下記に構成図を添付します。

Terraformリソース

関連する Terraform リソースは以下です。

Manages a VM instance resource within GCE. For more information see the official documentation and API.

🗂 フォルダ構成

フォルダ構成は以下の様にしています。

  • environments
    配下では環境(開発、ステージング、本番など)ごとに module を呼び出す root module となるコードを格納します

  • environments/dev/setup
    配下では開発環境で setup module を呼び出す root module となるコードを格納します

  • modules
    配下では再利用可能な Terraform コード(モジュール)を格納します

.
├── README.md
├── environments # 🆕 各環境を想定(開発、ステージング、本番など)
│   ├── dev
│   │   └── setup # 🆕 setup module を呼び出す root module 等を格納する
│   │       ├── main.tf
│   │       └── variable.tf
│   ├── prd
│   └── stg
└── modules # 🆕 再利用可能なTerraformコード(モジュール)を格納するディレクトリ
    └── setup
        ├── compute_instance.tf
        ├── provider.tf
        └── variable.tf

💻 実際のコード

実装した Terraform のコードは以下です。

  • environments/dev/setup/main.tf

このファイルは modules 配下の setup module を参照する root module となるコードを格納しています。

environments/dev/setup/main.tf
module "master" {
  source = "../../../modules/setup"
}
  • environments/dev/setup/variable.tf

このファイルでは、デフォルトの変数値を定義しています。
[PROJECT_ID] には先に確認したご自身の「プロジェクトID」を格納してください。

environments/dev/setup/variable.tf
variable "project_id" {
  default = "[PROJECT_ID]" // your google project
}
variable "region" {
  default = "asia-northeast1"
}
variable "environment" {
  default = "dev"
}
  • modules/setup/compute_instance.tf

このファイルでは、ComputeEngine のインスタンスを作成するための設定ファイルです。
関連する Terraform リソースで挙げたリソースはここで呼び出します。

modules/setup/compute_instance.tf
resource "google_compute_instance" "sample_instance" {
  name         = "sample-instance"
  machine_type = "f1-micro"
  zone         = "asia-northeast1-a" // your zone name:今回はasia-northeast1-a

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-11"

    }
  }

  network_interface {
    network = "default" // your network name:今回はdefault
  }
}
  • modules/setup/provider.tf

このファイルは Terraform のプロバイダ設定を定義しています。
GoogleCloudPlatform をプロバイダとして使用し、5.0 以上のバージョンを要求するように記載しています。

modules/setup/provider.tf
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.project_id
  region  = var.region
}
  • modules/setup/variable.tf

このファイルでは Terraform で使用する変数を定義しています。

modules/setup/variable.tf
variable "project_id" {}
variable "region" {}
variable "environment" {}

🛠terraform の各種コマンド

ここからは terraform コマンドを使って実際にリソースの構築・削除をしてみましょう。
※ terraform コマンドを実行する前に gcloud auth logingcloud auth default-application login が必要になるため、先述の情報を確認し実行しましょう。

terraform init

  • terraform init

このコマンドは Terraform の初期化を行います。
Terraform 設定ファイルがあるディレクトリ( environments/dev/setup/ )に移動し、そのディレクトリでこのコマンドを実行します。
初期化には以下のような操作が含まれます:

  • プロバイダプラグインのダウンロードとインストール
  • バックエンドの初期化
  • モジュールのダウンロード
  • 依存関係ロックファイルの生成

terraform init コマンドを打つと下記のようになります。

$ cd environments/dev/setup # main.tf があるディレクトリに移動
$ terraform init

**Initializing the backend...

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.**

この実行を行うと local に .terraform/ フォルダと .terraform.lock.hcl が生成されます。

  • .terraform/

このディレクトリには、Terraformの初期化プロセス中にダウンロードされたプロバイダプラグインとモジュールが格納されます。

  • .terraform.lock.hcl

このファイルは、プロバイダのバージョンをロックするためのものです。terraform init を実行すると、このファイルが生成され、使用するプロバイダとそのバージョン、ハッシュ値などの詳細が記録されます。

これで初期化は完了です。

terraform plan

  • terraform plan

このコマンドは Terraform が行う予定の操作を表示します。
現在の状態と設定ファイルに基づいて、作成、更新、または削除されるリソースを示します。
このコマンドは実際には何も変更を行いませんが、変更の影響を確認するための重要なステップです。

terraform plan コマンドを打つと下記のようになります。

Terraform used the selected providers to generate the following execution plan. Resource actions
are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.master.google_compute_instance.sample_instance will be created
  + resource "google_compute_instance" "sample_instance" {
      ...
    }

Plan: 1 to add, 0 to change, 0 to destroy.

────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take
exactly these actions if you run "terraform apply" now.

実施に google_compute_instance リソースが作成される計画になることが分かります。

これで計画の確認は完了です。

terraform apply

  • terraform apply

このコマンドは Terraform が計画した変更を実際に適用します。
具体的には、 terraform plan で表示された変更をユーザーが承認した後、それらの変更が GoogleCloud に適用されます。

terraform apply コマンドを打つと下記のようになります。


Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.master.google_compute_instance.sample_instance will be created
  + resource "google_compute_instance" "sample_instance" {
      ... 略 ...
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 

変更が意図通りであった場合は yes と打ちます。

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.master.google_compute_instance.sample_instance: Creating...
module.master.google_compute_instance.sample_instance: Still creating... [10s elapsed]
module.master.google_compute_instance.sample_instance: Creation complete after 15s [id=projects/[PROJECT_ID]/zones/asia-northeast1-a/instances/sample-instance]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

これで意図通りの GoogleCloud リソースが作成されました。
また、 terraform apply --auto-approve というフラグを用いることで、変更の承認を待たずに実行することも可能です。

この実行を行うと local に terraform.tfstate が生成されます。

  • terraform.tfstate

このファイルは、Terraform がリソースの現在の状態を追跡するために使用する重要なファイルです。
このファイルは、 terraform apply コマンドが実行されるたびに更新され、これによって Terraform は次回の terraform planterraform apply の実行時に何を変更すべきかを判断することができます。
つまり、 terraform.tfstate ファイルは、 Terraform が実際のリソースの状態と設定ファイルの状態とを同期させるための情報となります。

※ また、 terraform.tfstate ファイルは機密情報を含む可能性があるため、適切なセキュリティ対策を講じることが重要です。
例えば、リモートバックエンドを使用して状態ファイルを保管し、適切なアクセス制御を設定することが一般的です。
これにより、複数の人間やシステムが共有でき、また同時に行われる操作から状態データを保護することができます。
これは後ほどのセクションで行います。

これでリソースの作成は完了です。

terraform destroy

  • terraform destroy

このコマンドは Terraform が管理しているリソースをすべて削除します。
Terraform 設定ファイルで定義されているリソースがすべて削除されます。
今回課金を意図していない方は必ずこの操作まで行いましょう。

terraform destroy コマンドを打つと下記のようになります。

module.master.google_compute_instance.sample_instance: Refreshing state... [id=projects/[PROJECT_ID]/zones/asia-northeast1-a/instances/sample-instance]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # module.master.google_compute_instance.sample_instance will be destroyed
  - resource "google_compute_instance" "sample_instance" {
      ... 略 ...
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: 

変更が意図通りであった場合は yes と打ちます。

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

module.master.google_compute_instance.sample_instance: Destroying... [id=projects/[PROJECT_ID]/zones/asia-northeast1-a/instances/sample-instance]
... 略 ...
module.master.google_compute_instance.sample_instance: Destruction complete after 2m24s

Destroy complete! Resources: 1 destroyed.

これで意図した GoogleCloud リソースが削除されました。
また、こちらも terraform destroy --auto-approve というフラグを用いることで、変更の承認を待たずに実行することも可能です。

これでリソースの削除は完了です。

🪣 terraform.tfstate を CloudStrageに保存する

ここまでで Terraform のリソースの作成・削除を行うことができました。
しかし、上記のままでは local に terraform.tfstate が存在してしまうため、複数人での開発には向いていない状態になってしまいます。
この状態を回避するために GoogleCloud では GoogleCloudStorage のバケットに保存することが推奨されています。

デフォルトでは、Terraform はローカルの terraform.tfstate という名前のファイルに状態を保存します。複数のユーザーが Terraform を同時に実行していて、各マシンが現在のインフラストラクチャを独自に認識している場合は、このデフォルト構成が原因でチームでの Terraform の使用が難しくなる場合があります。
https://cloud.google.com/docs/terraform/resource-management/store-state?hl=ja

これにより上記のようなケースを回避できます。

CloudStorage の構築

terraform.tfstate ファイルを管理するための CloudStorage リソースを作成して行きます。

Terraformリソース

関連する Terraform リソースは以下です。

Creates a new bucket in Google cloud storage service (GCS). Once a bucket has been created, its location can't be changed.
For more information see the official documentation and API.

🗂 フォルダ構成

フォルダ構成は以下の様に追加しています。
今回は commons という環境で共通のリソースを置くためのフォルダを用意し、その中に backend_setup フォルダを用意しました。ここに tfstate を管理するための CloudStorage の resource を定義します。

.
├── README.md
├── commons # 🆕 環境で共通のリソースを置く想定
│   └── backend_setup # 🆕 Cloud Storageを構成する
│       ├── main.tf
│       ├── provider.tf
│       └── variable.tf
├── environments # 各環境を想定(開発、ステージング、本番など)
└── modules # 再利用可能なTerraformコード(モジュール)を格納するディレクトリ

💻 実際のコード

実装した Terraform のコードは以下です。

  • commons/backend_setup/main.tf

このファイルは、GoogleCloudStorage(GCS)バケットを作成する Terraform 設定ファイルです。
関連する Terraform リソースで挙げたリソースはここで呼び出します。

commons/backend_setup/main.tf
resource "google_storage_bucket" "terraform_state" {
  name     = "sample-terraform-state-bucket" // your gcs bucket name
  location = "ASIA"
  versioning {
    enabled = true
  }
}
  • commons/backend_setup/provider.tf

このファイルは Terraform のプロバイダ設定を定義しています。
GoogleCloudPlatform をプロバイダとして使用し、5.0 以上のバージョンを要求するように記載しています。

commons/backend_setup/provider.tf
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.project_id
  region  = var.region
}

  • commons/backend_setup/variable.tf

このファイルでは Terraform で使用する変数を定義しています。
[PROJECT_ID] には先に確認したご自身の「プロジェクトID」を格納してください。

commons/backend_setup/variable.tf
variable "project_id" {
  default = "[PROJECT_ID]"
}
variable "region" {
  default = "asia-northeast1"
}

commons/backent_setup に移動し、上記の状態で tarraform init → terraform apply までを行えば、GoogleCloudStorage の bucket が作成されます。

backend_setup で作成された tfstate を bucket 管理にする

terraform apply が終わった段階ではまだ local に terraform.tfstate が存在し、その中身に状態が記載されているはずです。
ここからはその terraform.tfstate を CloudStorage に移動し、local の terraform.tfstate を削除します。

🗂 フォルダ構成

フォルダ構成は以下の様にしています。
新しく backend.tf を追加しています。

.
├── README.md
├── commons # 環境で共通のリソースを置く想定
│   └── backend_setup # Cloud Storageを構成する
│       ├── backend.tf # 🆕 tfstate を Cloud Storage で管理する
│       ├── main.tf
│       ├── provider.tf
│       └── variable.tf
├── environments # 各環境を想定(開発、ステージング、本番など)
└── modules # 再利用可能なTerraformコード(モジュール)を格納するディレクトリ

💻 実際のコード

実装した Terraform のコードは以下です。

  • commons/backend_setup/backend.tf

このファイルは、Terraform のバックエンド設定を指定するファイルです。
この設定により、Terraform は先に作成した GoogleCloudStorage バケットに terraform.tfstate を保存し、その名前は commons/backend_setup というプレフィックスで始まることになります。
これにより、複数の環境やプロジェクトの状態を同じバケット内で効果的に管理することができます。

commons/backend_setup/backend.tf
terraform {
  backend "gcs" {
    bucket = "sample-terraform-state-bucket" // your gcs bucket name
    prefix = "commons/backend_setup"         // your gcs prefix
  }
}

この状態で terraform apply をすれば、 GoogleCloudStorage に terraform.tfstate が移動されます。

setup module で作成したリソースの状態の移行

terraform.tfstate を GoogleCloudStorage で管理する準備が完了したので、先ほど作成した setup module のリソースの tfstate も GooleCloudStorafe に移行しましょう。
そのために backend.tf ファイルの追加を行います。

🗂 フォルダ構成

フォルダ構成は以下の様にしています。
新しく backend.tf を追加しています。

.
├── README.md
├── commons # 環境で共通のリソースを置く想定
├── environments
│   └── dev
│       └── setup
│           ├── backend.tf # 🆕 tfstate を Cloud Storage で管理する
│           ├── main.tf
│           └── variable.tf
├── environments # 各環境を想定(開発、ステージング、本番など)
└── modules # 再利用可能なTerraformコード(モジュール)を格納するディレクトリ

💻 実際のコード

実装した Terraform のコードは以下です。

  • commons/backend_setup/backend.tf

このファイルは、Terraform のバックエンド設定を指定するファイルです。
この設定により、先ほどと同様に Terraform は GoogleCloudStorage バケットに terraform.tfstate を保存し、その名前は dev/setup というプレフィックスで始まることになります。

environments/dev/setup/backend.tf
terraform {
  backend "gcs" {
    bucket = "sample-terraform-state-bucket" // your gcs bucket name
    prefix = "dev/setup"                     // your gcs prefix
  }
}

environments/dev/setup に移動し、上記の状態で terraform apply をすれば、 GoogleCloudStorage に terraform.tfstate が移動されます。

🎍 最後に

お疲れ様でした!
少し長かったですが、これで GoogleCloud のリソースを Terraform で構築していく準備ができました!
説明が不十分な点、誤字脱字などございましたら、ご指摘いただければと思います。

今後は上記の構成を元に、様々な GoogleCloud のリソースを構築していければと思います!
2024年はシリーズ化を目指します🔥
それでは良いお年を!

Discussion