关于 pulumi-cdk-to-pulumi
用于指导 CDK 到 Pulumi 迁移的技能,涵盖资源转换、自定义资源、资产处理、验证和 PR 报告,面向处理 AWS 基础设施迁移的 Agent。
主要功能
- 01分步迁移工作流
- 02CDK 资源盘点与转换
- 03自定义资源替换指导
- 04资产与打包迁移指导
- 05导入与预览验证
- 06面向 PR 的迁移报告
适用场景
- 01将 CDK 项目转换为 Pulumi 代码
- 02识别迁移中的遗漏资源或自定义资源
- 03规划 CDK 资产及构建步骤的处理方式
- 04交付前验证已导入的堆栈
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pulumi/ agent-skills --skill pulumi-cdk-to-pulumi安装后在 Claude Code 中输入/pulumi-cdk-to-pulumi确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
cdk-convert.mdcdk-importer.mdcloudformation-id-lookup.mduse_cases.yamlagents/openai.yaml详细介绍
关键成功要求
迁移输出必须满足以下所有要求:
-
完整覆盖资源
- CDK 合成的每个 CloudFormation 资源都必须:
- 在 Pulumi 程序中表示,或
- 在最终报告中明确说明原因。
- CDK 合成的每个 CloudFormation 资源都必须:
-
成功部署
- 生成的 Pulumi 程序在结构上必须有效,并能够成功执行
pulumi up(假设配置正确)。
- 生成的 Pulumi 程序在结构上必须有效,并能够成功执行
-
最终迁移报告
- 始终输出适用于 Pull Request 的正式迁移报告。
- 内容包括:
- CDK → Pulumi 资源映射
- Provider 决策(aws-native 与 aws)
- 行为差异
- 缺失内容或需要手动完成的步骤
- 验证说明
信息缺失时
如果用户提供的 CDK 项目不完整、存在歧义或缺少构件(例如 cdk.out),请先提出有针对性的问题,再生成 Pulumi 代码。
迁移工作流
请严格按以下顺序执行此工作流:
1. 信息收集
1.1 验证 AWS 凭证(ESC)
运行 AWS 命令(例如 aws cloudformation list-stack-resources)和 CDK 命令(例如 cdk synth)需要通过 Pulumi ESC 加载凭证。
- 如果用户已提供 ESC 环境,请使用该环境。
- 如果未指定 ESC 环境,请先询问用户要使用哪个 ESC 环境,再运行 AWS 命令。
你必须向用户确认 AWS 区域。如果使用了错误的 AWS 区域,cdk synth 的结果可能不正确。
1.2 合成 CDK
运行或检查:
npx cdk synth --quiet
- 始终使用
--quiet运行synth,以防止模板输出到 stdout。
如果失败,请检查 cdk.json 或 package.json 中是否配置了自定义合成行为。
1.3 识别 CDK 栈和环境
读取 cdk.out/manifest.json:
jq '.artifacts | to_entries | map(select(.value.type == "aws:cloudformation:stack") | {displayName: .key, environment: .value.environment}) | .[]' cdk.out/manifest.json
示例输出:
{
"displayName": "DataStack-dev",
"environment": "aws://616138583583/us-east-2"
}
{
"displayName": "AppStack-dev",
"environment": "aws://616138583583/us-east-2"
}
在创建的 Pulumi 栈中,必须设置 aws:region 和 aws-native:region 配置变量。例如:
pulumi config set aws-native:region us-east-2 --stack dev
pulumi config set aws:region us-east-2 --stack dev
1.4 构建资源清单
针对每个栈:
aws cloudformation list-stack-resources \
--region <region> \
--stack-name <stack> \
--output json
1.5 分析 CDK 结构
提取:
- 特定环境的条件逻辑
- 栈依赖关系和跨栈引用
- 运行时配置(上下文/环境变量)
- 构造类型(L1、L2、L3)
2. 代码转换(CDK → PULUMI)
- 使用
cdk2pulumi工具执行初始转换。按照 cdk-convert.md 中的说明进行转换。 - 阅读转换报告并补全所有遗漏。例如,如果转换未能转换某个资源,你必须自行手动转换。
2.1 自定义资源处理
CDK 使用 Lambda 支持的自定义资源来实现 CloudFormation 不支持的功能。在合成的 CloudFormation 中,这些资源会显示为:
- 资源类型:
AWS::CloudFormation::CustomResource或Custom::<name> - 元数据包含
aws:cdk:path,其中记录了处理程序名称(例如,aws-s3/auto-delete-objects-handler)
默认行为:cdk2pulumi 会将自定义资源重写为 aws-native:cloudformation:CustomResourceEmulator,由其调用原始 Lambda。此方式可用,但也有一些取舍(依赖 Lambda、冷启动和最终一致性)。
按处理程序类型采用的迁移策略:
| 处理程序 | 策略 |
|---|---|
aws-certificatemanager/dns-validated-certificate-handler | 替换为 aws.acm.Certificate、aws.route53.Record 和 aws.acm.CertificateValidation |
aws-ec2/restrict-default-security-group-handler | 替换为 aws.ec2.DefaultSecurityGroup 资源,并设置空的入站/出站规则 |
aws-ecr/auto-delete-images-handler | 将 aws-native:ecr:Repository 替换为 aws.ecr.Repository,并设置 forceDelete: true |
aws-s3/auto-delete-objects-handler | 将 aws-native:s3:Bucket 替换为 aws.s3.Bucket,并设置 forceDestroy: true |
aws-s3/notifications-resource-handler | 替换为 aws.s3.BucketNotification |
aws-logs/log-retention-handler | 替换为 aws.cloudwatch.LogGroup,并显式设置 retentionInDays |
aws-iam/oidc-handler | 替换为 aws.iam.OpenIdConnectProvider |
aws-route53/delete-existing-record-set-handler | 替换为 aws.route53.Record,并设置 allowOverwrite: true |
aws-dynamodb/replica-handler | 替换为 aws.dynamodb.TableReplica |
跨账号/区域处理程序:
aws-cloudfront/edge-function→ 使用aws.lambda.Function,并设置region: "us-east-1"aws-route53/cross-account-zone-delegation-handler→ 使用单独的 aws 提供程序,并通过跨账号角色进行身份代入
未知处理程序的优雅降级:
- 保留
CustomResourceEmulator(默认行为) - 在迁移报告中记录该自定义资源,包括:
- 原始处理程序名称和用途(如果可以从 CDK 路径中判断)
- 说明其会在运行时调用 Lambda
- 建议用户评估是否可以替换为原生资源
2.2 提供程序策略
- 默认:只要资源类型可用,就使用
aws-native。 - 回退:当 aws-native 不支持等效功能时,使用
aws。
2.3 资源与打包
CDK 使用资源和打包来处理部署产物。CDK CLI 会在 CloudFormation 部署前处理这些产物,并将其放在 cdk.out 目录中,与 *.assets.json 元数据文件并列。CloudFormation 模板中包含对资源位置(S3 存储桶/键或 ECR 存储库/标签)的硬编码引用。
# Inspect asset definitions
jq '.files, .dockerImages' cdk.out/*.assets.json
按资源类型选择迁移策略:
| 资源类型 | 检测方式 | Pulumi 迁移 |
|---|---|---|
| Docker 镜像 | assets.json 中的 dockerImages | 使用 docker-build.Image 进行构建和推送。将硬编码的 ECR URI 替换为镜像输出。 |
| 带构建命令的文件 | files 中带有 executable 字段 | 向用户标记——需要在 Pulumi 中设置构建命令 |
| 静态文件 | files 中没有 executable,且 CDK 源码中没有打包 | 使用 pulumi.FileArchive 或 pulumi.FileAsset |
| 已打包的文件 | files 中没有 executable,但 CDK 源码使用了打包 | 向用户标记——需要在 Pulumi 中设置打包 |
检测 CDK 源码中的打包:
检查 CDK 源码,查看是否使用了打包结构(NodejsFunction、PythonFunction、GoFunction,或使用 bundling 选项的资源)。如果使用了打包,则需要在 Pulumi 中复现构建步骤,以便持续开发;否则,源代码变更后需要手动重新运行 cdk synth。
检测到打包时,告知用户:
检测到构建步骤:此 CDK 应用使用 <BUNDLING_TYPE>,会在合成期间构建可部署的产物。持续开发需要在 Pulumi 中复现此构建步骤。
选项:
- CI/CD 流水线(推荐):将构建步骤移至 CI 流水线,并在 Pulumi 中引用预构建的产物
- Pulumi Command Provider:使用
command.local.Command在pulumi up期间运行构建命令- 预构建脚本:创建一个在
pulumi up之前运行并将产物输出到已知位置的构建脚本每种选项在缓存、可复现性和部署速度方面各有取舍。对于生产工作负载,通常优先选择选项 1。
2.4 aws-native 的 TypeScript 处理
aws-native 的输出通常包含 undefined。避免使用 ! 非空断言。始终使用 .apply() 安全地解包:
// ❌ WRONG - Will cause TypeScript errors
functionName: lambdaFunction.functionName!,
// ✅ CORRECT - Handle undefined safely
functionName: lambdaFunction.functionName.apply(name => name || ""),
2.5 保留环境逻辑
保留所有条件行为:
if (currentEnv.createVpc) {
// create resources
} else {
const vpcId = pulumi.output(currentEnv.vpcId);
}
3. 导入资源(可选)
转换后,你可以选择导入现有资源,交由 Pulumi 管理。如果用户未提出此要求,应将其作为转换后的后续步骤建议给用户。
- 始终先使用
cdk-importer工具执行自动导入。按照 cdk-importer.md 执行自动导入。 - 对于自动工具导入失败的资源,请手动导入。
如果需要手动导入资源:
-
按照 cloudformation-id-lookup.md 查找 CloudFormation 导入标识符。
-
使用 web-fetch 工具获取 Pulumi 官方文档的内容。
-
查找 AWS 导入 ID -> https://www.pulumi.com/docs/iac/guides/migration/aws-import-ids/
3.1 导入后运行预览
执行导入后,需要运行 pulumi preview,确保没有变更。没有变更意味着:
- 不更新
- 不替换
- 不创建
- 不删除
如果存在变更,必须进行调查并更新程序,直到没有变更。
与用户协作
如果用户请求帮助规划或执行从 CDK 到 Pulumi 的迁移,请根据以上信息引导用户采用自动迁移方式。
详细文档
当用户希望偏离上述推荐路径时,使用网页抓取工具获取 Pulumi 官方文档中的内容 → https://www.pulumi.com/docs/iac/guides/migration/migrating-to-pulumi/migrating-from-cdk/migrating-existing-cdk-app
此文档涵盖以下主题:
- 迁移策略
- 转换还是重写
- 导入还是重新生成
- 最佳实践
- 处理多个 CDK 堆栈
- 处理 CDK 阶段
- 代码组织
- 转换 CDK 构造
- 执行策略
- 自动化迁移(推荐)
- 手动迁移
输出格式(必需)
执行迁移时,始终提供:
- 概述(高层级描述)
- 迁移计划摘要
- Pulumi 代码输出(TypeScript;按文件组织)
- 资源映射表(CDK → Pulumi)
- 自定义资源摘要(如有):
- 已迁移为原生 Pulumi 资源的处理程序
- 保留为
CustomResourceEmulator的处理程序及其理由 - 任何需要用户注意的处理程序
- 资产和打包摘要(如有):
- 已迁移:成功转换的资产(例如,Docker 镜像 →
docker-build.Image,静态文件 →pulumi.FileArchive) - 需要注意:包含打包步骤的资产、提供的选项,以及(如已做出)决策
- 已迁移:成功转换的资产(例如,Docker 镜像 →
- 最终迁移报告(可用于 PR)
- 后续步骤(可选重构)
确保代码语法有效,并按文件清晰分隔。