前提
- 機械学習を使った情報推薦をGKE上で行なっている
- えいやっで作ったので、GKEはgcloudコマンドで作った
- 当時どんなコマンドを打ったかはもう覚えてない...
- 別の話題として、GKE上でのサービスアカウントの取り扱いをちゃんとしたい(Workload Identityを導入したい)なと思っているのだが、これをやるには試行錯誤が割と必要
- GKEの設定もTerraformでIaCしたい
- 前職でもTerraformは触っていたものの、スーパーSREであるid:heleeenさんがあれこれ準備してくれていた下地が大きかった
- ゼロからだけど、頑張っていきましょう
というわけで、モジュール分割とかあれこれイケてない部分があるけど、石を投げないでください...。
backendを指定する
Terraformは現在どこまで適用したか、手元のコードと差分はどこにあるかを計算するためにstateファイル(tfstate)というものをbackendに持っている。stateは手元に持っておいてもよいが、PC変えたりrmでミスって消したりすると悲しいので、クラウドに置いておくとよい。S3やDynamoDBも指定できるようだが、今はGCPでリソースをあれこれ作っているので、GCSをbackendに指定する。
このGCSは画面から手でポチポチ作りました。
この辺の情報を元に、main.tfに書いていきます。
provider "google" { credentials = file("~/.config/gcloud/terraform-my-project@my-project.json") project = "my-project" region = "us-west1" zone = "us-west1-a" } terraform { backend "gcs" { bucket = "my-project-terrarom-state-file" } }
Terraformを実行する
Terraformを実行する際にはGCPのAPIをあれこれ叩くことになるので、サービスアカウントを発行します。自分でやるなら何でもいいけど、チームでやるんだったら個人のアカウントじゃないほうがいいはず。
% gcloud iam service-accounts create terraform-my-project \ display-name "Account for Terraform" % gcloud projects add-iam-policy-binding my-project \ --member serviceAccount:terraform-my-project@my-project.iam.gserviceaccount.com \ --role roles/owner
Makefileで便利コマンドを用意する
Terraformのコマンドを毎回覚えきれないので、Makefileでよく叩くコマンドを用意しておきます。production環境やstaging環境など、いくつか環境がある場合には-var-file=
で環境毎に切り替えれるようにしておくと便利だけど、お財布の関係で趣味プロジェクトには一つしか環境はないです。
REMOTE_BUCKET_NAME := my-project-terrarom-state-file create_credentials: gcloud iam service-accounts keys create ~/.config/gcloud/terraform-my-project@my-project.json --iam-account=terraform-my-project@my-project.iam.gserviceaccount.com init: terraform fmt --recursive terraform init -backend-config="bucket=$(REMOTE_BUCKET_NAME)" -reconfigure plan: init terraform plan apply: init terraform apply destroy: terraform destroy
make plan
で「意図してないリソースの削除とかはなさそうね、よし!」と確認して、make apply
。CFnと同じ感じですね。updateだと思っていたら、delete & createとかが時々あるので注意する。
GKEの設定をTerraformで行なう
実際にやりたかったのはここ。とはいえ、概ねここと同じことを書いてあげればよい。
https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_cluster
node_count = 1
かつpreemptible = true
なのは「いつクラスタが落ちても許します」ということなので、あまりよろしくはない。安く済ませようと思うと、preemptibleな f1-microのマシンを3台並べるのがよさそうだが、機械学習のタスク的にメモリはある程度欲しいので、この構成にしている(バッチなので、こけてもまあ即死はしない)。
esource "google_container_cluster" "my-project" { name = "my-project" remove_default_node_pool = true initial_node_count = 1 } resource "google_container_node_pool" "primary_preemptible_nodes" { name = "my-node-pool" cluster = google_container_cluster.my-project.name node_count = 1 node_config { oauth_scopes = [ "https://www.googleapis.com/auth/devstorage.read_only", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring", "https://www.googleapis.com/auth/service.management.readonly", "https://www.googleapis.com/auth/servicecontrol", "https://www.googleapis.com/auth/trace.append" ] machine_type = "n1-standard-1" preemptible = true service_account = "default" } timeouts { create = "30m" update = "20m" } }
クラスタに紐付いているservice_account = "default"
というのが非常に厄介(?)で、かなり強い権限を持っている。GKEのpodを通じてあれこれできすぎてしまってよくない。この辺をWorkload Identityを使ってもっと安全にしていきましょう、というのを次のエントリで書きます。