这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段,并于 2023 年 6 月 1 日终止支持。
教程:创建第一个 AWS CDK 应用程序
通过使用 AWS CDK 命令行界面(AWS CDK CLI)开发第一个 CDK 应用程序、引导 AWS 环境并在 AWS 上部署应用程序,开始使用 AWS Cloud Development Kit (AWS CDK)。
先决条件
在开始本教程之前,请先完成 开始使用 AWS CDK 中的所有设置步骤。
关于本教程
在本教程中,您将使用 AWS CDK 在 AWS 上创建和部署一个简单的应用程序。该应用程序由一个 AWS Lambda 函数组成,调用该函数会返回一条 Hello World!
消息。该函数将通过 Lambda 函数 URL 调用,该网址充当 Lambda 函数的专用 HTTP(S) 端点。
在本教程中,您将执行以下操作:
-
创建您的项目:使用 CDK CLI cdk init
命令创建 CDK 项目。
-
配置 AWS 环境:配置要将应用程序部署到的 AWS 环境。
-
引导 AWS 环境:使用 CDK CLI cdk bootstrap
命令引导 AWS 环境,为部署做好准备。
-
开发应用程序:使用 AWS 构造库中的构造定义 Lambda 函数和 Lambda 函数 URL 资源。
-
为应用程序做好部署准备:使用 CDK CLI 构建应用程序并合成 AWS CloudFormation 模板。
-
部署应用程序:使用 CDK CLI cdk deploy
命令部署应用程序并预置 AWS 资源。
-
与应用程序交互:通过调用已部署的 Lambda 函数并接收响应,在 AWS 上与该函数进行交互。
-
修改应用程序:修改 Lambda 函数并部署以实现更改。
-
删除应用程序:删除使用 CDK CLI cdk destroy
命令创建的所有资源。
步骤 1:创建 CDK 项目
在此步骤中,您将新建一个 CDK 项目。CDK 项目应位于自己的目录中,并具有自己的本地模块依赖关系。
创建 CDK 项目
-
在您选择的起始目录中,创建并导航到名为 hello-cdk
的目录:
$
mkdir hello-cdk && cd hello-cdk
请务必完全按照此处所示命名项目目录 hello-cdk
。CDK CLI 使用这个目录名命名 CDK 代码中的内容。如果您使用了其他目录名称,则在本教程中将遇到问题。
-
在 hello-cdk
目录中,使用 CDK CLI cdk init
命令初始化新的 CDK 项目。使用以下 --language
选项指定 app
模板和首选编程语言:
- TypeScript
-
$
cdk init app --language typescript
- JavaScript
-
$
cdk init app --language javascript
- Python
-
$
cdk init app --language python
创建应用程序后,还应输入以下两条命令。它们会激活应用程序的 Python 虚拟环境并安装 AWS CDK 核心依赖关系。
$
source .venv/bin/activate
# On Windows, run `.\venv\Scripts\activate` instead
$
python -m pip install -r requirements.txt
- Java
-
$
cdk init app --language java
如果您使用的是 IDE,现在可以打开或导入项目了。例如,在 Eclipse 中,依次选择文件 > 导入 > Maven > 现有的 Maven 项目。确保将项目设置设为使用 Java 8(1.8)。
- C#
-
$
cdk init app --language csharp
如果您使用的是 Visual Studio,请在 src
目录中打开解决方案文件。
- Go
-
$
cdk init app --language go
创建应用程序后,还应输入以下命令,以安装应用程序所需的 AWS 构造库模块。
$
go get
cdk init
命令会在 hello-cdk
目录中创建文件和文件夹的结构,以帮助组织 CDK 应用程序的源代码。这种文件和文件夹的结构称为 CDK 项目。花点时间探索 CDK 项目。
如果您已安装 Git,则使用 cdk init
创建的每个项目也会初始化为 Git 存储库。
在项目初始化过程中,CDK CLI 会创建一个包含单个 CDK 堆栈的 CDK 应用程序。CDK 应用程序实例是使用 App
构造创建的。以下内容是 CDK 应用程序文件的一部分相关代码:
- TypeScript
-
位于 bin/hello-cdk.ts
中:
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { HelloCdkStack } from '../lib/hello-cdk-stack';
const app = new cdk.App();
new HelloCdkStack(app, 'HelloCdkStack', {
});
- JavaScript
-
位于 bin/hello-cdk.js
中:
#!/usr/bin/env node
const cdk = require('aws-cdk-lib');
const { HelloCdkStack } = require('../lib/hello-cdk-stack');
const app = new cdk.App();
new HelloCdkStack(app, 'HelloCdkStack', {
});
- Python
-
位于 app.py
中:
#!/usr/bin/env python3
import os
import aws_cdk as cdk
from hello_cdk.hello_cdk_stack import HelloCdkStack
app = cdk.App()
HelloCdkStack(app, "HelloCdkStack",)
app.synth()
- Java
-
位于 src/main/java/.../HelloCdkApp.java
中:
package com.myorg;
import software.amazon.awscdk.App;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.StackProps;
import java.util.Arrays;
public class HelloCdkApp {
public static void main(final String[] args) {
App app = new App();
new HelloCdkStack(app, "HelloCdkStack", StackProps.builder()
.build());
app.synth();
}
}
- C#
-
位于 src/HelloCdk/Program.cs
中:
using Amazon.CDK;
using System;
using System.Collections.Generic;
using System.Linq;
namespace HelloCdk
{
sealed class Program
{
public static void Main(string[] args)
{
var app = new App();
new HelloCdkStack(app, "HelloCdkStack", new StackProps
{});
app.Synth();
}
}
}
- Go
-
位于 hello-cdk.go
中:
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
// ...
func main() {
defer jsii.Close()
app := awscdk.NewApp(nil)
NewHelloCdkStack(app, "HelloCdkStack", &HelloCdkStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
// ...
CDK 堆栈是使用 Stack
构造创建的。以下内容是 CDK 堆栈文件的一部分相关代码:
- TypeScript
-
位于 lib/hello-cdk-stack.ts
中:
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class HelloCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Define your constructs here
}
}
- JavaScript
-
位于 lib/hello-cdk-stack.js
中:
const { Stack } = require('aws-cdk-lib');
class HelloCdkStack extends Stack {
constructor(scope, id, props) {
super(scope, id, props);
// Define your constructs here
}
}
module.exports = { HelloCdkStack }
- Python
-
位于 hello_cdk/hello_cdk_stack.py
中:
from aws_cdk import (
Stack,
)
from constructs import Construct
class HelloCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Define your constructs here
- Java
-
位于 src/main/java/.../HelloCdkStack.java
中:
package com.myorg;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
public class HelloCdkStack extends Stack {
public HelloCdkStack(final Construct scope, final String id) {
this(scope, id, null);
}
public HelloCdkStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
// Define your constructs here
}
}
- C#
-
位于 src/HelloCdk/HelloCdkStack.cs
中:
using Amazon.CDK;
using Constructs;
namespace HelloCdk
{
public class HelloCdkStack : Stack
{
internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
// Define your constructs here
}
}
}
- Go
-
位于 hello-cdk.go
中:
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type HelloCdkStackProps struct {
awscdk.StackProps
}
func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
return stack
}
// ...
在此步骤中,您将为 CDK 堆栈配置 AWS 环境。通过这样做,您可以指定要将 CDK 堆栈部署到哪个环境。
首先,确定要使用的 AWS 环境。AWS 环境由 AWS 账户 和 AWS 区域 组成。
使用 AWS CLI 在本地机器上配置安全凭证时,可以使用 AWS CLI 获取特定配置文件的 AWS 环境信息。
使用 AWS CLI 获取 AWS 账户 ID
-
运行以下 AWS CLI 命令,以获取 default
配置文件的 AWS 账户 ID:
$
aws sts get-caller-identity --query "Account" --output text
-
如果您更喜欢使用命名配置文件,请使用 --profile
选项提供配置文件的名称:
$
aws sts get-caller-identity --profile your-profile-name
--query "Account" --output text
使用 AWS CLI 获取 AWS 区域
-
运行以下 AWS CLI 命令,以获取您为 default
配置文件配置的区域:
$
aws configure get region
-
如果您更喜欢使用命名配置文件,请使用 --profile
选项提供配置文件的名称:
$
aws configure get region --profile your-profile-name
接下来,您将通过修改应用程序文件中的 HelloCdkStack
实例,为 CDK 堆栈配置 AWS 环境。在本教程中,您将对 AWS 环境信息进行硬编码。我们建议将此方法用于生产环境。有关配置环境的其他方法的信息,请参阅配置可使用 AWS CDK 的环境。
步骤 3:引导 AWS 环境
在此步骤中,您将引导上一步中配置的 AWS 环境。这会让您的环境为 CDK 部署做好准备。
要引导环境,请从 CDK 项目的根目录运行以下命令:
$
cdk bootstrap
通过从 CDK 项目的根目录进行引导,您无需提供任何其他信息。CDK CLI 会从项目中获取环境信息。在 CDK 项目之外进行引导时,必须使用 cdk bootstrap
命令提供环境信息。有关更多信息,请参阅 引导环境以用于 AWS CDK。
步骤 4:构建 CDK 应用程序
在大多数编程环境中,都是在进行更改后生成或编译代码。这在使用 AWS CDK 时不是必需的,因为 CDK CLI 会自动执行此步骤。但是,当您想捕获语法和类型错误时,仍然可以手动构建。以下是 示例:
- TypeScript
-
$
npm run build
> hello-cdk@0.1.0 build
> tsc
- JavaScript
-
无需执行任何构建步骤。
- Python
-
无需执行任何构建步骤。
- Java
-
$
mvn compile -q
或者在 Eclipse 中按 Control-B
(其他 Java IDE 可能会有所不同)
- C#
-
$
dotnet build src
或者在 Visual Studio 中按 F6
- Go
-
$
go build
步骤 5 :列出应用程序中的 CDK 堆栈
此时,您应该有一个包含单个 CDK 堆栈的 CDK 应用程序。要进行验证,请使用 CDK CLI cdk list
命令显示堆栈。输出应显示名为 HelloCdkStack
的单个堆栈:
$
cdk list
HelloCdkStack
如果您看不到此输出,请验证您所在的项目工作目录是否正确,然后重试。如果您仍然看不到堆栈,请重复 步骤 1:创建 CDK 项目 并重试。
步骤 6:定义 Lambda 函数
在此步骤中,您将从 AWS 构造库导入 aws_lambda
模块,并使用 Function
L2 构造。
按如下方式修改 CDK 堆栈文件:
- TypeScript
-
位于 lib/hello-cdk-stack.ts
中:
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
// Import the Lambda module
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class HelloCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Define the Lambda function resource
const myFunction = new lambda.Function(this, "HelloWorldFunction", {
runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime
handler: "index.handler",
code: lambda.Code.fromInline(`
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello World!'),
};
};
`),
});
}
}
- JavaScript
-
位于 lib/hello-cdk-stack.js
中:
const { Stack } = require('aws-cdk-lib');
// Import the Lambda module
const lambda = require('aws-cdk-lib/aws-lambda');
class HelloCdkStack extends Stack {
constructor(scope, id, props) {
super(scope, id, props);
// Define the Lambda function resource
const myFunction = new lambda.Function(this, "HelloWorldFunction", {
runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime
handler: "index.handler",
code: lambda.Code.fromInline(`
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello World!'),
};
};
`),
});
}
}
module.exports = { HelloCdkStack }
- Python
-
位于 hello_cdk/hello_cdk_stack.py
中:
from aws_cdk import (
Stack,
aws_lambda as _lambda, # Import the Lambda module
)
from constructs import Construct
class HelloCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Define the Lambda function resource
my_function = _lambda.Function(
self, "HelloWorldFunction",
runtime = _lambda.Runtime.NODEJS_20_X, # Provide any supported Node.js runtime
handler = "index.handler",
code = _lambda.Code.from_inline(
"""
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello World!'),
};
};
"""
),
)
- Java
-
位于 src/main/java/.../HelloCdkStack.java
中:
package com.myorg;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
// Import Lambda function
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;
public class HelloCdkStack extends Stack {
public HelloCdkStack(final Construct scope, final String id) {
this(scope, id, null);
}
public HelloCdkStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
// Define the Lambda function resource
Function myFunction = Function.Builder.create(this, "HelloWorldFunction")
.runtime(Runtime.NODEJS_20_X) // Provide any supported Node.js runtime
.handler("index.handler")
.code(Code.fromInline(
"exports.handler = async function(event) {" +
" return {" +
" statusCode: 200," +
" body: JSON.stringify('Hello World!')" +
" };" +
"};"))
.build();
}
}
- C#
-
位于 src/main/java/.../HelloCdkStack.java
中:
using Amazon.CDK;
using Constructs;
// Import the Lambda module
using Amazon.CDK.AWS.Lambda;
namespace HelloCdk
{
public class HelloCdkStack : Stack
{
internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
// Define the Lambda function resource
var myFunction = new Function(this, "HelloWorldFunction", new FunctionProps
{
Runtime = Runtime.NODEJS_20_X, // Provide any supported Node.js runtime
Handler = "index.handler",
Code = Code.FromInline(@"
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello World!'),
};
};
"),
});
}
}
}
- Go
-
位于 hello-cdk.go
中:
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
// Import the Lambda module
"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
)
type HelloCdkStackProps struct {
awscdk.StackProps
}
func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// Define the Lambda function resource
myFunction := awslambda.NewFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.FunctionProps{
Runtime: awslambda.Runtime_NODEJS_20_X(), // Provide any supported Node.js runtime
Handler: jsii.String("index.handler"),
Code: awslambda.Code_FromInline(jsii.String(`
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello World!'),
};
};
`)),
})
return stack
}
// ...
让我们详细了解一下 Function
的构造。像所有构造一样,Function
类采用三个参数:
-
scope:将 Stack
实例定义为 Function
构造的父级。所有定义 AWS 资源的构造都是在堆栈的作用域内创建的。您可以在构造内部定义构造,从而创建层次结构(树)。在本例中,以及大多数情况下,作用域是 this
(Python:self
)。
-
ID:AWS CDK 应用程序中 Function
的构造 ID。此 ID 加上基于函数在堆栈中的位置的哈希值,可在部署过程中唯一标识函数。当您在应用程序中更新构造并重新部署以更新已部署的资源时,AWS CDK 仍会引用此 ID。在本例中,构造 ID 是 HelloWorldFunction
。函数也可以有一个名称,使用 functionName
属性指定。它不同于构造 ID。
-
props:一组定义函数属性的值。在本例中,您将定义 runtime
、handler
和 code
属性。
在 AWS CDK 支持的语言中,props 的表示方式不同。
-
在 TypeScript 和 JavaScript 中,props
是单个参数,您可以传入一个包含所需属性的对象。
-
在 Python 中,props 作为关键字参数传递。
-
在 Java 中,提供生成器用于传递 props。有两种 props:一个用于 FunctionProps
,第二个用于 Function
,以便您一步构建构造及其 props 对象。示例代码使用了后者。
-
在 C# 中,您将使用对象初始化程序实例化一个 FunctionProps
对象,并将其作为第三个参数传递。
如果构造的 props 是可选的,则可以完全省略 props
参数。
所有构造都采用相同的三个参数,因此在了解新构造时很容易明确方向。如您预期的那样,您可以对任何构造子类化,对其进行扩展以适合您的需求,也可更改其默认值。
步骤 7:定义 Lambda 函数 URL
在此步骤中,您将使用 Function
构造的 addFunctionUrl
助手方法定义 Lambda 函数 URL。要在部署时输出此 URL 的值,您需要使用 CfnOutput
构造创建 AWS CloudFormation 输出。
在 CDK 堆栈文件中添加以下内容:
- TypeScript
-
位于 lib/hello-cdk-stack.ts
中:
// ...
export class HelloCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Define the Lambda function resource
// ...
// Define the Lambda function URL resource
const myFunctionUrl = myFunction.addFunctionUrl({
authType: lambda.FunctionUrlAuthType.NONE,
});
// Define a CloudFormation output for your URL
new cdk.CfnOutput(this, "myFunctionUrlOutput", {
value: myFunctionUrl.url,
})
}
}
- JavaScript
-
位于 lib/hello-cdk-stack.js
中:
const { Stack, CfnOutput } = require('aws-cdk-lib'); // Import CfnOutput
class HelloCdkStack extends Stack {
constructor(scope, id, props) {
super(scope, id, props);
// Define the Lambda function resource
// ...
// Define the Lambda function URL resource
const myFunctionUrl = myFunction.addFunctionUrl({
authType: lambda.FunctionUrlAuthType.NONE,
});
// Define a CloudFormation output for your URL
new CfnOutput(this, "myFunctionUrlOutput", {
value: myFunctionUrl.url,
})
}
}
module.exports = { HelloCdkStack }
- Python
-
位于 hello_cdk/hello_cdk_stack.py
中:
from aws_cdk import (
# ...
CfnOutput # Import CfnOutput
)
from constructs import Construct
class HelloCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Define the Lambda function resource
# ...
# Define the Lambda function URL resource
my_function_url = my_function.add_function_url(
auth_type = _lambda.FunctionUrlAuthType.NONE,
)
# Define a CloudFormation output for your URL
CfnOutput(self, "myFunctionUrlOutput", value=my_function_url.url)
- Java
-
位于 src/main/java/.../HelloCdkStack.java
中:
package com.myorg;
// ...
// Import Lambda function URL
import software.amazon.awscdk.services.lambda.FunctionUrl;
import software.amazon.awscdk.services.lambda.FunctionUrlAuthType;
import software.amazon.awscdk.services.lambda.FunctionUrlOptions;
// Import CfnOutput
import software.amazon.awscdk.CfnOutput;
public class HelloCdkStack extends Stack {
public HelloCdkStack(final Construct scope, final String id) {
this(scope, id, null);
}
public HelloCdkStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
// Define the Lambda function resource
// ...
// Define the Lambda function URL resource
FunctionUrl myFunctionUrl = myFunction.addFunctionUrl(FunctionUrlOptions.builder()
.authType(FunctionUrlAuthType.NONE)
.build());
// Define a CloudFormation output for your URL
CfnOutput.Builder.create(this, "myFunctionUrlOutput")
.value(myFunctionUrl.getUrl())
.build();
}
}
- C#
-
位于 src/main/java/.../HelloCdkStack.java
中:
// ...
namespace HelloCdk
{
public class HelloCdkStack : Stack
{
internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
// Define the Lambda function resource
// ...
// Define the Lambda function URL resource
var myFunctionUrl = myFunction.AddFunctionUrl(new FunctionUrlOptions
{
AuthType = FunctionUrlAuthType.NONE
});
// Define a CloudFormation output for your URL
new CfnOutput(this, "myFunctionUrlOutput", new CfnOutputProps
{
Value = myFunctionUrl.Url
});
}
}
}
- Go
-
位于 hello-cdk.go
中:
// ...
func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// Define the Lambda function resource
// ...
// Define the Lambda function URL resource
myFunctionUrl := myFunction.AddFunctionUrl(&awslambda.FunctionUrlOptions{
AuthType: awslambda.FunctionUrlAuthType_NONE,
})
// Define a CloudFormation output for your URL
awscdk.NewCfnOutput(stack, jsii.String("myFunctionUrlOutput"), &awscdk.CfnOutputProps{
Value: myFunctionUrl.Url(),
})
return stack
}
// ...
为了简化本教程,Lambda 函数 URL 是在不进行身份验证的情况下定义的。部署后,它将创建一个可公开访问的端点,该端点可用于调用函数。完成本教程后,请按照 步骤 12:删除应用程序 删除这些资源。
步骤 8:合成 CloudFormation 模板:
在此步骤中,您将通过使用 CDK CLIcdk
synth
命令合成 CloudFormation 模板,为部署做好准备。此命令会对 CDK 代码执行基本验证,运行 CDK 应用程序,并从 CDK 堆栈中生成 CloudFormation 模板。
如果应用程序包含多个堆栈,则必须指定要使用哪些堆栈进行合成。由于应用程序包含单个堆栈,CDK CLI 会自动检测该堆栈以进行合成。
如果您没有合成模板,CDK CLI 将在您部署时自动执行此步骤。但是,建议您在每次部署之前运行此步骤,以检查是否存在合成错误。
在合成模板之前,您可以选择构建应用程序,以捕获语法和类型错误。有关说明,请参阅 步骤 4:构建 CDK 应用程序。
要合成 CloudFormation 模板,请在项目根目录运行以下命令:
$
cdk synth
如果您收到如下错误,请确认您是否位于 hello-cdk
目录中并重试:
--app is required either in command-line, in cdk.json or in ~/.cdk.json
如果成功,CDK CLI 会将 YAML 格式的 CloudFormation 模板输出到 stdout
中,并将 JSON 格式的模板保存在项目的 cdk.out
目录中。
下面是 CloudFormation 模板的示例输出:
Resources:
HelloWorldFunctionServiceRoleunique-identifier
:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Version: "2012-10-17"
ManagedPolicyArns:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Metadata:
aws:cdk:path: HelloCdkStack/HelloWorldFunction/ServiceRole/Resource
HelloWorldFunctionunique-identifier
:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: "
\ exports.handler = async function(event) {
\ return {
\ statusCode: 200,
\ body: JSON.stringify('Hello World!'),
\ };
\ };
\ "
Handler: index.handler
Role:
Fn::GetAtt:
- HelloWorldFunctionServiceRoleunique-identifier
- Arn
Runtime: nodejs20.x
DependsOn:
- HelloWorldFunctionServiceRoleunique-identifier
Metadata:
aws:cdk:path: HelloCdkStack/HelloWorldFunction/Resource
HelloWorldFunctionFunctionUrlunique-identifier
:
Type: AWS::Lambda::Url
Properties:
AuthType: NONE
TargetFunctionArn:
Fn::GetAtt:
- HelloWorldFunctionunique-identifier
- Arn
Metadata:
aws:cdk:path: HelloCdkStack/HelloWorldFunction/FunctionUrl/Resource
HelloWorldFunctioninvokefunctionurlunique-identifier
:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunctionUrl
FunctionName:
Fn::GetAtt:
- HelloWorldFunctionunique-identifier
- Arn
FunctionUrlAuthType: NONE
Principal: "*"
Metadata:
aws:cdk:path: HelloCdkStack/HelloWorldFunction/invoke-function-url
CDKMetadata:
Type: AWS::CDK::Metadata
Properties:
Analytics: v2:deflate64:unique-identifier
Metadata:
aws:cdk:path: HelloCdkStack/CDKMetadata/Default
Condition: CDKMetadataAvailable
Outputs:
myFunctionUrlOutput:
Value:
Fn::GetAtt:
- HelloWorldFunctionFunctionUrlunique-identifier
- FunctionUrl
Parameters:
BootstrapVersion:
Type: AWS::SSM::Parameter::Value<String>
Default: /cdk-bootstrap/unique-identifier
/version
Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]
Rules:
CheckBootstrapVersion:
Assertions:
- Assert:
Fn::Not:
- Fn::Contains:
- - "1"
- "2"
- "3"
- "4"
- "5"
- Ref: BootstrapVersion
AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.
每个生成的模板默认都包含一个 AWS::CDK::Metadata
资源。AWS CDK 团队使用此元数据深入了解 AWS CDK 的使用情况,并找到改进的方法。有关详细信息,包括如何选择退出版本报告,请参阅版本报告。
通过定义单个 L2 构造,AWS CDK 创建了一个广泛的 CloudFormation 模板,其中包含 Lambda 资源,以及资源在应用程序中进行交互所需的权限和粘合逻辑。
步骤 9:部署 CDK 堆栈
在此步骤中,您将使用 CDK CLI cdk deploy
命令部署 CDK 堆栈。此命令会检索生成的 CloudFormation 模板并通过 AWS CloudFormation 部署模板,将资源预置为 CloudFormation 堆栈的一部分。
在项目的根目录中运行以下命令。如果系统提示,请确认更改:
$
cdk deploy
✨ Synthesis time: 2.69s
HelloCdkStack: start: Building unique-identifier
:current_account-current_region
HelloCdkStack: success: Built unique-identifier
:current_account-current_region
HelloCdkStack: start: Publishing unique-identifier
:current_account-current_region
HelloCdkStack: success: Published unique-identifier
:current_account-current_region
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:
IAM Statement Changes
┌───┬───────────────────────────────────────┬────────┬──────────────────────────┬──────────────────────────────┬───────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼───────────────────────────────────────┼────────┼──────────────────────────┼──────────────────────────────┼───────────┤
│ + │ ${HelloWorldFunction.Arn} │ Allow │ lambda:InvokeFunctionUrl │ * │ │
├───┼───────────────────────────────────────┼────────┼──────────────────────────┼──────────────────────────────┼───────────┤
│ + │ ${HelloWorldFunction/ServiceRole.Arn} │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │
└───┴───────────────────────────────────────┴────────┴──────────────────────────┴──────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬───────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐
│ │ Resource │ Managed Policy ARN │
├───┼───────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${HelloWorldFunction/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │
└───┴───────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Do you wish to deploy these changes (y/n)? y
与 cdk synth
类似,您无需指定 AWS CDK 堆栈,因为应用程序包含单个堆栈。
部署过程中,CDK CLI 会在部署堆栈时显示进度信息。完成后,您可以前往 AWS CloudFormation 控制台查看 HelloCdkStack
堆栈。您也可以前往 Lambda 控制台查看 HelloWorldFunction
资源。
部署完成后,CDK CLI 将输出端点 URL。复制此 URL 以供下一步使用。以下是 示例:
...
HelloCdkStack: deploying... [1/1]
HelloCdkStack: creating CloudFormation changeset...
✅ HelloCdkStack
✨ Deployment time: 41.65s
Outputs:
HelloCdkStack.myFunctionUrlOutput = https://<api-id>
.lambda-url.<Region>
.on.aws/
Stack ARN:
arn:aws:cloudformation:Region
:account-id
:stack/HelloCdkStack/unique-identifier
✨ Total time: 44.34s
步骤 10:在 AWS 上与应用程序交互
在此步骤中,您将通过函数 URL 调用 Lambda 函数,从而在 AWS 上与应用程序交互。访问网址时,Lambda 函数会返回 Hello World!
消息。
要调用函数,请通过浏览器或命令行访问函数 URL。以下是 示例:
$
curl https://<api-id>
.lambda-url.<Region>
.on.aws/
"Hello World!"%
步骤 11:修改应用程序
在此步骤中,您将修改调用 Lambda 函数时返回的消息。您可以使用 CDK CLI cdk diff
命令执行 diiff,以预览更改并部署,从而更新应用程序。然后,您可以在 AWS 上与应用程序交互,以查看新消息。
按如下方式修改 CDK 堆栈文件中的 myFunction
实例:
- TypeScript
-
位于 lib/hello-cdk-stack.ts
中:
// ...
export class HelloCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Modify the Lambda function resource
const myFunction = new lambda.Function(this, "HelloWorldFunction", {
runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime
handler: "index.handler",
code: lambda.Code.fromInline(`
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello CDK!'),
};
};
`),
});
// ...
- JavaScript
-
位于 lib/hello-cdk-stack.js
中:
// ...
class HelloCdkStack extends Stack {
constructor(scope, id, props) {
super(scope, id, props);
// Modify the Lambda function resource
const myFunction = new lambda.Function(this, "HelloWorldFunction", {
runtime: lambda.Runtime.NODEJS_20_X, // Provide any supported Node.js runtime
handler: "index.handler",
code: lambda.Code.fromInline(`
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello CDK!'),
};
};
`),
});
// ...
}
}
module.exports = { HelloCdkStack }
- Python
-
位于 hello_cdk/hello_cdk_stack.py
中:
# ...
class HelloCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Modify the Lambda function resource
my_function = _lambda.Function(
self, "HelloWorldFunction",
runtime = _lambda.Runtime.NODEJS_20_X, # Provide any supported Node.js runtime
handler = "index.handler",
code = _lambda.Code.from_inline(
"""
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello CDK!'),
};
};
"""
),
)
# ...
- Java
-
位于 src/main/java/.../HelloCdkStack.java
中:
// ...
public class HelloCdkStack extends Stack {
public HelloCdkStack(final Construct scope, final String id) {
this(scope, id, null);
}
public HelloCdkStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
// Modify the Lambda function resource
Function myFunction = Function.Builder.create(this, "HelloWorldFunction")
.runtime(Runtime.NODEJS_20_X) // Provide any supported Node.js runtime
.handler("index.handler")
.code(Code.fromInline(
"exports.handler = async function(event) {" +
" return {" +
" statusCode: 200," +
" body: JSON.stringify('Hello CDK!')" +
" };" +
"};"))
.build();
// ...
}
}
- C#
-
// ...
namespace HelloCdk
{
public class HelloCdkStack : Stack
{
internal HelloCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
// Modify the Lambda function resource
var myFunction = new Function(this, "HelloWorldFunction", new FunctionProps
{
Runtime = Runtime.NODEJS_20_X, // Provide any supported Node.js runtime
Handler = "index.handler",
Code = Code.FromInline(@"
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello CDK!'),
};
};
"),
});
// ...
}
}
}
- Go
-
// ...
type HelloCdkStackProps struct {
awscdk.StackProps
}
func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// Modify the Lambda function resource
myFunction := awslambda.NewFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.FunctionProps{
Runtime: awslambda.Runtime_NODEJS_20_X(), // Provide any supported Node.js runtime
Handler: jsii.String("index.handler"),
Code: awslambda.Code_FromInline(jsii.String(`
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello CDK!'),
};
};
`)),
})
// ...
目前,您的代码更改尚未对已部署的 Lambda 资源执行任何直接更新。您的代码定义了所需的资源的状态。要修改已部署的资源,您将使用 CDK CLI 将所需状态合成到新 AWS CloudFormation 模板中。然后,您将把新的 CloudFormation 模板部署为更改集。更改集仅进行必要的更改,以达到新的所需状态。
要预览您的更改,请运行 cdk diff
命令。以下是 示例:
$
cdk diff
Stack HelloCdkStack
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
Resources
[~] AWS::Lambda::Function HelloWorldFunction HelloWorldFunctionunique-identifier
└─ [~] Code
└─ [~] .ZipFile:
├─ [-]
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello World!'),
};
};
└─ [+]
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello CDK!'),
};
};
✨ Number of stacks with differences: 1
要创建此 diff,CDK CLI 会查询 AWS 账户 账户,以获取 HelloCdkStack
堆栈的最新 AWS CloudFormation 模板。然后,它将最新的模板与刚从应用程序中合成的模板进行比较。
要实现您的更改,请运行 cdk deploy
命令。以下是 示例:
$
cdk deploy
✨ Synthesis time: 2.12s
HelloCdkStack: start: Building unique-identifier
:current_account-current_region
HelloCdkStack: success: Built unique-identifier
:current_account-current_region
HelloCdkStack: start: Publishing unique-identifier
:current_account-current_region
HelloCdkStack: success: Published unique-identifier
:current_account-current_region
HelloCdkStack: deploying... [1/1]
HelloCdkStack: creating CloudFormation changeset...
✅ HelloCdkStack
✨ Deployment time: 26.96s
Outputs:
HelloCdkStack.myFunctionUrlOutput = https://unique-identifier
.lambda-url.<Region>
.on.aws/
Stack ARN:
arn:aws:cloudformation:Region
:account-id
:stack/HelloCdkStack/unique-identifier
✨ Total time: 29.07s
要与应用程序交互,请重复 步骤 10:在 AWS 上与应用程序交互。以下是 示例:
$
curl https://<api-id>
.lambda-url.<Region>
.on.aws/
"Hello CDK!"%
步骤 12:删除应用程序
在此步骤中,您将使用 CDK CLI cdk destroy
命令删除应用程序。此命令将删除与 CDK 堆栈关联的 CloudFormation 堆栈,后者包含您创建的资源。
要删除应用程序,请运行 cdk destroy
命令并确认删除应用程序的请求。以下是 示例:
$
cdk destroy
Are you sure you want to delete: HelloCdkStack (y/n)? y
HelloCdkStack: destroying... [1/1]
✅ HelloCdkStack: destroyed
后续步骤
恭喜您!您已完成本教程,并已使用 AWS CDK 在 AWS Cloud 中成功创建、修改和删除资源。您现在已准备就绪,可以开始使用 AWS CDK 了。
要了解有关以首选编程语言使用 AWS CDK 的更多信息,请参阅使用 AWS CDK 库。
有关其他资源,请参阅以下资源:
AWS CDK 是一个开源项目。要贡献内容,请参阅 Contributing to the AWS Cloud Development Kit (AWS CDK)。