如何在单个 CDK 项目中传递用于跨堆栈引用的构造对象?

5 分钟阅读
0

我想在单个 AWS Cloud Development Kit(AWS CDK)项目中传递用于跨堆栈引用的构造对象。

简短描述

要进行跨堆栈引用,请使用以下方法之一:

  • (AWS CloudFormation 原生方法)创建堆栈和跨堆栈引用
  • (参数存储方法)创建堆栈和跨堆栈引用以避免 AWS CloudFormation 错误

解决方法

(AWS CloudFormation 原生方法)创建堆栈和跨堆栈引用

**注意:**以下步骤创建了两个名为 VpcStackSecurityGroupStack 的示例堆栈。VpcStack 是一个生产者堆栈,而 SecurityGroupStack 是一个消费者堆栈。在 SecurityGroupStack, 中 已创建一个安全组来引用 VpcStack中的 Amazon VPC ID。创建堆栈时,您可以自定义名称。

1.    创建一个项目并在空目录中调用 cdk init

mkdir my-project
cd my-project
cdk init --language typescript

2.在 lib/my-project-stack.ts 文件中,导入 AWS CDK 模块:

import as 'aws-cdk-lib/aws-ec2';
import * as cdk from 'aws-cdk-lib';

3.    定义一个堆栈并为 Amazon VPC 设置一个属性(在本例中为 VpcStack):

export class VpcStack extends cdk.Stack {
  public readonly vpc: ec2.IVpc;

  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    this.vpc = new ec2.Vpc(this, 'Cross-Ref-Vpc', {
      maxAzs: 2,
      natGateways: 1,
    });
  }
}
  1. 定义一个接口来指定您想从目标堆栈接收的 props:
interface VpcStackProps extends cdk.StackProps {
  vpc: ec2.IVpc;
}

5.    创建另一个使用 VpcStack 中的 ExportValue的堆栈:

  • SecurityGroupStack 使用 props 中的 VpcStackProps
  • 添加 vpc: props.vpc 在安全组属性中进行交叉引用。
export class SecurityGroupStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: VpcStackProps) {
    super(scope, id, props);
    const securityGroupName = "BastionHostSg";
    const SecurityGroup = new ec2.SecurityGroup(this, 'securityGroupName', {
      vpc: props.vpc,
      allowAllOutbound: true,
      securityGroupName: securityGroupName,
    });
  }
}
  1. bin/my-project/ts 文件中,添加以下内容:
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import {VpcStack, SecurityGroupStack} from '../lib/my-project-stack';
const app = new cdk.App();
const vpc_stack = new VpcStack(app, 'vpc-stack', {});
const sg_stack = new SecurityGroupStack(app, 'sg-stack', {
    vpc: vpc_stack.vpc,
});
  1. 通过运行以下命令来部署 AWS CDK 应用程序:
npm update
``````plaintext
cdk deploy --all

**注意:**部署 AWS CDK 应用程序时,vpc-stack 中的 ExportValuesg-stack 导入。

(参数存储方法)创建堆栈和跨堆栈引用以避免 CloudFormation 错误

创建 AWS Certificate Manager (ACM) 堆栈和应用程序负载均衡器 (ALB) 堆栈

如果您收到 AWS CloudFormation 错误消息Export EXPORT_NAME 无法更新,因为 STACK_NAME 正在使用该导出,请完成以下步骤:

1.    创建一个项目并在空目录中调用 cdk init

mkdir my-project
cd my-project
cdk init --language typescript
  1. lib/my-project-stack.ts 重命名为 lib/acm-stack.ts。然后,导入以下 AWS CDK 模块:
import \* as cdk from 'aws-cdk-lib';
import \* as acm from "aws-cdk-lib/aws-certificatemanager";
import \* as ssm from "aws-cdk-lib/aws-ssm";
import {Construct} from 'constructs';
  1. lib/acm-stack.ts 中定义和导出接口 acmProps
export interface acmProps extends cdk.StackProps {
 readonly acmName: string;
 readonly acmArnExportPath: string;
}
  1. 将以下内容添加到文件 acm-stack.ts中:
  • 定义一个名为 acmStack 的堆栈
  • 使用指定的 domainName 和指定的 validation 集创建 ACM 证书。
  • 创建 SSM 参数存储,将证书 ARN 作为一个值来添加。

**重要事项:**务必查看所有 AWS 命令行界面(AWS CLI)命令,并用您的值替换 example 字符串的所有实例。例如,用您指定的域名替换 example_domainName

export class acmStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props: acmProps) {
    super(scope, id, props);
    const cert = new acm.Certificate(this, 'Certificate', {
        domainName: 'example_domainName.com',
        validation: acm.CertificateValidation.fromDns(),
    });
    const parameter = new ssm.StringParameter(this, 'acmArnParameter', {
        parameterName: props.acmArnExportPath,
        stringValue: cert.certificateArn,
    });
    }
}

**注意:**对于 validation: 属性,您可以根据自己的特定要求来修改验证方法。有关更多信息,请参阅验证方法

  1. /lib 目录中创建一个名为 albStack 的文件。然后,导入以下 AWS CDK 模块:
import * as cdk from 'aws-cdk-lib';
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import * as ssm from "aws-cdk-lib/aws-ssm";
import * as acm from "aws-cdk-lib/aws-certificatemanager";
import {Construct} from 'constructs';
  1. 定义接口:
export interface albProps extends cdk.StackProps {
    readonly acmArnExportPath: string;
}
  1. 将下面的代码添加到 AWS CDK 应用程序中的 lib/alb-stack.ts 文件中执行以下操作:
  • 使用 natGateway 创建 Amazon VPC 以降低成本。
  • 定义 acmArn 以从 SSM 参数存储中检索值。
  • 定义用于将 acmArn 从 String 类型转换为IListenerCertificate类型的证书。
  • 创建 ALB。
  • 添加侦听器和 sslCertificateArn 用于引用证书(类型:IListenerCertificate中的值]。
export class albStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props: albProps) {
    super(scope, id, props);
    const vpc = new ec2.Vpc(this, "VPC", { natGateways:1 });
    const acmArn = ssm.StringParameter.valueForStringParameter(this, props.acmArnExportPath);
    const certificate = acm.Certificate.fromCertificateArn(this, 'acm', acmArn);
    const alb = new elbv2.ApplicationLoadBalancer(this, 'ALB', {
        vpc,
        internetFacing: true,
        });
        alb.addRedirect();
    const listener = alb.addListener ('Listener',{
        port: 443,
        certificates: [certificate],
        });
        listener.addTargets('Instance', {port: 80});
    }
}
  1. 将下面的代码添加到您的 bin/my-project.ts 文件中执行以下操作:
  • 定义 env 变量。
  • 定义 certificateArnSsmPath
  • 定义 AWS CDK 应用程序。
  • 使用 AWS CDK 堆栈名称 cdk-ssm-acm-stack定义 ACM 堆栈。
  • 使用 AWS CDK 堆栈名称 cdk-ssm-alb-stack定义 ALB 堆栈。
  • 为 ACM 和 ALB 堆栈添加依赖关系,确保在 ALB 堆栈之前创建 ACM 堆栈。
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import {acmStack, acmProps} from '../lib/acm-stack';
import {albStack, albProps} from '../lib/alb-stack';
import {addDependency} from 'aws-cdk-lib/core/lib/deps';

const env = {account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION}
const certificateArnSsmPath = "/cdk/acm/cross-stacks-reference/certArn";
const app = new cdk.App();
const acm_stack = new acmStack(app, "cdk-ssm-acm-stack", {
    env: env,
    acmName: "ssm-acm",
    acmArnExportPath: certificateArnSsmPath,
});
const alb_stack = new albStack(app, "cdk-ssm-alb-stack", {
    env: env,
    acmArnExportPath: certificateArnSsmPath,
});
alb_stack.addDependency(acm_stack)
  1. 使用以下命令来部署 AWS CDK 应用程序:
npm update
``````plaintext
cdk deploy --all

续订 ACM 证书

要在到期之前续订 ACM 证书并确保 CloudFormation 不会停留在 UPDATE_COMPLETE_CLEANUP_IN_PROGRESS 状态,请完成以下步骤:

  1. lib/acm-stack.ts 文件中添加新证书并将其命名为 renew。然后,将 parameter 中的 stringValue 属性更改为 renew.certificateArn
export class acmStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props: acmProps) {
    super(scope, id, props);
    const cert = new acm.Certificate(this, 'Certificate', {
        domainName: 'example_domainName.com',
        validation: acm.CertificateValidation.fromDns(),
    });
    const renew = new acm.Certificate(this, 'renewCertificate', {
       domainName: 'example_domainName.com',
       validation: acm.CertificateValidation.fromDns(),
    });
    const parameter = new ssm.StringParameter(this, 'acmArnParameter', {
        parameterName: props.acmArnExportPath,
        stringValue: renew.certificateArn,
    });
    }
}
  1. 更新 AWS CDK 应用程序:
cdk deploy --all
  1. 更新堆栈后,通过执行以下操作清理旧证书:
  • 移除证书构造或通过在证书构造前添加 // 将其注释掉。
  • example_domainName 替换为指定的域名。
export class acmStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props: acmProps) {
    super(scope, id, props);
    // const cert = new acm.Certificate(this, 'Certificate', {
    //     domainName: 'example_domainName.com',
    //     validation: acm.CertificateValidation.fromDns(),
    // });
    const renew = new acm.Certificate(this, 'renewCertificate', {
       domainName: 'example_domainName.com',
       validation: acm.CertificateValidation.fromDns(),
    });
    const parameter = new ssm.StringParameter(this, 'acmArnParameter', {
        parameterName: props.acmArnExportPath,
        stringValue: renew.certificateArn,
    });
    }
}
  1. 更新 AWS CDK 应用程序以清理旧证书:
AWS 官方
AWS 官方已更新 1 年前