Pulumi + TypeScript IaC実践:2026年開発者のためのInfrastructure as Codeガイド

DevOps

2026年、なぜPulumi + TypeScriptが開発者に優しいのか

TerraformはHCLでインフラを定義しますが、これはドメイン固有言語(DSL)です。開発者は新しい構文を学び、文字列補間を扱い、限られたIDEサポートに苦しむ必要があります。Pulumiは本物のプログラミング言語でインフラを定義できます。TypeScriptなら型チェック、IDE自動補完、npmエコシステム、条件ロジック、ループなど、すべて使い慣れたものが使えます。

次元 Terraform (HCL) Pulumi (TypeScript) CDK (TypeScript)
言語 HCL (DSL) TypeScript TypeScript
型安全性 なし 完全 完全
IDEサポート 限定 完全 完全
条件ロジック count/for_each if/else/for if/else/for
モジュール再利用 Terraform Module npmパッケージ Construct
状態管理 State File Pulumi Cloud/セルフホスト CDK Cloud
テスト terraform test Mocha/Jest Jest
学習曲線

Pulumiアーキテクチャ

┌─────────────────────────────────────────────────────┐
│              Pulumi CLI (pulumi)                      │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐     │
│  │ Engine     │  │ Language   │  │ Resource   │     │
│  │ (オーケストレーション)│──│ Host       │──│ Provider   │     │
│  └────────────┘  │ (Node.js)  │  │ (gRPC)     │     │
│                  └────────────┘  └────────────┘     │
└─────────────────────────────────────────────────────┘

プロジェクトセットアップ

curl -fsSL https://get.pulumi.com | sh
pulumi login
mkdir my-infra && cd my-infra
pulumi new aws-typescript

AWSリソースのデプロイ

import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
import * as pulumi from "@pulumi/pulumi";

const env = pulumi.getStack();

const vpc = new awsx.ec2.Vpc("main-vpc", {
    cidrBlock: "10.0.0.0/16",
    subnets: [
        { type: "public", cidrMask: 24 },
        { type: "private", cidrMask: 24 },
    ],
    tags: { Environment: env },
});

const db = new aws.rds.Instance("app-db", {
    engine: "postgres",
    engineVersion: "16.4",
    instanceClass: "db.t3.medium",
    allocatedStorage: 100,
    storageType: "gp3",
    dbName: "appdb",
    username: "appadmin",
    password: pulumi.Config.requireSecret("db-password"),
    skipFinalSnapshot: true,
    tags: { Environment: env },
});

export const dbEndpoint = db.endpoint;

GCPリソースのデプロイ

import * as gcp from "@pulumi/gcp";

const cluster = new gcp.container.Cluster("app-cluster", {
    project: gcp.config.project,
    location: "us-central1",
    initialNodeCount: 3,
    nodeConfig: { machineType: "e2-medium" },
});

export const clusterName = cluster.name;

Azureリソースのデプロイ

import * as azure from "@pulumi/azure";

const resourceGroup = new azure.core.ResourceGroup("app-rg", {
    location: "East Asia",
    tags: { Environment: pulumi.getStack() },
});

const aks = new azure.containerservice.KubernetesCluster("app-aks", {
    resourceGroupName: resourceGroup.name,
    location: resourceGroup.location,
    defaultNodePool: { name: "default", nodeCount: 3, vmSize: "Standard_D2s_v3" },
    identity: { type: "SystemAssigned" },
});

export const aksFqdn = aks.fqdn;

Stack管理と設定

pulumi stack init dev
pulumi stack init prod
pulumi config set aws:region us-east-1
pulumi config set db-password "secret-value" --secret
pulumi stack select prod
pulumi up
const config = new pulumi.Config();
const instanceCount = config.requireNumber("instance-count");
const dbPassword = config.requireSecret("db-password");
const isProd = pulumi.getStack() === "prod";

インフラのテスト

import * as pulumi from "@pulumi/pulumi";
import { describe, it, expect } from "mocha";

pulumi.runtime.setMocks({
    newResource: (args) => ({ id: `${args.name}-id`, state: args.inputs }),
    call: (args) => args.inputs,
});

describe("Infrastructure", () => {
    it("should use larger DB in production", () => {
        const isProd = true;
        const dbInstanceClass = isProd ? "db.r6g.xlarge" : "db.t3.medium";
        expect(dbInstanceClass).to.equal("db.r6g.xlarge");
    });
});

Pulumi vs Terraform vs CDK

次元 Pulumi Terraform CDK
言語 TS/Python/Go/C# HCL TS/Python/Java/C#
Provider 200+ 3000+ AWS中心
テスト ネイティブ terraform test Jest
マルチクラウド ネイティブ ネイティブ AWS中心

5つのよくある落とし穴

1. 実行時にOutput値が利用不可

PulumiのOutput<T>は非同期で、実行時に直接値にアクセスできません。

2. リソース依存の未正確宣言

Pulumiは依存を自動推論しますが、明示的な宣言が必要な場合があります。

3. Stack設定に秘密を平文で保存

--secretフラグで機密設定を保護してください。

4. destroy保護の無視

本番環境ではリソース保護を有効にして、誤削除を防止してください。

5. 並列デプロイによる競合状態

複数のStackが同じリソースを同時にデプロイすると競合が発生します。


10のエラートラブルシューティング

# 症状 原因 解決方法
1 requireSecretが暗号化値を返却 apply外で使用 applyまたはinterpolateを使用
2 リソース作成タイムアウト クラウドAPIレート制限 並行度を確認
3 Providerバージョン非互換 package.jsonが古い pulumi plugin install
4 Stack状態破損 デプロイ中断 pulumi state unprotect
5 型エラー TypeScript型不一致 tsc --noEmit
6 循環依存 リソース間の相互参照 依存グラフを再構築
7 設定欠落 Stack設定未設定 pulumi config
8 権限不足 クラウド認証情報の権限不足 IAMロールを確認
9 ドリフト検出 手動でクラウドリソースを変更 pulumi refresh
10 既存リソースのインポート失敗 リソースIDが不正 ID形式を確認

おすすめツール


まとめ:Pulumi + TypeScriptは開発者が使い慣れたプログラミング言語でインフラを定義でき、型安全性、IDEサポート、npmエコシステムの恩恵を受けられます。2026年、Pulumiは200以上のProviderをサポートし、AWS、GCP、Azureなどの主要クラウドプラットフォームをカバーしています。TypeScriptに慣れた開発者にとって、PulumiはTerraformよりも自然で効率的なIaCの選択肢です。

ブラウザローカルツールを無料で試す →

#Pulumi#IaC#TypeScript#基础设施即代码#AWS#GCP#Azure#云资源管理