こんにちは、HolyShehe AI技術ブログへようこそ。私は普段インフラ管理工作をしているエンジニアですが、
なぜPulumiなのか?
従来のTerraformなどのIaCツールは独自のDSL(Domain Specific Language)を学ぶ必要がありました。一方、PulumiはTypeScript、Python、Go、C#などの、普段使っているプログラミング言語でインフラを定義できます。これにより、条件分岐やループを使った柔軟なインフラ管理が可能になります。
さらに、HolyShehe AIのAPIを組み合わせることで、インフラ構成の最適化提案や自動コード生成,甚至是被災時の自動復旧スクリプトの作成まで、AIの力で自動化できます。HolyShehe AIの2026年価格はGPT-4.1 $8/MTok、Claude Sonnet 4.5 $15/MTok、DeepSeek V3.2 $0.42/MTokと、コストパフォーマンスに優れています。
必要な環境の準備
Step 1: Pulumi CLIのインストール
まず、PulumiのCLIをインストールします。macOSの場合はHomebrew、Windowsの場合はChocolateyまたはMSIインストーラーを使います。
# macOS
brew install pulumi
Windows (Chocolatey)
choco install pulumi
Linux
curl -fsSL https://get.pulumi.com | sh
インストール確認
pulumi version
出力: v3.x.x
Step 2: Node.jsとTypeScriptの準備
PulumiをTypeScriptで使うので、Node.js环境を構築します。
# Node.jsバージョン確認(v18以上を推奨)
node --version
v20.10.0
プロジェクトフォルダの作成
mkdir pulumi-ai-infra
cd pulumi-ai-infra
初期化
pulumi new typescript
必要なパッケージインストール
npm install @pulumi/pulumi @pulumi/aws
Step 3: HolyShehe AI APIキーの取得
HolyShehe AIにログインして、APIキーを取得します。ダッシュボードの「API Keys」セクションから生成できます。HolyShehe AIは¥1=$1の超優遇レート(中国語ベースの海外サービスを避けるなら注目の選択肢)で、WeChat PayやAlipayにも対応しています。登録すれば無料クレジットもらえます!
実践:AI APIを呼び出すPulumiリソースを作成
infraestructura設計
今回の目標は、EC2インスタンス上にAI APIを呼び出すLambda関数をデプロイすることです。以下の構成を作成します:
- AWS VPC(Virtual Private Cloud)
- EC2インスタンス(踏み台サーバー)
- S3バケット(ログ保存用)
- Lambda関数(HolyShehe AI API呼び出し)
Pulumiプロジェクト的文件の作成
// index.ts
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// 設定値の取得
const config = new pulumi.Config();
const openaiApiKey = config.requireSecret("holySheepApiKey");
const environment = config.get("environment") || "development";
// ========================================
// 1. VPCの作成
// ========================================
const vpc = new aws.ec2.Vpc("ai-api-vpc", {
cidrBlock: "10.0.0.0/16",
enableDnsHostnames: true,
enableDnsSupport: true,
tags: {
Name: ai-api-vpc-${environment},
Environment: environment,
},
});
// サブネットの作成
const subnet = new aws.ec2.Subnet("ai-api-subnet", {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
availabilityZone: "us-east-1a",
mapPublicIpOnLaunch: false,
tags: {
Name: ai-api-subnet-${environment},
},
});
// インターネットゲートウェイ
const igw = new aws.ec2.InternetGateway("ai-api-igw", {
vpcId: vpc.id,
tags: { Name: ai-api-igw-${environment} },
});
// ルートテーブル
const routeTable = new aws.ec2.RouteTable("ai-api-rt", {
vpcId: vpc.id,
routes: [
{
cidrBlock: "0.0.0.0/0",
gatewayId: igw.id,
},
],
});
new aws.ec2.RouteTableAssociation("ai-api-rta", {
subnetId: subnet.id,
routeTableId: routeTable.id,
});
// ========================================
// 2. S3バケット(ログ保存用)
// ========================================
const logBucket = new aws.s3.Bucket("ai-api-log-bucket", {
bucket: ai-api-logs-${environment}-${pulumi.getStack()},
acl: "private",
versioning: {
enabled: true,
},
lifecycleRule: [{
enabled: true,
expiration: 365,
transitions: [{
days: 30,
storageClass: "STANDARD_IA",
}],
}],
tags: {
Environment: environment,
},
});
// ========================================
// 3. IAMロール(Lambda用)
// ========================================
const lambdaRole = new aws.iam.Role("ai-api-lambda-role", {
name: ai-api-lambda-role-${environment},
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Action: "sts:AssumeRole",
Effect: "Allow",
Principal: {
Service: "lambda.amazonaws.com",
},
}],
}),
});
new aws.iam.RolePolicyAttachment("lambda-basic-exec", {
role: lambdaRole.name,
policyArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
});
new aws.iam.RolePolicy("lambda-s3-policy", {
role: lambdaRole.id,
policy: logBucket.id.apply(id => JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"s3:PutObject",
"s3:GetObject",
],
Resource: arn:aws:s3:::ai-api-logs-${environment}-${pulumi.getStack()}/*,
}],
})),
});
// ========================================
// 4. Lambda関数(HolyShehe AI API呼び出し)
// ========================================
const apiHandler = new aws.lambda.Function("ai-api-handler", {
functionName: ai-api-handler-${environment},
role: lambdaRole.arn,
runtime: "nodejs18.x",
handler: "index.handler",
timeout: 30,
memorySize: 256,
code: new pulumi.asset.AssetArchive({
"index.js": new pulumi.asset.StringAsset(`
const https = require('https');
exports.handler = async (event) => {
const apiKey = process.env.HOLY_SHEEP_API_KEY;
// HolyShehe AI APIへのリクエスト
const payload = JSON.stringify({
model: "gpt-4.1",
messages: [
{ role: "system", content: "あなたはインフラ管理の助手です。" },
{ role: "user", content: event.prompt || "インフラの最適化提案をしてください。" }
],
max_tokens: 500,
temperature: 0.7,
});
const options = {
hostname: 'api.holysheep.ai',
port: 443,
path: '/v1/chat/completions',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': \Bearer \${apiKey}\,
'Content-Length': Buffer.byteLength(payload),
},
};
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => {
try {
const result = JSON.parse(data);
resolve({
statusCode: 200,
body: JSON.stringify({ success: true, data: result }),
});
} catch (e) {
reject(new Error('Failed to parse API response'));
}
});
});
req.on('error', reject);
req.write(payload);
req.end();
});
};
`),
}),
environment: {
variables: {
HOLY_SHEEP_API_KEY: openaiApiKey,
LOG_BUCKET: logBucket.id,
ENVIRONMENT: environment,
},
},
});
// Lambda関数のARNを出力
export const lambdaArn = apiHandler.arn;
export const vpcId = vpc.id;
export const logBucketName = logBucket.id;
export const apiEndpoint = apiHandler.invokeArn;
Pulumi設定ファイルの作成
# Pulumi..yaml に設定を保存
config:
pulumi-ai-infra:holySheepApiKey:
secure: AAABBBCCCDDDEEEFFF...
pulumi-ai-infra:environment: production
ヒント:APIキーは「pulumi config set --secret pulumi-ai-infra:holySheepApiKey YOUR_API_KEY」で安全に保存してください。secretオプションを使うことで、KMSで暗号化されます。
デプロイの実行
# プレビュー(変更内容の確認)
pulumi preview
デプロイ
pulumi up
出力例:
Previewing update (production)
View Live: https://app.pulumi.com/...
Resources:
+ 8 to create
Do you want to proceed? [Yes] yes
Updating (production)
Duration: 2m45s
Outputs:
lambdaArn: "arn:aws:lambda:us-east-1:123456789:function:ai-api-handler-production"
vpcId: "vpc-0a1b2c3d4e5f6g7h8"
logBucketName: "ai-api-logs-production-abc123"
Resources:
8 created
AIを活用したインフラ最適化の実例
HolyShehe AIのAPIを使って、インフラコストを自動最適化するスクリプトを作成しました。以下のコードは、月の利用コストを分析して最適化の提案を生成するものです。
// optimizer.ts - AIを活用したインフラ最適化
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const config = new pulumi.Config();
interface CostReport {
service: string;
monthlyCost: number;
utilization: number;
recommendations: string[];
}
const HOLY_SHEEP_API_KEY = config.requireSecret("holySheepApiKey");
// コストデータを取得する関数
async function fetchCostData(): Promise {
// 実際の実装ではCost Explorer APIを使用
return [
{ service: "EC2", monthlyCost: 450, utilization: 0.35, recommendations: [] },
{ service: "RDS", monthlyCost: 280, utilization: 0.45, recommendations: [] },
{ service: "CloudWatch", monthlyCost: 85, utilization: 0.80, recommendations: [] },
{ service: "S3", monthlyCost: 120, utilization: 0.60, recommendations: [] },
];
}
// HolyShehe AI APIを呼び出して最適化提案を取得
async function getOptimizationFromAI(costData: CostReport[]): Promise<string> {
const apiUrl = new URL("https://api.holysheep.ai/v1/chat/completions");
const requestBody = {
model: "deepseek-v3.2",
messages: [
{
role: "system",
content: `あなたはAWSコスト最適化の専門家です。
以下のコストデータに基づき、具体的な改善案をJSON形式で提案してください。
{
"actions": [
{
"priority": "high|medium|low",
"service": "サービス名",
"action": "取るべきアクション",
"estimatedSavings": "USD/月",
"risk": "低|中|高"
}
],
"summary": "全体の要約"
}`
},
{
role: "user",
content: AWSコストデータを分析してください:${JSON.stringify(costData, null, 2)}
}
],
max_tokens: 1500,
temperature: 0.3,
};
const response = await fetch(apiUrl.toString(), {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": Bearer ${HOLY_SHEEP_API_KEY},
},
body: JSON.stringify(requestBody),
});
if (!response.ok) {
throw new Error(API request failed: ${response.status});
}
const result = await response.json();
return result.choices[0].message.content;
}
// メイン処理
export async function runCostOptimization() {
console.log("コストデータの取得中...");
const costData = await fetchCostData();
const totalCurrentCost = costData.reduce((sum, item) => sum + item.monthlyCost, 0);
console.log(現在の月間コスト: $${totalCurrentCost});
console.log("AIによる最適化提案を取得中...");
const aiSuggestions = await getOptimizationFromAI(costData);
console.log("=== AI最適化提案 ===");
console.log(aiSuggestions);
// 提案をS3に保存
const timestamp = new Date().toISOString();
console.log(推奨事項は logs/suggestions-${timestamp}.json に保存されます);
return {
currentCost: totalCurrentCost,
suggestions: aiSuggestions,
timestamp,
};
}
HolyShehe AIの具体的な活用メリット
私が実際にHolyShehe AIを使って感じているメリットは他にもたくさんあります:
- latency :50ms未満の応答速度でリアルタイムのインフラ監視と自動対応が可能
- pricing :DeepSeek V3.2が$0.42/MTokと破格の安さで、コスト重視の開発者に最適
- 支払い方法 :WeChat Pay、Alipay対応で中国人民元のまま決済可能(面倒な外汇換算不要)
- 信頼性 :私も何度か利用していますが、リクエスト失敗率は0.1%以下で安定しています
よくあるエラーと対処法
エラー1: APIキー認証エラー (401 Unauthorized)
// エラー内容
Error: Request failed with status code 401
{
"error": {
"message": "Invalid authentication credentials",
"type": "invalid_request_error",
"code": "invalid_api_key"
}
}
// 原因:APIキーが無効または期限切れ
// 解決方法
// 1. キーが正しく設定されているか確認
pulumi config get holySheepApiKey
// 2. キーがsecretで保存されているか確認(再設定)
pulumi config set --secret pulumi-ai-infra:holySheepApiKey YOUR_ACTUAL_API_KEY
// 3. スタックによって異なるキーを使用する場合
pulumi config set --secret pulumi-ai-infra:holySheepApiKey YOUR_KEY --stack production
// 4. 環境変数として直接設定(開発時のみ)
export HOLY_SHEEP_API_KEY=YOUR_API_KEY
// 5. コードでの正しい読み込み方
const config = new pulumi.Config();
const apiKey = config.requireSecret("holySheepApiKey");
// 絶対にハードコードしないこと!
エラー2: レートリミットExceeded (429 Too Many Requests)
// エラー内容
Error: Request failed with status code 429
{
"error": {
"message": "Rate limit exceeded for gpt-4.1",
"type": "rate_limit_error",
"retry_after": 5
}
}
// 原因:短時間に大量のリクエストを送信した
// 解決方法
// 1. リトライロジックを実装(指数バックオフ)
async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.response?.status === 429 && i < maxRetries - 1) {
const waitTime = Math.pow(2, i) * 1000;
console.log(Retry after ${waitTime}ms...);
await new Promise(resolve => setTimeout(resolve, waitTime));
} else {
throw error;
}
}
}
}
// 2. 安いモデルに変更してコストも節約
const requestBody = {
model: "deepseek-v3.2", // $0.42/MTok - コスト効率最高
messages: [...],
max_tokens: 500, // 必要最低限に設定
};
// 3. バッチ処理でリクエストをまとめる
const batchPrompts = ["prompt1", "prompt2", "prompt3"];
const batchRequest = {
model: "deepseek-v3.2",
messages: batchPrompts.map(p => ({ role: "user", content: p })),
};
エラー3: Pulumiリソースの依存関係エラー
// エラー内容
Error: Resource 'lambda-function' is missing required property 'role'
and depends on 'lambda-role' which was created with errors.
Diagnostics:
aws:lambda/function:Function resource 'lambda-function' has a problem:
"role": one value does not match regular expression...
// 原因:Lambda関数がIAMロールを作成するのを待つ前に実行された
// 解決方法
// 1. 明示的な依存関係を追加
const lambdaFunction = new aws.lambda.Function("api-handler", {
// ... other options
role: lambdaRole.arn, // pulumiが自動的に依存関係を解決
});
// 2. apply()を使って非同期依存関係を処理
const s3Bucket = new aws.s3.Bucket("log-bucket", {...});
const lambdaWithBucket = new aws.lambda.Function("handler", {
// ...
environment: {
variables: {
BUCKET_NAME: s3Bucket.id, // pulumiのOutputは自動的に解決
},
},
});
// 3. カスタムリソースで複雑な依存関係を管理
const customDeps = pulumi.all([vpc.id, subnet.id]).apply(([vpcId, subnetId]) => {
return { vpcId, subnetId };
});
// 4. スタック参照を使った跨スタック依存関係
const infraStack = new pulumi.StackReference("acmecorp/infra/production");
const vpcId = infraStack.getOutput("vpcId");
const subnetId = infraStack.getOutput("subnetId");
エラー4: TypeScriptコンパイルエラー
// エラー内容
error TS2322: Type 'Output<string>' is not assignable to type 'string'
// 原因:PulumiのOutput型を直接文字列として使用した
// 解決方法
// ❌ 間違い
const vpcId: string = vpc.id; // vpc.idはOutput
// ✅ 正しい方法1: apply()を使用
const securityGroup = new aws.ec2.SecurityGroup("sg", {
vpcId: vpc.id, // Pulumiが自動的に処理
});
// ✅ 正しい方法2: apply()で値を変換
vpc.id.apply(id => {
console.log(VPC ID: ${id});
return id;
});
// ✅ 正しい方法3: 出力先での使用
new aws.ec2.SecurityGroupRule("rule", {
type: "ingress",
fromPort: 443,
toPort: 443,
protocol: "tcp",
sourceSecurityGroupId: securityGroup.id, // 自動的に解決
});
// ✅ 正しい方法4: エクスポートでの使用
export const vpcId = vpc.id; // スタック出力で自動的に文字列化
次のステップ
今回の記事を基に、以下のことにチャレンジしてみてください:
- 複数環境の構築:staging、production環境を Pulumi Stack で管理
- CI/CD統合:GitHub Actionsと組み合わせて自動デプロイ
- コスト監視ダッシュボード:CloudWatchとHolyShehe AIで異常検知