Gemcook Tech Blog
🔖

CDKTFのTerraform StateをCloudflare R2で管理する

2024/06/24に公開

こんにちは。
元々は AWS メインで使っていたのですが、最近何かと Cloudflare を使う機会が増えてきた筆者です。

Cloudflare のリソースを作成する途中で CDKTF の Terraform State (以下 tfstate)を Cloudflare R2 で管理するために色々調べたので、調査結果を紹介します。
元々は S3 バケットに tfstate を置いていたのですが、そのためだけに AWS 環境を間借りするのももったいないので R2 に移行したいなーと考えていました。

CDKTFTerraform の解説は公式ドキュメントを参照してください。
Cloudflare リソースを CDKTF で管理する方法は私が以前書いた記事を参考にどうぞ!(宣伝)

https://zenn.dev/gemcook/articles/0669e504ca38a7

結論

CDKTF の tfstate は R2 で管理できる。以下の設定が必要

  1. tfstate 用 R2 バケットを作成
  2. S3Backend を継承して R2 バケット用の独自コンストラクタを作成
  3. Stack で R2 バケット用のコンストラクタを呼び出す
  4. tfstate 用 R2 バケットの認証情報を設定

バージョン

  • Terraform v1.8.5
  • CDKTF v0.20.7

tfstate とは

tfstate とは Terraform が管理するリソースの状態を記録したファイルです。
チーム開発で複数人が同じリソースを管理する場合、tfstate を共有することでリソースの状態を同期することができます。
つまりこの tfstate ファイルをどこかのストレージに保存しておく必要があります。

Terraform での tfstate 管理

tfstate を R2 で管理したいなーと思って色々調べていたところ、Terraform(CDKTF ではない)で tfstate を R2 に保存するフューチャーさんの記事を見つけました。

https://future-architect.github.io/articles/20231016a/

R2 は S3 互換のストレージなので、Terraform の S3Backend の各プロパティに R2 の値を設定することで tfstate を R2 に保存することができるということ。なるほどー!

Terraform でできるなら CDKTF でもできるはず!🔥
ということで試してみました。

CDKTF での tfstate 管理

R2 バケット作成

まずは tfstate を管理するための R2 バケットが必要なのでコンソールで作成しておきます。

R2Backend コンストラクタの作成

S3 バケットで tfstate を管理するための S3Backend コンストラクタを継承して、R2 のエンドポイントを指定する R2Backend コンストラクタを作成します。

r2-backend.ts
import { S3Backend } from "cdktf";
import type { Construct } from "constructs";
import { CLOUDFLARE_ACCOUNT_ID } from "./constants";

export class R2Backend extends S3Backend {
  constructor(scope: Construct, stackID: string) {
    super(scope, {
      // R2バケット名
      bucket: "example-tfstate",
      // 各tfstateファイルのキー
      key: `terraform.${stackID}.tfstate`,
      // リージョンはus-east-1もしくはautoを指定。詳細はS3互換のR2ドキュメントを参照
      // https://developers.cloudflare.com/r2/api/s3/api/
      region: "us-east-1",
      endpoints: {
        // R2のエンドポイント。アカウントIDはコンソール or APIで取得
        s3: `https://${CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`,
      },
      // 各チェックをスキップ
      skipRegionValidation: true,
      skipCredentialsValidation: true,
      skipRequestingAccountId: true,
      skipS3Checksum: true,
      // AWSのプロファイルを指定
      profile: "ExampleProfile",
    });
  }
}

各 Stack で R2Backend を呼び出して使います。

my-stack.ts
import { provider } from "@cdktf/provider-cloudflare";
import { TerraformStack } from "cdktf";
import { R2Backend } from "./r2-backend";
import type { Construct } from "constructs";

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

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

    new R2Backend(this, id);
  }
}

AWS プロファイルで認証設定を追加

R2Backend で AWS のプロファイルを指定しているので、プロファイルを設定しておきます。
Cloudflare R2 は S3 互換であり、AWS CLI の S3 コマンドに対応しています。
つまり aws configure の設定を認証に使用できるということです!

https://developers.cloudflare.com/r2/examples/aws/aws-cli/

まずは Cloudflare のコンソールから API トークンを作成します。

作成した API トークンを AWS のプロファイルに設定します。
aws configure で設定するもしくは ~/.aws/config~/.aws/credentials にプロファイルを設定しておきます。

# .aws/config
[profile ExampleProfile]
region=auto
# .aws/credentials
[ExampleProfile]
aws_access_key_id = xxxxxxxxxx # アクセス キー ID
aws_secret_access_key = yyyyyyyyy # シークレット アクセス キー

以上で設定は完了です。
デプロイすると tfstate が R2 に保存されていることが確認できました!

まとめ

Terraform で tfstate を管理する方法の記事があったので、CDKTF でも試しましたが問題なくできました。
Cloudflare にリソースを寄せたい方はぜひ試してみてください!

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

Discussion