はじめまして、DMP (データマネジメントプラットフォーム) グループの すぎみつ です。
最近はスキルアップ手当*1で昇降デスクの購入を検討しています。電動式昇降デスクのすゝめによると自分に最適なデスクの高さは74cmでした。
さて、DMP グループでは現在 GCP のリソース管理に CDK for Terraform を利用していまして、CDK for Terraform の利用例についてご紹介します。
はじめに
DMP グループはレアジョブグループのデータ基盤の整備をメイン業務の一つとしています。 現在は既にあるデータ基盤を新たに BigQuery を中心とした Google Cloud Platform に移行しています。
レアジョブ英会話を始めとした各サービスは AWS で構成されており、収集対象となるデータは AWS から GCP に転送する流れとなります。
今回詳細には触れませんが、データ転送を行うパイプラインは AWS 側にあり、リソースの管理は AWS CDK で行っています。弊社の AWS リソースの管理は殆ど AWS CDK で統一されておりそれに倣っています。
AWS と GCP を扱う環境なので、IaC は Terraform や Pulumi といったマルチクラウド対応のサービスを使いたいところですが、同じように書ける CDK for Terraform を利用することにしました。
CDK for Terraformとは
CDK for Terraform は簡単に言うと HCL を書かなくても、AWS CDK で書ける Terraformです。マルチクラウド対応する CDK になります。
www.terraform.io
AWS CDK とコンポーネントを共有していて、AWS CDK のようにコードで書いた定義を Terraform の HCL プロジェクトで利用する インフラ構成ファイル( Json ファイル)に変換し、Terraform でリソースの作成を行えます。
CDK for Terraform でのプロジェクト作成からデプロイまでの一連の操作は CDKTF CLI で行います。 https://www.terraform.io/cdktf/concepts/cdktf-architecture
サンプルの紹介
簡単にサンプルを紹介します。
サービスアカウントと GCS バケットの作成し、作成した GCS バケットに対してサービスアカウントからのアクセス権を許可する例になります。
CDK For Terraform のインストールとそれに必要な準備は公式の以下リンクを参照してください。
Install CDK for Terraform and Run a Quick Start Demo | Terraform - HashiCorp Learn
プロジェクトの作成
CDKTF CLI を実行していきます。 今回のプロジェクトは TypeScript で作成します。
$ cdktf init --template=typescript
プロジェクト初期化後のディレクトリ構成は以下のようになります。
cdk_for_tf というディレクトリ名以下にプロジェクトを作成しました。
.cdk_for_tf ├── __tests__ ├── cdktf.json ├── help ├── jest.config.js ├── main.ts ├── node_modules ├── package-lock.json ├── package.json ├── setup.js └── tsconfig.json
実装
修正後の main.ts は以下になります。
import { Construct } from "constructs"; import { App, TerraformStack, GcsBackend } from "cdktf"; import { GoogleProvider, ServiceAccount, StorageBucket, StorageBucketIamBinding } from "./.gen/providers/google"; class MyStack extends TerraformStack { constructor(scope: Construct, name: string) { super(scope, name); // リモートバックエンドの指定 new GcsBackend(this, { bucket: 'cdktf-example-remote-backend', prefix: 'state', }) const provider = new GoogleProvider(this, 'Set GCP provider',{ project: `${project_id}` }) // サービスアカウントの作成 const serviceAccount = new ServiceAccount(this, 'Create Service Account',{ provider: provider, accountId: 'cdktf-example-service-account', displayName: 'cdktf-example-service-account', }) // GCSバケット作成 const bucket = new StorageBucket(this, 'Create GCS Bucket', { provider: provider, location: 'ASIA-NORTHEAST1', name: 'cdktf-example-gcs-bucket', uniformBucketLevelAccess: true, dependsOn: [serviceAccount] }) // GCSバケットへの権限追加 new StorageBucketIamBinding(this, 'Add role roles/storage.legacyBucketReader', { provider: provider, bucket: bucket.name, role: 'roles/storage.legacyBucketReader', members: [`serviceAccount:${serviceAccount.email}`], dependsOn: [serviceAccount, bucket] }) // オブジェクトへの権限追加 new StorageBucketIamBinding(this, 'Add role roles/storage.objectViewer', { provider: provider, bucket: bucket.name, role: 'roles/storage.objectViewer', members: [`serviceAccount:${serviceAccount.email}`], dependsOn: [serviceAccount, bucket] }) } } const app = new App(); new MyStack(app, "cdk_for_tf"); app.synth();
デプロイ
deploy コマンドで構成ファイルの生成及びリソースの作成まで纏めてできるためcdktf deploy
を実行します。尚、GCP のクレデンシャルは gcloud の認証で済ませているものとします。
$ cdktf deploy cdk_for_tf Initializing the backend... cdk_for_tf Successfully configured the backend "gcs"! Terraform will automatically use this backend unless the backend configuration changes. cdk_for_tf Initializing provider plugins... - Finding hashicorp/google versions matching "4.25.0"... cdk_for_tf - Using hashicorp/google v4.25.0 from the shared cache directory cdk_for_tf 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. cdk_for_tf cdk_for_tf Terraform has been successfully initialized! cdk_for_tf Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: cdk_for_tf # google_service_account.CreateServiceAccount (Create Service Account) will be created # google_storage_bucket.CreateGCSBucket (Create GCS Bucket) will be created # google_storage_bucket_iam_binding.Addroleroles--storagelegacyBucketReader (Add role roles--storage.legacyBucketReader) will be created # google_storage_bucket_iam_binding.Addroleroles--storageobjectViewer (Add role roles--storage.objectViewer) will be created Plan: 4 to add, 0 to change, 0 to destroy. ─────────────────────────────────────────────────────────────────── Saved the plan to: plan To perform exactly these actions, run the following command to apply: terraform apply "plan" cdk_for_tf google_service_account.CreateServiceAccount (Create Service Account): Creating... cdk_for_tf google_service_account.CreateServiceAccount (Create Service Account): Creation complete after 2s cdk_for_tf google_storage_bucket.CreateGCSBucket (Create GCS Bucket): Creating... cdk_for_tf google_storage_bucket.CreateGCSBucket (Create GCS Bucket): Creation complete after 2s cdk_for_tf google_storage_bucket_iam_binding.Addroleroles--storagelegacyBucketReader (Add role roles--storage.legacyBucketReader): Creating... google_storage_bucket_iam_binding.Addroleroles--storageobjectViewer (Add role roles--storage.objectViewer): Creating... cdk_for_tf google_storage_bucket_iam_binding.Addroleroles--storageobjectViewer (Add role roles--storage.objectViewer): Creation complete after 9s cdk_for_tf google_storage_bucket_iam_binding.Addroleroles--storagelegacyBucketReader (Add role roles--storage.legacyBucketReader): Creation complete after 9s cdk_for_tf Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
deploy が成功しました。
出力を見ると内部では構成ファイルを作成してから、terraform plan
の実行後、terraform apply
が実行されているのが確認できますね。
結果確認
デプロイされた結果を確認します。
# バケット一覧確認 $ gsutil ls gs://cdktf-example-gcs-bucket/ gs://cdktf-example-remote-backend/ # リモートバックエンド用に予め作成したバケット # バケットのメタ情報確認 $ gsutil ls -L -b gs://cdktf-example-remote-backend/ gs://cdktf-example-remote-backend/ : Storage class: STANDARD Location type: region Location constraint: ASIA-NORTHEAST1 ~省略~ Public access prevention: enforced
バケットに対する権限を確認します。(コマンド結果は一部省略しています)
$ gsutil iam get gs://cdktf-example-gcs-bucket/ { "bindings": [ { "members": [ "serviceAccount:cdktf-example-service-account@${project_id}.iam.gserviceaccount.com" ], "role": "roles/storage.legacyBucketReader" }, { "members": [ "serviceAccount:cdktf-example-service-account@${project_id}.iam.gserviceaccount.com" ], "role": "roles/storage.objectViewer" } }
想定通りにリソースが作成できたことを確認できました。
懸念するところ
- 商用サポートはない
- 質問があれば Hashicorp社の HashiCorp Discuss から、バグや機能リクエストがあれば Github から。
- 利用者が少ない気がする
- Web 上の記事が少ないです。この記事もそうですがあってもエントリ的なものになっています。
今利用している GCP サービスの種類も構成も大きく無く、致命的な問題に遭遇していないですが、今後利用を拡大していく上で障壁になる可能性はあります。バグ判断や代替策案を講じるために費やす時間の大きさを懸念するところではあります。
お前の技術力次第だろと言われればおしまいですが。。。
おわりに
今回は CDK for Terraform の簡単な例を紹介をしました。
今後は GCP の基盤も拡張されていくので、運用を踏まえた具体的な良し悪しを紹介できたらと思います。