🏃‍♀️

初めてのGCPをterraformで~ちょっとしたApplyまで~

2022/07/14に公開

すっかり AWS に毒されているわたくしですが、GCP 触る機会があったので
terraform 管理の導入を書いておきます。

1. サービスアカウントを作成してキーを発行する

まず対象のプロジェクトを選択してサービスアカウントのページに行きます。

01

「サービスアカウントを作成」をクリックして適当な名前をいれてサービスアカウントを作成します。

02

すると、こんな感じでアカウントができるので、アカウント名をクリックします。
※すでに存在しないサービスアカウント名なのでそのまま載せるわ
03

作成したサービスアカウントを開いて、上のタブからキーを選びます。
04

鍵が空なので、新規作成を選びます。
すると次にキータイプを選ばされます。私はおとなしく推奨の JSON を選びます。作成します。

05
06

クレデンシャルが記載された JSON ファイルが落っこちてくるので、確保しておきます。

2. gcloud コマンドのインストール

いきなり terraform から書き始めてやってみたらうまくいかず、
gcloud でプロジェクト選択したら解決したので必要なんだなと解釈してここで入れます。

インストールは公式を見てください。

$ gcloud --version
Google Cloud SDK 392.0.0
alpha 2022.06.24
beta 2022.06.24
bq 2.0.75
bundled-python3-unix 3.9.12
core 2022.06.24
gsutil 5.10

インストールできたら設定します。
gcloud init --console-onlyとコマンドを打ちます。

「You must log in to continue. Would you like to log in (Y/n)?」ときかれるのでそのまま Enter をカチッとやります。
するとながーい URL が発行されるので、ブラウザに貼り付けて遷移します。
このとき「Enter verification code: 」を待ち受けのままにします。

$ gcloud init --console-only
WARNING: The `--console-only/--no-launch-browser` are deprecated and will be removed in future updates. Use `--no-browser` as a replacement.
Welcome! This command will take you through the configuration of gcloud.

Your current configuration has been set to: [default]

You can skip diagnostics next time by using the following flag:
  gcloud init --skip-diagnostics

Network diagnostic detects and fixes local network connection issues.
Checking network connection...done.
Reachability Check passed.
Network diagnostic passed (1/1 checks passed).

You must log in to continue. Would you like to log in (Y/n)?

Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=hogehogehoge~~~~~~

Enter verification code:

07
08

認証したい Google アカウントを選びます。なんやかんや聞かれるので許可します。

09
すると、「verification code」をコピーできるページにうつるので、コピーしてターミナルにもどって貼り付けて Enter。

先ほど認証した Google アカウントでログインできたことがわかる出力がされて、
プロジェクトを選べるようになります。
どれをデフォルトプロジェクトにするのか番号で答えます。

上の「verification code」の入力とデフォルトプロジェクトの設定をしてないと、
サービスアカウントのファイルを置いててもエラーに成みたいです。

You are logged in as: [exsample@gmail.com].

Pick cloud project to use:
 [1] my-terraform-prototype-for-gcp
 [2] hogehoge-12345
 [3] Enter a project ID
 [4] Create a new project
Please enter numeric choice or text value (must exactly match list item):  1

Your current project has been set to: [my-terraform-prototype-for-gcp].

こんな感じで設定できれば OK です。
他にも色々出力されるので読んどいてください。

3. terraform

これでやっと terraform です。
が、tfstate の保存先のバケットをあらかじめ GCS に作っておきます。

terraform はこんな感じにしときます。
今回は terraform で VPC をそれっぽく作ったらゴールです。

$ tree -a
.
├── .credential.json
├── .gitignore
├── .tflint.hcl
├── main.tf
├── variables.tf
├── tfstate.tf
├── resouce.tf
└── terraform.tfvars

認証キーを変数にセット

GOOGLE_APPLICATION_CREDENTIALSにキーをセットしないと怒られたのでします。
パスは適当に読み替えてください。
適宜.bash_profile とかに書くとイイと思います。

export GOOGLE_APPLICATION_CREDENTIALS=${PATH}/.credential.json

terraform の各種ファイル準備

.credential.json

1. サービスアカウントを作成してキーを発行するでダウンロードした JSON の認証ファイルをどっかにおきます。
必ず.gitignore に書いておきましょう。
あと名前は私が勝手につけたので好きな名前にするといいです。

.gitignore

terraform で Git 管理しないやつを書いておきます。私はいつもベースは gitignore.io まかせです。
あと ↑ のクレデンシャルも書いておきましょう。

.tflint.hcl

plugin "google" {
    enabled = true
    version = "0.18.0"
    source  = "github.com/terraform-linters/tflint-ruleset-google"
}

main.tf

# ----------------------------------
# Terraform configuration
# ----------------------------------

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 3.90.1"
    }
  }

  required_version = ">= 1.0.11"
}


provider "google" {
  region      = "asia-northeast1"
  credentials = file(".credential.json")
  project     = "my-terraform-prototype-for-gcp"
}

variables.tf

# ----------------------------------
# variables
# ----------------------------------

variable "project" {
  type = string
}

variable "environment" {
  type = string
}

tfstate.tf

# ----------------------------------
# tfstate
# ----------------------------------

terraform {
  backend "gcs" {
    bucket = "my-terraform-bucket"
  }
}

resouce.tf

# ----------------------------------
# VPC
# ----------------------------------

resource "google_compute_network" "vpc_network" {
  name = "${var.environment}-${var.project}"
}

terraform.tfvars

# ----------------------------------
# general
# ----------------------------------

project        = "my-terraform-prototype-for-GCP"
environment    = "dev"

terraform コマンドの実行

あとはいつもどおりやるだけです。

$ terraform init

Initializing the backend...

Successfully configured the backend "gcs"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Reusing previous version of hashicorp/google from the dependency lock file
- Installing hashicorp/google v3.90.1...
- Installed hashicorp/google v3.90.1 (signed by HashiCorp)

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.

$ tflint --init
Installing `google` plugin...
Installed `google` (source: github.com/terraform-linters/tflint-ruleset-google, version: 0.18.0)

$ terraform validate
Success! The configuration is valid.

$ tflint


$ 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:

  # google_compute_network.vpc_network will be created
  + resource "google_compute_network" "vpc_network" {
      + auto_create_subnetworks         = true
      + delete_default_routes_on_create = false
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + mtu                             = (known after apply)
      + name                            = "dev-my-terraform-prototype-for-gcp"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

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.


$ 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:

  # google_compute_network.vpc_network will be created
  + resource "google_compute_network" "vpc_network" {
      + auto_create_subnetworks         = true
      + delete_default_routes_on_create = false
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + mtu                             = (known after apply)
      + name                            = "dev-my-terraform-prototype-for-gcp"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

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

google_compute_network.vpc_network: Creating...
google_compute_network.vpc_network: Still creating... [10s elapsed]
google_compute_network.vpc_network: Still creating... [20s elapsed]
google_compute_network.vpc_network: Still creating... [30s elapsed]
google_compute_network.vpc_network: Still creating... [40s elapsed]
google_compute_network.vpc_network: Creation complete after 46s [id=projects/my-terraform-prototype-for-gcp/global/networks/dev-my-terraform-prototype-for-gcp]

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

わーい

4. 振り返り・ハマったとこ

あらかじめ入っていた tflint で GCP のルール使ったら

Error: Incompatible API version with plugin "google". Plugin version: 10, TFLint versions: [9]

こちらは tflint-ruleset-google にある通り、TFLint のバージョンは v0.35+なんですけど
以前 brew で入れたバージョンが v0.33 でした。
brew でうまいことあがらんかなと思ったのですがうまくいかなかったので、brew の方をけして
公式どおりに入れなおしました。

その後念のため tflint 関係のディレクトリを消して tflinet --init しなおしたら解決 🙌!

Discussion