AWS SAMの超詳細解説

# はじめに
この記事はDevOps on AWS大全の一部です。
DevOps on AWS大全の一覧は[こちら](https://qiita.com/tech4anyone/items/b06f88035d27c6ef13b2)。

この記事ではAWS SAMに関連する内容を超詳細にまとめています。

具体的には以下流れで説明します。

- AWS SAMとは
- AWS SAMの仕組み
- AWS SAM for Advance

AWSの区分でいう「Level 200：トピックの入門知識を持っていることを前提に、ベストプラクティス、サービス機能を解説するレベル」の内容です。

# この記事を読んでほしい人
- AWS SAMがどういうサービスか説明できるようになりたい人
- AWS SAMを採用するときのベストプラクティスを説明できるようになりたい人
- AWS Certified DevOps Engineer Professionalを目指している人

# AWS SAMとは
AWS SAMとはサーバレスアプリケーションの開発とデプロイを支援するためのフレームワークです。
CloudFormationの拡張機能として用意されており、SAMテンプレートとSAM CLIで構成されています。

サーバレスアプリケーションを構築するためには処理を行うLambdaだけではなく多数のコンポーネントを作る必要があります。
例えば、Lambdaの前段に外部IFとしてのAPI Gateway/AppSyncや、Lambdaの後段にデータストレージとしてのDynamoDBやS3が必要になります。

これらをCloudFormationと比較して短いテンプレートで作れるようにしたのがAWS SAMです。

# AWS SAMの仕組み
AWS SAMは大きく分けて2つ、SAMテンプレートとSAM CLIで構成されています。
ここではそれぞれを分けて説明します。

## SAMテンプレート
SAMテンプレートはCloudFormationをラッピングしたものです。
扱えるリソースがサーバレスアプリケーションで使うものに特化している代わりにCloudFormationよりも短く直感的な書き方でテンプレートを作ることができます。

例えばHelloWorldを表示できるLambdaを作る場合を例にとってCloudFormationテンプレートとSAMテンプレートを比較してみましょう。

まずはCloudFormationテンプレートです。

```yaml
AWSTemplateFormatVersion: '2010-09-09'

Resources:
  HelloWorldFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: hello_world.handler
      Role: !GetAtt HelloWorldFunctionRole.Arn
      FunctionName: HelloWorldFunction
      Runtime: python3.8
      Code:
        S3Bucket: your-s3-bucket-name
        S3Key: your-s3-key
      Description: 'Hello World Lambda Function'

  HelloWorldFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: HelloWorldFunctionRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: HelloWorldFunctionPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
```

CloudFormationテンプレートのResource部分を見るとLambdaだけではなくIAMロールも作成されているのがわかります。
これはLambdaを実行するためにIAMロールが必要なためです。

一方、SAMテンプレートを見てみましょう
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'

Resources:
  HelloWorldFunction:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: hello_world.handler
      Runtime: python3.8
      CodeUri: ./
      FunctionName: HelloWorldFunction
      Description: 'Hello World Lambda Function'
      Events:
        HelloWorldApi:
          Type: Api
          Properties:
            Path: /hello
            Method: get
```

IAMロールの記述が消えている分短くなっていることがわかると思います。
AWS SAMがアプリケーションと直接関係ない部分を抽象化してくれます。
これがAWS SAMテンプレートのほうが記述量が少なくなる理由です。

実際に動作させる際にはAWS SAMテンプレートがCloudFormationテンプレートに自動で変換され、その時にAWS SAMで明示的に記載していないリソースの記述も自動で生成されます。

## SAM CLI
AWS SAMの構成要素のもう一方であるSAM CLIはAWS CLIと比較してSAMに特化したCLIです。
SAM CLIを利用する際にはAWS CLIとは別に、SAM CLIをインストールする必要があります。

SAM CLIはSAMテンプレートのバリデーションチェックだけではなく、SAMテンプレートのひな型生成やアプリケーションのビルド、デプロイなど多くの操作を行うことが可能です。
そのため、SAMを用いた開発をする際にはぜひ利用してみてください。

1つ、CLIという言葉と結びつきにくいSAM CLIの特徴があります。
それは開発者のローカル環境でLambdaやAPIのエンドポイントを起動し、実行テストができるということです。
ローカル環境での実行のためにはDockerのインストールが必要ですが、この機能を用いることでLambdaの試験を手軽に行うことができるため開発効率が大幅に向上します。

# AWS SAM for Advance
ここまでSAMテンプレートとSAM CLIについて解説してきましたが最後にデプロイ部分について説明します。

AWS SAMを用いたLambdaのデプロイはCodeDeployと統合されています。

![](https://storage.googleapis.com/zenn-user-upload/36231df8a907-20231117.png)

そのため、Lambdaエイリアスを用いたトラフィック分割の方式でデプロイされます。
1つ特徴としてはトラフィックを許可する前後のHookでデプロイのバリデーションをチェックしてくれるという点です。

もちろん、CloudWatchAlarmと連携した自動ロールバックも具備されているのでSAMを使った場合、基本的なリリースで困ることはありません。

# まとめ
この記事ではAWS SAMに関連する内容を超詳細にまとめました。

- AWS SAMとは
- AWS SAMの仕組み
- AWS SAM for Advance

次回はAWS CDKについて超詳細解説します。