SAM 模板和 Cloudformation 模板的区别

Posted

技术标签:

【中文标题】SAM 模板和 Cloudformation 模板的区别【英文标题】:Difference between SAM template and Cloudformation template 【发布时间】:2018-10-12 22:22:01 【问题描述】:

我发现很难理解 SAM 模板和 Cloudformation 模板之间的区别。我知道 SAM 模板可用于定义像 Lambda 这样的无服务器应用程序,但这与 Cloudformation 模板有何不同?语法不同吗?我仍然可以在 cloudformation 模板中指定 Lambda 定义。所以,我的问题是我为什么要关心 SAM?不知道只有云形成模板就足够了吗?

【问题讨论】:

它应该简化无服务器模板的创建。例如,SAM 转换可以推断您必须在常规 CloudFormation 模板中明确指定的内容。例如:它可以根据定义在 Lambda 函数上的事件集合来推断 API Gateway 资源。 【参考方案1】:

从 CloudFormation 的角度来看,SAM 是一种转换。含义:SAM 模板在语法上是等效的,但它们允许您更简洁地定义无服务器应用程序。 SAM 模板最终在幕后扩展为完整的 CFN。如果你已经了解 CFN,但想少写 YAML 代码,SAM 可能对你有好处。这个想法是为了减少你的工作量。

【讨论】:

那么对于无服务器资源,我可以选择使用简洁的 SAM 还是详细的 Cloudformation? 当然。在此处查看规范、操作指南和示例:github.com/awslabs/serverless-application-model/tree/master 如果我必须在一个堆栈中设置由 AWS Lambda、API Gateway 和 DynamoDB 组成的新无服务器架构......我应该使用 SAM 还是 Cloudformation? 如果这些是您需要的唯一资源(Lambda、APIGW、DDB),那么从 SAM 开始。如果您以后需要其他资源(VPC、CloudWatch 等),不难“过渡”到更通用的 Cloudformation 模板,该模板可以同时使用 SAM 和非 SAM 资源。 SAM 识别所有 Cloudformation 资源,因此实际上不存在非 SAM 资源。如果需要,您可以在 SAM 模板中定义整个 VPC,因为它最终会在某个时候传递给 Cloudformation。【参考方案2】:

就像@Luis Colon 所说,SAM 是一种转换。这意味着,在 SAM 模板的顶部有一个 Transform 语句,让 CloudFormation 知道在此 SAM 模板上运行一个内部函数 Transform 以将其转换为 CloudFormation 模板。因此,所有 SAM 模板最终都会转换为 CF 模板,但对于最终用户来说,在大多数情况下,只使用 SAM 模板会更容易。例如,对于一个由您正在创建的新 API 触发 Lambda 的简单应用程序,SAM 模板将让您比 CloudFormation 用更少的行数完成此操作。

为了扩展这一点,无服务器框架的行为类似。无服务器旨在跨平台(AWS、Azure 等)工作。它的语法看起来与 SAM 非常相似,而且它也将模板转换为目标平台(即 AWS)的更完整版本的模板(即 CloudFormation 模板)。

【讨论】:

【参考方案3】:

SAM 模板是 Cloudformation 的超集。任何 Cloudformation 模板都可以通过 SAM 原样运行,并且可以正常工作。 SAM 支持 Cloudformation 模板中可用的所有类型,因此您可以将 SAM 视为“CloudFormation++”。

但是,SAM 还为您提供了额外的“转换”,让您可以简洁地定义某些概念,SAM 会弄清楚您的意思并填补缺失的部分,以创建完整、扩展、合法的 Cloudformation 模板。

示例:对于主要处理 Lambda 函数的 SAM(和无服务器框架)用户,最有用的转换之一是 Lambda 函数上的 Events 属性——SAM 将添加访问该函数所需的所有对象通过 API Gateway 中的 API 路径运行。

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: HelloWorldFunction
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Events:  # <--- "Events" property is not a real Cloudformation Lambda property
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get

上面显示的 SAM 模板 sn-p 被转换/扩展为几个 API Gateway 对象(一个 RestApi、一个部署和一个阶段)。此 sn-p 中使用的 AWS::Serverless::Function 类型不是真正的 Cloudformation 类型——您不会在文档中找到它。 SAM 将其扩展为一个 Cloudformation 模板,其中包含一个 AWS::Lambda::Function 对象和 Cloudformation 可以理解的几个不同的 AWS::ApiGateway::* 对象。

为了让您了解这为您节省了多少手动编码,以下是上述 SAM 模板的扩展版本作为完整 Cloudformation 模板的样子:

Resources:
  HelloWorldFunctionHelloWorldPermissionProd:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      FunctionName:
        Ref: HelloWorldFunction
      SourceArn:
        Fn::Sub:
        - arn:aws:execute-api:$AWS::Region:$AWS::AccountId:$__ApiId__/$__Stage__/GET/hello
        - __Stage__: "*"
          __ApiId__:
            Ref: ServerlessRestApi

  HelloWorldFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Action:
          - sts:AssumeRole
          Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Tags:
      - Value: SAM
        Key: lambda:createdBy

  ServerlessRestApiProdStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      DeploymentId:
        Ref: ServerlessRestApiDeployment_NNN
      RestApiId:
        Ref: ServerlessRestApi
      StageName: Prod

  ServerlessRestApiDeployment_NNN:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId:
        Ref: ServerlessRestApi
      Description: 'RestApi deployment id: ???'
      StageName: Stage

  ServerlessRestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Body:
        info:
          version: '1.0'
          title:
            Ref: AWS::StackName
        paths:
          "/hello":
            get:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:$AWS::Region:lambda:path/2015-03-31/functions/$HelloWorldFunction.Arn/invocations
              responses: 
        swagger: '2.0'

  HelloWorldFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket: aws-sam-cli-managed-default-samclisourcebucket-???
        S3Key: temp/???
      Tags:
      - Value: SAM
        Key: lambda:createdBy
      Handler: app.lambdaHandler
      Role:
        Fn::GetAtt:
        - HelloWorldFunctionRole
        - Arn
      Timeout: 3
      Runtime: nodejs12.x

以前,如果您要编写纯 Cloudformation,则必须为要创建的每个 API 网关端点手动一遍又一遍地编写所有这些代码。现在,使用 SAM 模板,您可以将 API 定义为 Lambda 函数的“事件”属性,而 SAM(或无服务器框架)会处理这些苦差事。

在过去,当我们不得不手动完成所有这些工作时,它完全糟透了。但现在,一切又恢复了辉煌。

【讨论】:

以上是关于SAM 模板和 Cloudformation 模板的区别的主要内容,如果未能解决你的问题,请参考以下文章

CloudFormation - SAM 模板的结构无效。 “资源”部分是必需的

如何知道 sam/cloudformation 堆栈 lambda 正在执行啥

AWS - SAM cli yaml 模板不适用于 cloudformation 堆栈

SAM API 网关与 Cloudformation WAFRegional

为啥我的 cloudformation 模板超过 1 MB?

如何自定义 AWS Codestar / Cloudformation 模板来创建特定的代码构建项目?