如何使用CloudFormation创建Lambda函数的新版本?

67

我正在使用CloudFormation创建一个新版本的Lambda函数。

我希望拥有同一Lambda函数的多个版本,这样我可以(a)将别名指向不同的版本-比如DEV和PROD- (b)能够回滚到早期的版本。

以下是我的Lambda版本定义:

LambdaVersion:
  Type: AWS::Lambda::Version
  Properties:
    FunctionName:
      Ref: LambdaFunction

运行 "aws cloudformation create-stack" 时会创建一个版本,但后续的 "aws cloudformation update-stack" 命令没有任何作用。没有新的 Lambda 版本被创建。

我试图在将新的 zip 文件上传到 S3 并运行 "update-stack" 后创建一个 Lambda 函数的新版本。我可以在 CloudFormation 中完成吗? AWS::Lambda::Version 真的有问题(如 https://github.com/hashicorp/terraform/issues/6067#issuecomment-211708071 中所述),还是我没有理解到什么?

更新 1/11/17
亚马逊支持官方回复:"...要发布任何新版本,您需要定义一个额外的 AWS::Lambda::Version 资源..."

AWS CloudFormation/Lambda 团队,如果您正在阅读此文——这是不可接受的,请修复它。

14个回答

45

我有一个类似的用例(需要使用CloudFormation管理在CloudFront中用于@edge的lambda函数,其中始终需要特定的lambda函数版本,而不是$LATEST),我的搜索使我首先找到了这个问题,但经过更深入的挖掘,我很高兴地发现现在有原生支持自动lambda版本控制的新AutoPublishAlias功能的AWS无服务器应用程序模型(基本上是您的CloudFormation模板的可选额外集合)。

在这里宣布:https://github.com/awslabs/serverless-application-model/issues/41#issuecomment-347723981

详情请参见:

基本上,您可以在AWS::Serverless::Function定义中包括AutoPublishAlias

MyFunction:
  Type: "AWS::Serverless::Function"
  Properties:
    # ...
    AutoPublishAlias: MyAlias

然后在 CloudFormation 模板的其他位置,您可以使用以下 YAML 语法引用最新发布版本:!Ref MyFunction.Version


2
这很简单,应该成为新的批准答案。谢谢。 - Hugodby
9
尽管这看起来是个好答案,但需要注意的是答案依赖于AWS SAM。请注意,函数类型是AWS :: Serverless :: Function。对我没有用。 - Blueshirts
这可能不是官方答案,因为我们中的一些人可能是由于版本泄漏问题(https://github.com/serverless/serverless/issues/400)而在此处。当您使用AutoPublishAlias时会发生这种情况,并且会产生一些影响。例如,我将其用于“staging”,但也希望针对同一版本设置“production”别名。自定义资源可以两种方式工作,而AutoPublishAlias只能解决我的CI / CD挑战的一部分。 - rainabba

25
这篇帖子已经过时了。我在这里更新它,以便其他人可以看到截至2020年6月9日版本的正确解决方案,而无需额外的自定义版本化Lambda函数。
这个:
Description: Lambda Example
Resources:
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Code:
        ZipFile: |
          'Example Code';
      Runtime: nodejs12.x
      Timeout: 5

变成这样:
Description: Lambda Example
Transform: AWS::Serverless-2016-10-31
Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      AutoPublishAlias: live
      Handler: index.handler
      InlineCode: |
        'Example Code';
      Runtime: nodejs12.x
      Timeout: 5
Transform: 允许在 CloudFormation 模板中使用 AWS::Serverless::Function,从而支持 Lambda 版本控制。然后,您可以通过 { "Fn::Sub": "${ServerlessLambdaFunction.Version}" } 引用版本化的 ARN。
不要像我一样被上面过时的“最佳答案”误导,那是为某人的书编写的。
不客气。

1
这很简单且运行良好 - 应该是批准的答案。 - pbthorste
1
这对于codeuri没有起作用。它发布了实时版本,但没有更新函数代码。你有codeuri的工作示例吗? - Lavesh
请注意,AutoPublishAlias通过将给定的别名附加到函数名称作为CFN资源名称来通过转换工作。这意味着您不能使用包含非字母数字字符的别名。 - Corey Cole
这可能会有自己的问题:https://github.com/aws/aws-cdk/issues/5334 - jawsnnn
@Lavesh 函数代码可以通过在 S3 中生成新的 zip 文件名来更新,例如将随机字符串附加到 zip 名称中。在我的 CI 中,我生成一个随机字符串,将其附加到 zip 名称中,将此 zip 文件上传到 S3,并将相同的字符串作为参数传递给 aws cloudformation deploy,以便 CodeUri/Key 接收随机字符串。据我所知,强制更新 Lambda 函数的唯一方法是在代码更改时(因为现在它总是会更新,无论代码是否更改)。 - nichoio
"Fn::Sub": "${ServerlessLambdaFunction.Version}" - Warren Parad

24

AWS::Lambda::Version 没有用处,您必须添加一个新资源来支持每个 Lambda 版本。如果您想要在每次 Cloudformation 更新时发布新的版本,则必须对系统进行修改。

我解决了这个问题,创建了一个 Lambda 后端自定义资源,该资源会在每次部署时触发。在此 Lambda 中,我会针对给定参数的 Lambda 函数创建一个新版本。

有关 Lambda 的源代码,请查看 http://serverless-arch-eu-west-1.s3.amazonaws.com/serverless.zip

以下是使用此部署 Lambda 函数的示例 Cloudformation(您可能需要进行一些修改):

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "DeploymentTime": {
      "Type": "String",
      "Description": "It is a timestamp value which shows the deployment time. Used to rotate sources."
    }
  },
  "Resources": {
    "LambdaFunctionToBeVersioned": {
      "Type": "AWS::Lambda::Function",
       ## HERE DEFINE YOUR LAMBDA AS USUAL ##
    },
    "DeploymentLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "lambda.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path": "/",
        "ManagedPolicyArns": [
          "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
        ],
        "Policies": [
          {
            "PolicyName": "LambdaExecutionPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "lambda:PublishVersion"
                  ],
                  "Resource": [
                    "*"
                  ]
                }
              ]
            }
          }
        ]
      }
    },
    "DeploymentLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Role": {
          "Fn::GetAtt": [
            "DeploymentLambdaRole",
            "Arn"
          ]
        },
        "Handler": "serverless.handler",
        "Runtime": "nodejs4.3",
        "Code": {
          "S3Bucket": {
            "Fn::Sub": "serverless-arch-${AWS::Region}"
          },
          "S3Key": "serverless.zip"
        }
      }
    },
    "LambdaVersion": {
      "Type": "Custom::LambdaVersion",
      "Properties": {
        "ServiceToken": {
          "Fn::GetAtt": [
            "DeploymentLambda",
            "Arn"
          ]
        },
        "FunctionName": {
          "Ref": "LambdaFunctionToBeVersioned"
        },
        "DeploymentTime": {
          "Ref": "DeploymentTime"
        }
      }
    }
  }
}

(免责声明:此代码是我书中的一部分,有关Lambda和API Gateway的更多信息,请查看:https://www.amazon.com/Building-Serverless-Architectures-Cagatay-Gurturk/dp/1787129195


2
谢谢!太疯狂了。我已经通过我们的企业支持计划向 AWS 提出了支持请求,如果他们确认 AWS::Lambda::Version 是无用的,我会尝试这个并接受这个答案。 - boris
2
@boris 你好Boris,这个功能是否已经实现了? - lekev87
太棒了,我花了两天时间尝试在每次发布时限制角色创建,非常感谢! - SilentTremor
1
应该放入HERE_DEFINE_YOUR_LAMBDA中的是什么?那不是实际的Lambda函数代码,那是什么? - Grzegorz Oledzki
2
@GrzegorzOledzki 我已经编辑了代码以进行澄清。这是实际的 Lambda 代码。 - Çağatay Gürtürk
显示剩余2条评论

12

AWS::Lambda::Version资源仅表示单个已发布的Lambda函数版本-它不会在每次代码更新时自动发布新版本。为了实现这一点,您有两个选项:

1. 自定义资源

您可以实现自己的自定义资源,该资源在每次更新时调用PublishVersion

对于此方法,每次更新堆栈时,您仍需要更改至少一个参数,以触发Custom Resource上的更新,从而触发PublishVersion操作。(但是,您不必实际更新模板。)

以下是完整的工作示例:

Launch Stack

Description: Publish a new version of a Lambda function whenever the code is updated.
Parameters:
  Nonce:
    Description: Change this string when code is updated.
    Type: String
    Default: "Test"
Resources:
  MyCustomResource:
    Type: Custom::Resource
    Properties:
      ServiceToken: !GetAtt MyFunction.Arn
      Nonce: !Ref Nonce
  MyFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          var response = require('cfn-response');
          exports.handler = function(event, context) {
            return response.send(event, context, response.SUCCESS, {Result: '${Nonce}'});
          };
      Runtime: nodejs4.3
  LambdaDeploy:
    Type: Custom::LambdaVersion
    Properties:
      ServiceToken: !GetAtt LambdaDeployFunction.Arn
      FunctionName: !Ref MyFunction
      Nonce: !Ref Nonce
  LambdaDeployFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: "index.handler"
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          var AWS = require('aws-sdk');
          var response = require('cfn-response');
          exports.handler = (event, context) => {
            console.log("Request received:\n", JSON.stringify(event));
            if (event.RequestType == 'Delete') {
              return response.send(event, context, response.SUCCESS);
            }
            var lambda = new AWS.Lambda();
            lambda.publishVersion({FunctionName: event.ResourceProperties.FunctionName}).promise().then((data) => {
              return response.send(event, context, response.SUCCESS, {Version: data.Version}, data.FunctionArn);
            }).catch((e) => {
              return response.send(event, context, response.FAILED, e);
            });
          };
      Runtime: nodejs4.3
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal: {Service: [lambda.amazonaws.com]}
          Action: ['sts:AssumeRole']
      Path: /
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
      - PolicyName: PublishVersion
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action: ['lambda:PublishVersion']
            Resource: '*'
Outputs:
  LambdaVersion:
    Value: !GetAtt LambdaDeploy.Version
  CustomResourceResult:
    Value: !GetAtt MyCustomResource.Result

2. 模板预处理器

你可以使用像嵌入式Ruby这样的模板预处理器(或者在每次部署时手动更新模板),通过更改AWS::Lambda::Version资源的逻辑ID,在每次代码更新时发布新版本。

例如:

# template.yml
Description: Publish a new version of a Lambda function whenever the code is updated.
<%nonce = rand 10000%>
Resources:
  LambdaVersion<%=nonce%>:
    Type: AWS::Lambda::Version
    Properties:
      FunctionName: !Ref MyFunction
  MyCustomResource:
    Type: Custom::Resource
    Properties:
      ServiceToken: !GetAtt MyFunction.Arn
      Nonce: <%=nonce%>
  MyFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          var response = require('cfn-response');
          exports.handler = function(event, context) {
            return response.send(event, context, response.SUCCESS, {Result: '<%=nonce%>'});
          };
      Runtime: nodejs4.3
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal: {Service: [lambda.amazonaws.com]}
          Action: ['sts:AssumeRole']
      Path: /
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Outputs:
  LambdaVersion:
    Value: !GetAtt LambdaVersion<%=nonce%>.Version
  CustomResourceResult:
    Value: !GetAtt MyCustomResource.Result

要通过erb模板预处理器传递template.yml来创建/更新堆栈,请运行:

运行:

aws cloudformation create-stack --stack-name myteststack --template-body file://template.yml --parameters "$(cat parameters.json)"

或者

aws cloudformation update-stack --stack-name myteststack --template-body file://template.yml --parameters "$(cat parameters.json)"
aws cloudformation [create|update]-stack \
  --stack-name [stack_name] \
  --template-body file://<(ruby -rerb -e "puts ERB.new(ARGF.read).result" < template.yml) \
  --capabilities CAPABILITY_IAM

1
我想要同一Lambda函数的多个版本,以便我可以: (a) 指向不同版本的别名 - 如DEV和PROD - (b) 能够回滚到早期版本 - boris
您可能想考虑使用CodePipline将不同的CloudFormation配置模板部署到同一个CloudFormation模板中。这可能是一种更可靠的维护开发和生产环境的方式。 - Eric Nord
@boris 感谢您提供的额外信息,我已经更新了我的答案,并提供了两种不同方法的完整示例模板。 - wjordan
这个解决方案是否也适用于S3存储桶(不使用Code:)?我遇到了错误。Lambda函数已经存在一个版本(1)。请修改函数以创建新版本。 - Felipe Alvarez
@wjordan 是的,我同意Boris的观点,除非你(愚蠢地?)在CloudFormation中添加了一个无限列表的Lambda版本,否则Lambda将不会自动保留以前版本的列表,以便您可以轻松回滚。 - Johny19
是的,但使用纯CloudFormation 应该有更简单的方法! - Blueshirts

7

答案已更新至2018年2月

您可以使用AWS SAM(无服务器应用程序模型)及其sam packagesam deploy命令来更新Lambda。它们类似于aws cloudformation packageaws cloudformation deploy命令,但还可以让您自动更新Lambda版本。

SAM可以打包你的代码(或者使用你创建的ZIP包),将其上传到S3,并从中更新Lambda的$LATEST版本。如果这是你所需要的全部,那么也可以使用aws cloudformation而不是SAM完成此操作;代码示例与下面相同,但仅使用CloudFormation的标准声明。然后,使用SAM,如果进行了适当配置,还可以自动发布版本并更新别名以指向它。它还可以选择使用AWS CodeDeploy逐渐将流量从旧版本移动到新版本,并在出现错误时回滚。所有这些都在安全Lambda部署中解释。
每次更新堆栈时,技术上来说,您需要让 AWS::Lambda::FunctionCode 指向 S3 中的程序包。这将确保当您更新堆栈时,Lambda 的 $LATEST 版本将从新程序包中更新。然后,您还可以自动发布新版本并切换别名。为此,请创建一个 SAM 模板,类似于(超集) CloudFormation 模板。它可以包括特定于 SAM 的声明,例如下面的 AWS::Serverless::Function 的声明。将 Code 指向源代码目录(或预打包的 ZIP),并设置 AutoPublishAlias 属性。
...

MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      ...  # all usual CloudFormation properties are accepted 
      AutoPublishAlias: dev  # will publish a Version and create/update Alias `dev` to point to it
      Code: ./my/lambda/src
...

运行:

$ sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket my-bucket

该软件包将源目录内容打包为ZIP(如果Code尚未是ZIP),将其上传到新的自动生成的密钥下的S3,并生成最终的CloudFormation模板到packaged.yaml,并为您将适当的Code引用放入其中; 就像这样:
...
MyFunction:
    Properties:
      Code:
        S3Bucket: my-bucket
        S3Key: ddeeaacc44ddee33ddaaee223344
...

现在您可以使用生成的 packaged.yaml 与 SAM 一起创建函数版本:
sam deploy --template-file packaged.yaml --stack-name my-stack [--capabilities ...]

这将更新Lambda的$ LATEST版本,并且如果定义了AutoPublishAlias,则会将其发布为新版本并更新别名以指向新发布的版本。
请参阅SAM GitHub存储库中的示例,获取完整的模板代码。

这并没有解决通过CloudFormation向Lambda函数添加多个版本的问题。所有这些做的就是使用提供的一些不错的工具来生成一些CloudFormation并更新代码到$LATEST。它不会向Lambda函数添加版本。 - Nathan Phetteplace
1
是的,我确实没有意识到问题也包括这个。我已经更新了答案,也包括了这一点(发布版本并将别名更新为它)。 - Tim

5
寻找与从S3部署的Lambda函数配合使用的类似工具。
我的用例是这样的:
- 您有一个CloudFormation模板,它从S3存储桶位置创建Lambda函数 - 您需要更新此函数,因此在本地进行代码更改并将更改推送到S3 - 现在您想要将这些更改推送到Lambda,因此尝试更新堆栈,CloudFormation表示没有要更新的更改,因此您必须手动使用AWS Lambda控制台更新代码。
对此不满意,我寻找了替代方案,并遇到了这个问题。没有答案完全适合我,因此我借鉴了一些想法并调整了这里的答案,并编写了自己的Python版本。
此代码是从@wjordan的答案中修改而来,所以要感谢他提供的想法和原始答案。区别在于:
- 这是用Python编写的 - 它适用于从S3存储桶部署的Lambda代码 - 它更新代码并发布新版本
您需要一个随机参数。当需要重新发布代码时,更改此参数的值。这是为了确保CloudFormation将更新您的自定义资源。更新自定义资源后,它将运行最终更新Lambda代码的Python代码。
希望这能帮助某人。
Description: Publish a new version of a Lambda function whenever the code is updated.
Parameters:
  Nonce:
    Description: Change this string when code is updated.
    Type: String
    Default: "Test"
Resources:
  MyCustomResource:
    Type: Custom::Resource
    Properties:
      ServiceToken: !GetAtt MyFunction.Arn
      Nonce: !Ref Nonce
  MyFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        S3Bucket: BucketContainingYourLambdaFunction
        S3Key: KeyToYourLambdaFunction.zip
      Runtime: "python3.6"
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal: {Service: [lambda.amazonaws.com]}
          Action: ['sts:AssumeRole']
      Path: /
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  LambdaDeployCustomResource:
    Type: Custom::LambdaVersion
    Properties:
      ServiceToken: !GetAtt LambdaDeployFunction.Arn
      FunctionName: !Ref MyFunction
      S3Bucket: BucketContainingYourLambdaFunction
      S3Key: KeyToYourLambdaFunction.zip
      Nonce: !Ref Nonce
  LambdaDeployFunction:
    Type: AWS::Lambda::Function
    DependsOn: LambdaDeployFunctionExecutionRole
    Properties:
      Handler: "index.handler"
      Role: !GetAtt LambdaDeployFunctionExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          import boto3
          import json
          import logging
          import cfnresponse
          import time
          from botocore.exceptions import ClientError

          def handler(event, context):
            logger = logging.getLogger()
            logger.setLevel(logging.INFO)
            logger.info (f"Input parameters from cloud formation: {event}")
            responseData = {}
            if (event["RequestType"] == 'Delete'):
              logger.info("Responding to delete event...")
              cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)

            try:            
              lambdaClient = boto3.client('lambda')
              s3Bucket = event['ResourceProperties']['S3Bucket']
              s3Key = event['ResourceProperties']['S3Key']
              functionName = event['ResourceProperties']['FunctionName']
              logger.info("Updating the function code for Lambda function '{}' to use the code stored in S3 bucket '{}' at key location '{}'".format(functionName, s3Bucket, s3Key))
              logger.info("Sleeping for 5 seconds to allow IAM permisisons to take effect")
              time.sleep(5)             
              response = lambdaClient.update_function_code(
                FunctionName=functionName,
                S3Bucket='{}'.format(s3Bucket),
                S3Key='{}'.format(s3Key),
                Publish=True)
              responseValue = "Function: {}, Version: {}, Last Modified: {}".format(response["FunctionName"],response["Version"],response["LastModified"])
              responseData['Data'] = responseValue
              cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, response["FunctionArn"])
            except ClientError as e:
              errorMessage = e.response['Error']['Message']
              logger.error(errorMessage)
              cfnresponse.send(event, context, cfnresponse.FAILED, responseData)
      Runtime: "python3.6"
      Timeout: "30"
  LambdaDeployFunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal: 
            Service: lambda.amazonaws.com
          Action: 
            - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
      - PolicyName: ReadS3BucketContainingLambdaCode
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action: 
              - s3:GetObject              
            Resource: ArnOfS3BucketContainingLambdaCode/*
      - PolicyName: UpdateCodeAndPublishVersion
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action: 
              - lambda:UpdateFunctionCode
              - lambda:PublishVersion
            Resource: '*'
Outputs:
  LambdaVersion:
    Value: !GetAtt LambdaDeploy.Version
  CustomResourceResult:
    Value: !GetAtt MyCustomResource.Result 

2

很遗憾,使用CloudFormation无法完成此操作。您需要在CloudFormation模板中为每个版本添加新的AWS :: Lambda :: Version部分。

最接近的解决方案是创建.erb模板,并生成包含所有版本的CloudFormation模板。


2
这是一个有些巧妙的方法,需要使用gitlab-ci(或类似工具),但我发现通过将提交哈希传递到云形成模板(通过模板参数)非常有用。 (与@Jerry的答案有点相似,但使用了提交哈希。)
在这种情况下,您可以执行以下操作:
在模板中设置一个参数来存储提交哈希值,例如:
AWSTemplateFormatVersion: '2010-09-09'
Description: Template for Lambda Sample.
Parameters:
  ciCommitSha:
    Type: String
  s3Bucket:
    Type: String
  ...

您可以在 Lambda 资源中引用它,如下所示:
  CFNLambda:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: cfn_trigger_fn
      Description: lambda which gets triggered by cloudformation
      Runtime: python3.7
      Code:
        S3Bucket: !Ref s3Bucket
        S3Key: !Join [ ".", [ !Ref ciCommitSha, "zip"]]
      Handler: function.handler
      ...

您的CI流水线需要像这样(假设您将云形成模板命名为stack-template.yaml):
variables:
  REGION: us-east-1
  S3_BUCKET_NAME: my-bucket

stages:
 - build
 - push
 - deploy

build-package:
  stage: build
  script:
    - some code to produce a deployment package called function.zip
  artifacts:
    name: deployment_package
    paths:
      - function.zip


push-code:
  stage: push
  script:
    - aws s3 cp function.zip s3://$S3_BUCKET_NAME/$CI_COMMIT_SHA.zip

deploy-trigger-stack:
  stage: deploy
  script: 
      - aws cloudformation deploy
            --template-file stack-template.yaml
            --stack-name my-stack
            --region $REGION
            --no-fail-on-empty-changeset
            --capabilities CAPABILITY_NAMED_IAM
            --parameter-overrides
            ciCommitSha=$CI_COMMIT_SHA
            s3Bucket=$S3_BUCKET_NAME

你可以使用这种技术来触发 EC2 元数据上的 cfn-init。

1
  1. 我们可以制作一个Lambda部署包;
  2. 将Lambda包与版本一起作为Cloud Formation参数传递,例如"LambdaPakcageNameWithVersion";
  3. 使用"LambdaPakcageNameWithVersion"作为Lambda代码的s3键;
  4. 当运行aws-cli命令更新cloudformation堆栈或运行CI/CD管道时,将部署新的Lamdba包。

  MyLambda:
    Type: AWS::Lambda::Function
    Properties:
      Role: LambdaRole
      Code:
        S3Bucket: LambdaPackageS3Bucket
        S3Key: !Sub "${LambdaPakcageNameWithVersion}"
      FunctionName: LambdaFunctionName
      Handler: lambda_function.lambda_handler
      Runtime: python3.6
      Timeout: 60


1

Worked for me the following:

"LambdaAlias": {
            "Type": "AWS::Lambda::Alias",
            "DeletionPolicy" : "Retain",
            "Properties": {
                "FunctionName": {
                    "Ref": "LambdaFunction"
                },
                "FunctionVersion": {
                    "Fn::GetAtt": ["LambdaVersion","Version"]
                },
                "Name": "MyAlias"
            }

所以我只需要添加DeletionPolicy: Retain。 - Mircea Pacurar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接