AWS Hands-on for Beginners Serverless #2 AWS SAM を使ってテンプレートからサーバーレスな環境を構築する：学習メモ

## はじめに

AWSハンズオン for Beginnersシリーズとして提供されている「[AWS Hands-on for Beginners Serverless #2 AWS SAM を使ってテンプレートからサーバーレスな環境を構築する](https://pages.awscloud.com/event_JAPAN_Ondemand_Hands-on-for-Beginners-Serverless-2_LP.html)」を実施した際のメモです。
AWS SAM(Serverless Application Model)とは、サーバーレスアプリケーション構築用のオープンソースフレームワークです。CloudFormationを使用することでも、Lambdaなどのサーバレスアプリケーションをプロビジョニング可能ですが、SAMを使用することでより簡潔に記載できます。
また、SAM CLIを使用してローカル環境にサーバレスサービスの仮想的な実行環境を作成し、デバッグ実行も可能です。CLIでAWS環境でのデプロイも容易になっています。
本ハンズオンでは「[Serverless #1 サーバーレスアーキテクチャで翻訳 Web APIを構築する](https://pages.awscloud.com/event_JAPAN_Hands-on-for-Beginners-Serverless-2019_LP.html?trk=aws_blog)」で構築したサーバレスサービス主体の翻訳WebアプリケーションをこのAWS SAMを使用し、構築します。
なお、Serverless #1の学習メモは[ここ](https://qiita.com/kenryo/items/2edd17d21e3cfa206874)に記載しています。

## アジェンダ

1. 前回のハンズオンの復習と今回のハンズオンの概要
2. AWS SAMの紹介とAWS Cloud9の紹介
3. Cloud9のセットアップ+[Option]Cloud9で簡単なLambda関数を作成する
4. SAMでLambda関数を作成する ①
5. SAMでLambda関数を作成する ②
6. SAMでAPI Gatewayのリソースを作成し、Lambda関数と連携させる
7. SAMでDynamoDB TBLを作成し、Lambda関数を連携させる
8. [Option]SAM CLIを使ってみる ①
9. [Option]SAM CLIを使ってみる ②
10. クリーンアップ & 落ち穂拾い & まとめ

## メモ

### ゴール

- AWS Serverless Application Model(SAM)を用いて、サーバレス構成を自動構築します。
- [Serverless#1](https://pages.awscloud.com/event_JAPAN_Hands-on-for-Beginners-Serverless-2019_LP.html?trk=aws_blog)で構築した構成をSAMで作成していきます。

### Serverless#1で使用したサービスについて

#### Lambda

サーバを構築する必要なくプログラムを実行できるサービスです。サーバの構築や必要なミドルウェアのインストール、スケーリングなどを考えず使用でき、プログラムの記述に集中できます。

#### API Gateway

サーバの構築、管理が必要なくAPIの作成、管理ができるサービスです。可用性の担保、スケーリング、APIキーの管理といった作業をAPI Gateway側でやってもらうことでLambdaと同様ビジネスの差別化につながる作業に集中できます。

#### DynamoDB

データをkey-value形式で管理するフルマネージドなNoSQLデータベースサービスです。データが3つのAZに保存されるため高い可用性があります。また、ストレージの容量制限がないことも特徴です。

### AWS SAM概要

AWS SAMとは、CloudFormationの拡張機能であり、サーバレスアプリケーションを構築するために使用するオープンソースです。なお、CloudFormationとは、テンプレートファイルの記述に従ってAWSがサービスのプロビジョニングを行うサービスです。SAM、CloudFormationを使用することで、差分比較が楽になったり、環境差異による障害が少なくなるため、開発の効率が向上します。

### AWS SAMのプロパティ

SAMは大きく2つのプロパティで構成されます。
1つ目は「Type」であり、どのサーバレスサービスを構築するかを指定します。例えば、「[AWS::Serverless::Function](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-resource-function.html)」と指定すると、Lambdaをプロビジョニングすることになります。
2つ目は「Properties」であり、「Type」で作成するサービスの詳細情報を記載します。「Type」により、必須非必須の項目があります。例えば、「[AWS::Serverless::Function](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-resource-function.html)」では「[FunctionName](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-functionname)」という値を「Properties」配下に定義でき、Lambda関数名を指定します。

### AWS SAMを使ったプロビジョニングまでの流れ

1. SAMテンプレートを作成します。SAMテンプレートとはCloudFormationテンプレートの拡張で、前節で記載した「Type」「Properties」などを記載し、どのサーバレスサービスをどのようにプロビジョニングするか記載したファイルです。詳細は[ここ](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html)を参照ください。
2. 「aws cloudformation package」コマンドを実行し、SAMテンプレートをS3バケットにアップロードします。[こちら](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-cli-package.html)を見るとわかるようにアップロード後のファイルのローカルファイルを参照しているプロパティ「CodeUri」の値がS3のパスに変換されています。このコマンドを使用することでS3のパスを意識せずにローカルでSAMテンプレートを作成できます。

```bash
aws cloudformation package --template-file template.yaml --s3-bucket your-backet-name --output-template-file packaged-template.yaml
```

3. 「aws cloudformation deploy」コマンドを実行し、AWSにサービスをプロビジョニングします。

```bash
aws cloudformation deploy --template-file ./packaged-template.yaml --stack-name your-backet-name --capabilities CAPABILITY_IAM
```

### Cloud9について

Cloud9とは、ブラウザでプログラミングができるクラウドベースのIDEです。複数人でリアルタイムにペアプログラミングが可能であり、サーバレスサービスの作成もできます。料金はCloud9内部で実行されるEC2インスタンスの稼働時間およびEBS使用量により決定します。
Cloud9コンソール上からLambdaを新規作成できます。LambdaのソースはCloud9上で変更、実行でき、デプロイすることでLambdaコンソール上に反映されます。

### LambdaにAmazon Translateの操作権限を付与する

LambdaにAmazon Translateの操作権限を付与するため、SAMテンプレートの当該Lambdaの「Properties」に「Policies」を追加し、Translateのポリシー名を記載する必要があります。

### API GatewayからLambdaを呼び出す

「Type」に「AWS::Serverless::Api」を指定することでAPI GatewayにAPIをプロビジョニングできます。
当該APIから指定のLambda関数を呼び出すには、「Properties」に「Events」を追加し、当該API Gatewayの論理名を「RestApiId」に追加します。また、HTTPメソッドやリクエストパスを指定する必要もあります。

### LambdaにDynamoDBの操作権限を付与する

「Type」に「AWS::serverless:simpledb」を指定することでDynamoDBのテーブルをプロビジョニングできます。
「Properties」には、主キーやプロビジョニングキャパシティなどを指定します。LambdaからDynamoDBを操作するため、当該Lambdaの「Properties」に「Policies」を追加し、DynamoDBのポリシー名を記載する必要があります。

### SAM CLIについて

SAM CLIとは、サーバレスアプリケーションをローカル環境で実行できるツールです。AWS CLIを使用するよりも簡潔にSAMのpackage、deployできます。
実行環境にDockerをインストールする必要があります。Cloud9には最初からDockerがインストールされています。

### 雑記

「aws cloudformation package」コマンドで変換したSAMテンプレートを格納するため、事前にS3バケットを作成する必要があります。
本ハンズオンでは以下のAWS CLIコマンドでバケットを作成しました。

```bash
aws s3 mb s3://your-backet-name
```

## ハンズオンの感想

[Serverless#1](https://pages.awscloud.com/event_JAPAN_Hands-on-for-Beginners-Serverless-2019_LP.html?trk=aws_blog)ではAWS管理コンソールからボタンを押しながらアプリケーションのデプロイをしていました。今回のSAMを使用することでテンプレートによる自動プロビジョニングができます。
これによりヒューマンエラーがなくなり、再デプロイも容易になるので是非活用していきたいです。