こんにちは!クラウドインフラ・SREの世界へようこそ。
今日は、多くの開発者が頭を悩ませる「マイクロサービス間の複雑な通信」と「インフラの構築・管理」を、驚くほどエレガントに解決する魔法のようなアプローチについてお話しします。
取り上げるのは、Azure Container Apps (ACA) と Dapr (Distributed Application Runtime)、そしてインフラストラクチャをTypeScriptなどの慣れ親しんだ言語で安全に定義できる Pulumi の組み合わせです。
「コンテナの管理も、サービス間の非同期通信やリトライ制御も、全部コードで美しく自動化したい」
そんな願いを叶える極限の知見を、初心者の方にもわかるように優しく、しかし妥協のないプロの視点で解説していきます。これをマスターすれば、明日のインフラ構築が劇的に楽しく、そして楽になりますよ!
—
1. なぜこの構成なのか?(ツールの役割と全体像)
まずは、今回使用する3つの強力なプレイヤーたちの役割を整理しておきましょう。
1. Pulumi (インフラ構成管理):
Terraformと違って、TypeScriptやPythonといった本物のプログラミング言語でインフラを書けます。変数、ループ、関数、そして強力な型システムが使えるため、大規模なインフラでも破綻しない「真に冪等(べきとう)で DRY なコード」を書くことができます。
2. Azure Container Apps (ACA):
Kubernetesの複雑な設定(YAML地獄)に悩まされることなく、KnativeやKEDAといった最先端のOSS技術の恩恵を受けられるサーバーレスコンテナ環境です。「コンテナを動かしたいだけなのに、なぜKubernetesクラスターのアップグレードをしなきゃいけないんだっけ?」というSREの絶望を解消してくれます。
3. Dapr (分散アプリケーションランタイム):
マイクロサービス同士の通信(サービス間呼び出し)、Pub/Subメッセージング、ステート管理などを抽象化してくれるサイドカーです。「どの言語で書いても、どのクラウドに引っ越しても、コードを書き換えずに安全な通信ができる」という、マイクロサービスアーキテクチャの救世主です。
この3つを組み合わせることで、「堅牢で、スケーラブルで、完全にコード化されたマイクロサービス基盤」が手に入ります。
—
2. 環境構築と基礎セットアップ
それでは、手を動かしていきましょう。今回はモダンな開発の標準である TypeScript を用いた Pulumi プロジェクトを作成します。
事前準備
以下のツールがインストールされていることを確認してください。
- Node.js (LTS推奨)
- Pulumi CLI
- Azure CLI (あらかじめ `az login` でログインしておいてください)
プロジェクトの初期化
適当なディレクトリを作成し、Pulumiプロジェクトを初期化します。
mkdir aca-dapr-pulumi
cd aca-dapr-pulumi
pulumi new azure-typescript
途中でプロジェクト名やスタック名(`dev` など)、Azureのリージョン(`japaneast` など)を聞かれるので、画面の指示に従って進めてください。これだけで、TypeScriptのプロジェクト骨組みが完成します。
—
3. PulumiによるAzure Container Apps & Dapr基盤のコード化
ここからが本番です。`index.ts` を開き、Azure Container Apps環境と、Daprサイドカーを統合したコンテナアプリを定義していきます。
今回は、「APIを受信してバックエンドにDapr経由でメッセージを渡すフロントエンド」と、「それを受け取るバックエンド」の2つのマイクロサービスを想定したコードを構築します。
以下のコードをご自身の `index.ts` に貼り付けてみてください。一つひとつに丁寧なコメントを入れています。
import as pulumi from “@pulumi/pulumi”;
import as azure from “@pulumi/azure-native”;
// 1. リソースグループの作成
// すべてのリソースを綺麗にまとめるための箱を用意します。
const resourceGroup = new azure.resources.ResourceGroup(“rg-aca-dapr-dev”, {
location: “japaneast”,
});
// 2. Log Analytics ワークスペースの作成
// Container Appsのログやメトリクスを収集するために必須です。
const workspace = new azure.operationalinsights.Workspace(“law-aca”, {
resourceGroupName: resourceGroup.name,
location: resourceGroup.location,
sku: {
name: “PerGB2018”,
},
});
// 3. Container Apps Managed Environment の作成
// ここにDaprの有効な環境を構築します。
const environment = new azure.app.ManagedEnvironment(“aca-env”, {
resourceGroupName: resourceGroup.name,
location: resourceGroup.location,
appLogsConfiguration: {
destination: “log-analytics”,
logAnalyticsConfiguration: {
customerId: workspace.customerId,
sharedKey: workspace.primarySharedKey,
},
},
});
// 4. バックエンドサービスの定義 (Dapr有効)
const backendApp = new azure.app.ContainerApp(“backend-app”, {
resourceGroupName: resourceGroup.name,
managedEnvironmentId: environment.id,
configuration: {
// イングレス(外部からのアクセス設定): 内部通信のみ許可
ingress: {
external: false,
targetPort: 8080,
transport: “http”,
},
// ★ ここが肝!Daprサイドカーの有効化
dapr: {
enabled: true,
appId: “backend-service”, // 他のサービスからこのIDで呼び出せます
appPort: 8080,
appProtocol: “http”,
},
},
template: {
containers: [{
name: “backend”,
// サンプルとしてMicrosoft公式のダミーイメージを使用
image: “mcr.microsoft.com/azuredocs/aci-helloworld:latest”,
resources: {
cpu: 0.5,
memory: “1.0Gi”,
},
}],
},
});
// 5. フロントエンドサービスの定義 (Dapr経由でバックエンドを呼び出す)
const frontendApp = new azure.app.ContainerApp(“frontend-app”, {
resourceGroupName: resourceGroup.name,
managedEnvironmentId: environment.id,
configuration: {
// 外部からのインターネット公開を許可
ingress: {
external: true,
targetPort: 8080,
transport: “http”,
},
dapr: {
enabled: true,
appId: “frontend-service”,
appPort: 8080,
appProtocol: “http”,
},
},
template: {
containers: [{
name: “frontend”,
image: “mcr.microsoft.com/azuredocs/aci-helloworld:latest”,
resources: {
cpu: 0.5,
memory: “1.0Gi”,
},
}],
},
});
// 6. 出力値の定義 (外部からフロントエンドにアクセスするためのURLを表示)
export const frontendUrl = pulumi.interpolate`https://${frontendApp.configuration.ingress?.fqdn}`;
—
4. コードの解説とベストプラクティス
上記のコードには、SREとして現場で絶対に押さえておきたいベストプラクティスが詰まっています。
- 型安全性によるインフラミス防止:
TypeScriptで書かれているため、プロパティのスペルミスなどをIDE(VS Codeなど)が即座に検知してくれます。「デプロイしてからパラメータエラーに気づく」という絶望的なタイムロスとはもうお別れです。
- Daprによるセキュアなサービス間通信:
`backendApp` の `ingress.external` を `false` に設定している点に注目してください。これにより、バックエンドはインターネットから完全に隔離され、Daprのサイドカーを経由した内部ネットワークからしかアクセスできないセキュアな要塞となります。
- 依存関係の暗黙的・明示的解決:
Pulumiは、変数としてリソース同士(例: `environment.id`)を紐づけるだけで、自動的に正しいデプロイ順序(リソースグループ $\rightarrow$ ログ基盤 $\rightarrow$ 環境 $\rightarrow$ アプリ)を計算して実行してくれます。
—
5. 動作確認(HelloWorld)
コードの準備ができたら、いよいよデプロイです!以下のコマンドを叩くだけで、Azure上にインフラが構築されます。
pulumi up
実行すると、作成されるリソースのプレビューが表示されます。内容を確認して `yes` を選択すれば、数分でAzure Container AppsとDaprの基盤がデプロイされます。
デプロイが完了すると、ターミナルに以下のような出力が表示されます。
Outputs:
frontendUrl: “https://frontend-app.xxxx.japaneast.azurecontainerapps.io”
Info:
1 to 5 changes (5 to create)
表示された `frontendUrl` にブラウザでアクセスし、無事に画面が表示されれば大成功です!
—
おわりに
いかがでしたでしょうか?
Pulumiを使うことで、複雑なクラウドインフラや最新のコンテナ技術(Azure Container Apps & Dapr)を、美しく、安全に、そしてプログラムとしてコントロールできるようになります。
「インフラをコードで書く」ということは、単に作業を自動化するだけではありません。システム全体のアーキテクチャがコードという「生きたドキュメント」になり、チーム全員で共有・レビューできるという圧倒的なメリットをもたらしてくれます。
これをマスターすれば、毎日のインフラ運用や環境構築のストレスが劇的に軽くなり、本来注力すべきアプリケーション開発に集中できるようになりますよ。
それでは、素晴らしいクラウドライフを!