Lean Baseball

No Engineering, No Baseball.

小さいプロダクト開発におけるGCP利用の勘どころ - 個人的なプロダクトを三日でローンチした話

私個人の話なのですが.

最近は仕事でAWSやGCPのサーバレスアーキテクチャにふれる機会が増えた*1と同時に,

  • 自分が気になる世の中のニュース(グルメとかいろいろ)だけをいい感じに集めてまとめて読みたい
  • その中でも特に⚾, 速報とかいい感じに通知させたい

という怠け者欲ライフハック欲が高まってきたので, GCP(とちょっとしたPythonスクリプト)でSlack Botを作りました.

趣味開発で雑にはじめた結果, 三日程度でできちゃった*2のでその知見をメモ代わりに残します.

おしながき

TL;DR

  • GCPでクローラーを軸にしたBot作るなら「Cloud Functions」「Cloud Pub/Sub」「Cloud Scheduler」三つの組み合わせで爆速でイケる!
  • 気になる料金は...これからわかるが試算した結果, (今回の使い方だと)月額$1.0程度
  • 個人開発を楽しんでいこう, イベントがない今時期だからこそ

対象読者

「GCPとはなんぞや?」「Slackなにそれおいしいの?」的な解説はしません, わかってる前提で話を進めます.

  • 情報を収集したり使ったりする手段をいい感じにして怠けたい人,
  • 何でも良いのでプログラミングができる人かつ, 個人とか趣味で開発とかが好き・苦にならない人. ちなみに出てくる言語はPythonです.*3
  • サーバレスアーキテクチャ覚えたいなあー, とかGCP使ったサーバレスってどんな感じなん?っていうエンジニアな人.*4

作ったもの

全体像は絵で描くとこんな感じです.

f:id:shinyorke:20200314152038p:plain
この絵がすべてです.

左から順を追って説明すると,

  1. Cloud Scheduler」が毎日の活動時間中に10分間隔で発火, 「Cloud Pub/Sub」の指定したトピックにメッセージを送付
  2. Cloud Pub/Sub」のメッセージをトリガーにして「Cloud Functions」が起動
  3. Functions内の関数(Pythonで実装)がサイトのクローリングとクレンジングをした上でメッセにまとめてSlackにPost.

なお, 通知の制御(主に重複とか, 何回も通知が来るのはウザい)は「Cloud Firestore」に通知の状態を持っておくことによって実現しています.*5

割となんてことは無いSlack Botだと思ってくれればと思います.

GCPをフル活用して実質三日でBotをローンチした

Bot自体は先週の土日(3/7, 3/8)のそれぞれ半日でコードを書いて完成.*6

GCPへのローンチは, 一昨日(3/13)に仕事終わりのオフィスに居残ってビール片手にGCPのサービスを検証しまくった結果, 3時間くらいでできました.*7

Gitのコミットログ + GCP上の作業時間を合計すると多分12時間ちょいです, ハッカソンで作品作ったぐらいのボリュームですね.

Bot本体の開発

元々うっすらと, 「やきう⚾の情報をまとめるBot欲しいなー」と思っていて*8, いつ作ろうかと思案していた矢先に,

というやりとり*9&ウチ(JX通信社)のつよつよマンから聞いたrequests-htmlを(ちょっとドキュメントとコードを読んだ後に)おすすめしたのですが,

ワイ「使ったこと無いモノを薦めるのもアレだしちょっと遊びでコード書くか*10

というモチベーションの元, サクッと仕様を決めて開発をスタートしました.

なお, 開発そのものはrequests-htmlを程よく使うことによりアッサリいけました*11&大人にクローラーを開発する話は過去のエントリーに結構書いたので今回は省略します.

shinyorke.hatenablog.com

物足りない方は是非クローラー本をご参考に :bow:*12

GCPの何を使うかで試行錯誤

このエントリーの肝はむしろここです.

運用は最初からGCPと決めていました.

理由としては,

  • 自分自身のお勉強・知見を得る目的で, 「経験ほぼゼロのGCPでサーバレス」な開発に挑戦したかった.*13
  • プライベートで使っている分析環境およびデータセットはGCP上にまとめている
  • AWS Lambdaでやればきっと瞬殺で終わる&Lambdaも良いサービスだがGCP上での経験が積みたくて(大切なので二度言う)

サーバレスなモノは(GCPに限らず他のクラウドプラットフォームも)従量課金でSlackのBot一個程度ならたかがしれてるだろう.

というのもあり, やりたいモノであったGCPに振り切りました.

今回は,

  • 動かすのはPythonスクリプト
  • Cron的なJOBに従い動くバッチである
  • Web(HTTP)でオープンにするようなAPIとかはナシ

というシンプルな条件の元,

  • プランA「GCE(Google Compute Engine)」上でDockerのContainerとして定期実行
  • プランB「Cloud Run + Cloud Scheduler」の組み合わせでやる
  • プランC「Cloud Functions + Cloud Scheduler」←今回採用した構成

この3つのプランから考え, プランB・プランCをどっちも動かしてお試ししました(プランAは既にやったことあるので考えただけ).

プランA「GCEを使う」

まず真っ先に思いついたのが,

  • 開発したBotをDocker imageにしてGCR(Google Container Registry)にpush
  • GCRに上げたimageからGCEのVMを起動, バッチとして動かす

でした.

これについては既に個人の野球分析でやった実績*14があり楽っちゃ楽なのですが,

  • 言うてもVMなのでずっと立ち上げっぱなしにする必要がある.
  • Botを動かす時間はせいぜい一日10時間ちょい, 残りの14時間はリソースを遊ばせることに.
  • (なんとなくの)試算で$1/日, 一ヶ月で$30前後と予想, 払える金額だが遊んでる時間が長いのでもったいない!

こっちとしては使った時間だけお金を払いたい感じなので即効で却下しました.

プランB「Cloud Run + Cloud Scheduler」

次に考えた&試したのが,

  • 開発したBotをDocker imageにしてGCR(Google Container Registry)にpush
  • Cloud Runのサービスとして起動, Cloud Schedulerからトリガーを出して動かす

でした.

これは実際に公式のクイックスタートを追いながらWeb APIとして立ち上げ, Cloud SchedulerからAPIを叩いて実行してうまくいきました, これは楽だし便利.

ただ,

  • 別にWebアプリを作りたいわけではない
  • 現時点ではCloud RunはWebのトリガーでしか動かないと思ってました. Pub/Sub対応してたのにこのエントリーを書いてる途中に気がついたorz*15
  • 言うてもBotなコードなので別にDocker化するほどでも無いのでは(今更)

若干の勘違いと調査不足は置いておいて, 原点に立ち直った私は「Botとしてもっとシンプルな方法でいこうぜ!」って事で舵を切り直しました.

採用した構成「Cloud Functions + Cloud Scheduler」

というわけで今回採用した構成はこちらになりました.

f:id:shinyorke:20200314152038p:plain
【再掲】この絵がすべてです.

Cloud FunctionsのPub/Sub使うよチュートリアルに従いサンプルを作成, Cloud SchedulerからのトリガーでPub/Subのトピックにメッセしたら今までの試行錯誤は何だったのか?的な感じでうまくいきました👍

使った感想としては,

  • requirements.txtを用意するだけでライブラリのインストールとかよしなにしてくれるのすごく楽.*16
  • 運用後のデバッグがくっそ楽.エラーレポーティングが詳細でわかりやすい(Sentryとかいらない).

ちなみにエラーレポーティングはこんな感じでリンク先を掘るとかなり詳細に追えて素晴らしいです.

f:id:shinyorke:20200315124215p:plain
かなり助かる

さて気になるお値段は?

個人プロジェクトそしてもちろん仕事もコスト管理大事です.

ということで今回の構成(Functions + Pub/Sub + Scheduler + Firestore)において,

「Botが10,000回/月 APIをコール」したときのコスト(月額)を試算してみました.

サービス 試算した金額 根拠
Cloud Functions $1.0 回数は無料枠内, 送信は5GB未満, 関数の実行時間を60秒未満とした時のリソース金額のみ上乗せ, ちなみにメモリは128MB
Cloud Pub/Sub $0 TiB単位で課金, 流石にそこまでいかない
Cloud Scheduler $0 請求アカウント全体で1つのJobのみ, 無料枠に収まる
Firestore $0 100,000ものドキュメントは無い, 行って10,000程度なので無料枠内

一ヶ月あたりたった$1.0, 見誤ったとしても$3.0ぐらいだなとわかりました.

毎日飲んでいるりんご黒酢と胡麻麦茶のほうが高い*17くらいです, やった.

先ほどのGCEを使った例の試算だと(状況にもよりますが)少なくとも$20以上はかかるので全然お安いといえます.

世の中サーバレスなアーキテクチャで開発することが流行っていますが, コスト面ではかなり美味しいのがわかります.*18

結び - 個人的プロジェクトのすすめ

昨今の新型肺炎の騒ぎで色々と辛かったりきついこともあるかと思いますが!

こういう時にふと時間ができたら個人開発をオススメしたいなと.

  • スキルや経験といった自己投資として. 例えばサーバレスなアーキテクチャは実際使わないとわからないモノも多いのでこういうときに試すといいよとか.*19
  • 自分自身の生活や仕事の効率化・ライフハックとして. 普段めんどくさいことを1日2日かけてプログラミングで楽できるのは良いことだし, そこで空いた時間で別のこともできます.*20
  • 結果的に仕事に活きたり次のチャンスに繋がる.

最近は個人開発も結構フォーカスされてる&事例も増えているのでキャッチアップすると良いかなと.

というわけで, GCPを使った小さいプロダクト開発の記録でした.

*1:それはなぜかというと, 現在在籍しているJX通信社がサーバレスアーキテクチャな会社だからです.

*2:ちなみにすべての情報ソースに対して開発終わったわけではないです&今回は野球のソースを中心に紹介します.

*3:Cloud Functionsがサポートしている言語ならどれでもいいです, 現時点ではNode.js, Go langそしてPythonの三択となります.

*4:個人ブログなので会社の見解とか諸々関係ないですが, 弊社を気にしてくださる方は読んでくれたほうが嬉しいです.

*5:これは書くと長いので端折りますが控えめに言って便利でした.

*6:自宅, カフェ, 外の居酒屋と場所を転々としながらクローラー作った

*7:ちなみにウチの会社は金曜日の夜や週末などに自発的に仕事以外のもくもくをする人がいたり, 有志でボードゲームとかを嗜んだりとTGIFチックな活動がとても雰囲気良いです.

*8:開幕に間に合わせましたが肝心の開幕がいつなのかっていうツラミ

*9:その後のむーむーさんの成果は大変素晴らしいまとめなブログとしてまとまっているのでご興味ある方是非&このエントリーでやってることとほぼ被っています(AWSかGCPの違いですね).

*10:人にオススメするものは事後でもいいので触っておく, が私の基本的なスタンスです.

*11:これはまた別の機会に書きたい

*12:これはマジ名著です.

*13:過去にGAEや後述するGCE(Compute Engine)および今はBigQueryやGKEとか使っていますが, サーバレスの小さいSaaSは普段AWSでやってたのでほぼ未経験

*14:昨年検証した, 類似性スコアの算出に使いました, 全選手を総当りで計算する必要があった&半日回せば後は用済みっていう使い方でした(こういう使い方をする分にはVMは大変素晴らしいです).

*15:Pub/Sub無理かーって思ってたらブログ書いてる最中にPub/Subイケるよって見つけました.

*16:個人的にはここがAWS Lambdaより楽で助かるな感あります, まあserverlessとか使えばいいんですけど.

*17:合わせて270円くらいです, これが毎日.

*18:エンジニアリングの基本は「限られたリソースを上手く使い切る」だと思っていてそれがサーバレスな仕組みのピタゴラスイッチでできるのはかなり良いことだと思います.

*19:最初の方に述べた通り今回は自分がGCPに慣れるためにやりました.

*20:いわゆる, 「退屈なこと」「仕事ごっこ」をいい感じにするってことです.