こんにちは!クラウドインフラの深淵を覗く旅へようこそ。
今回は、世界中のエッジで超高速にコードを実行する「Cloudflare Workers」と、その背後で圧倒的な低遅延を発揮するサーバーレスSQLデータベース「Cloudflare D1」を、Pulumiを使って完璧にコード管理(IaC)する方法を解説します。
「エッジコンピューティングのインフラ管理って、なんだか難しそう……」
「コンソールをポチポチするデプロイから卒業したい!」
そんなあなたのために、今回は基礎の基礎から、明日から現場で使える実践的なコードまで、優しく知的に、そして徹底的に深掘りしていきましょう。これをマスターすれば、手動デプロイの恐怖から解放され、毎日のインフラ管理が劇的に楽になりますよ。
—
1. なぜエッジコンピューティングにIaC(Pulumi)が必要なのか?
エッジのスピード感と、手動管理の限界
Cloudflare Workersは、ユーザーのブラウザから最も近い世界中のデータセンター(エッジ)でJavaScript/TypeScriptコードを実行する仕組みです。この「爆速」がウリですが、インフラストラクチャの構成はどうでしょう?
- Workersのスクリプト
- D1データベースのインスタンス
- ルーティングを行うためのDNSレコードやRoutes
これらをCloudflareのダッシュボードでポチポチ作っていたらどうなるでしょうか。「ステージング環境と本番環境で設定が微妙にズレた」「メンバーが手動で設定を変更してしまい、原因不明のバグが起きた」……。こうしたインフラの「ドリフト(予期せぬズレ)」は、SREにとって最大の敵です。
Pulumiがもたらす「真の宣言的インフラ」
ここで登場するのが Pulumi です。JSONやYAMLだけでなく、TypeScriptやPythonといった使い慣れたプログラミング言語を使ってインフラを定義できる次世代のIaCツールです。
Terraformも素晴らしいツールですが、CloudflareのようなモダンなSaaS/PaaSを扱う場合、Pulumiの「本物のプログラミング言語を使える表現力」は圧倒的なアドバンテージになります。条件分岐やループ、関数化を駆使して、エッジの構成を美しく、かつ冪等性(何度実行しても同じ結果になること)を担保して管理できるのです。
—
2. 環境構築とプロジェクトの初期化
それでは、実際に手を動かしていきましょう。今回は使い慣れた TypeScript を使って環境を構築します。
前提条件
- Node.js (v18以上推奨)
- Pulumi CLI のインストール済み (`curl -s https://get.pulumi.com | sh`)
- Cloudflare アカウント(APIトークンを発行しておいてください)
プロジェクトの作成
まずは作業用ディレクトリを作り、Pulumiプロジェクトを初期化します。
mkdir cloudflare-workers-d1-pulumi
cd cloudflare-workers-d1-pulumi
pulumi new typescript –name cloudflare-edge-stack –description “Cloudflare Workers & D1 with Pulumi” –yes
対話形式でプロジェクト名やスタック名(`dev`など)を聞かれるので、適宜設定してください。完了すると、プロジェクト内に `index.ts` や `package.json` が生成されます。
Cloudflareプロバイダのインストールと設定
PulumiからCloudflareを操作するためには、Cloudflare用のプロバイダパッケージが必要です。
npm install @pulumi/cloudflare
次に、PulumiにCloudflareの認証情報を教えます。環境変数として設定するのが最もセキュアでスマートです。
export CLOUDFLARE_API_TOKEN=”あなたのCloudflareAPIトークン”
export CLOUDFLARE_ACCOUNT_ID=”あなたのCloudflareアカウントID”
—
3. Workers、D1、DNSを一気通貫でプロビジョニングする
ここからが本番です。`index.ts` を書き換えて、以下の3つを同時に構築・統合します。
1. Cloudflare D1 データベース(データの保存先)
2. Cloudflare Worker(エッジで動くコード)
3. DNSレコード(アクセス用のドメイン設定)
以下のコードを `index.ts` にそのまま貼り付けてみてください。丁寧なコメントを入れています。
import as pulumi from “@pulumi/pulumi”;
import as cloudflare from “@pulumi/cloudflare”;
// 1. 設定情報の取得(Pulumi Config または環境変数から)
const config = new pulumi.Config();
const zoneId = config.require(“cloudflareZoneId”); // 例: “your-domain.comのZone ID”
const domainName = config.require(“domainName”); // 例: “api.your-domain.com”
// 2. Cloudflare D1 データベースのプロビジョニング
const database = new cloudflare.D1Database(“my-edge-db”, {
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
name: “production-users-db”,
});
// 3. Cloudflare Worker スクリプトのデプロイ
// ※ 本番では別ディレクトリのビルド成果物を渡すのが一般的ですが、今回はインラインで記述します
const workerScript = new cloudflare.WorkerScript(“my-edge-worker”, {
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
name: “my-edge-api”,
content: `
export default {
async fetch(request, env, ctx) {
// D1データベースへのクエリ実行例
const { results } = await env.DB.prepare(“SELECT 1 as val”).all();
return new Response(JSON.stringify({
message: “Hello from Cloudflare Workers & D1 via Pulumi!”,
db_result: results
}), {
headers: { “Content-Type”: “application/json” }
});
}
};
`,
// D1データベースをWorkerからバインド(結びつけ)する
databaseBindings: [{
name: “DB”,
databaseId: database.id,
}],
});
// 4. ワーカーをカスタムドメイン(ルート)に紐付ける
const workerRoute = new cloudflare.WorkerRoute(“my-edge-route”, {
zoneId: zoneId,
pattern: `${domainName}/`,
scriptName: workerScript.name,
});
// 5. プレースホルダーとしてDNSレコードを作成(実際のエッジルーティングに必要)
const dnsRecord = new cloudflare.Record(“my-dns-record”, {
zoneId: zoneId,
name: domainName,
type: “CNAME”,
value: “ghs.hosted.cloudflare.com”, // Workerのプレースホルダーとして適切な値
proxied: true, // Cloudflareのプロキシ(CDN/WAF)を有効化
});
// エクスポート:デプロイ完了後にURLを確認できるようにする
export const url = pulumi.interpolate`https://${domainName}`;
export const d1DatabaseId = database.id;
補足:Pulumi Configの設定
上記のコードで必要となる `cloudflareZoneId` と `domainName` をPulumiの構成値として登録します。
pulumi config set cloudflareZoneId “あなたのCloudflareのゾーンID”
pulumi config set domainName “api.example.com”
—
4. デプロイと動作確認:魔法の瞬間
コードの準備が整いました。いよいよインフラを構築(デプロイ)します。以下のコマンドを実行してください。
pulumi up
画面に「これから作成されるリソースの計画(Preview)」が表示されます。
- D1データベースが作成されること
- Workerスクリプトがアップロードされ、D1がバインドされること
- DNSとルートが設定されること
内容を確認して `yes` を選択すると、数秒から数十秒でプロビジョニングが完了します!
処理が終わると、ターミナルに以下のような出力が表示されます。
Outputs:
d1DatabaseId : “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”
url : “https://api.example.com”
ブラウザで `https://api.example.com` にアクセスするか、`curl` で叩いてみてください。
curl https://api.example.com
見事にCloudflareのエッジからJSONレスポンスが返ってくれば成功です!D1データベースへの接続もコードレベルで統合されているため、エッジ側からシームレスにSQLを叩く準備が整っています。
—
5. ローカル開発から本番デプロイまでのシームレスなワークフロー
「コードで管理できるのは分かったけど、ローカルでの動作確認はどうするの?」
ここが重要です。Cloudflare公式のローカル開発ツールである Wrangler と Pulumi は、実は非常に相性が良いのです。
1. ローカル開発: 日々のコード変更やSQLのテストには `wrangler dev` を使用し、ローカルのエッジ環境で高速にフィードバックを得る。
2. インフラの変更・本番デプロイ: D1の追加、環境変数の変更、カスタムドメインの追加といった「インフラストラクチャの変更」が発生したタイミングで `pulumi up` を実行する。
CI/CDパイプライン(GitHub Actionsなど)に組み込む場合も非常にシンプルです。
name: Deploy Infrastructure & Edge
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pulumi/action-github-actions@v5
with:
command: up
stack-name: dev
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
このワークフローをリポジトリに置いておくだけで、`main` ブランチにマージされた瞬間に、世界中のエッジサーバーへとあなたのアプリケーションが自動的に、美しく同期されます。
—
おわりに
今回は、Pulumiを用いたCloudflare WorkersとD1データベースの統合管理について、実践的なコードを交えて解説しました。
コンソール画面をマウスでカチカチクリックして設定を変更していた時代はもう終わりです。インフラをコードとして定義し、バージョン管理し、自動化する。このアプローチを一度マスターしてしまえば、手動作業のストレスには二度と戻れなくなるはずです。
「これをマスターすれば、毎日の作業が劇的に楽になりますよ。」
ぜひ今回のコードをご自身の環境で動かしてみて、エッジコンピューティングとIaCがもたらす圧倒的なスピード感と心地よさを体感してください。あなたのクラウドライフがより素晴らしいものになることを応援しています!