新しく発表されたAWS機能を最大限つかってモザイクアートのサービス作ってみた

最近AWSのモチベーションも上がってきたので、以前ハッカソンで作ったSpictsというサービスをAWSに移すことにしました。それにあたり、僕の苦節の記録をチームメンバーに伝え、めっちゃ僕頑張ったんだよ感を出すために記事を書いてみました。

どうせやるなら最先端のサービスを詰め込めるだけ詰め込んでしまおうということで、Lambda, Fargate, Amplify, を画像処理, サーバー, フロントで使うことにしました。(LambdaはLayerが出たからセーフ)

####作ったサービス: [Spicts](https://spicts.net/create/)
エモいモザイクアート生成サービス

頑張るとこんなものができる。
![spictsMosaicArt1.png](https://qiita-image-store.s3.amazonaws.com/0/185233/2099fda4-939f-b701-658e-4af77e7864a7.png)

すっごいエモい。
ちなみにハッカソンの際の画像です。


#####完成した構成図はこんな感じ。
![spicts-diagram.png](https://qiita-image-store.s3.amazonaws.com/0/185233/f716a24e-5756-d5b7-c1f3-bbb325d24e7b.png)

ハッカソンの際には個人の好きな言語で開発するわけにもいかないので言語選択など合わせましたが、今回は1人での開発で、時間もあるので言語選択からやりたい放題。

##使用言語/フレームワーク

###Python 2.7
当初は3.6で書かれていたが、OpenCVのモジュールの関係(後述)で2系に下げた。このサービスの核となるコードであり、モザイクアートを作っている張本人。モジュールはOpenCVやPillowを使っていた気がする。コードも移行にあたり少し書きなおした。早く2020年になって2.7のサポートが終了してほしい。切実に。
https://github.com/Keijun-KUMAGAI/spicts-lambda

###Nuxt.js
Vueのフレームワーク。フロントサイドはもともとVueで書かれていたが、自分が使いたいというそれだけの理由でNuxtに変えてみました。ちなみにそもそものコード量が圧倒的に少ないので、メリットは全然感じられませんでしたね。強いて言うならVuexとVue-Router書くのが少し楽になったぐらい。
https://github.com/Keijun-KUMAGAI/spicts-client

###Node.js
画像処理の箇所を除いてFlaskで書かれていたサーバーサイドをExpressに書き換えました。Node.jsな理由は自分が慣れているから。実はハッカソン中にAWSのKeyがここから流失して18万払うことになりそうだったのは内緒の話。そのせいもあってか、なんとなくGithubのレポジトリも公開したくない。


##AWS関連サービス

###Lambda
ざっくり説明するならば、AWSにコードを関数としてデブロイして管理・使用ができるサービス。Api Gatewayと組み合わせるとserver lessでAPIが更生できたりして自由度が高い。料金も秒単位で課金されお財布に優しい。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html

想定外だったが、今回の一番のボトルネックになった。理由はOpenCVてめぇだこのやろう。
OpenCVは標準ライブラリとしてAWS:Linaxに含まれていないものを触るため普通にインストールしたOpenCVを使うことは動かない。調べると以下のサイトに従ってAWS:Linaxで一度ビルドしないといけないらしい。3.6でビルドしても良かったが、2.7で確実にできるのならばと、2.7に変更。

https://github.com/aeddi/aws-lambda-python-opencv

あと、推しポイントはRe:invent 2018で発表されたLambda Layerを使ったこと。
最初はOpenCVを含めた50MBのものZipファイルを家の遅い環境で何度もテストのためにS3にアップロードしていたのでLayerを使ったことによって本当に楽になりました。もうLambda Layer Loverです。LLLです。

ここいらが参考になった
https://dev.classmethod.jp/cloud/aws/lambda-layer-basics-how-it-works/

画像処理はやはり少し重く、Lambdaのメモリを少し増やして対応しました。

あとは、AWSのチュートリアル参考にしてフロントから呼び出すためにAPI Gatewayと接続しておきました。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-on-demand-https-example.html

###Fargate

AWSでAPIをホスティングできて最近のいい感じのないかなーと探してみたところ、AppSync, API Gateway, Fargateなどが選択肢に挙がりました。その中で一番語感がよくてかっこよさそうなFargateを選択。意味がわからない英語ってかっこよく聞こえるじゃない。
https://aws.amazon.com/jp/fargate/

どうやらECSのサービスの一部のご様子。ECSのクラスターなどの管理をAWSに丸投げすることでサーバー・クラスターなどの管理から解放されるらしい。
2019年1月から料金安くなったみたいですね。今コンテナ2個で動かしてますが使用量は月額で1000円ぐらいです。唯一お金がかかっている箇所ですね。問題児。

コンテナ系のサービスなのでAPIをDockerで囲ってDocker-HubにPush。流石にECRまでは使いませんでした。ApplicationLoadBarancherの設定やら、TargetGroupの設定でかなり詰まったんですが、以下を参考に半日ほどかけてなんとか突破。初めてやることって難しいですね。理解した後の二周目は5分で全部設定できたのですが。

https://tech.mti.co.jp/entry/2017/12/06/190200
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ECS_GetStarted.html

こうやって苦労して作ったAPIサーバーがAmplifyからHttpsでアクセスできないとなった時は本当に心が折れかけましたね。調べるとRoute53, ACMなどを使って解決できそうなので、景気良くspicts.netドメインを購入して解決。
https://aws.amazon.com/jp/certificate-manager/



ちなみにここで環境変数として各コンテナにS3とDynamoDBのKeyを渡しています。コンテナ削除すると自動的に次のコンテナ立ち上がるのめっちゃ気持ちいいです。
あと、使っててこれKubernatesと何が違うんやろとか思い始めたので偉い人よかったら教えてください。


##Amplify
言ってしまえばHTMLなどの静的コンテンツのホスティングサービス。しかしそれで終わらないのがAWS。Github, Bitbucketなどからのブランチの接続、AutoDeployment、コードのビルドなどかなり使い勝手がよい。この子も2018 Re:inventで登場した新生児。東京でのサービスが開始されていないため、泣く泣くオハイオに置いて使ってます。アクセスに時間がかかるのはそのためかなと。
https://aws.amazon.com/jp/amplify/

今回初めて使ったサービスの中(DynamoDB, Route53, Amplify, Fargate)で一番簡単に扱えました。Githubに接続してbuildコマンドとファイルの吐き出し先を指定するだけで終了です。Route53への接続も簡単でした。最高です。

あとAWSさんから「今、テスト機能Amplifyにつけようとがんばってるんやけど、ヒアリングしたいから電話かけてくれへん？」みたいな旨の英語のメール届いたので近々CIの機能とか追加されるかもしれません。

Netlify? 知らない子ですねぇ。

##DynamoDB
AWSではよく使われるNoSQLのデータベースですね。7年前からあるAWSのサービスですね。Re:invent 2018ではTransactionやらOn-Demandなどいろいろ機能が追加され、より一層使われる場面が増えそうです。

https://aws.amazon.com/jp/dynamodb/
https://aws.amazon.com/jp/blogs/database/amazon-dynamodb-related-content-from-aws-reinvent-2018/

特に理由もないがAWSで統一するためにFirebaseのFireStoreからこちらに移行。正直これだけ小さいサービスだとメリットがわからない。それでもDynamoDBを使っているという優越感には浸れる。もうAPI叩くだけで楽しい。

Documentはここら辺を参照
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html

もっと新しいサービスDocumentDB, Neptuneも使ってみたかったが、今回は断念。DocumentDBは１日動かしただけで$13取られたし、GraphDBはよくわからん! やっぱりDynamoDBが一番楽。(初めて使った)

###CloudWatch Event
特に変なことはしていません。cronを設定して一日に一回Lambdaが発火するようにしただけ。

##総括
個人的にAmplifyとFargateがこの構成の一番カッコいいところだと思っています。何より色が違う。かこいい。すごい。
最初よくわからんサービスでもコンソール眺めながらぽちぽちしてると意外と使い方わかったりするもんですね。Fargateとか完全にそれでした。あとは、Circle-CIとかAuto Scalingとか設定ですが、明らかに個人サービスでやる規模でないので迷うところです...
あとは、CloudFormationとか使ってみたいですね。コンソールでぽちぽちして操作するのは古いと知って衝撃でした。
次にハッカソンがあった時には今回のようなサービスを駆使して技術点を稼いで優勝を狙いたいですね。