使用CloudFormation从SNS触发Lambda?

7

如何使用CloudFormation从SNS触发Lambda?

3个回答

14

我们所做的是将 SNS(Simple Notification Service) 指向一个有资格的 Lambda 而不是直接指向 Lambda。基本上,创建一个 Lambda,然后创建一个别名,使用 SNS 将其指向 Lambda 的别名。

当您有新的 Lambda 代码时(您的 CI / CD 可以执行以下操作),更新 Lambda 函数代码,创建新的 Lambda 版本,并将别名重新指向新版本。这样,当 Lambda 代码更新时,SNS 不需要进行任何更改。

Resources: 
  AwsServerlessExpressFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: mylambda
      Description: mylambda 
      Runtime: nodejs8.10
      Handler: index.handler
      MemorySize: 512
      Timeout: 60
      Role: !Ref LambdaExecutionRoleArn

  AwsServerlessExpressFunctionAlias:
    Type: AWS::Lambda::Alias
    Properties:
      FunctionName: !Ref AwsServerlessExpressFunction
      FunctionVersion: '$LATEST'
      Name: live

  SNSTopic: 
    Type: AWS::SNS::Topic
    Properties: 
      DisplayName: mysnstopic
      TopicName: mysnstopic
      Subscription:  
      - 
        Endpoint: !Ref AwsServerlessExpressFunctionAlias
        Protocol: lambda

  LambdaInvokePermission: 
    Type: AWS::Lambda::Permission
    Properties: 
      Action: lambda:InvokeFunction
      Principal: sns.amazonaws.com
      SourceArn:  !Ref SNSTopic 
      FunctionName: !Ref AwsServerlessExpressFunctionAlias

如果您使用CloudFormation更新堆栈,则每次更新都会同时更新SNS和Lambda。在这种情况下,我认为Lambda别名是不必要的? - Z.Wei

9

在使用SNS主题的时候,您不应忘记添加LambdaFunctionPermission

以下是Cloud Formation模板中资源部分的yaml代码:

Resources:
  SNSTopic: 
    Type: AWS::SNS::Topic
    Properties: 
      DisplayName: sns-topic-for-lambda
      TopicName: sns-topic-for-lambda
      Subscription:  
      - Endpoint: !GetAtt LambdaFunction.Arn
        Protocol: lambda

  LambdaFunctionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt LambdaFunction.Arn
      Principal: sns.amazonaws.com

  LambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
    ...

4
你可以使用事件来设置触发器。
  lambda:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: 
      ------
      Events:
        SNS1:
          Type: SNS
          Properties:
            Topic:
              Ref: SNSTopic1
  SNSTopic1:
    Type: 'AWS::SNS::Topic'

参考资料: https://docs.aws.amazon.com/lambda/latest/dg/serverless_app.html#serverless_app_resources

这篇文章介绍了如何使用AWS Lambda构建无服务器应用程序。无服务器应用程序是指在不需要管理服务器的情况下运行的应用程序,可以根据需要自动扩展和缩小。您可以使用Lambda函数、API网关、DynamoDB等AWS服务来构建无服务器应用程序。

这应该是主题 ARN,而不是 Ref。https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#sns - Biplob Biswas
ref 用于引用变量。 - Sudharsan Sivasankaran
我知道,但如果你看过链接,你就会发现主题“ARN”是必需的。不过,刚刚检查了一下,“Ref”和“Fn::GetAtt”都返回主题的ARN。所以对于SNS主题仍然有效,但是对于每个资源,ref并不等同于ARN。https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html - Biplob Biswas
想法是将ARN作为参数传递,因为它是一种静态资源,这只是一个例子。你可以自由使用它。 - Sudharsan Sivasankaran
您可以使用Fn:GetAtt <资源名称>,Ref:将ARN作为参数传递,并且Fn:GetAtt根据资源生成不同的值。正如我之前提到的,在SNS主题的情况下,Ref:和Fn:GetAtt提供相同的值,因此在这种情况下它起作用,但是当需要ARN时,Ref:并不适用于每个资源。 - Biplob Biswas
这个“Events”部分已经被弃用了吗?我在最新的Lambda CloudFormation文档中没有看到它。也许可以使用Lambda权限代替? - Z.Wei

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