インフラ構成管理のコード化が可能な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 "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 "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
【参考】 リソース作成時のエラー
@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" {