AWSサンプルプロジェクトから学ぶサーバレスアーキテクチャ

# 構築してみるAWSサーバレス

[PARONYM Advent Calendar 2020 - Qiita](https://qiita.com/advent-calendar/2020/paronym) の7日目です。

## はじめに

昨今注目を浴びているサーバレスアーキテクチャ。うまく使えばサーバの構築・運用・保守の手間が省けエンジニアはサービスの実装に注力することができます。
しかし便利な反面新たに学ばなくてはならないことが沢山あり、学びはじめのエンジニアは何からはじめたらいいか悩ましいところです。
本記事では、AWS公式で作成されたサンプルプロジェクトを使用してサーバレスアーキテクチャを構築し、サーバレスの学習のきっかけになることを目的としています。

## 注意

サンプルプロジェクトをAWSにデプロイすると料金が発生する場合があります。**デプロイは自己責任でお願いします。**

## 本記事で使用するサンプルプロジェクト

AWSには公式から提供される便利なサンプルプロジェクトがあります。今回はその一つを使用して実際にクラウド上に一つのサービスを展開してみます。

[aws-samples/lambda-refarch-webapp](https://github.com/aws-samples/lambda-refarch-webapp)

使用するサービス

- [AWS Lambda](https://aws.amazon.com/jp/lambda/)
- [Amazon API Gateway](https://aws.amazon.com/jp/api-gateway/)
- [Amazon DynamoDB](https://aws.amazon.com/jp/dynamodb/)
- [Amazon Cognito](https://aws.amazon.com/jp/cognito/)
- [AWS Amplify Console](https://aws.amazon.com/jp/amplify/console/)


このサンプルプロジェクトは上記らのサービスを使用して簡単なTODOアプリを構築していきます。
デプロイには以下のツールをします。

- [AWS CLI コマンドラインインターフェイス](https://aws.amazon.com/jp/cli/)
- [AWS SAM サーバーレスアプリケーションモデル](https://aws.amazon.com/jp/serverless/sam/)

デプロイの方法は、[README.md](https://github.com/aws-samples/lambda-refarch-webapp/blob/master/README.md)にも記載されています。

### フロント

ビルドで生成される全ての静的リソース（HTML、JS、CSSなど）は[AWS Amplify Console](https://aws.amazon.com/jp/amplify/console/)を用いてデプロイされます。

### バックエンド

バックエンドは[Amazon API Gateway](https://aws.amazon.com/jp/api-gateway/)と[AWS Lambda](https://aws.amazon.com/jp/lambda/)を用いたREST APIを提供します。
データの保存場所としては、[Amazon DynamoDB](https://aws.amazon.com/jp/dynamodb/)を使用しています。

### 認証

[Amazon Cognito](https://aws.amazon.com/jp/cognito/)のユーザプールを利用して認証機能を提供している。

## 前提条件

- Githubアカウントを所持していること
- dockerがインストールされていること
- AWSアカウントを所持していること
- AWS CLIがインストールされていること
- SAMがインストールされていること

## 準備

[aws-samples/lambda-refarch-webapp](https://github.com/aws-samples/lambda-refarch-webapp)
上記リポジトリを自身のGithubアカウントへForkします。
これは、Amplifyコンソール用にGithubでパーソナルアクセストークンを作成し、デプロイでGitHubリポジトリのURLを指定する必要があるためです。

パーソナルトークンは以下のページを参照して作成してください。
[個人アクセストークンを使用する - GitHub Docs](https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token)

トークンは後で使うため、保存しておいてください。

## デプロイ

まず環境変数を設定します。

```
$ export AWS_DEFAULT_REGION=<リージョン 例：ap-northeast-1>
$ export STACK_NAME=<CloudFormation stack名 ※ユニークである必要あり>
```

デプロイ実行

```
$ ./deploy.sh
```

実行中に入力を求められるが、`AWS Region`、`Parameter Repository`と`Parameter OauthToken`以外はデフォルトの値で問題ありません。

- `AWS Region` : リージョン
- `Parameter Repository` : GithubのリポジトリURL
- `Parameter OauthToken` : 準備で作成したパーソナルアクセストークン

```
〜〜省略〜〜
Configuring SAM deploy
======================

	Looking for config file [samconfig.toml] :  Found
	Reading default arguments  :  Success

	Setting default arguments for 'sam deploy'
	=========================================
	Stack Name [serverless]:
	AWS Region [ap-northeast-1]: ap-northeast-1
	Parameter VersionParam [v1]:
	Parameter StageNameParam [prod]:
	Parameter CognitoDomainName [mytodoappdemo]:
	Parameter Repository []: <リポジトリURL>
	Parameter Branch [master]:
	Parameter OauthToken: <パーソナルアクセストークン>
	#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
	Confirm changes before deploy [y/N]:
	#SAM needs permission to be able to create roles to connect to the resources in your template
	Allow SAM CLI IAM role creation [Y/n]:
	Save arguments to configuration file [Y/n]:
	SAM configuration file [samconfig.toml]:
	SAM configuration environment [default]:
〜〜省略〜〜
```

デプロイが完了したら、AWSコンソールにログインして`Amplify`からフロントのソースコードをデプロイします。

![スクリーンショット 2020-12-07 1.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147939/fc2279f1-b784-bac5-f14e-b3fb13d1629d.png)

ビルドが完了したら、URLにアクセスし動作確認してみます。

![スクリーンショット 2020-12-07 1.28.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147939/722e1d98-4a26-1052-42eb-bd67d440ec31.png)

以下の画像がデプロイされたTODOアプリの画面です。

![スクリーンショット 2020-12-07 1.28.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147939/64e32286-e785-fd25-8dec-591478ce9304.png)

## 削除

使用しなくなったアプリは削除することが鉄則です。
AWS上に作成されたリソースを削除するには`cloudformation`のコマンドを使用して削除します。

```
aws cloudformation delete-stack \
--stack-name $STACK_NAME
```

忘れがちがCloudWatchのログ・グループも削除しておきます。

```
for log_group in $(aws logs describe-log-groups --log-group-name-prefix '/aws/lambda/'$STACK_NAME --query "logGroups[*].logGroupName" --output text); do
  echo "Removing log group ${log_group}..."
  aws logs delete-log-group --log-group-name ${log_group}
  echo
done
```

## まとめ

一口にサーバレスといっても、複数のクラウドサービスを併用しないと一つのアプリケーションを構築することはできません。
AWSのサーバレスの代表サービスといえば`Lambda`ですが、今回のサンプルプロジェクトの様に一つのサービスを構築するためには各サービスを併用して処理を分散し構築していく必要があります。

- [AWS Lambda](https://aws.amazon.com/jp/lambda/)
- [Amazon API Gateway](https://aws.amazon.com/jp/api-gateway/)
- [Amazon DynamoDB](https://aws.amazon.com/jp/dynamodb/)
- [Amazon Cognito](https://aws.amazon.com/jp/cognito/)
- [AWS Amplify Console](https://aws.amazon.com/jp/amplify/console/)

今後プロダクトでサーバレスを利用していくのであればこれらサービスのベストプラクティスを学習し、適切に運用していく必要があります。
本記事で作成したサンプルプロジェクトは削除しても再度同じコマンドを実行すればデプロイされるため、是非何度でも構築・削除を繰り返し、動いているコードを学び、自身が携わっているプロダクトの役に立ててください。