集中力が10分しか持たないハチワレ先生

集中力が10分しか持たないハチワレ先生

技術メインの雑記ブログ

AWS でサーバレスな寮飯確認 Bot を作った話

こんにちわ、krkettleです
今回は AWS で寮飯確認 Bot を作った、そしてサポートを終了した話を書きたいと思います

背景

私は社員寮在住なのですが、ありがたいことに
夕食は寮で提供されます(代金は取られますが良心的だと思います)
ある日の夜、同期と寮食を食べようとした時に同期がポツリ

「うわー、今日の夕食カレーか!昼に食べちゃったよ」

寮では食堂の掲示板にその週の献立が掲示されるのですが
毎週献立を撮っておくのは面倒なものです...

そこで、当時私が AWS ソリューションアーキテクトの資格を取ろうと
思っていたこともあり、練習も兼ねて寮生の悩みを解決することにしました
(AWS SAA に合格できました!)

krkettle.hatenablog.com

AWS 構成

家賃が安いが売りの社員寮に住む寮生から、なけなしのお金を取るわけにはいきません
そこで以下のコンセプトで構成を考えることにしました

  • 出来る限り安く(出来れば無料で)
  • 運用コストをできる限り抑える
  • 最小構成でまず動くものを

全体構成図は以下の通りです

AWS全体構成図
AWS全体構成図

寮飯確認 Bot のフロー

  1. 利用者は事前に LINE の寮飯確認 Bot チャンネルに登録
  2. 運営者が寮飯の献立画像を撮影し S3 にアップロード
  3. 寮食が提供される曜日の 11:30 に献立画像を寮飯確認 Bot に送信

画像アップロード

当初の予定では下図のように S3 への画像アップロードもシステム化する予定でした
(覚えたての React と S3 の静的ホスティングを使って Web アプリっぽく)

当初のAWS全体構成図
当初のAWS全体構成図

しかし、コア要素でないところに時間を掛けたくないのと
「最小構成でまず動くものを」というコンセプトから外れるため後回しにして
まずは手動で AWS コンソールから運営者(私のみ)がアップロードすることにしました

メッセージ送信

今回は無料のLINE Messaging APIを利用しました
この API では Push/Reply が可能ですが、今回は Push(Bot 側から送信する)だけを採用しました
その理由は以下の 2 点です

  • 無料枠では送信可能なメッセージ数が固定なので、無駄な返信で消費しないようにするため
  • 返信のたびに Lambda が起動するとお金がかかってしまうため

CloudWatch Eventsを使って指定の時間にLambdaが起動します
Lambda は S3 にアップロードした画像を Messaging API 経由で寮飯確認 Bot チャンネルに送信します

認証情報の管理

LINE Messaging API ではアクセストークンを発行する必要があるため
認証情報の管理が必須になりますが、AWS では認証情報の管理として以下の2つが有名です

全体構成図でも書いているように、選んだのはパラメータストアです
理由は機能・非機能的に問題がなく無料だからです

両者の比較は以下の記事が参考になりました
参考: AWS の Parameter Store と Secrets Manager、結局どちらを使えばいいのか?比較

監視・通知

寮生に閉じられた完全無料なシステムとはいえ、
「ダウンしたら利用者から連絡がくるまで放置」というのは忍びないので
CloudWatch, Chatbotで監視・通知機能をつけました
仕組みは単純で Lambda で例外が発生したら管理者の Slack に通知します

S3 の署名付き URL でハマる

AWS は非常に使いやすくドキュメントも豊富なので
設計を含め全部で 3 時間ほどで最低限の機能が動くところまで出来ました
ただ S3 の署名付き URLで少しハマりました

なぜ署名付き URL を使ったのか

理由としては以下の通りです

  • アップロード画像に有効期限をつけたかった
    • 献立は毎週変わるので古い画像はアクセスされないようにしたかった
  • S3 バケットを非公開にしたかった
    • 誤って S3 から直接画像をダウンロードされないようにするため
    • 今から考えるとそれほど必要なかったかも
  • (AWS SAA の試験対策時に知って使ってみたかったから)

発行者の認証情報に応じて署名付き URL の長さが変わる

今回署名付き URL は IAM ロールを付与した Lambda で発行しました
しかし以下の参考記事にある通り、IAM ロールを用いて署名付き URL を発行する場合
一時的な認証情報を用いるため、その情報を URL に含める必要があります
そのため、IAM ユーザを用いる場合よりも IAM ロールを用いる場合は URL が長くなります

署名付き URL が長いと何が問題なのか

通常であれば URL が長いのはそれほど問題にはならないはず(?)
しかし今回はLINE Messaging API の仕様に落とし穴がありました...

Image URL (Max character limit: 1000)

URL の最大長が1000に設定されていたんですね
(私の使い方がイレギュラーだと思うので、この仕様が悪いわけではないと思います)
これが原因となり Lambda でメッセージ通知時に例外が発生していました

どう解決したか

スマートなやり方ではないと思うのですが
Bitly APIを利用して署名付き URL の短縮 URL を発行して回避しました

今考えると

  • そこまでして署名付き URL を使う必要はなかった
  • 公開用の S3 バケットを用意して削除イベントを作るでもよかった
  • 使ったことない技術使ってみたい気持ちが先行した感がある

本番環境と同じ環境で行うテストが大事

このハマり点のタチの悪いところはLambda で実行してみて初めて気づくという点です
自動テスト、CI/CD の設定は全く出来ていなかったので、ソースコードのチェックには
実行環境をローカルに Docker 環境で作って検証していました

krkettle.hatenablog.com

しかしローカル環境では IAM ユーザの認証情報を使用していため正常終了していました
よく言われることですが、本番環境とテスト環境は同じにしておくことが大事だなと実感しました

サービス開始、そしてサービス終了まで

晴れてサービス開始となりましたが、その数ヶ月後に終わりを迎えることとなりました

サービス開始

ハマりポイントはあったものの、AWS 様様で最低限動くサービスがサクッと完成しました

寮生の同期何人かに寮飯確認 Bot のアカウントを伝え利用してもらいました
「こんなの個人で作れるんだ」「すごいね!」という感想が嬉しかったです

拡張を考える

運用しているうちに利用者の同期からこんなコメントが

  • 画像だけだとつまらないから、何か追加で配信してよ
  • 献立の画像は 1 週間分の物が送られてくるけど、その日の分だけ切り出してよ

完全無料のアプリとはいえ、ありがたいご意見には応えたくなります

文章も送ってみる

1 つ目の要望は簡単に対応できました
今まで画像しか配信していませんでしたが当然文章も配信可能です
毎日労いの言葉を添えるようにアップデートしました

献立の画像を切り出す

2 つ目の要求には画像処理が必要になります
学部時代の記憶を掘り起こしOpenCVなどでゴニョゴニョしましたが
実用に耐えうるものは出来ず、これに関しては一旦断念しました

自動化したい気持ちが強くなる

ソースコードを変更するたびに zip で固めて Lambda にアップロードするのは
流石に面倒だし署名付き URL の件もあったので自動化したい気持ちが強くなりました

丁度その頃 Udemy でAWS Code シリーズの講座を受講していたこともあり
Serverless Framework, AWS CDKあたりで CI/CD 環境作ろうと思っていました

サービス終了

思い描いていた拡張は叶うことなく、サービスは突如終わりを迎えます
理由としては「業務が忙しくなってきた」という月並みな言い訳もありますが
最大の理由は献立撮影&S3 へのアップロードが面倒だったからです

技術に関することであればたとえ無料でも頑張れたのですが、
「毎週写真を撮って、S3 に上げる」という単純な作業が面倒になってしまったのです...

怠惰

これが最大の理由となり、サービスは数ヶ月の歴史に幕を閉じました

サービスを振り返って

終焉はあっけなかったですが結果ローコスト・ハイリターンだったと思います

よかった点

  1. AWS の使った開発ができた
  2. AWS 利用料が無料枠の範囲内でサービスを運営できた
  3. 同期の何人かに実際にサービスを利用してもらえた

反省点

  1. モチベーションの維持方法を考えるべきだった
    • 募金という形式でも利用料を取れば義務感が生じたかも
    • 一人で運営せずに運営側に仲間を巻き込めばサボらなかったかも
  2. せめて自動テストまではやり切りたかった

プロダクト開発してみると色々学べるのは分かってるんだけど、最初の一歩がなかなか出んのよね...