Help us understand the problem. What is going on with this article?

Terraform+GCPを体験する

インフラ構成管理のコード化が可能なTerraformを使って、google cloudのインフラ設定のコード化を体験してみます。

以下のハンズオン記事を実際にやりつつ、記事の内容を流用させて頂きつつ、自分の理解した内容を追記していきます。
https://qiita.com/donkomura/items/6289bb31fecfce2cda79

環境

macOS High Sierra
Google Cloud SDK v265.0.0
terraform_0.12.9

GCPプロジェクト APIの有効化

cloud pub/sub
cloud functions
cloud scheduler
app engine

以下よりアクセスして、右上の「コンソール」リンクへ。検索バーで上記サービスを検索して有効化していく。
https://cloud.google.com/

cloud pub/subやapp engineなどは、認証情報の設定が必要で、「サービスアカウント」で
設定するのが推奨。

ダウンロード、パス設定

% mkdir myterraform; cd myterraform
% curl -sL https://releases.hashicorp.com/terraform/0.12.9/terraform_0.12.9_darwin_amd64.zip
% unzip terraform_0.12.9_darwin_amd64.zip
Archive:  terraform.zip
  inflating: terraform

.zprofile.zshrcなどにパス追加、souceコマンドで反映

export PATH=$PATH:~/myterraform/  

コマンド確認

% terraform --version                                                                                        [21:23:08]
Terraform v0.12.9

作成するTerraformの構成

Cloud Scheduler → Coud Pub/Sub → Cloud functions → Slack

Schedulerでジョブ登録、Pub/Subでメッセージの作成・送信を行う、
その送信内容や送信先をCloud functionsで設定する。
ジョブ実行結果をSlackに通知します。

プロバイダー定義

マネージドサービスのAWSやGCPの認証情報や各種設定情報を定義するための
プロバイダーを作成します。

provider.tf
provider "google" {
  credentials = "${file("<your-credential-file-path>")}"
  project     = "${lookup(var.project_name, "${terraform.workspace}")}"
  region      = "asia-northeast1"
}

Terraformのシンタックス

TerraforではHCL(HashiCorp Configuration Language)のシンタックスが採用されています。

リソース設定方法

リソースは、Terraformで管理する対象の基本単位。操作や設定方法を記述します。

resource <リソース種類> <リソース名> {
  <設定項目1> = <設定値1>
  <設定項目2> = <設定値2>
}
項目 説明
リソース種類 Terraform内でのGCPやAWSなどで定義されているリソースの型。例) google_compute_instance
リソース名 Terraformモジュール内でのリソース参照に使用される。
設定項目 リソース種類内で使える設定項目の指定。リソース型によって決まります。
設定値 設定項目に設定する値。他のリソースの値を参照する際は<リソースの種類>.<リソースの名前>.<設定項目>と指定します。

※リソース種類、リソース名はTerraformモジュール内で一意である必要があります。

google_cloud_scheduler_jobにおける記述例は以下。
リソースブロックで、リソース型がgoogle_cloud_scheduler_jobの設定が行われています。

resource "google_cloud_scheduler_job" "slack-notify-scheduler" {
  name        = "slack-notify-daily"
  project     = "${lookup(var.project_name, "${terraform.workspace}")}"
  ・・・
}

プロジェクト名の設定に、lookup関数が使われていて、
variableブロックで以下のように定義しておくと、project_nameを外だしできます。

var.<変数名>で参照可能。terraform.workspaceは「production, development, staging」などの
環境名称が入ります。これで設定値を切り替えたりします。

variable "project_name" {
  default = {
    tf-sample = "<your-project>"
  }
}

リソース設定を作成

参考サイトの設定の、リージョン、ロケーションだけ変更して作成しました。

main.tf、variable.tfを以下のサイトから拝借。
https://qiita.com/donkomura/items/6289bb31fecfce2cda79#%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E4%BD%9C%E6%88%90

Cloud Schedulerに登録するジョブ

定時実行されるソースは、参考にさせて頂いたページでは、Goジョブを実行するとの設定になっていました。
※runtimeの設定の箇所

resource "google_cloudfunctions_function" "slack_notification" {
  name        = "SlackNotification"
  project     = "${lookup(var.project_name, "${terraform.workspace}")}"
  region      = "asia-northeast1"
  runtime     = "go111"

src以下にhello.go作っておいてみましたが、
動作に必要なモジュールが不足していて、ビルドエラーとなっちゃいました。

参考元ページで共有していただいたソースのsrc以下をそのまま配置しました。
go.modに必要モジュールがあったのかも。Goも触りぐらいは理解しておかないとなぁ。

% ll                                                                                                    
 -rw-r--r--  1 user123  staff    55 Oct 25 23:42 go.mod
 -rw-r--r--  1 user123  staff  1979 Oct 25 23:43 slack-notify.go

Web hookの設定

Slackがなければ、以下よりDLして、Web hookアプリを設定から追加します。

Slackのインストール先
https://slack.com/intl/ja-jp/help/articles/207677868

Web hookのURLをvariable.tfに追記。

認可、認証ファイル

GCPのcredentialファイルは、以下の手順で作成します。

  • GCPにリソース作成可能なサービスアカウントを「IAMと管理」→「サービスアカウント」で作成
  • 「IAM」でサービスアカウントに適切な「役割」を設定。簡単なのオーナーを設定ですが。可能であれば、今回操作するリソースに関係する権限のみを付与する
  • 「サービスアカウント」で作成アカウントの操作から「鍵を作成」でjsonを生成
  • main.tfが配置されている直下にjsonファイルを配置。※git管理の場合は.gitignoreに追記
  • variable.tfにjsonファイル名を追記
variable.tf
variable "credential" {
  default = {
    data = "xxx.json"
  }
}

リソースを作成

設定ファイルが書けたら、設定ファイル内で使われているプラグインのインストールをします。

% terraform init                                                                                             [17:00:05]

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "google" (hashicorp/google) 2.16.0...
- Downloading plugin for provider "archive" (hashicorp/archive) 1.3.0...

次に設定ファイルの内容が文法的に正しいかterraform validateコマンドでチェックします。
問題なければ、続けてplanコマンドで、設定内容が意図通りか確認していきます。

% terraform validate                                                                                         [17:04:53]
Success! The configuration is valid.

% terraform plan                                                                                             [21:34:18]
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.archive_file.function_zip: Refreshing state...
・・・
Plan: 5 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

設定が問題なければ、terraform applyでGCP環境に適用していきます。

% terraform apply                                                                                            
data.archive_file.function_zip: Refreshing state...

An execution plan has been generated and is shown below.

・・・

Do you want to perform these actions in workspace "tf-sample"?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

google_pubsub_topic.slack_notify: Creating...
google_storage_bucket.slack_functions_bucket: Creating...
google_storage_bucket.slack_functions_bucket: Creation complete after 3s [id=projectId-scheduler-bucket]
google_storage_bucket_object.functions_zip: Creating...
google_storage_bucket_object.functions_zip: Creation complete after 1s [id=projectId-scheduler-bucket-functions.zip]
google_pubsub_topic.slack_notify: Creation complete after 5s [id=projects/projectId/topics/slack-notify]
google_cloudfunctions_function.slack_notification: Creating...
google_cloud_scheduler_job.slack-notify-scheduler: Creating...
google_cloud_scheduler_job.slack-notify-scheduler: Creation complete after 2s [id=slack-notify-daily]
google_cloudfunctions_function.slack_notification: Still creating... [10s elapsed]
google_cloudfunctions_function.slack_notification: Still creating... [20s elapsed]
google_cloudfunctions_function.slack_notification: Still creating... [30s elapsed]
google_cloudfunctions_function.slack_notification: Still creating... [40s elapsed]
google_cloudfunctions_function.slack_notification: Creation complete after 46s [id=projectId/asia-northeast1/SlackNotification]

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

作成リソースの確認

リソース作成できてました。OK!

% gcloud beta scheduler jobs list                                                                  ID                  LOCATION         SCHEDULE (TZ)           TARGET_TYPE  STATE
slack-notify-daily  asia-northeast1  0 8 * * * (Asia/Tokyo)  Pub/Sub      ENABLED

% gcloud functions list                                                                                      NAME               STATUS  TRIGGER        REGION
SlackNotification  ACTIVE  Event Trigger  asia-northeast1

% gcloud pubsub topics list                                                                                  ---
name: projects/nice-beanbag-257013/topics/slack-notify

ジョブ実行による通知確認

設定した8時にmeshi-botからの通知がきてました!
次はなんのご飯が通知されるんだろう。なんか楽しいw

スクリーンショット 2019-10-26 11.23.22.png

【参考】 リソース作成時のエラー

@donkomuraさんにフォローして頂き、エラー解消できました。感謝です!!
エラーにの原因は以下でした。

  • variableのcredentialにリソース作成が可能な権限が付与されたサービスアカウントのjsonが設定していない
  • variableのproject_nameにプロジェクトの「名前」を設定していた。※「id」を設定することで指定プロジェクトにリソースを作成できました。

リソース作成時のエラー内容は以下

% terraform apply                                                                                            
data.archive_file.function_zip: Refreshing state...

An execution plan has been generated and is shown below.

・・・

Error: googleapi: Error 403: The project to be billed is associated with an absent billing account., accountDisabled

  on main.tf line 16, in resource "google_storage_bucket" "slack_functions_bucket":
  16: resource "google_storage_bucket" "slack_functions_bucket" {

Error: Error creating Topic: googleapi: Error 403: User not authorized to perform this action.

  on main.tf line 31, in resource "google_pubsub_topic" "slack_notify":
  31: resource "google_pubsub_topic" "slack_notify" {
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした