【问题标题】:CDK not updatingCDK 不更新
【发布时间】:2021-12-03 00:16:09
【问题描述】:

更新我的堆栈后运行 cdk deploy:

export function createTaskXXXX (stackScope: Construct, workflowContext: WorkflowContext) {
  const lambdaXXXX = new lambda.Function(stackScope, 'XXXXFunction', {
    runtime: Globals.LAMBDA_RUNTIME,
    memorySize: Globals.LAMBDA_MEMORY_MAX,
    code: lambda.Code.fromAsset(CDK_MODULE_ASSETS_PATH),
    handler: 'xxxx-handler.handler',
    timeout: Duration.minutes(Globals.LAMBDA_DURATION_2MIN),
    environment: {
      YYYY_ENV: (workflowContext.production) ? 'prod' : 'test',
      YYYY_A_LOCATION: `s3://${workflowContext.S3ImportDataBucket}/adata-workflow/split-input/`,
      YYYY_B_LOCATION: `s3://${workflowContext.S3ImportDataBucket}/bdata-workflow/split-input/`  <--- added
    }
  })
  lambdaXXXX.addToRolePolicy(new iam.PolicyStatement({
    effect: Effect.ALLOW,
    actions: ['s3:PutObject'],
    resources: [
        `arn:aws:s3:::${workflowContext.S3ImportDataBucket}/adata-workflow/split-input/*`,
        `arn:aws:s3:::${workflowContext.S3ImportDataBucket}/bdata-workflow/split-input/*` <---- added
    ]
  }))

我意识到这些更改并未在 stack.template.json 更新:

...
        "Runtime": "nodejs12.x",
        "Environment": {
          "Variables": {
            "YYYY_ENV": "test",
            "YYYY_A_LOCATION": "s3://.../adata-workflow/split-input/"
          }
        },
        "MemorySize": 3008,
        "Timeout": 120
      }
...

我已经清理了 cdk.out 并尝试了 deploy --force,但从未看到任何更新。

是删除堆栈并重新部署唯一的最终替代方案,还是我遗漏了什么?我认为至少 synth 应该会产生不同的结果。

(我也在本地系统中更改为 cdk 1.65.0 以匹配 package.json) 谢谢。

已编辑:我 git clone 项目,并再次执行 npm install 和 cdk synth 并最终看到更改,我不想每次都这样做,有什么可能会阻止正确的合成器生成吗?

EDITED 2:在旧项目与 synth 工作的 git 新项目之间存在差异之后,我意识到我的一些具有 .ts 的项目文件(例如 cdk.ts 我的应用程序定义)也具有具有 .ts 的副本。 js 和 .d.ts.,例如 cdk.js 和 cdk.d.ts。我是否可能错误地运行了一些编译 Typescript 的命令,我将继续调查,感谢所有答案。

【问题讨论】:

  • 您确定在运行cdk 命令之前已保存.ts 文件吗?
  • 嗨,是的,请确保保存它(尽管 Intellij 会自动保存),我将在两个文件夹之间进行比较,旧项目文件夹失败的地方和我从 git 获得的新文件夹,看看我是否可以找到更多细节,但它适用于新克隆的 git。
  • 我发现了一些带有 .d.ts 和 .js 的额外文件,这可能是原因,谢谢。

标签: aws-cdk


【解决方案1】:

因为 CDK 使用 Cloudformation,它执行一个动作来确定一个 ChangeSet。也就是说,如果它认为没有任何改变,它就不会改变那个资源。

当然,这可能会很烦人,因为有时它认为它是相同的,并且在实际发生更改时不会更新 - 我发现这最常见于 Layers 并使用某种形式的 make 文件来生成 zip对于图层。即使它制作了一个“新”zip,无论它用于确定 zip 是否已更新,都会将其召回为相同的,因为......无论使用什么压缩/散列/等更改。

您可以通过使用日期时间更新描述来解决此问题。它在 synth 分配(这是 cdk 部署的一部分),因此如果您执行 datetime 的 current now()

您也可以使用cdk diff 来查看它认为的更改是什么。

最后...始终记得在部署之前保存您的文件,因为根据您的 IDE,命令行可能无法使用它;)

【讨论】:

  • 是的,两个差异都无法触发更改,我使用 Intellij,但确保全部保存,并从提示符执行命令。我将尝试在两个文件夹之间进行区分。谢谢。
  • 我发现了一些带有 .d.ts 和 .js 的额外文件,这可能是原因,谢谢。
【解决方案2】:

我认为它会在我看到代码的地方更新,但我不知道为什么它不能。

建议将有关Lambda的部分注释一次并部署,然后取消注释并再次部署,然后重新创建Lambda。

【讨论】:

    【解决方案3】:

    这就是我的做法。到目前为止工作得很好。基本上你可以做到以下几点:

    1. 将您的 lambda 代码作为 zip 文件推送到 s3 存储桶。存储桶必须启用版本控制。 .

    2. 下面的 CDK 代码将执行以下操作:

      1. 创建自定义资源。它基本上为我在 S3 中的 lambda zip 文件调用 s3.listObjectVersions。我获取了第一个返回值,它似乎一直是最新的对象版本(尽管我无法通过文档确认这一点)。我还为自定义资源创建了一个角色。
      2. 创建 lambda 并将代码指定为 s3 中的 zip 文件和自定义资源返回的对象版本!这是最重要的部分。
      3. 创建一个新的 lambda 版本。

    然后,当您部署 CDK 堆栈时,lambda 的代码会更新!

    const versionIdKey = 'Versions.0.VersionId';
    const isLatestKey = 'Versions.0.IsLatest'
    const now = new Date().toISOString();
    
    const role = new Role(this, 'custom-resource-role', {
        assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
    });
    role.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess')); // you can make this more specific
    
    
    // I'm not 100% sure this gives you the most recent first, but it seems to be doing that every time for me.  I can't find anything in the docs about it...
    const awsSdkCall: AwsSdkCall = {
        action: "listObjectVersions",
        parameters: {
            Bucket: buildOutputBucket.bucketName, // s3 bucket with zip file containing lambda code.
            MaxKeys: 1,
            Prefix: LAMBDA_S3_KEY, // S3 key of zip file containing lambda code
        },
        physicalResourceId: PhysicalResourceId.of(buildOutputBucket.bucketName),
        region: 'us-east-1', // or whatever region
        service: "S3",
        outputPaths: [versionIdKey, isLatestKey]
    };
    
    const customResourceName = 'get-object-version'
    const customResourceId = `${customResourceName}-${now}` // not sure if `now` is neccessary...
    
    const response = new AwsCustomResource(this, customResourceId, {
        functionName: customResourceName,
        installLatestAwsSdk: true,
        onCreate: awsSdkCall,
        onUpdate: awsSdkCall,
        policy: AwsCustomResourcePolicy.fromSdkCalls({resources: AwsCustomResourcePolicy.ANY_RESOURCE}), // you can make this more specific
        resourceType: "Custom::ListObjectVersions",
        role: role 
    })
    
    const fn = new Function(this, 'my-lambda', {
        functionName: 'my-lambda',
        description: `${response.getResponseField(versionIdKey)}-${now}`,
        runtime: Runtime.NODEJS_14_X,
        memorySize: 1024,
        timeout: Duration.seconds(5),
        handler: 'index.handler',
        code: Code.fromBucket(buildOutputBucket, LAMBDA_S3_KEY, response.getResponseField(versionIdKey)),  // This is where the magic happens. You tell CDK to use a specific S3 object version when updating the lambda.
        currentVersionOptions: {
            removalPolicy: RemovalPolicy.DESTROY,
        },
    });
    
    new Version(this, `version-${now}`, { // not sure if `now` is neccessary...
        lambda: fn,
        removalPolicy: RemovalPolicy.DESTROY
    })
    

    请注意: 为此,您必须在每次 cdk 部署之前将您的 lambda 邮政编码上传到 S3。这可以是与以前相同的代码,但 s3 存储桶版本控制将创建一个新版本。作为额外自动化的一部分,我使用代码管道来执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-01
      • 2022-01-02
      • 1970-01-01
      • 2023-01-30
      • 2019-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多