Gemcook Tech Blog
🌩️

CDKTFでCloudflareリソースのIaCを実現する

2024/06/10に公開

こんにちは。最近 Cloudflare にお熱なエンジニアです。元々は AWS メインで CDK をバリバリに使っていました。
Cloudflare で IaC をやるときに Terraform で HCL[1] かー。という気分になっていたところに CDKTF に出会い半年程使って体験が良かったので紹介します。

CDKTF 概要

CDKTF(Cloud Development Kit for Terraform)は CDK の概念を Terraform に持ち込んだフレームワークで、TypeScript や Python などを使って様々なクラウドのリソースを管理できます。
AWS のリソースを管理するなら基本的に CDK で事足りますが、CDKTF は CDK のベストプラクティスを活かしつつ AWS 以外のクラウドリソース管理ができるので CDK ユーザーには凄くおすすめです。
(CDKTF の開発には CDK の開発者チームも関わっているので、CDK との親和性がかなり高い)

より詳しい情報は公式ドキュメントからどうぞ
https://developer.hashicorp.com/terraform/cdktf

今回は R2Bucket を作成するサンプルで CDKTF の使い方を紹介します。

想定読者

  • CDK には触れたことがあるが、Terraform, CDKTF に触れたことがない人
  • Terraform 使いたいが HCL が苦手な人

事前準備

CDKTF の Init は公式ドキュメントに書かれているのでそちらを参照。
CDKTF も CDK と同じく TypeScript がおすすめなので、本記事では TypeScript での実装とします。

https://developer.hashicorp.com/terraform/tutorials/cdktf/cdktf-install

Cloudflare Provider のインストール

CDKTF では各 Provider の定義がパッケージとして提供されているので @cdktf/provider-cloudflare をインストール

https://github.com/cdktf/cdktf-provider-cloudflare/tree/de5bb8eb668f25de70e488673dd2af2c8cad947d

$ npm install @cdktf/provider-cloudflare

R2 サンプル

試しに R2Bucket を作成するサンプルを用意します。

main.ts
import { App } from "cdktf";
import { MyStack } from "./stack/my-stack";

const app = new App();
new MyStack(app, "MyStack");
app.synth();
stack/my-stack.ts
import { provider, r2Bucket } from "@cdktf/provider-cloudflare";
import { TerraformStack } from "cdktf";
import type { Construct } from "constructs";

const CLOUDFLARE_ACCOUNT_ID = "xxxxxxxxxxxxx";

export class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new provider.CloudflareProvider(this, "cloudflare");

    new r2Bucket.R2Bucket(this, "hoge-bucket", {
      accountId: CLOUDFLARE_ACCOUNT_ID,
      name: "hoge-bucket",
    });
  }
}

CDK ユーザーにはおなじみの記法でスタックを定義できます 🚄

Env の設定

アプリケーションを作成する場合基本的に環境分けしたくなりますね 🐇
環境変数の管理は色々方法がありますが、通常の環境変数であれば TypeScript のコード内で管理してしまうのが楽でしょう。
私はこんな感じで管理してます。

main.ts
function firstUpperCase(str: string): string {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

const app = new App();
const envMap = {
  dev: {},
  stg: {},
  prd: {},
};
[("dev", "stg", "prd")].forEach((env) => {
  const envValues = envMap[env];
  const firstUpperEnv = firstUpperCase(env);
  new MyStack(app, `MyStack-${firstUpperEnv}`, envValues);
});
app.synth();
stack/my-stack.ts
export class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string, envValues: EnvValues) {
    super(scope, id);

    new provider.CloudflareProvider(this, "cloudflare");

    new r2Bucket.R2Bucket(this, "hoge-bucket", {
      accountId: CLOUDFLARE_ACCOUNT_ID,
      name: "hoge-bucket",
    });
  }
}

環境分けや環境変数の値がわかりやすいのも CDK 由来の良さですね 🌈

認証情報の設定

Cloudflare の認証情報を環境変数で設定する必要があります。Cloudflare では現在 API トークンが推奨されているため、以下の手順で API トークンを作成し、環境変数に設定します。

https://developers.cloudflare.com/fundamentals/api/get-started/create-token/

CLI 上で export すると CDKTF 上から参照されるようになります。

$ export CLOUDFLARE_API_TOKEN=xxxxxxxxxxxxx

Diff, Deploy, Destroy

Diff, Deploy, Destroy は CDK と同じですね。

$ npx cdktf diff HogeStack

$ npx cdktf deploy HogeStack

$ npx cdktf destroy HogeStack

tfstate の管理

CDKTF と CDK との大きな違いの一つに tfstate の存在があります。
tfstate は Terraform が管理するリソースの状態を保存するファイルで、どのスタックで何のリソースが作成されているかなどが記録されています。

https://developer.hashicorp.com/terraform/cdktf/concepts/remote-backends

ローカルで管理もできますが、誤って消したりするとリソースの状態がわからなくなるので S3 などのリモートで保存することが推奨されます。(当然チーム開発時にはリモートで管理することが必須)

リモートで管理する場合、例えば S3 に保存するには次のように記載します。

./stack/my-stack.ts
export class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new provider.CloudflareProvider(this, "cloudflare");

    // tfstate を S3 に保存
    new S3Backend(this, {
      bucket: "tfstate-bucket",
      key: "terraform.tfstate",
      region: "us-east-1",
    });

    new r2Bucket.R2Bucket(this, "hoge-bucket", {
      accountId: CLOUDFLARE_ACCOUNT_ID,
      name: "hoge-bucket",
    });
  }
}

↑ では S3Backend コンストラクトを用いて S3 に保存していますが、私は Cloudflare R2 で管理するようにしました。
Diff, Deploy 時に AWS への認証が無駄に挟まってしまうので、Cloudflare で一元管理したかったからですね。
R2 で tfstate を管理する方法は別途記事にしたいと思います。
(R2Backend は公式サポートされてないなど、色々事情がここでは割愛)

まとめ

Terraform を TypeScript で書ける CDKTF はかなり便利で、CDK ユーザーにとっては特におすすめのツールです。
CDKTF はいいぞ!🚀

脚注
  1. Hashicorp Configuration Language ↩︎

GitHubで編集を提案
Gemcook Tech Blog
Gemcook Tech Blog

Discussion