GCP リソースを Terraform で作成する

Posted on 2021-04-19 in zakki

GCP のリソースを Terraform で作成するために、サービスアカウントの作成やその他もろもろを行ったのでメモ。なお、GCP プロジェクトは既存のものを使用したので新規で作成をしていません。

サービスアカウントの作成

Terraform 用のサービスアカウントを GCP コンソールから作成する。

[IAM と管理 ] - [ サービスアカウント ] から [ サービスアカウントを作成 ] を選択して進める。

サービスアカウント名 : terraform-exec
サービスアカウント ID: terraform-exec@(project-id).iam.gserviceaccount.com
サービスアカウントの説明 : 任意

サービスアカウントにプロジェクトのアクセスを許可する。

AWS の IAM ポリシーと同等?

今回は Terraform の remote state に GCS を用いたいのでストレージ管理者を付与。ストレージ管理とストレージオブジェクト管理は何が違うのか良く分かっていない。

ストレージ管理者
Storage オブジェクト管理者

ユーザーにこのサービス アカウントへのアクセスを許可する。

今回はスルー。

鍵を作成

[IAM と管理 ] - [ サービスアカウント ] から先ほど作成したサービスアカウントの [ 操作 ] から [ 鍵を管理 ] を選択する。アカウントを直接クリックして [ キー ] に移動してもよい。

[ 鍵の追加 ] - [ 新しい鍵を作成 ] を選択する。JSONを選択して作成、ダウンロードしておく。

Cloud SDK インストール

Cloud SDKは Google Cloud にホストされているリソースやアプリケーションの管理に使用できる一連のツール ( 公式の記載ママ )。AWS でいう AWS CLI と同様の立ち位置のものなのか。

今回は Cloud SDK を使用して GCS のバケット作成のみを実施したため、必ずしも必要ではなさそうですがせっかく導入したので記載。基本的にこちらのナビゲートを見ながら実施。

$ curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-335.0.0-linux-x86_64.tar.gz

$ ./google-cloud-sdk/install.sh
Welcome to the Google Cloud SDK!

To help improve the quality of this product, we collect anonymized usage data
and anonymized stacktraces when crashes are encountered; additional information
is available at <https://cloud.google.com/sdk/usage-statistics>. This data is
handled in accordance with our privacy policy
<https://cloud.google.com/terms/cloud-privacy-notice>. You may choose to opt in this
collection now (by choosing 'Y' at the below prompt), or at any time in the
future by running the following command:

    gcloud config set disable_usage_reporting false

Do you want to help improve the Google Cloud SDK (y/N)?  N

Your current Cloud SDK version is: 335.0.0
The latest available version is: 336.0.0

To install or remove components at your current SDK version [335.0.0], run:
  $ gcloud components install COMPONENT_ID
  $ gcloud components remove COMPONENT_ID

To update your SDK installation to the latest version [336.0.0], run:
  $ gcloud components update

Do you want to continue (Y/n)?  Y

The Google Cloud SDK installer will now prompt you to update an rc
file to bring the Google Cloud CLIs into your environment.

Enter a path to an rc file to update, or leave blank to use
[/home/xxxxxxxxxx/.config/fish/config.fish]:
Backing up [/home/xxxxxxxxxx/.config/fish/config.fish] to [/home/xxxxxxxxxx/.config/fish/config.fish.backup].
[/home/xxxxxxxxxx/.config/fish/config.fish] has been updated.

==> Start a new shell for the changes to take effect.


For more information on how to get started, please visit:
  https://cloud.google.com/sdk/docs/quickstarts

導入した環境の shell は fish ですが、config.fishに以下が追加されていた。

# The next line updates PATH for the Google Cloud SDK.
if [ -f '/home/xxxxxxxxxx/google-cloud-sdk/path.fish.inc' ]; . '/home/xxxxxxxxxx/google-cloud-sdk/path.fish.inc'; end

gcloud init して gcloud の初期化を実施する。ブラウザで Google にログインして認証を進める。

$ ./google-cloud-sdk/bin/gcloud init
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)?  Y

Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=( 略 )

利用するプロジェクトを選択する。

Pick cloud project to use:
 [1] xxxxxx-xxxxx-project
 [2] Create a new project
Please enter numeric choice or text value (must exactly match list
item):  1

Your current project has been set to: [xxxxxx-xxxxx-project].

Not setting default zone/region (this feature makes it easier to use
[gcloud compute] by setting an appropriate default value for the
--zone and --region flag).
See https://cloud.google.com/compute/docs/gcloud-compute section on how to set
default compute region and zone manually. If you would like [gcloud init] to be
able to do this for you the next time you run it, make sure the
Compute Engine API is enabled for your project on the
https://console.developers.google.com/apis page.

.botoという名前のファイルを作成したログがある。.boto構成ファイルのリファレンスはこちら

このページでは、gsutil が boto 構成ファイルを使用する方法と、このファイルを使用して共同作業を行う例について説明します。boto 構成ファイルは、Amazon S3 SDK for Python である boto でも使用されます。

なるほど、知らなんだ。

Created a default .boto configuration file at [/home/xxxxxxxxxx/.boto]. See this file and
[https://cloud.google.com/storage/docs/gsutil/commands/config] for more
information about configuring Google Cloud Storage.
Your Google Cloud SDK is configured and ready to use!

* Commands that require authentication will use paraselene92@gmail.com by default
* Commands will reference project `xxxxxx-xxxxx-project` by default
Run `gcloud help config` to learn how to change individual settings

This gcloud configuration is called [default]. You can create additional configurations if you work with multiple accounts and/or projects.
Run `gcloud topic configurations` to learn more.

Some things to try next:

* Run `gcloud --help` to see the Cloud Platform services you can interact with. And run `gcloud help COMMAND` to get help on any gcloud command.
* Run `gcloud topic --help` to learn about advanced features of the SDK like arg files and output formatting

サービスアカウントの認証

サービスアカウントを使用したアクセスを可能にするために認証を行う。サービスアカウントを新規作成したときに、払い出した鍵ファイルを使用する。

$ gcloud auth activate-service-account terraform-exec@xxxxxx-xxxxx-project.iam.gserviceaccount.com --key-file=./xxxxxx-xxxxx-project-5d944688f2cc.json

Activated service account credentials for: [terraform-exec@xxxxxx-xxxxx-project.iam.gserviceaccount.com]

認証状況を確認する。

$ gcloud auth list
                       Credentialed Accounts
ACTIVE  ACCOUNT
        paraselene92@gmail.com
*       terraform-exec@xxxxxx-xxxxx-project.iam.gserviceaccount.com

GCS バケットの作成

Terraform の remote state を格納するための GCS バケットを gcloud(gsutil) を使用して作成する。

$ gsutil mb -c multi_regional -l Asia gs://terraform/
Creating gs://terraform/...
AccessDeniedException: 403 The project to be billed is associated with an absent billing account.

403が返ってきたので?となったが、原因を当たったところこちらが原因のようだった。GCP コンソールの上部バーからアカウントの有料化を行った。

$ gsutil mb -c multi_regional -l Asia gs://terraform/
Creating gs://terraform/...
ServiceException: 409 A Cloud Storage bucket named 'terraform' already exists. Try another name. Bucket names must be globally unique across all Google Cloud projects, including those outside of your organization.

409が返却されて、ん?と思ったけど S3 と同様にバケット名がユニークではないといけないことを思い出しバケット名を変更して再実施したところ成功した。

$ gsutil mb -c multi_regional -l Asia gs://terraform-exersize/
Creating gs://terraform-exersize/...

コンソールで確認するとバケットが作成されていることを確認できた。

Terraform でのリソース作成

Terraform でリソース作成するために必要な tf ファイルを作成する。

  • terraform.tf
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 3.64.0"
    }
  }
  required_version = "~> 0.14.0"
}
  • provider.tf

projectはコンソールに表示されている名前ではなくてIDを指定する。

provider "google" {
  credentials = file("./xxxxxx-xxxxx-project-5d944688f2cc.json")
  project = "xxxxxx-xxxxx-project"
  region  = "asia-northeast-1"
}
  • backend.tf

Terraform v0.15.0 ではpathは廃止されたため、基本的にはprefixを使用するべきだが、後の検証で使用するためここではあえてpathを使用している。

terraform {
  backend "gcs" {
    bucket      = "terraform-exersize"
    path        = "terraform/terraform.tfstate"
    credentials = "./xxxxxx-xxxxx-project-5d944688f2cc.json"
  }
}

この段階で一度initしてみる。

$ terraform init

Initializing the backend...

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

Initializing provider plugins...
- Finding hashicorp/google versions matching "~> 3.64.0"...
- Installing hashicorp/google v3.64.0...
- Installed hashicorp/google v3.64.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

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.

$ terraform plan

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
  • cloud_storage.tf

リソースの 1 つとして GCS バケットを 1 つ作成する tf を用意した。

resource "google_storage_bucket" "example" {
  name          = "terraform-example-2021"
  location      = "ASIA-NORTHEAST1"
  force_destroy = true
}

applyしてみる。

$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_storage_bucket.example will be created
  + resource "google_storage_bucket" "example" {
      + bucket_policy_only          = (known after apply)
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "ASIA-NORTHEAST1"
      + name                        = "terraform-example-2021"
      + project                     = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + uniform_bucket_level_access = (known after apply)
      + url                         = (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_storage_bucket.example: Creating...
google_storage_bucket.example: Creation complete after 1s [id=terraform-example-2021]

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

GCS バケットのリソースが作成できた。

$ gsutil ls
gs://terraform-example-2021/
gs://terraform-exersize/

GCP Terraform