You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS CDK Lambda版本管理问题:保留旧版本保障Step Functions运行

CDK部署Lambda+Step Functions:旧版本调用权限与版本保留问题

需求背景

  • 通过AWS CDK部署包含Lambda函数和Step Functions的云栈
  • 执行cdk deploy推送新版本时,正在运行的Step Functions执行流必须能继续调用部署时对应的旧版本Lambda
  • 部分Lambda需要启用预置并发,因此必须通过Alias或Version实现版本管理

现有实现代码

PythonFunction类定义

import * as python from "@aws-cdk/aws-lambda-python-alpha";
import * as cdk from "aws-cdk-lib";
import { DockerImage, Duration } from "aws-cdk-lib";
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
import * as lambda from "aws-cdk-lib/aws-lambda";
import { execSync } from "child_process";
import { Construct } from "constructs";
import { artifactoryIndexUrl } from "../../../utils/jfrog";
import { FunctionVersionProps } from "../common/function-version";

export interface PythonFunctionProps extends python.PythonFunctionProps {}

export class PythonFunction extends python.PythonFunction {
  constructor(scope: Construct, id: string, props: PythonFunctionProps) {
    const stack = cdk.Stack.of(scope);

    const pipCacheDir = execSync("pip cache dir").toString().trim();
    const poetryCacheDir = execSync("poetry config cache-dir").toString().trim();

    super(scope, id, {
      timeout: Duration.seconds(30),
      tracing: lambda.Tracing.ACTIVE,
      bundling: {
        image: DockerImage.fromBuild(__dirname, {
          buildArgs: {
            IMAGE: props.runtime.bundlingImage.image,
          },
        }),
        commandHooks: {
          beforeBundling(inputDir: string, outputDir: string): string[] {
            return [`pip config set global.index-url ${artifactoryIndexUrl}`];
          },
          afterBundling(inputDir: string, outputDir: string): string[] {
            return [];
          },
        },
        assetExcludes: ["**/__pycache__", "**/*.pyc", "**/*.pyo", "**/.pytest_cache", "**/tests", "README.md"],
        assetHashType: cdk.AssetHashType.SOURCE,
        volumes: [
          {
            hostPath: pipCacheDir,
            containerPath: "/tmp/pip-cache",
          },
          {
            hostPath: poetryCacheDir,
            containerPath: "/tmp/poetry-cache",
          },
        ],
      },
      ...props,
    });

    this.addToRolePolicy(
      new PolicyStatement({
        actions: ["ssm:GetParameter"],
        resources: [`arn:${stack.partition}:ssm:${stack.region}:${stack.account}:parameter/vita-*`],
      })
    );
  }

  version(props?: FunctionVersionProps): lambda.IFunction {
    const id = this.node.id;
    const version = this.currentVersion;
    const aliasName = `v${version.version}`;
    return new lambda.Alias(this, `${id}Alias`, {
      aliasName,
      version,
      ...(props?.provisionedConcurrency && { provisionedConcurrentExecutions: props?.provisionedConcurrency.value }),
    });
  }
}

FunctionVersionProps接口

export interface FunctionVersionProps {
  provisionedConcurrency?: {
    value: number;
  };
}

Step Functions中调用Lambda版本

prepareSegmentsFn: prepareSegmentsFn.version({
        provisionedConcurrency: {
          value: 1,
        },
      }),

问题现象

  • 使用.currentVersion时,每次cdk deploy会生成新版本(版本号递增),同时CDK会自动删除旧版本
  • 正在运行的Step Functions执行流调用旧版本Lambda时,出现403权限错误:

{
"Error": "Lambda.AWSLambdaException",
"Cause": "User: arn:aws:sts:::assumed-role/Stack--/ is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:eu-central-1:***:function:Stack-SharedDeleteModelFn659FE70B-2IgdOOYDRn78:v34 because no identity-based policy allows the lambda:InvokeFunction action (Service: Lambda, Status Code: 403, Request ID: ***)"
}

解决方案

1. 保留旧Lambda版本

修改version方法,显式创建Lambda版本并设置保留策略,避免CDK删除旧版本:

version(props?: FunctionVersionProps): lambda.IFunction {
  const id = this.node.id;
  // 显式创建版本,设置RemovalPolicy.RETAIN防止旧版本被销毁
  const version = new lambda.Version(this, `${id}Version`, {
    lambda: this,
    removalPolicy: cdk.RemovalPolicy.RETAIN,
  });

  const aliasName = `v${version.version}`;
  const alias = new lambda.Alias(this, `${id}Alias`, {
    aliasName,
    version,
    ...(props?.provisionedConcurrency && { 
      provisionedConcurrentExecutions: props.provisionedConcurrency.value 
    }),
  });

  return alias;
}

2. 扩展Step Functions执行角色的权限

确保Step Functions的执行角色拥有调用目标Lambda所有版本/别名的权限,而不是仅当前版本:

// 假设stateMachineRole是Step Functions的执行角色
stateMachineRole.addToPolicy(new PolicyStatement({
  actions: ["lambda:InvokeFunction"],
  resources: [
    // 匹配目标Lambda的所有版本和别名
    `${prepareSegmentsFn.functionArn}:*`,
    // 如有其他Lambda,添加对应的ARN模式
    `${anotherLambdaFn.functionArn}:*`
  ]
}));

3. 确保Step Functions任务绑定到版本/别名

在定义Step Functions的Lambda调用任务时,直接使用创建的Alias/Version实例,确保部署时生成对应版本的引用:

import * as tasks from "aws-cdk-lib/aws-stepfunctions-tasks";

// 创建调用Lambda的Step Functions任务
new tasks.LambdaInvoke(this, "PrepareSegmentsTask", {
  lambdaFunction: prepareSegmentsFn.version({
    provisionedConcurrency: { value: 1 }
  }),
  // 其他任务配置(如输入输出处理)
});

内容的提问来源于stack exchange,提问作者Or Shemtov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:44:52