【実務・中級編】PulumiとOpenAI APIを連携させたIaC自動生成ボットの作り方:チャットからインフラをデプロイする実験的試み – インフラ構成管理(IaC)活用バイブル

PulumiとOpenAI APIが生み出すインフラの未来:チャットから安全にクラウドリソースをデプロイする実験的試み

こんにちは。テックリードの私だ。

日々、Terraformの巨大なHCL(HashiCorp Configuration Language)と格闘し、状態ファイルのロック競合に頭を悩ませ、AWSの複雑なIAMポリシーを前に絶望していないだろうか? 「こういう構成のVPCをサクッと作ってよ」とSlackで投げられた要件を、わざわざ数時間かけてコードに落とし込み、`plan`を通す作業は、もはや現代のエンジニアリングにおける高級な苦行でしかない。

私たちはコードを書くためにエンジニアになったのではない。ビジネス価値を高速にデプロイするためにインフラを支配しているのだ。

今回は、次世代のインフラストラクチャ・アズ・コード(IaC)フレームワークである Pulumi と OpenAI API を完全に同期させ、自然言語のチャットプロンプトから安全にPulumiコードを動的生成・プレビュー・デプロイまで完結させる「実験的AIインフラボット」の核心を解説する。

単なるお遊びのプロトタイプではない。実務の現場で耐えうる冪等性(Idempotency)の担保、LLMハルシネーション対策の厳格なバリデーション、そしてチーム開発におけるガバナンスまで踏み込んだ、プロのための実践的知見を伝授しよう。

—

1. なぜ「Pulumi × OpenAI」なのか?

TerraformやOpenHCLベースのツールに対して、Pulumiが圧倒的な優位性を持つ理由は一つ。「本物のプログラミング言語(TypeScript, Python, Go, C#など)」でインフラを記述できる点にある。

LLM(Large Language Model)にとって、独自ドメイン言語であるHCLを出力させるよりも、世界中の膨大なコードベースを学習したTypeScriptやPythonを出力させる方が、圧倒的に精度が高い。LLMはプログラミング言語の構文木、型システム、エコシステムを深く理解している。

この特性を活かし、「自然言語プロンプト $\rightarrow$ OpenAI API(コード生成) $\rightarrow$ Pulumi Engine(バリデーション & プレビュー)」 というパイプラインを構築する。

—

2. 開発スピードを極限まで高める:Pulumi開発の秘匿テクニック

本題に入る前に、日々のPulumi開発をマッハで加速させるための「プロの隠し味」を共有しておこう。

👑 開発効率を爆上げするVS Codeプラグイン

  • Pulumi Extension: リソースのホバープレビュー、スタックの状態確認、ログ追跡がIDE内で完結する。これなしでの開発は目隠しで高速道路を走るようなものだ。
  • Error Lens: コード上の型エラーやPulumiのプロパティ不足をリアルタイムでインライン表示。LLMが生成したコードのデバッグ速度が3倍になる。

⌨️ キーボードショートカット(Mac / Win)

  • `Cmd + Shift + P` (Mac) / `Ctrl + Shift + P` (Win) から `Pulumi: Preview` を即座に呼び出せるよう、カスタムキーバインド(例: `Cmd + Alt + P`)を割り当てておけ。指をマウスに伸ばした瞬間からエンジニアの生産性は死に始める。

—

3. アーキテクチャ概要:AIインフラボットの全貌

今回構築するシステムのデータフローは以下の通りだ。

[ Slack / CLI ]
│ (自然言語プロンプト)
▼
[ FastAPI Backend ]
│ (プロンプト + スキーマ制約)
▼
[ OpenAI API (GPT-4o) ]
│ (TypeScriptコード片)
▼
[ 厳格なAST/Regex バリデーション ] ──(NG)──> [ エラー返却 ]
│ (OK)
▼
[ Pul Automation API ]
│ (インメモリで pulumi preview 実行)
▼
[ 結果(Diff)をユーザーに通知 ]

ここで最大の肝となるのは、OpenAIが出力したコードをそのまま信じて実行しないことだ。インフラストラクチャにおいて「ちょっとしたハルシネーション(幻覚)」は、S3バケットのパブリック公開や、セキュリティグループの `0.0.0.0/0` 開放といった致命的なセキュリティインシデントに直結する。

—

4. 実装:安全なAI駆動型Pulumiコード生成エンジン

それでは、核心となるPython実装を見ていこう。ここではPulumiの強力な武器である Automation API を使用する。ファイルI/Oを介さずに、プログラム内から動的にPulumiのライフサイクル(プレビューやアップ)を完全制御できる。

依存関係の定義 (`requirements.txt`)

pulumi>=3.100.0
pulumi-aws>=6.0.0
openai>=1.12.0
pydantic>=2.6.0
fastapi>=0.110.0
uvicorn>=0.27.0

1. セキュアなコード生成&バリデーションエンジン (`bot_engine.py`)

import os
import re
from openai import OpenAI
from pydantic import BaseModel, Field

client = OpenAI(api_key=os.environ.get(“OPENAI_API_KEY”))

class InfrastructureRequest(BaseModel):
prompt: str = Field(…, description=”構築したいインフラの自然言語説明”)
environment: str = Field(“staging”, description=”対象環境 (staging / production)”)

class CodeGenerator:
SYSTEM_PROMPT = “””
あなたは世界最高峰のPulumiおよびAWSインフラストラクチャ・アーキテクトです。
ユーザーの自然言語要求に基づき、Pulumi TypeScript (AWS) のコード断片を生成してください。

【絶対遵守ルール】
1. 出力は有効なTypeScriptのコードブロック( … )のみにすること。余計な解説は一切不要。
2. リソース名には必ず環境名(例: staging)をプレフィックス/サフィックスとして付与し、既存リソースと衝突しないようにすること。
3. セキュリティグループやS3バケットなどのパブリック公開は厳禁。プライベートな設定をデフォルトとすること。
4. Pulumiのインポート文(`import as aws from “@pulumi/aws”;` 等)を含めること。
“””

@classmethod
def generate_pulumi_code(cls, req: InfrastructureRequest) -> str:
response = client.chat.completions.create(
model=”gpt-4o”,
messages=[
{“role”: “system”, “content”: cls.SYSTEM_PROMPT},
{“role”: “user”, “content”: f”環境: {req.environment}\n要求: {req.prompt}”}
],
temperature=0.1, # 創造性を抑え、正確性を重視
)

raw_content = response.choices[0].message.content
return cls._extract_and_validate_code(raw_content)

@staticmethod
def _extract_and_validate_code(content: str) -> str:
# MarkdownのコードブロックからTypeScript部分を抽出
match = re.search(r”\s(.?)\s”, content, re.DOTALL)
if not match:
raise ValueError(“LLMが有効なTypeScriptコードブロックを出力しませんでした。”)

code = match.group(1)

# 危険なキーワードのブラックリスト検証(セキュリティの防壁)
dangerous_patterns = [
r”0\.0\.0\.0/0″, # 全面開放のIP
r”publicRead”, # S3のパブリック読み取り
r”destroy\s\(“, # 意図しない削除系メソッドの直書き
]

for pattern in dangerous_patterns:
if re.search(pattern, code):
raise SecurityError(f”セキュリティポリシー違反検知: 危険なパターン ‘{pattern}’ が含まれています。”)

return code

class SecurityError(Exception):
pass

—

5. Pulumi Automation APIによるインメモリプレビューの実行

コードが安全であることを検証したら、次はPulumi Engineにこれを渡し、実際のクラウド環境に対する影響(Diff)を計算させる。ファイルシステムを汚さず、一時的なスタックとしてメモリ上で安全にハンドリングする。

プレビュー実行モジュール (`runner.py`)

import os
from pulumi.automation import LocalWorkspace, Stack, InlineProgramArgs

def run_pulumi_preview(ts_code: str, stack_name: str = “ai-bot-staging”) -> str:
“””
動的に生成されたTypeScriptコードを受け取り、
一時的なワークスペース上で pulumi preview を実行して結果を返す。
“””

# インフラ定義を一時的なファイルとして書き出す(PulumiのTSプロジェクト構造に合わせる)
project_dir = f”/tmp/pulumi_{stack_name}”
os.makedirs(project_dir, exist_ok=True)

with open(os.path.join(project_dir, “index.ts”), “w”) as f:
f.write(ts_code)

with open(os.path.join(project_dir, “Pulumi.yaml”), “w”) as f:
f.write(“””
name: ai-infrastructure-bot
runtime: nodejs
description: AI-generated infrastructure stack
“””)

# インラインプログラムとしてPulumiを実行
def pulumi_program():
# index.ts が自動的にロードされるように設定
pass

args = InlineProgramArgs(
project_name=”ai-infrastructure-bot”,
stack_name=stack_name,
program=pulumi_program,
work_dir=project_dir
)

try:
# ローカルワークスペースの初期化
workspace = LocalWorkspace(work_dir=project_dir)
stack = Stack.select_or_create(stack_name=stack_name, workspace=workspace)

# スタックの構成設定(例: AWSリージョン)
stack.set_config(“aws:region”, “ap-northeast-1″)

# プレビューの実行
preview_result = stack.preview()

return f”””
=== Pulumi Preview 成功 ===
変更サマリー:

  • 追加 (Create): {preview_result.change_summary.get(‘CREATE’, 0)}
  • 更新 (Update): {preview_result.change_summary.get(‘UPDATE’, 0)}
  • 削除 (Delete): {preview_result.change_summary.get(‘DELETE’, 0)}

“””
except Exception as e:
return f”Pulumiプレビュー実行失敗: {str(e)}”

—

6. チーム開発で役立つ設定の共有化ルール

このようなAI駆動型のIaCツールをチームに導入する場合、個人のローカル環境依存を排除し、ガバナンスを効かせることが極めて重要だ。以下の設定ファイルをリポジトリのルートに配置し、チーム全体でルールを強制せよ。

1. 組織共通のPulumi設定 (`Pulumi.yaml`) のベストプラクティス

name: core-infrastructure-governance
runtime: nodejs
description: Enterprise-grade infrastructure managed by AI & Pulumi
config:
pulumi:tags:
value:
Environment: staging
ManagedBy: “AI-Infrastructure-Bot”
Repository: “github.com/org/infra-repo”

2. VS Code ワークスペース設定 (`.vscode/settings.json`)

チーム全員が同一のフォーマット規則と静的解析の恩恵を受けるための設定だ。

{
“editor.formatOnSave”: true,
“editor.codeActionsOnSave”: {
“source.fixAll.eslint”: “explicit”
},
“typescript.suggest.completeFunctionCalls”: true,
“files.associations”: {
“Pulumi..yaml”: “yaml”
}
}

—

7. 実務での安全な適用可能性についての考察

「チャットからインフラを生やす」というアプローチは、デモとしては非常に魅力的だが、SREの現場にこれをそのまま本番環境(Production)へ適用するのは自殺行為である。

実務で運用するための要件を最後に整理しておこう。

1. 「Preview(計画)」までの自動化に留める
チャットボットが実行してよいのは、あくまで `pulumi preview` までだ。`pulumi up`(適用)の実行権限は、ボットには持たせない。最終的なデプロイは、出力されたDiffを確認した上で、人間がGitHub上のPull Requestをマージする、あるいは専用の承認フロー(Approval Gate)を通過させる設計に厳格に制限すべきである。
2. 生成コードのGitコミット&監査証跡
LLMが生成したコードは、一過性のものではなく、必ず自動的にfeatureブランチとしてGitリポジトリにコミットし、PRを作成するフローに組み込むこと。IaCの本質は「コードによる状態の管理と履歴の監査可能性」にある。AIが生成したものであろう例外はない。
3. コスト見積もり(Infracost)の統合
コード生成とプレビューの間に、[Infracost](https://www.infracost.io/) などのコスト見積もりツールを挟むべきだ。「このプロンプトを実行すると、月額いくらインフラ費用が増加するか」をチャット上で定量的にフィードバックする仕組みを作って初めて、実用に耐えうる「プロのAIインフラボット」となる。

—

結びに代えて

PulumiとOpenAI APIの融合は、インフラ構築のパラダイムシフトの序章に過ぎない。私たちは「YAMLやHCLの構文を覚える作業」から解放され、「どのようなシステムアーキテクチャがビジネスに最適か」という本質的な設計に集中できる時代に突入している。

だが忘れてはならない。ツールがいかに高度になろうとも、インフラの信頼性、可用性、セキュリティに対する最終的な責任を負うのは、画面の前に座る我々エンジニア自身だ。

機械にコードを書かせ、人間が知性で統御する。この黄金比をマスターしたチームこそが、これからのインフラ自動化のフロンティアを制することになる。さあ、今すぐ手を動かし、あなたの開発パイプラインにこの知見を組み込んでみてほしい。

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