常见 AWS CDK 问题疑难解答 - AWS Cloud Development Kit (AWS CDK) v2

这是 AWS CDK v2 开发者指南。较旧的 CDK v1 于 2022 年 6 月 1 日进入维护阶段,并于 2023 年 6 月 1 日终止支持。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

常见 AWS CDK 问题疑难解答

本主题介绍如何对以下问题进行故障排除 AWS CDK。

更新后 AWS CDK, AWS CDK 工具包 (CLI) 报告与 AWS 构造库不匹配

AWS CDK 工具包(提供cdk命令)的版本必须至少等于主 AWS 构造库模块的版本aws-cdk-lib。该工具包旨在向后兼容。该工具包的最新 2.x 版本可以与该库的任何 1.x 或 2.x 版本一起使用。因此,我们建议您在全球范围内安装此组件并使其保持最新状态。

npm update -g aws-cdk

如果您需要使用该 AWS CDK 工具包的多个版本,请在您的项目文件夹中本地安装该工具包的特定版本。

如果您使用的是 TypeScript 或 JavaScript,则您的项目目录中已经包含 CDK Toolkit 的版本化本地副本。

如果您使用的是其他语言,请使用npm安装 AWS CDK Toolkit,省略该-g标志并指定所需的版本。例如:

npm install aws-cdk@2.0

要运行本地安装的 AWS CDK Toolkit,请使用命令npx aws-cdk而不是仅使用命令cdk。例如:

npx aws-cdk deploy MyStack

npx aws-cdk运行 AWS CDK 工具包的本地版本(如果存在)。当项目没有本地安装时,它会回退到全局版本。你可能会发现设置一个 shell 别名cdk很方便,以确保总是以这种方式调用。

macOS/Linux
alias cdk="npx aws-cdk"
Windows
doskey cdk=npx aws-cdk $*

返回列表

部署我的 AWS CDK 堆栈时,我收到一个NoSuchBucket错误

您的 AWS 环境尚未引导,因此没有用于在部署期间存放资源的 Amazon S3 存储桶。您可以使用以下命令创建暂存存储桶和其他必需的资源:

cdk bootstrap aws://ACCOUNT-NUMBER/REGION

为避免产生意外 AWS 费用, AWS CDK 不会自动引导任何环境。您必须显式引导要部署的每个环境。

默认情况下,引导资源是在当前 AWS CDK 应用程序中的堆栈使用的一个或多个区域中创建的。或者,它们是在您的本地 AWS 个人资料(设置为aws configure)中指定的区域中使用该个人资料的帐户创建的。您可以在命令行上指定不同的账户和区域,如下所示。(如果您不在应用程序目录中,则必须指定账户和区域。)

cdk bootstrap aws://ACCOUNT-NUMBER/REGION

有关更多信息,请参阅 正在引导

返回列表

部署我的 AWS CDK 堆栈时,我收到一条forbidden: null消息

您部署的堆栈需要引导资源,但使用的 IAM 角色或账户没有写入权限。(部署包含资产或合成大于 50K 的 AWS CloudFormation 模板的堆栈时,会使用暂存存储桶。) 使用有权s3:*对错误消息中提及的存储桶执行操作的账户或角色。

返回列表

合成 AWS CDK 堆栈时,我会收到消息 --app is required either in command-line, in cdk.json or in ~/.cdk.json

这条消息通常意味着当你发布问题时,你不在 AWS CDK 项目的主目录中cdk synth。此目录cdk.json中的文件由cdk init命令创建,包含运行(从而合成) AWS CDK 应用程序所需的命令行。例如,对于一个 TypeScript 应用程序,默认值是cdk.json这样的:

{ "app": "npx ts-node bin/my-cdk-app.ts" }

我们建议仅在项目的主目录中发出cdk命令,这样 AWS CDK 工具包就可以在cdk.json那里找到并成功运行您的应用程序。

如果由于某种原因这不切实际, AWS CDK Toolkit 会在另外两个位置查找应用程序的命令行:

  • cdk.json在你的主目录中

  • cdk synth命令本身上使用-a选项

例如,您可以按如下方式合成来自 TypeScript 应用程序的堆栈。

cdk synth --app "npx ts-node my-cdk-app.ts" MyStack

返回列表

合成 AWS CDK 堆栈时,我收到错误消息,因为 AWS CloudFormation 模板包含的资源太多

AWS CDK 生成并部署 AWS CloudFormation 模板。 AWS CloudFormation 对堆栈可以包含的资源数量有硬性限制。有了这个 AWS CDK,你可以比预期的更快地突破这个限制。

注意

在撰写本文时, AWS CloudFormation 资源限制为 500。有关当前资源限制,请参阅AWS CloudFormation 配额。

C AWS onstruct Library 的更高级别、基于意图的构造会自动配置日志、密钥管理、授权和其他目的所需的任何辅助资源。例如,向一个资源授予另一个资源的访问权限会生成相关服务进行通信所需的任何 IAM 对象。

根据我们的经验,在现实世界中使用基于意图的构造会导致每个构造需要 1-5 个 AWS CloudFormation 资源,尽管情况可能有所不同。对于无服务器应用程序,通常每个 API 端点有 5-8 个 AWS 资源。

模式代表更高的抽象级别,允许你用更少的代码定义更多的 AWS 资源。例如使用创建 AWS Fargate 服务 AWS CDK,中的 AWS CDK 代码生成了 50 多个 AWS CloudFormation 资源,而只定义了三个结构!

超过 AWS CloudFormation 资源限制是 AWS CloudFormation 合成过程中的错误。如果您的堆栈超过限制的 80%,则会发出警告。 AWS CDK 您可以通过在堆栈上设置maxResources属性来使用不同的限制,也可以通过设置为 0 maxResources 来禁用验证。

提示

您可以使用以下实用程序脚本获得合成输出中资源的精确计数。(由于每个 AWS CDK 开发者都需要 Node.js,因此脚本是用编写的 JavaScript。)

// rescount.js - count the resources defined in a stack // invoke with: node rescount.js <path-to-stack-json> // e.g. node rescount.js cdk.out/MyStack.template.json import * as fs from 'fs'; const path = process.argv[2]; if (path) fs.readFile(path, 'utf8', function(err, contents) { console.log(err ? `${err}` : `${Object.keys(JSON.parse(contents).Resources).length} resources defined in ${path}`); }); else console.log("Please specify the path to the stack's output .json file");

当堆栈的资源数量接近限制时,可以考虑重新架构以减少堆栈包含的资源数量:例如,通过组合一些 Lambda 函数,或者将堆栈分成多个堆栈。CDK 支持堆栈之间的引用,因此你可以用任何对你来说最有意义的方式将应用程序的功能分成不同的堆栈。

注意

AWS CloudFormation 专家们经常建议使用嵌套堆栈作为资源限制的解决方案。通过NestedStack构造 AWS CDK 支持这种方法。

返回列表

我为我的 Auto Scaling 组或 VPC 指定了三个(或更多)可用区,但它只部署在两个可用区中

要获取您请求的可用区数量,请在堆栈的env属性中指定账户和区域。如果未同时指定两者,则默认情况下 AWS CDK,会将堆栈合成为与环境无关的堆栈。然后,您可以使用将堆栈部署到特定区域 AWS CloudFormation。由于某些区域只有两个可用区,因此与环境无关的模板使用的可用区不超过两个。

注意

过去,区域偶尔会推出只有一个可用区。与环境无关的 AWS CDK 堆栈无法部署到此类区域。但是,在撰写本文时,所有 AWS 区域都至少有两个可用区。

您可以通过覆盖堆栈的 availablilityZones(Python:availability_zones) 属性来显式指定要使用的区域,从而更改此行为。

有关在合成时指定堆栈的账户和区域,同时保留部署到任何区域的灵活性的更多信息,请参阅环境

返回列表

我的 S3 存储桶、DynamoDB 表或其他资源在我发布时没有被删除 cdk destroy

默认情况下,可以包含用户数据的资源的 removalPolicy (Python:removal_policy) 属性为RETAIN,并且在堆栈被销毁时不会删除该资源。相反,资源是堆栈中的孤立资源。然后,您必须在堆栈销毁后手动删除资源。在你这样做之前,重新部署堆栈会失败。这是因为部署期间创建的新资源的名称与孤立资源的名称冲突。

如果您将资源的移除策略设置为DESTROY,则该资源将在堆栈被销毁时被删除。

TypeScript
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as s3 from 'aws-cdk-lib/aws-s3'; export class CdkTestStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const bucket = new s3.Bucket(this, 'Bucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); } }
JavaScript
const cdk = require('aws-cdk-lib'); const s3 = require('aws-cdk-lib/aws-s3'); class CdkTestStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); const bucket = new s3.Bucket(this, 'Bucket', { removalPolicy: cdk.RemovalPolicy.DESTROY }); } } module.exports = { CdkTestStack }
Python
import aws_cdk as cdk from constructs import Construct import aws_cdk.aws_s3 as s3 class CdkTestStack(cdk.stack): def __init__(self, scope: Construct, id: str, **kwargs): super().__init__(scope, id, **kwargs) bucket = s3.Bucket(self, "Bucket", removal_policy=cdk.RemovalPolicy.DESTROY)
Java
software.amazon.awscdk.*; import software.amazon.awscdk.services.s3.*; import software.constructs; public class CdkTestStack extends Stack { public CdkTestStack(final Construct scope, final String id) { this(scope, id, null); } public CdkTestStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); Bucket.Builder.create(this, "Bucket") .removalPolicy(RemovalPolicy.DESTROY).build(); } }
C#
using Amazon.CDK; using Amazon.CDK.AWS.S3; public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props) { new Bucket(this, "Bucket", new BucketProps { RemovalPolicy = RemovalPolicy.DESTROY }); }
注意

AWS CloudFormation 无法删除非空的 Amazon S3 存储桶。如果您将 Amazon S3 存储桶的移除策略设置为DESTROY,并且该存储桶包含数据,则尝试销毁该堆栈将失败,因为该存储桶无法删除。您可以通过将存储桶的 autoDeleteObjects prop 设置为,在尝试销毁存储桶之前 AWS CDK 删除存储桶中的对象true

返回列表