Terraformでサーバレス顔認識を構築する(Amazon Rekognition)

こんにちは、SREエンジニアやってます@hayaosatoです。
以前、Amazon Rekognition(以下、rekognition)を用いたサーバレスな動画の顔分析のアプリケーションを作りました。
その時の記事は[こちら](https://qiita.com/hayaosato/items/274c06d4466f168d662d)
今回はそのアプリケーションのインフラをTerraformで定義することで一気にサーバレスでフルコード化されたアプリケーションにしてやろうじゃないかという試みです。
コードは[こちら](https://github.com/hayaosato/advent-calendar-2019/tree/master/face_detection)

## アプリケーション
前回のおさらいも兼ねてさらっとどのような機能を実装するかというと、
S3にあげられた動画をrekognitionの`face_detection`で解析。
その後解析終了次第その解析結果のJSONをSlackにて通知するというものです。

## インフラ
ここからが本題で、サーバレスなアプリケーションをTerraformで一気に作っていきたいと思います。
システム構成は以下のようになります。
![顔面みっけ君システム.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312728/648323b8-f32d-2a6c-6892-1bab436c34bf.jpeg)
ここで、システムはrekognition以前と以降の大きく2つに分かれるのですが、rekognitionの解析を呼び出す時点でSNSなどはできている必要があるので
一気に説明してしまいます。

### 構成
#### IAM系
この構成の場合、Lambdaが実行するためのIAM、RekognitionがSNSにメッセージを発行するためのIAMが必要です。
RekognitionのためのIAMRoleも[このように](https://github.com/hayaosato/advent-calendar-2019/blob/master/face_detection/terraform/main.tf#L21-L36)作ります。
Lambda自身へのRekognitionの呼び出し等のIAMRoleも[このように](https://github.com/hayaosato/advent-calendar-2019/blob/master/face_detection/terraform/main.tf#L3-L18)作ります。
また、SNSには`配信再試行ポリシー (HTTP/S)`も定義する必要があるので、[このように](https://github.com/hayaosato/advent-calendar-2019/blob/master/face_detection/terraform/main.tf#L20-L36)作りました。
IAM系はポリシーチューニングがとてもつらみが深いので管理するかどうかは別ですが、できることなら管理したいなぁと思いつつ、、、(察し)

#### Lambda関数
Lambda自身にもいくつか付随するリソースを作る必要があり、CloudWatch Log Groupも[このように](https://github.com/hayaosato/advent-calendar-2019/blob/master/face_detection/terraform/main.tf#L45-L48)作ります。

Lambdaの場合はarchiveプロバイダの`archive_file`を利用することでソースコードをzipに固めてそのままアップロードすることができます。
これをすることによって、Terraformにソースコードの更新を組み込むことで`terraform apply`で再作成なしにソースコードの更新をすることができます。
Lambda関数については[このように](https://github.com/hayaosato/advent-calendar-2019/blob/master/face_detection/terraform/main.tf#L39-L66)作成しており、get_face_detectionもほぼ同様に作成できます。

#### トリガ系
今回Lambda関数のトリガとなるリソースはS3とSNSです。
S3は[このように]()、SNSのトピックは[このように](https://github.com/hayaosato/advent-calendar-2019/blob/master/face_detection/terraform/main.tf#L143-L152)それぞれ作ります。
しかし、それぞれリソースを作成するだけではLambda関数は起動してくれず、Lambda側のトリガ設定(`aws_lambda_permission`)が必要になります。
S3のトリガは[このように](https://github.com/hayaosato/advent-calendar-2019/blob/master/face_detection/terraform/main.tf#L68-L74)、SNSのトリガは[このように](https://github.com/hayaosato/advent-calendar-2019/blob/master/face_detection/terraform/main.tf#L135-L141)作成します。
SNSとLambdaとの連携系の記事は以前に[こちら](https://qiita.com/hayaosato/items/fc3e4e8be285e8dbbd5c)にも書いているので、是非ご覧いただけると。

##　結果
以上でできました。
解析開始
<img width="209" alt="スクリーンショット 2019-12-07 23.44.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312728/860b471f-2943-1032-b6db-94d982bd8eae.png">
解析完了
<img width="221" alt="スクリーンショット 2019-12-07 23.44.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312728/aa6c1269-4a94-18fc-3179-1fb7385e62b2.png">
その後JSONファイルがSlackにアップロードされました。


## 最後に
今回はAWSのサービスを利用してサーバレスなアーキテクチャを構築しつつ、Terraformでインフラのコード化も行いました。
サーバレスは楽ですし、コード管理されていて変更が確認しやすいしいいですよね〜

## 参考
- [Rekognition](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rekognition.html)
- [Terraform Documentation](https://www.terraform.io/docs/index.html)