PyCon JP 2020のTwitter実況システムをGKE上に作った話

SREのたっち(@TatchNicolas)です。

今年のPyCon JPはオンライン開催でした。JX通信社はSilverスポンサーとして協賛したほか、イベントをより盛り上げるために、参加者の反応をリアルタイムに配信に反映するシステムを開発・提供しました。

jxpress.net

アプリケーションはPythonで作られており、基盤としてGKEを採用しました。データ分析基盤や昨年の開発合宿等で社内向けのプロジェクトにKubernetesの採用した事例は過去にもあったのですが、今回はじめて社外向けのシステムに採用したので、その裏側について書いてみたいと思います。

できたもの

構成図

構成としては比較的シンプルだと思います。

基本的な処理はGKE上で行い、データの永続化はFirestoreを使っています。一部、ブラウザで動く運営向けフィード画面上の操作(いいね・リツイート)について、Firebaseを使った書き込みをトリガーとしてCloud Functionsを使って反映させています。

f:id:TatchNicolas:20200827091516p:plain
PyCon JP 2020 SNSリアルタイム配信システム 構成図

(一部リソースは省略しています)

設計のポイント

前提としては、

  • 継続的に提供するサービスではなく、PyCon JP 2020が開催されている二日間のみ稼働すればよい
  • Kubernetes採用の理由は「普通に作っても面白くない、今までと違うことにチャレンジしよう
  • 一方で、短期間 + 開発チームは普段の業務と並行してすすめるため、あまり欲張りはできない

以上から、 「今までよりちょっと便利」を感じてもらいつつも「今までと違いすぎない」 を目指して構成を考えました。

やってみて

Kubernetes投入のハードルは思った以上に低かった

もともとJX通信社ではECSを使い倒しているので、「これはECSでいうとXXみたいな何か」という説明で、Kubernetesに馴染みのないメンバーにもすんなり理解してもらえたと思います。毎週社内の有志でKubernetes勉強会を開催していたので予備知識としても全くのゼロからのスタートではなく、実践の場として良い機会を作れたなと思います。

(最近は本を読むより、それぞれが作りたいものを作ってもくもくする時間になりつつあります。)

永続化や認証はFirebaseを利用したので、複雑になりがちな部分をうまくマネージドに逃がせたことも導入の容易さに繋がったと思います。

port forward のおかげでローカル開発が捗った

今回のプロジェクトでは単にツイートを取得してくるだけでなく、不適切な書き込みをできるだけ除去するために幾つかの機械学習モデルをWeb API化して利用しています。

実際には構成図のcrawlerから利用されていて、収集したツイートをスコアリングしています。ローカルでのcrawler動作確認時にもツイートの内容を判定するためにモデルを叩きにいきたいのですが、そのためにモデルをダウンロードしたりdocker-composeなど用意して推論APIをローカルに立てるのも面倒です。さらに、手元のマシンのリソースも余分に消費してしまいます。

そこで kubectl port-forward <推論APIのService> <ローカルのポート>:<推論APIのポート> とlocalhostで使えるようにすることで、別途APIを立てることなくスムーズに開発ができるようになりました。

APIのURLは環境変数としてcrawlerに渡すようにしているので、切り替えも簡単に行えます。

これは普段のECSの開発では無かった体験なので、開発メンバーからも「こりゃ便利だ」と言ってもらえました。

Secretsのおかげで開発用のAPIキーを簡単に共有できた

Slack連携やTwitter APIの取得のために、いくつか秘匿情報としてPodに渡したいAPIキーがありました。コーディング時は前述の推論APIのURLと同様、実際にSlack/TwitterのAPIを叩きたいのですが、メンバーが自分でキーを用意するのはやはり面倒です。

こちらも検証および本番環境ではSecretsリソースを使って環境変数としてアプリケーションへ渡しているので、ローカルで使いたい場合は検証環境から各種キーを取得して環境変数へセットするワンライナーを用意することで、各メンバーがそれぞれキーを発行することなく利用でき、開発に集中することができました

export SLACK_CHANNEL=$(kubectl get configmap crawler --template="{{.data.SLACK_CHANNEL}}")
export SLACK_TOKEN=$(kubectl get secret crawler --template="{{.data.SLACK_TOKEN}}"|base64 -D)

上記をそのままdirenvの .envrc に書いておけば、下準備はほとんど必要なく、pullしてきてすぐに開発を始められます。

まとめ

PyCon JPに限らず、様々なテックカンファレンスがオンラインで開催されている中で、JX通信社としてイベントを少しでも盛り上げるために貢献できたことはとても嬉しいです。

今回のPyCon向け配信システムに限らず、チーム全体での開発のスピードを上げるために、Kubernetesを使って社内のマイクロサービス基盤を改善していく取り組みも行っています。次回はもうすこしKubernetesのエコシステムを生かした仕組みづくりについて書いてみたいと思います。