【入門編】Pulumiでよくあるエラー10選と解決策:デプロイ失敗時のトラブルシューティング – インフラ構成管理(IaC)活用バイブル

こんにちは!インフラエンジニアの皆さん、日々のクラウド運用の自動化、お疲れ様です。

Terraformに別れを告げ、TypeScriptやPython、Goといった慣れ親しんだプログラティング言語でインフラを記述できる「Pulumi」の世界へようこそ。このツールを使いこなせるようになると、条件分岐やループ、関数といったプログラミングの恩恵をそのままインフラ構築に受けられるため、毎日の作業が劇的に楽になりますよ。

とはいえ、強力なツールにはそれなりの「ハマりどころ」が存在します。特にPulumiを触り始めたばかりの頃は、見慣れないエラーに直面して手が止まってしまうことも多いはずです。

そこで今回は、Pulumiでのデプロイ時に遭遇しがちな「よくあるエラー10選」の中から、特に現場で致命傷になりやすい4つのテーマを厳選し、その切り分け方と解決策を魂を込めて解説します。

—

1. 認証エラー・権限不足エラーの切り分け方法

クラウドインフラ構築の最初の壁が「認証」です。Pulumi自体は単なるオーケストレーターであり、AWS、Azure、GCPなどのクラウドプロバイダーの権限をそのまま借用して動いています。

よくあるエラー

> `error: AWS Error: AccessDenied: User is not authorized to perform: ec2:CreateVpc`

現場の知見と解決策

このエラーに直面した時、多くの人は「IAMポリシーが足りないんだな」と思い込み、やみくもに権限を追加しがちです。しかし、プロのSREはまず「Pulumiがどの認証情報を読んでいるか」を疑います。

Pulumiは以下の優先順位で認証情報を解決します。
1. プロバイダーの設定ファイルやコード内の明示的なクレデンシャル
2. 環境変数(例: `AWS_ACCESS_KEY_ID`)
3. クラウドベンダーの公式CLIの設定(例: `~/.aws/credentials` や `gcloud auth`)

切り分けのステップ:
まずは、Pulumiを実行するターミナルで、対象のクラウドCLIが正しく動作しているか確認してください。

例: AWSの場合、現在の認証情報を確認
aws sts get-caller-identity

ここで意図しないIAMユーザーやロールが表示された場合は、環境変数が汚染されている可能性が高いです。コード内で明示的にプロバイダーを設定し、環境変数の混入を防ぐのがベストプラクティスです。

import as pulumi from “@pulumi/pulumi”;
import as aws from “@pulumi/aws”;

// 明示的に特定のプロファイルを使用するプロバイダーを定義
const myProvider = new aws.Provider(“my-provider”, {
region: “ap-northeast-1”,
profile: “production-admin”, // 利用するCLIプロファイル名を指定
});

// リソース作成時にプロバイダーを明示的に紐付ける
const myVpc = new aws.ec2.Vpc(“my-vpc”, {
cidrBlock: “10.0.0.0/16”,
}, { provider: myProvider });

—

2. リソースの依存関係(DependsOn)に起因するデプロイ失敗の解消

Pulumiは、コード内の変数参照(例:あるリソースのIDを別のリソースの引数に渡す)を解析して自動的に依存関係グラフを構築します。しかし、「コード上では参照していないが、論理的に順番を守る必要がある」ケースでデプロイ失敗が起きます。

よくあるエラー

> `error: Updating (production): aws:iam/rolePolicyAttachment:RolePolicyAttachment failed: NoSuchEntity: The role cannot be found.`

IAMロールを作成した直後にポリシーをアタッチしようとした際、AWS側の伝播(Eventual Consistency)のタイムラグや、Pulumiの作成順序の制御ミスによって発生します。

現場の知見と解決策

変数として渡されていないリソース同士の順序を強制したい場合は、明示的な依存関係オプションである `dependsOn` を使用します。

import as aws from “@pulumi/aws”;

// 1. IAMロールの作成
const role = new aws.iam.Role(“my-role”, {
assumeRolePolicy: “…”,
});

// 2. ポリシーの作成
const policy = new aws.iam.Policy(“my-policy”, {
policy: “…”,
});

// 3. アタッチメント(ロールとポリシーの存在が前提)
const attachment = new aws.iam.RolePolicyAttachment(“my-attachment”, {
role: role.name,
policyArn: policy.arn,
}, {
// dependsOnで明示的に依存関係を定義し、作成順序を保証する
dependsOn: [role, policy],
});

—

3. タイムアウトやレートリミット対策

大規模なインフラストラクチャを一度にデプロイしようとすると、クラウドベンダーのAPI制限(レートリミット)に引っかかったり、リソースの初期化に時間がかかりすぎてタイムアウトエラーが発生します。

よくあるエラー

> `error: aws:ec2/natGateway:NatGateway resource is taking too long to create (timeout: 30m)`

現場の知見と解決策

Pulumiでは、リソースオプションの `customTimeouts` を使ってタイムアウト時間を延長できます。また、大量のリソースを並列作成してレートリミットを叩く場合は、`pulumi up` の並列度(Parallelism)を制限するのが有効です。

import as aws from “@pulumi/aws”;

const natGateway = new aws.ec2.NatGateway(“main”, {
allocationId: eip.id,
subnetId: subnet.id,
}, {
// タイムアウトを40分に延長
customTimeouts: {
create: “40m”,
update: “40m”,
delete: “20m”,
},
});

さらに、CLIで実行する際は `–parallel` フラグを使って同時実行数を絞ることで、API制限を回避できます。

同時リクエスト数を「2」に制限して安全にデプロイ
pulumi up –parallel 2

—

4. スタックがロックされた場合の強制解除手順

チーム開発やCI/CDパイプラインで最も恐ろしいエラーが「スタックのロック」です。前回のデプロイが予期せぬ中断(強制終了やネットワーク切断など)をした場合、Pulumiの状態(State)ファイルにロックが残り、次回のデプロイができなくなります。

よくあるエラー

> `error: the stack is currently locked by a lock (id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)`

現場の知見と解決策

「誰かがデプロイ中でなければ」、これは安全に解除できます。焦らず以下の手順を踏んでください。

解決手順:
1. 現在実際に他のデプロイが走っていないことを確認する(CI/CDのログなどを見る)。
2. 以下のコマンドで強制的にロックを解除(破棄)する。

–yes をつけることで対話プロンプトをスキップ可能
pulumi cancel –yes

もし、上記コマンドでも解除できない頑固なロックの場合は、バックエンドストレージ(Pulumi Service、S3、GCSなど)の状態を確認し、明示的にロックファイルやメタデータをクリアする必要があります(※Pulumi Serviceの場合はWebコンソールやCLIから管理可能です)。

—

基礎セットアップ & HelloWorld から学ぶ Pulumi の本質

ここからは、これからPulumiを触る方に向けて、最短で環境を構築し、正確に動作確認を行う手順を解説します。

1. ツールの役割と全体像

Pulumiは、「使い慣れたプログラミング言語でインフラの設計図を書き、それをクラウドのAPIコールに変換して実行するエンジン」です。

  • IaCコード(TypeScript/Python等) ➔ Pulumi CLI(差分計算・計画) ➔ クラウドAPI

2. インストール手順 (macOS / Linux / Windows)

まずはPulumi CLI本体をインストールします。

macOS (Homebrew)
brew install pulumi

Linux / WSL (公式インストールスクリプト)
curl -fsSL https://get.pulumi.com | sh

インストールが成功したか確認します。

pulumi version

3. 初めてのプロジェクト作成 (HelloWorld)

それでは、最もシンプルなTypeScript環境でAWS(またはローカル環境)にリソースを作るプロジェクトを初期化しましょう。

任意の空ディレクトリを作成し、プロジェクトをセットアップします。

mkdir pulumi-hello-world
cd pulumi-hello-world

対話式テンプレートの生成
pulumi new aws-typescript

途中で以下を聞か質問されますが、デフォルトのままでEnterを押していけばOKです。

  • `project name`: (デフォルトのまま)
  • `project description`: (デフォルトのまま)
  • `stack name`: `dev`
  • `aws:region`: `ap-northeast-1` (東京リージョン)

これで、プロジェクトの雛形(`index.ts`, `Pulumi.yaml`, `package.json` など)が自動生成されます。

4. 最もシンプルなコードを書く

生成された `index.ts` を開き、中身を以下のように書き換えてみてください。S3バケットを1つ作るだけの、極めてクリーンなコードです。

import as pulumi from “@pulumi/pulumi”;
import as aws from “@pulumi/aws”;

// 1. セキュアなS3バケットを定義
const bucket = new aws.s3.Bucket(“my-first-pulumi-bucket”, {
acl: “private”,
tags: {
Environment: “Development”,
ManagedBy: “Pulumi”,
},
});

// 2. スタックの出力(Outputs)としてバケット名のエクスポート
// デプロイ完了後にターミナルに値が表示されます
export const bucketName = bucket.id;
export const bucketDomainName = bucket.bucketDomainName;

5. 精度高い動作確認(デプロイと破棄)

それでは、このコードを実際にクラウドへ適用してみましょう。

pulumi up

実行すると、Pulumiがコードと現在のクラウド状態を比較し、作成されるリソースのプレビュー(差分)を表示してくれます。「`Do you want to perform this update?`」と聞かれるので、`yes` を選択します。

数秒後、デプロイが成功し、エクスポートした `bucketName` が画面に表示されれば大成功です!

最後に、検証が終わったらリソースを綺麗に掃除(削除)します。

pulumi destroy –yes

これで、あなたが作成したクラウド上のリソースは跡形もなく安全に削除されます。

—

まとめ

Pulumiは、エラーが発生した時でも「どのレイヤー(認証、依存関係、レートリミット、ステートロック)で起きているか」を論理的に切り分ければ、怖くありません。

プログラミング言語の柔軟性と、堅牢なIaCの思想を掛け合わせたPulumiをマスターすれば、あなたのインフラ管理は間違いなく次のステージへ進化します。ぜひ今日の知見を日々の開発に役立ててください!

タイトルとURLをコピーしました