首页 > 解决方案 > CDK:可以将为 EdgeFunction 资源创建的堆栈放在另一个(跨区域)堆栈中吗?

问题描述

问题陈述

我有我的主 CDK 堆栈eu-west-1,但EdgeFunctionus-east-1.

我注意到两个奇怪的事情EdgeFunction

  1. 即使在 a 中声明,NestedStack它们也会显示cdk lsedge-lambda-stack-nnnnnnnnn(除非给出明确的名称)。
  2. 删除主堆栈时,我们称之为primary,它不会删除 lambda 堆栈。可能是因为上面的 (1) 告诉我它不是NestedStack.

我曾尝试将其放入显式EdgeFunction创建的单独堆栈中us-east-1,然后从中交叉引用它,primary但由于“无法以跨环境方式使用资源”(以及其他方式)而失败。

问题

我问的原因是因为我有许多环境和许多 lambda,并且堆栈的组合爆炸使事情变得有点笨拙。

例子

CDK 版本 1.116

import "source-map-support/register";
import * as cdk from "@aws-cdk/core";
import * as cloudfront from "@aws-cdk/aws-cloudfront";
import * as lambda from "@aws-cdk/aws-lambda";
import * as path from "path";

class PrimaryStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        new SecondaryStack(this, "secondary-stack");
    }
}

class SecondaryStack extends cdk.NestedStack {
    constructor(scope: cdk.Construct, id: string) {
        super(scope, id);

        new cloudfront.experimental.EdgeFunction(this, "my-lambda", {
            runtime: lambda.Runtime.NODEJS_14_X,
            functionName: "my-lambda",
            handler: "index.handler",
            code: lambda.Code.fromAsset(
                path.join(__dirname, "..", "lib", "my-lambda"),
            ),
        });
    }
}


const app = new cdk.App();

new PrimaryStack(app, "primary", {
    env: { account: "123", region: "eu-west-1" },
});

cdk ls输出:

edge-lambda-stack-cnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
primary

标签: amazon-web-servicesaws-cdkaws-lambda-edge

解决方案


我与 AWS 高级支持人员进行了交谈,答案是 CDK 似乎无法通过使用嵌套堆栈来处理这个问题。

相反,为其中的 EdgeLambdas 创建一个单独的堆栈,us-east-1然后将 lambdas 的 ARN 导出到 SSM。

在另一个堆栈中,从 SSM 导入 ARN 并使用那些.

这将导致要处理的堆栈数量最少。您仍然需要分别部署这两个堆栈。

我最终使用的代码如下所示:

export function exportLambdaSsm(
    func: cloudfront.experimental.EdgeFunction,
): ssm.StringParameter {
    const funcName = // ...
    return new ssm.StringParameter(this, `${funcName}-param`, {
        // Parameter with slash must start with a slash
        parameterName: `/${funcName}`,
        stringValue: func.functionArn,
    });
}

export function importLambdaFromSsm(stack: Stack): lambda.IVersion {
    const funcName = // ...
    const funcResource = new cr.AwsCustomResource(stack, `${funcName}-param`, {
        policy: cr.AwsCustomResourcePolicy.fromStatements([
            new iam.PolicyStatement({
                effect: iam.Effect.ALLOW,
                actions: ["ssm:GetParameter*"],
                resources: [
                    stack.formatArn({
                        service: "ssm",
                        region: "us-east-1",
                        resource: "parameter",
                        resourceName: funcName,
                    }),
                ],
            }),
        ]),
        onUpdate: {
            // will also be called for a CREATE event
            service: "SSM",
            action: "getParameter",
            parameters: {
                Name: `/${funcName}`,
            },
            region: "us-east-1",
            // Update physical id to always fetch the latest version
            physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString()),
        },
    });

    return lambda.Version.fromVersionArn(stack, funcName, funcResource.getResponseField("Parameter.Value"));
}

请注意,在获取和存储 SSM 值时,关于斜线的位置有很多规则。我试图保持上面的代码正确。


推荐阅读