背景: Terraformを使いつつ、データマネジメントの観点から統制を取りたい
GCPでデータ基盤を管理する場合、Terraformはよい選択肢の一つです。データセットやそれに関連するIAMの管理、データセット内のビューの定義をIaCとして管理できます。
- google_bigquery_dataset | Resources | hashicorp/google | Terraform Registry
- google_bigquery_table | Resources | hashicorp/google | Terraform Registry
データマネジメント、特にメタデータ管理の観点でもTerraformは有用です。例えばこういう用途に使えます。
- descriptionにデータセットの生成元や活用場所を書ける
- 簡易データリネージ的な使い方
- データセットをTerraformで管理しているGitHubのURLをdescriptionに書いておくことで、定義を修正したい場合にどこを見ればいいか詳しくない人にもすぐ分かる
- labelに
owner
情報を付与することで問い合わせ先が分かるようにできる - labelに
has_pii
を付与しておくことで、個人情報を含んでいるデータセットか一目で分かるようにできる - ビューの場合は
schema
にカラムのdescriptionを書くことができる
様々なことに対応でき自由度が高いのは魅力ですが、自由度が高すぎることは問題点でもあります。というのも
- 人によってdescriptionの書き方がバラバラ
- 必須の項目なので入力しておいて欲しいが、人によって情報を入れてくれなかったりする
- (メタデータは関係ないけど)
google_bigquery_dataset
のaccess
はauthorativeでterraform管理外の権限を削除してしまう可能性がある- Additiveな振舞いをする
google_bigquery_dataset_access
を推奨したい - ref: google_bigquery_dataset の access 属性と google_bigquery_dataset_access - pokutuna
- Additiveな振舞いをする
などの状況が容易に起こってしまうからです。こうした事項を反映前のコードレビューでチマチマと指摘するでもよいですが、疲れますし漏れもでます。管理する人間側のコストを下げつつ、データマネジメントの観点からは統制も取りたいものです。
今回はTerraformのModuleを使うことで、これを実現できる方法を考えてみました。
Terraform Moduleを定義する
例: データセット
最初にBigQueryのデータセットについて見ていきます。やることは単純でgoogle_bigquery_dataset
のモジュールをwrapするモジュールを作るだけです。modules/dataset/dataset.tf
を以下のように定義します。
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/bigquery_dataset resource "google_bigquery_dataset" "dataset" { project = var.project_id location = var.location dataset_id = var.dataset_id description = <<-EOT ${var.description} このデータセットは ${var.source_code_management_url} で管理されています。 EOT labels = merge(local.default_labels, var.labels) lifecycle { # accessを使った権限管理はauthorative(terraform管理外で付与された権限も削除し得る)のため、事故に繋がりやすい # そのため、データセットへの権限付与はbigquery_dataset_accessを通じて行なう # ref: https://scrapbox.io/pokutuna/google_bigquery_dataset_%E3%81%AE_access_%E5%B1%9E%E6%80%A7%E3%81%A8_google_bigquery_dataset_access # ref: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/bigquery_dataset_access ignore_changes = [access] } } locals { default_labels = { owner = "syou6162" has_pii = var.has_pii managed_by = "terraform" } }
ラベルはキーを自由に設定できるため、何かしらの形で正規化しておきます(キー名が微妙に違うものがたくさん存在すると統制が取れなくなるため)。modules/dataset/variables.tf
の中でvalidation
として表現します。
... variable "labels" { type = map(string) default = {} description = "データセットに付与するラベル" # 無闇にラベルが増えていかないようにラベルのキーに制約を付ける。追加したい場合はここを修正する validation { condition = alltrue( [for k, v in var.labels : contains(["owner", "has_pii"], k) ]) error_message = "All key of labels must be one of `owner` / `has_pii`." } } ...
データマネジメントの観点から入れておいて欲しい以下の観点を強制することで、統制が取りやすくなります。
- 管理しているgithubなどのURLの情報
- データセットのオーナーが分かるようにディフォルトでラベルを差し込んでおく
- PIIに関する情報をラベルで必ず入れておく
使う側はwrapされたモジュールに情報を入れておくだけで、データマネジメントされやすい型に沿った情報を自動的に埋め込めます。
module "moduled_dataset_yoshida" { source = "modules/dataset" project_id = var.project_id location = var.location dataset_id = "syou6162_dataset_module_test" description = "これはテスト用のデータセットです" has_pii = false source_code_management_url = "https://github.com/syou6162/my_project/blob/master/dataset.tf" }
できあがりはこちら。データセットの詳細について知りたかったら誰に聞けばいいか分かりますし、定義を修正したかったらどこを見に行けばいいか一目で分かります。PIIの入ったデータセットを棚卸ししたかったらラベルの情報を元にCloud DataCatalogから一括検索をすることもできます。
今回はBigQueryのデータセットの例を取り上げましたが、ビューについても同様にすぐできると思います。
まとめ
Terraformを使ってBigQueryのデータセットやビューをモジュールとしてwrapする方法を紹介しました。データマネジメントしやすい形でwrapすることで管理をより効率的に分かりやすい形にどんどんしていきたいですね。