配置要与... 一起使用的环境 AWS CDK - AWS Cloud Development Kit (AWS CDK) v2

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

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

配置要与... 一起使用的环境 AWS CDK

您可以通过多种方式配置 AWS 环境,以便与一起使用 AWS Cloud Development Kit (AWS CDK)。根据您的具体需求,管理 AWS 环境的最佳方法会有所不同。

应用程序中的每个 CDK 堆栈最终都必须与环境相关联,才能确定堆栈部署到何处。

有关 AWS 环境的介绍,请参阅环境

您可以从中指定环境

可以在凭据和配置文件中指定环境,也可以使用构造库中Stack构造的env属性 AWS 来指定环境。

凭证和配置文件

您可以使用 AWS Command Line Interface (AWS CLI) 来创建credentials和存储、组织和管理您的 AWS 环境信息的config文件。要了解有关这些文件的更多信息,请参阅《AWS Command Line Interface 用户指南》中的配置和凭据文件设置

存储在这些文件中的值按配置文件进行组织。您如何命名配置文件以及这些文件中的键值对将因配置编程访问的方法而异。要了解有关不同方法的更多信息,请参阅为配置安全证书 AWS CDKCLI

通常, AWS CDK 解析credentials文件中的 AWS 账户 信息以及config文件中的 AWS 区域 信息。

配置好credentialsconfig文件后,您可以通过 AWS CDK CLI和通过环境变量指定要使用的环境。

堆栈构造的 env 属性

您可以使用Stack构造的env属性为每个堆栈指定环境。此属性定义了要使用的账户和区域。您可以将硬编码值传递给此属性,也可以传递 CDK 提供的环境变量。

要传递环境变量,请使用AWS_DEFAULT_ACCOUNTAWS_DEFAULT_REGION环境变量。这些环境变量可以传递credentialsconfig文件中的值。您也可以使用 CDK 代码中的逻辑来确定这些环境变量的值。

环境优先级为 AWS CDK

如果您使用多种方法来指定环境,则会 AWS CDK 遵循以下优先级:

  1. 使用Stack构造的env属性指定的硬编码值。

  2. AWS_DEFAULT_ACCOUNT以及使用Stack构造env属性指定的AWS_DEFAULT_REGION环境变量。

  3. 与您的credentialsconfig文件中的配置文件关联的环境信息,并CLI使用--profile选项传递给 CDK。

  4. 来自您的credentialsconfig文件的default个人资料。

何时指定环境

使用 CDK 进行开发时,首先要定义 CDK 堆栈,其中包含代表资源的结构。 AWS 接下来,将每个 CDK 堆栈合成一个模板。 AWS CloudFormation 然后,将CloudFormation 模板部署到您的环境中。您如何指定环境决定何时应用您的环境信息,并可能影响 CDK 的行为和结果。

在模板合成时指定环境

当您使用Stack构造的env属性指定环境信息时,您的环境信息将在模板合成时应用。运行cdk synthcdk deploy生成特定于环境 CloudFormation 的模板。

如果您在env属性中使用环境变量,则必须使用带有 CDK CLI 命令的--profile选项来传入包含您的凭据和配置文件中的环境信息的配置文件。然后,这些信息将应用于模板合成,以生成特定于环境的模板。

CloudFormation 模板中的环境信息优先于其他方法。例如,如果您提供不同的环境cdk deploy --profile profile,则配置文件将被忽略。

以这种方式提供环境信息时,您可以在 CDK 应用程序中使用依赖于环境的代码和逻辑。这也意味着,根据合成模板所在的机器、用户或会话,合成后的模板可能会有所不同。这种方法在开发过程中通常是可以接受或可取的,但不建议用于生产用途。

在堆栈部署时指定环境

如果你不使用Stack构造的env属性指定环境,CDK CLI 将在合成时生成一个与环境无关的模板 CloudFormation 。然后,您可以使用指定要部署到的环境cdk deploy --profile profile

如果您在部署与环境无关的模板时未指定配置文件,CDK CLI 将在部署时尝试使用您的credentialsdefault文件的配置文件中的环境值。config

如果部署时没有环境信息,则 AWS CloudFormation 将在部署时尝试通过与环境相关的属性(例如stack.accountstack.region、和stack.availabilityZones)来解析环境信息。

对于与环境无关的堆栈,堆栈中的构造不能使用环境信息,也不能使用需要环境信息的逻辑。例如,您不能编写类似的代码,if (stack.region ==== 'us-east-1')也不能使用需要环境信息的构造方法,例如Vpc.fromLookup。要使用这些功能,必须使用env属性指定环境。

对于与环境无关的堆栈,任何使用可用区域的构造都将看到两个可用区,从而允许将堆栈部署到任何区域。

如何使用来指定环境 AWS CDK

为每个堆栈指定硬编码环境

使用Stack构造的env属性为您的堆栈指定 AWS 环境值。以下是 示例:

TypeScript
const envEU = { account: '2383838383', region: 'eu-west-1' }; const envUSA = { account: '8373873873', region: 'us-west-2' }; new MyFirstStack(app, 'first-stack-us', { env: envUSA }); new MyFirstStack(app, 'first-stack-eu', { env: envEU });
JavaScript
const envEU = { account: '2383838383', region: 'eu-west-1' }; const envUSA = { account: '8373873873', region: 'us-west-2' }; new MyFirstStack(app, 'first-stack-us', { env: envUSA }); new MyFirstStack(app, 'first-stack-eu', { env: envEU });
Python
env_EU = cdk.Environment(account="8373873873", region="eu-west-1") env_USA = cdk.Environment(account="2383838383", region="us-west-2") MyFirstStack(app, "first-stack-us", env=env_USA) MyFirstStack(app, "first-stack-eu", env=env_EU)
Java
public class MyApp { // Helper method to build an environment static Environment makeEnv(String account, String region) { return Environment.builder() .account(account) .region(region) .build(); } public static void main(final String argv[]) { App app = new App(); Environment envEU = makeEnv("8373873873", "eu-west-1"); Environment envUSA = makeEnv("2383838383", "us-west-2"); new MyFirstStack(app, "first-stack-us", StackProps.builder() .env(envUSA).build()); new MyFirstStack(app, "first-stack-eu", StackProps.builder() .env(envEU).build()); app.synth(); } }
C#
Amazon.CDK.Environment makeEnv(string account, string region) { return new Amazon.CDK.Environment { Account = account, Region = region }; } var envEU = makeEnv(account: "8373873873", region: "eu-west-1"); var envUSA = makeEnv(account: "2383838383", region: "us-west-2"); new MyFirstStack(app, "first-stack-us", new StackProps { Env=envUSA }); new MyFirstStack(app, "first-stack-eu", new StackProps { Env=envEU });
Go
env_EU := awscdk.Environment{ Account: jsii.String("8373873873"), Region: jsii.String("eu-west-1"), } env_USA := awscdk.Environment{ Account: jsii.String("2383838383"), Region: jsii.String("us-west-2"), } MyFirstStack(app, "first-stack-us", &awscdk.StackProps{ Env: &env_USA, }) MyFirstStack(app, "first-stack-eu", &awscdk.StackProps{ Env: &env_EU, })

我们建议在生产环境中使用这种方法。通过以这种方式明确指定环境,可以确保堆栈始终部署到特定环境中。

使用环境变量指定环境

AWS CDK 提供了两个可以在 CDK 代码中使用的环境变量:CDK_DEFAULT_ACCOUNT和。CDK_DEFAULT_REGION当您在堆栈实例的env属性中使用这些环境变量时,可以使用 CDK CLI --profile 选项传递证书和配置文件中的环境信息。

以下是如何指定这些环境变量的示例:

TypeScript

通过 Node 的process对象访问环境变量。

注意

您需要在process中使用该DefinitelyTyped模块 TypeScript。 cdk init为你安装这个模块。但是,如果您使用的是添加之前创建的项目,或者您没有使用来设置项目,则应手动安装此模块cdk init

npm install @types/node
new MyDevStack(app, 'dev', { env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }});
JavaScript

通过 Node 的process对象访问环境变量。

new MyDevStack(app, 'dev', { env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }});
Python

使用os模块的environ字典来访问环境变量。

import os MyDevStack(app, "dev", env=cdk.Environment( account=os.environ["CDK_DEFAULT_ACCOUNT"], region=os.environ["CDK_DEFAULT_REGION"]))
Java

System.getenv()用于获取环境变量的值。

public class MyApp { // Helper method to build an environment static Environment makeEnv(String account, String region) { account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; return Environment.builder() .account(account) .region(region) .build(); } public static void main(final String argv[]) { App app = new App(); Environment envEU = makeEnv(null, null); Environment envUSA = makeEnv(null, null); new MyDevStack(app, "first-stack-us", StackProps.builder() .env(envUSA).build()); new MyDevStack(app, "first-stack-eu", StackProps.builder() .env(envEU).build()); app.synth(); } }
C#

System.Environment.GetEnvironmentVariable()用于获取环境变量的值。

Amazon.CDK.Environment makeEnv(string account=null, string region=null) { return new Amazon.CDK.Environment { Account = account ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), Region = region ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") }; } new MyDevStack(app, "dev", new StackProps { Env = makeEnv() });
Go
import "os" MyDevStack(app, "dev", &awscdk.StackProps{ Env: &awscdk.Environment{ Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), }, })

通过使用环境变量指定环境,可以将相同的 CDK 堆栈合成到不同环境的 AWS CloudFormation 模板中。这意味着您可以将相同的 CDK 堆栈部署到不同的 AWS 环境,而无需修改 CDK 代码。您只需要指定要在运行时使用的配置文件即可cdk synth

当将同一个堆栈部署到不同的环境时,这种方法非常适合开发环境。但是,我们不建议在生产环境中使用这种方法,因为相同的 CDK 代码可以合成不同的模板,具体取决于合成它的机器、用户或会话。

使用 CDK 从您的凭据和配置文件中指定环境 CLI

部署与环境无关的模板时,请在任何 CDK CLI 命令中使用该--profile选项来指定要使用的配置文件。以下是部署myStack使用和文件中定义的prod配置文件命名的 CDK 堆栈credentialsconfig示例:

$ cdk deploy myStack --profile prod

有关该--profile选项以及其他 CDK CLI 命令和选项的更多信息,请参阅AWS CDK CLI 命令参考

使用配置环境时的注意事项 AWS CDK

您在堆栈中使用构造定义的服务必须支持您要部署到的区域。有关 AWS 服务 每个区域支持的列表,请参阅按地区划分的AWS 服务

您必须拥有有效的 AWS Identity and Access Management (IAM) 证书,才能使用在您的指定环境 AWS CDK 中执行堆栈部署。

示例

从 CDK 堆栈中合成一个与环境无关 CloudFormation 的模板

在此示例中,我们从 CDK 堆栈中创建了一个与环境无关的 CloudFormation 模板。然后,我们可以将此模板部署到任何环境。

以下是我们的 CDK 堆栈示例。此堆栈定义了 Amazon S3 存储桶和存储桶所在区域的 CloudFormation 堆栈输出。在本例中env,未定义:

TypeScript
export class CdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Create the S3 bucket const bucket = new s3.Bucket(this, 'myBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); // Create an output for the bucket's Region new cdk.CfnOutput(this, 'BucketRegion', { value: bucket.env.region, }); } }
JavaScript
class CdkAppStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); // Create the S3 bucket const bucket = new s3.Bucket(this, 'myBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); // Create an output for the bucket's Region new cdk.CfnOutput(this, 'BucketRegion', { value: bucket.env.region, }); } }
Python
class CdkAppStack(cdk.Stack): def __init__(self, scope: cdk.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Create the S3 bucket bucket = s3.Bucket(self, 'myBucket', removal_policy=cdk.RemovalPolicy.DESTROY ) # Create an output for the bucket's Region cdk.CfnOutput(self, 'BucketRegion', value=bucket.env.region )
Java
public class CdkAppStack extends Stack { public CdkAppStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); // Create the S3 bucket Bucket bucket = Bucket.Builder.create(this, "myBucket") .removalPolicy(RemovalPolicy.DESTROY) .build(); // Create an output for the bucket's Region CfnOutput.Builder.create(this, "BucketRegion") .value(this.getRegion()) .build(); } }
C#
namespace MyCdkApp { public class CdkAppStack : Stack { public CdkAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { // Create the S3 bucket var bucket = new Bucket(this, "myBucket", new BucketProps { RemovalPolicy = RemovalPolicy.DESTROY }); // Create an output for the bucket's Region new CfnOutput(this, "BucketRegion", new CfnOutputProps { Value = this.Region }); } } }
Go
func NewCdkAppStack(scope constructs.Construct, id string, props *CdkAppStackProps) awscdk.Stack { stack := awscdk.NewStack(scope, &id, &props.StackProps) // Create the S3 bucket bucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{ RemovalPolicy: awscdk.RemovalPolicy_DESTROY, }) // Create an output for the bucket's Region awscdk.NewCfnOutput(stack, jsii.String("BucketRegion"), &awscdk.CfnOutputProps{ Value: stack.Region(), }) return stack }

当我们运行时cdk synth,CDK CLI 会生成一个 CloudFormation 模板,其中虚拟参数AWS::Region作为存储桶区域的输出值。此参数将在部署时解析:

Outputs: BucketRegion: Value: Ref: AWS::Region

要将此堆栈部署到我们的凭证和配置文件配置文件中指定的环境中,我们运行以下命令:dev

$ cdk deploy CdkAppStack --profile dev

如果我们不指定配置文件,CDK CLI 将尝试在我们的凭据和配置文件中使用配置文件中的环境信息。default

在模板合成时使用逻辑来确定环境信息

在此示例中,我们将stack实例的env属性配置为使用有效的表达式。我们另外指定了两个环境变量,CDK_DEPLOY_ACCOUNTCDK_DEPLOY_REGION。如果这些环境变量存在,则可以在合成时覆盖默认值:

TypeScript
new MyDevStack(app, 'dev', { env: { account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION }});
JavaScript
new MyDevStack(app, 'dev', { env: { account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION }});
Python
MyDevStack(app, "dev", env=cdk.Environment( account=os.environ.get("CDK_DEPLOY_ACCOUNT", os.environ["CDK_DEFAULT_ACCOUNT"]), region=os.environ.get("CDK_DEPLOY_REGION", os.environ["CDK_DEFAULT_REGION"])
Java
public class MyApp { // Helper method to build an environment static Environment makeEnv(String account, String region) { account = (account == null) ? System.getenv("CDK_DEPLOY_ACCOUNT") : account; region = (region == null) ? System.getenv("CDK_DEPLOY_REGION") : region; account = (account == null) ? System.getenv("CDK_DEFAULT_ACCOUNT") : account; region = (region == null) ? System.getenv("CDK_DEFAULT_REGION") : region; return Environment.builder() .account(account) .region(region) .build(); } public static void main(final String argv[]) { App app = new App(); Environment envEU = makeEnv(null, null); Environment envUSA = makeEnv(null, null); new MyDevStack(app, "first-stack-us", StackProps.builder() .env(envUSA).build()); new MyDevStack(app, "first-stack-eu", StackProps.builder() .env(envEU).build()); app.synth(); } }
C#
Amazon.CDK.Environment makeEnv(string account=null, string region=null) { return new Amazon.CDK.Environment { Account = account ?? System.Environment.GetEnvironmentVariable("CDK_DEPLOY_ACCOUNT") ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"), Region = region ?? System.Environment.GetEnvironmentVariable("CDK_DEPLOY_REGION") ?? System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION") }; } new MyDevStack(app, "dev", new StackProps { Env = makeEnv() });
Go
var account, region string var b bool if account, b = os.LookupEnv("CDK_DEPLOY_ACCOUNT"); !b || len(account) == 0 { account = os.Getenv("CDK_DEFAULT_ACCOUNT") } if region, b = os.LookupEnv("CDK_DEPLOY_REGION"); !b || len(region) == 0 { region = os.Getenv("CDK_DEFAULT_REGION") } MyDevStack(app, "dev", &awscdk.StackProps{ Env: &awscdk.Environment{ Account: &account, Region: &region, }, })

用这种方式声明堆栈的环境后,我们可以编写一个简短的脚本或批处理文件,并从命令行参数中设置变量,然后调用cdk deploy。示例如下:除前两个参数之外的任何参数都将传递给cdk deploy以指定命令行选项或参数:

macOS/Linux
#!/usr/bin/env bash if [[ $# -ge 2 ]]; then export CDK_DEPLOY_ACCOUNT=$1 export CDK_DEPLOY_REGION=$2 shift; shift npx cdk deploy "$@" exit $? else echo 1>&2 "Provide account and region as first two args." echo 1>&2 "Additional args are passed through to cdk deploy." exit 1 fi

将脚本另存为cdk-deploy-to.sh,然后执行chmod +x cdk-deploy-to.sh使其可执行。

Windows
@findstr /B /V @ %~dpnx0 > %~dpn0.ps1 && powershell -ExecutionPolicy Bypass %~dpn0.ps1 %* @exit /B %ERRORLEVEL% if ($args.length -ge 2) { $env:CDK_DEPLOY_ACCOUNT, $args = $args $env:CDK_DEPLOY_REGION, $args = $args npx cdk deploy $args exit $lastExitCode } else { [console]::error.writeline("Provide account and region as first two args.") [console]::error.writeline("Additional args are passed through to cdk deploy.") exit 1 }

该脚本的 Windows 版本用于提供 PowerShell 与 macOS/Linux 版本相同的功能。它还包含允许将其作为批处理文件运行的指令,以便可以轻松地从命令行调用。应将其另存为cdk-deploy-to.bat。该文件cdk-deploy-to.ps1将在调用批处理文件时创建。

然后,我们可以编写其他脚本,使用该cdk-deploy-to脚本部署到特定环境。以下是 示例:

macOS/Linux
#!/usr/bin/env bash # cdk-deploy-to-test.sh ./cdk-deploy-to.sh 123457689 us-east-1 "$@"
Windows
@echo off rem cdk-deploy-to-test.bat cdk-deploy-to 135792469 us-east-1 %*

以下是使用cdk-deploy-to脚本部署到多个环境的示例。如果第一次部署失败,则该过程将停止:

macOS/Linux
#!/usr/bin/env bash # cdk-deploy-to-prod.sh ./cdk-deploy-to.sh 135792468 us-west-1 "$@" || exit ./cdk-deploy-to.sh 246813579 eu-west-1 "$@"
Windows
@echo off rem cdk-deploy-to-prod.bat cdk-deploy-to 135792469 us-west-1 %* || exit /B cdk-deploy-to 245813579 eu-west-1 %*