使用CloudFormation创建Lambda

使用CloudFormation创建lambda有三种方式:

  1. inline。直接将lambda内容写到CloudFormation里。
  2. S3。 将lambda内容打包压缩,上传到S3。然后在CloudFormation里引用S3路径。
  3. S3 versoning。和上面相比,多了versioning这个选项,用于更新CloudFormation。

lambda inline

CloudFormation yaml:

Resources: 
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      Policies:
      - PolicyName: root
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action:
            - "s3:*"
            Resource: "*"
          - Effect: Allow
            Action:
            - "logs:CreateLogGroup"
            - "logs:CreateLogStream"
            - "logs:PutLogEvents"
            Resource: "*"
  ListBucketsS3Lambda: 
    Type: "AWS::Lambda::Function"
    Properties: 
      Handler: "index.handler"
      Role: 
        Fn::GetAtt: 
          - "LambdaExecutionRole"
          - "Arn"
      Runtime: "python3.7"
      Code: 
        ZipFile: |
          import boto3
          # Create an S3 client
          s3 = boto3.client('s3')
          def handler(event, context):
            # Call S3 to list current buckets
            response = s3.list_buckets()
            # Get a list of all bucket names from the response
            buckets = [bucket['Name'] for bucket in response['Buckets']]
            # Print out the bucket list
            print("Bucket List: %s" % buckets)
            return buckets

创建完成后可以到lambda界面里找到它:

image-20191106150021593

image-20191106150053845

总结:

  • 如果有依赖(例如依赖paromiko库),或者代码行数超过4000行,这种方式不适合。

  • 这种方式适合简单的lambda。

通过S3

先建立一个桶和一个路径,用于上传打包后的lambda代码:

image-20241003063409312

cloudformation代码如下(role的部分都一样,不同的是用S3指定代码位置):

Parameters:
  S3BucketParam:
    Type: String
  S3KeyParam:
    Type: String
Resources: 
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      Policies:
      - PolicyName: root
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action:
            - "s3:*"
            Resource: "*"
          - Effect: Allow
            Action:
            - "logs:CreateLogGroup"
            - "logs:CreateLogStream"
            - "logs:PutLogEvents"
            Resource: "*"
  ListBucketsS3Lambda: 
    Type: "AWS::Lambda::Function"
    Properties: 
      Handler: "index.handler"
      Role: 
        Fn::GetAtt: 
          - "LambdaExecutionRole"
          - "Arn"
      Runtime: "python3.7"
      Code: 
        S3Bucket: !Ref S3BucketParam
        S3Key: !Ref S3KeyParam

创建stack时,将S3的参数填写进去:

image-20241003063504473

创建完成后的效果:

image-20191106150831219

代码如果要更新,此时将代码打包上传到S3相同位置,再进行更新:

image-20241003063548199

由于参数为S3 bucketname和S3 path,两次检测到相同值,不会进行更新:

image-20191106151014947

一种解决方法是上传时起不同名字的zip,再将zip名称填写到cloudformation的参数中,但这种方法不太优雅。

lambda S3 Versioning

如果指定第三个变量versioning,每次更新并打包上传代码后,加上version id,cloudformation可以检测到变化,所以会进行更新:

Parameters:
  S3BucketParam:
    Type: String
  S3KeyParam:
    Type: String
  S3ObjectVersionParam:
    Type: String
Resources: 
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      Policies:
      - PolicyName: root
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action:
            - "s3:*"
            Resource: "*"
          - Effect: Allow
            Action:
            - "logs:CreateLogGroup"
            - "logs:CreateLogStream"
            - "logs:PutLogEvents"
            Resource: "*"
  ListBucketsS3Lambda: 
    Type: "AWS::Lambda::Function"
    Properties: 
      Handler: "index.handler"
      Role: 
        Fn::GetAtt: 
          - "LambdaExecutionRole"
          - "Arn"
      Runtime: "python3.7"
      Code: 
        S3Bucket: 
          Ref: S3BucketParam
        S3Key: 
          Ref: S3KeyParam
        S3ObjectVersion:
          Ref: S3ObjectVersionParam

在S3里重新上传新版本的代码。更新堆栈,填写version id:

image-20191106151634628

此时可以更新成功。