关于 pulumi-typescript
用于以 TypeScript 编写和部署 Pulumi 基础设施项目的技能,涵盖 Pulumi ESC 配置与密钥、可复用组件、堆栈引用,以及先预览和验证再部署的工作流。
主要功能
- 01TypeScript 项目设置与模式
- 02Pulumi ESC 配置和密钥
- 03可复用及多语言组件
- 04堆栈引用与输出处理
- 05预览、验证和部署工作流
适用场景
- 01使用 TypeScript 模板启动基础设施项目
- 02通过 ESC 管理堆栈配置和凭据
- 03在不同 Pulumi 语言间共享可复用组件
- 04部署前审查基础设施变更
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ dirien/ claude-skills --skill pulumi-typescript安装后在 Claude Code 中输入/pulumi-typescript确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/pulumi-best-practices-aws.mdpulumi-best-practices-azure.mdpulumi-best-practices-gcp.mdpulumi-esc.mdpulumi-patterns.mdpulumi-typescript.md详细介绍
Pulumi TypeScript 技能
开发工作流
1. 项目设置
# Create new TypeScript project
pulumi new typescript
# Or with a cloud-specific template
pulumi new aws-typescript
pulumi new azure-typescript
pulumi new gcp-typescript
项目结构:
my-project/
├── Pulumi.yaml
├── Pulumi.dev.yaml # Stack config (use ESC instead)
├── package.json
├── tsconfig.json
└── index.ts
2. Pulumi ESC 集成
请使用 Pulumi ESC 集中管理密钥和配置,而不是使用 pulumi config set 或堆栈配置文件。
将 ESC 环境关联到堆栈:
# Create ESC environment
pulumi env init myorg/myproject-dev
# Edit environment
pulumi env edit myorg/myproject-dev
# Link to Pulumi stack
pulumi config env add myorg/myproject-dev
ESC 环境定义(YAML):
values:
# Static configuration
pulumiConfig:
aws:region: us-west-2
myapp:instanceType: t3.medium
# Dynamic OIDC credentials for AWS
aws:
login:
fn::open::aws-login:
oidc:
roleArn: arn:aws:iam::123456789:role/pulumi-oidc
sessionName: pulumi-deploy
# Pull secrets from AWS Secrets Manager
secrets:
fn::open::aws-secrets:
region: us-west-2
login: ${aws.login}
get:
dbPassword:
secretId: prod/database/password
# Expose to environment variables
environmentVariables:
AWS_ACCESS_KEY_ID: ${aws.login.accessKeyId}
AWS_SECRET_ACCESS_KEY: ${aws.login.secretAccessKey}
AWS_SESSION_TOKEN: ${aws.login.sessionToken}
3. TypeScript 模式
创建基础资源:
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Get configuration from ESC
const config = new pulumi.Config();
const instanceType = config.require("instanceType");
// Create resources with proper tagging
const bucket = new aws.s3.Bucket("my-bucket", {
versioning: { enabled: true },
serverSideEncryptionConfiguration: {
rule: {
applyServerSideEncryptionByDefault: {
sseAlgorithm: "AES256",
},
},
},
tags: {
Environment: pulumi.getStack(),
ManagedBy: "Pulumi",
},
});
// Export outputs
export const bucketName = bucket.id;
export const bucketArn = bucket.arn;
使用组件资源实现复用:
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
interface WebServiceArgs {
port: pulumi.Input<number>;
imageUri: pulumi.Input<string>;
}
class WebService extends pulumi.ComponentResource {
public readonly url: pulumi.Output<string>;
constructor(name: string, args: WebServiceArgs, opts?: pulumi.ComponentResourceOptions) {
super("custom:app:WebService", name, {}, opts);
// Create child resources with { parent: this }
const lb = new aws.lb.LoadBalancer(`${name}-lb`, {
loadBalancerType: "application",
// ... configuration
}, { parent: this });
this.url = lb.dnsName;
this.registerOutputs({ url: this.url });
}
}
使用堆栈引用处理跨堆栈依赖:
import * as pulumi from "@pulumi/pulumi";
// Reference outputs from networking stack
const networkingStack = new pulumi.StackReference("myorg/networking/prod");
const vpcId = networkingStack.getOutput("vpcId");
const subnetIds = networkingStack.getOutput("privateSubnetIds");
使用 Outputs:
import * as pulumi from "@pulumi/pulumi";
// Use apply for transformations
const uppercaseName = bucket.id.apply(id => id.toUpperCase());
// Use pulumi.all for multiple outputs
const combined = pulumi.all([bucket.id, bucket.arn]).apply(
([id, arn]) => `Bucket ${id} has ARN ${arn}`
);
// Conditional resources
const isProd = pulumi.getStack() === "prod";
const monitoring = isProd ? new aws.cloudwatch.MetricAlarm("alarm", {
// ... configuration
}) : undefined;
4. 使用 pulumi env run 配合 ESC
运行任何命令,并注入 ESC 环境变量:
# Run pulumi commands with ESC credentials
pulumi env run myorg/aws-dev -- pulumi up
# Run tests with secrets
pulumi env run myorg/test-env -- npm test
# Open environment and export to shell
pulumi env open myorg/myproject-dev --format shell
5. 异步模式
// Export async function for top-level await
export = async () => {
const data = await fetchExternalData();
const resource = new aws.s3.Bucket("bucket", {
tags: { data: data.value },
});
return {
bucketName: resource.id,
};
};
6. 多语言组件
使用 TypeScript 创建可供任何 Pulumi 语言(Python、Go、C#、Java、YAML)使用的组件。
多语言组件的项目结构:
my-component/
├── PulumiPlugin.yaml # Required for multi-language
├── package.json
├── tsconfig.json
└── index.ts # Component definition
PulumiPlugin.yaml:
runtime: nodejs
使用恰当 Args 接口的组件:
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Args interface - use Input types for all properties
export interface SecureBucketArgs {
// Wrap all scalar members in Input types
bucketName: pulumi.Input<string>;
enableVersioning?: pulumi.Input<boolean>;
tags?: pulumi.Input<Record<string, pulumi.Input<string>>>;
}
export class SecureBucket extends pulumi.ComponentResource {
public readonly bucketId: pulumi.Output<string>;
public readonly bucketArn: pulumi.Output<string>;
// Constructor must have 'args' parameter with type annotation
constructor(name: string, args: SecureBucketArgs, opts?: pulumi.ComponentResourceOptions) {
super("myorg:storage:SecureBucket", name, {}, opts);
const bucket = new aws.s3.Bucket(`${name}-bucket`, {
bucket: args.bucketName,
versioning: { enabled: args.enableVersioning ?? true },
serverSideEncryptionConfiguration: {
rule: {
applyServerSideEncryptionByDefault: {
sseAlgorithm: "AES256",
},
},
},
tags: args.tags,
}, { parent: this });
this.bucketId = bucket.id;
this.bucketArn = bucket.arn;
this.registerOutputs({
bucketId: this.bucketId,
bucketArn: this.bucketArn,
});
}
}
发布以供多语言使用:
# Consume from git repository
pulumi package add github.com/myorg/my-component
# With version tag
pulumi package add github.com/myorg/[email protected]
# Local development
pulumi package add /path/to/local/my-component
多语言 Args 要求:
- 所有标量属性都使用
pulumi.Input<T> - 避免使用联合类型(
string | number)——不受支持 - 避免使用函数/回调——无法序列化
- 构造函数必须具有带类型声明的
args参数
带验证的部署工作流
请遵循此经过验证的工作流,确保安全部署:
1. 预览变更
pulumi preview
查看输出,了解将创建、修改或删除哪些资源。
2. 验证变更
检查预览输出,确认:
- 是否存在意外的资源删除或修改
- 资源的数量和类型是否正确
- 配置值(区域、实例类型、标签等)是否正确
如果变更看起来不正确,请在继续之前调查根本原因:
# Check current stack state
pulumi stack output
# Review ESC environment values
pulumi env open myorg/myproject-dev
# Verify configuration
pulumi config
3. 部署
验证无误后,部署变更:
pulumi up
4. 验证输出
部署成功后,确认输出:
pulumi stack output
将输出与预期值(例如存储桶名称、端点 URL、资源 ID)进行比较。
错误恢复
如果 pulumi up 在部署过程中失败:
- 检查错误消息,找出失败的具体资源
- 检查资源配置和 ESC 环境值
- 修复根本问题(例如 IAM 权限、无效配置)
- 再次运行
pulumi up——Pulumi 会从中断处继续 - 如果堆栈状态不一致,请使用
pulumi refresh将状态与实际云资源同步
最佳实践
安全性
- 所有密钥都使用 Pulumi ESC——切勿将密钥提交到堆栈配置文件
- 启用 OIDC 身份验证,而不是使用静态凭据
- 尽可能使用 TTL 较短的动态密钥
- 应用最小权限 IAM 策略
- 始终为 S3 存储桶启用服务器端加密(AES256 或 KMS)——这是必须遵守的默认要求
- 除非明确需要,否则阻止对 S3 存储桶的公开访问
- 为存储资源启用版本控制,以保护数据
代码组织
- 使用 ComponentResources 构建可复用的基础设施模式
- 利用 TypeScript 类型系统验证配置
- 将特定于堆栈的配置保存在 ESC 环境中
- 使用堆栈引用处理跨堆栈依赖
部署
- 在运行
pulumi up之前,始终运行pulumi preview - 使用 ESC 环境版本控制和标签进行发布
- 为所有资源实施恰当的标签策略
常用命令
# Environment Commands (pulumi env)
pulumi env init <org>/<project>/<env> # Create environment
pulumi env edit <org>/<env> # Edit environment
pulumi env open <org>/<env> # View resolved values
pulumi env run <org>/<env> -- <command> # Run with env vars
pulumi env version tag <org>/<env> <tag> # Tag version
# Pulumi Commands
pulumi new typescript # New project
pulumi config env add <org>/<env> # Link ESC environment
pulumi preview # Preview changes
pulumi up # Deploy
pulumi stack output # View outputs
pulumi destroy # Tear down
pulumi refresh # Sync state with cloud
参考资料
- references/pulumi-esc.md - ESC 模式和命令
- references/pulumi-patterns.md - 常见基础设施模式
- references/pulumi-typescript.md - TypeScript 专属指南
- references/pulumi-best-practices-aws.md - AWS 最佳实践
- references/pulumi-best-practices-azure.md - Azure 最佳实践
- references/pulumi-best-practices-gcp.md - GCP 最佳实践
评论
支持 Markdown