遠藤氏の自己紹介

遠藤大介氏:今日は「AWSのLambdaとPlanetScaleを組み合わせると、超絶スケールするWebアプリを作れちゃうぜ」という話をしていこうと思っています。

最初に自己紹介です。遠藤と申します。SonicGardenという会社で、プログラマーと執行役員をやっています。インフラと機械学習などが好きで、趣味もプログラムで仕事もプログラムな感じの人間なんですが、最近は機械学習周りが盛り上がっているので、そっちもいろいろやっています。

あと、ロードバイクに趣味で乗っているのですが、最近ちょっと乗れていません。それからゲーマーで、最近は『FF16』にどっぷり浸かっています。

(スライドを示して)ささっと2個ほど宣伝したいのですが、SonicGardenで無料のオンラインプログラミング合宿をやろうと思っていて、今、夏のキャンプの申し込み受付をしています(登壇時点)。

学生や第2新卒向けの無料のオンラインプログラミング合宿なので、もし周りの方で「ちょっとプログラミングをやってみたいんだよな」と思っているけれど一歩踏み出せないような人がいたら、ぜひ紹介してもらえるとうれしいです。

あと、これまた夏にあるのですが、「つくること、それが目的だ」という「ツクってアソぶハッカソン」というイベントもやろうと思っています。こちらも2023年8月17日から25日の夏休みの間でやるので、ハッカソンが好きな方がいたら、ぜひ後で「ツクアソ」とか「ツクってアソぶハッカソン」で検索してもらえるとうれしいなと思っています。

バズった時にいい感じにスケールするインフラは2ドルくらいから作れる

本題です。今日の話ですが、仕事以外で趣味でWebアプリを作っている時に、(そのアプリが)うまいことヒットすると急にSNSでバズったりして。「そういう時にいい感じにスケールしてくれるインフラはないもんかな?」って毎度思うんですね。

さらに欲を言えば、(そのインフラでは)Railsのような普通のフレームワークを使いたいし、データストアはリレーショナルデータベースを使いたい。バズった時とかに数百インスタンスくらい自動でスケールしてほしいし、Job系も実行したいし、One-offのタスクも実行したいと(いう感じで)、もう欲だらけになってきます。

「そんなインフラはあるんかいな?」というところで、「実は、2ドルくらいかけたら作れちゃうんです」という話を今日はしようと思っています。

(今日のイベントでは)今まで(登壇された方)の話でも「既存の技術を組み合わせると意外とニッチなんじゃね?」という話があったと思いますが、(僕が紹介する)組み合わせをやっている人は、意外と、そんなに見かけなかったので、今日は布教活動がてら、まだまだニッチで俺得なんですが、「(これからは)みんなが使えばいいな」と思っている話をしようと思います。

今日話すこと

(スライドを示して)今日話すことは、「AWSのLambdaとFargateを活用してWeb(サーバー)Job、One-offタスクなどの実行環境を作っちゃえばいいよね」ということです。

それから、PlanetScaleという化け物みたいなリレーショナルデータベースがあるんですが、それを使うとサーバーレス系のLambdaを組み合わせても怖くないというところをざざっと話していこうと思っています。

(スライドを示して)AWSに詳しい人は、この図スクショなどを撮ってもらって後で見ればだいたいの構成は理解できると思いますが、これだけ見ても「よくわからん」という方も多いと思うので、今日は(この後)そこらへんの話をしていきます。

基本的には、ユーザーのリクエストをAPI Gateway経由でLambdaで受けて、PlanetScaleのデータを見る感じの作りです。

LambdaとFargateそれぞれの強みを活かした実行環境

まず、LambdaとFargateを活用した実行環境で、それぞれの強みをちゃんと認識しておきましょう。

(スライドを示して)まずLambdaですが、大規模にスケールする瞬発力が半端ないんですね。一瞬で数百インスタンスにスケールしてくれるので、ドドッて人が来たとしても、とりあえずLambda側がスケールしてくれます。

なので、激しいスパイクへの柔軟性が半端ないんですね。あとは課金がミリ秒単位で、動いている時間しか課金されないので、波が激しいやつだとだいぶお財布にも優しいという強みがあります。

それ対してFargateの強みは、(Fargateが)Dockerのコンテナ系なので、長時間タスクの実行をしたり、あとはAWSが準備してくれているECS Execという機能を使うと、コンテナの中に入れるんですね。なので、SSH(Secure Shell)で入るような感じでサーバーに入れます。

(スライドを示して)なので、それぞれの強みを活かすと、Lambdaはスパイクの激しいWebのリクエストを受け付ける。そしてLambdaの実行時間は15分未満という制約があるので、15分未満で終わるような軽めのJobはLambdaに流しちゃえばいい。

それ以上かかるような重めのJobや、あとは「ちょっとコンテナに入っていろいろしたいんだけどな」みたいなOne-offタスク系はFargateに流しちゃう仕組みが取れます。

実はLambdaでもFargateとまったく同じDockerイメージが使える

これはけっこう大事なポイントかつ、意外とやっている人がいねぇなというニッチポイントなのですが、工夫すると、実はLambdaでもFargateとまったく同じDockerイメージが使えるんですよ。なので、Web用のDockerイメージ作って、Job用のやつを作ってとかをしなくていいんですね。

その時にベースのDockerイメージはどう作るかというと、LambdaのRuntime APIで、Lambdaとのやり取りができるように作ります。

(スライドを示して)Dockerファイルの最後のほうですが、Rubyの場合、AWSが準備してくれているaws_lambda_ricというものでLambdaと受け答えができるようにします。

「Fargateで動かす時はどうすんじゃい?」というと、FargateはDockerファイルの中で定義するcommandとかentryPointをオーバーライドできるので、ただただこんな感じでcommandとかentryPointを上書きします。

そうすると、中身のファイルやインストールされているライブラリなどは同じままで何を動かすか変えられるので、だいぶ柔軟性が高く同じイメージを使い回せます。ちなみにこのあたりのYAMLは、サーバーレスフレームワークのYAMLですね。

というわけで、WebもJobもOne-offも、すべてを単一のDockerイメージで実行できるので、ビルドを1回したらそのあたりを全部使い回せるという素敵な環境ができます。

実行環境におけるWebサーバー

Webサーバーは、API Gateway経由で呼び出されて、先ほどのRuntime Interface Clientに準拠している必要があります。

SonicGardenがRails、Rubyなどをメインでやっている会社なのと、僕がRailsが好きなのでRailsの話をします。Railsの場合はLambyというOSSがそのあたりの面倒を見てくれるので、このあたりのライブラリを使うと、Lambdaとのやり取りはいい感じにやってくれます。

実行環境における非同期Job

あとは非同期Jobですね。非同期Jobは、Webサーバーで同期処理しなくてもいいやつをポイポイと投げたい場合がまあまあ出てきますが、そういったものはSQS(Simple Queue Service)系に溜めて、Lambdaで順次実行していく感じで処理します。

これもRailsの場合だったらLambdakiqというとても便利なOSSがあって、これを使うと非同期JobもLambdaとSQSで組めます。

実行環境における定期Job

「じゃあ、定期的なJobはどうすんじゃい?」というと、定期的に動かしたいバッチ処理(なの)で、AWSのEventBridgeやCloudWatchイベントから実行します。短時間なものはLambdaに流して、長時間のものはFargateに(流す)ということで、Jobの作りによって振り分けてやればいい感じになっています。

(スライドを示して)例えばLambda側に割り振るやつだと、サーバーレスフレームワークだとeventsの下にscheduleと書いて、名前と、どのくらいの実行頻度かのレートみたいなやつを書くと実行できます。

あとはFargate側ですね。Fargate側もスケジュールの指定をして、AWS側を自動的に組んでくれるライブラリがあるので、こういうものを使うと、長時間のタスクなども組めます。

実行環境におけるOne-offタスク

One-offタスクですね。「One-offだけはサーバーでコンソール上で手動で実行したい」とか、Railsなら「rails cでコンソールに入って触りたい」とか、コンテナ内部からじゃないと調査できないことを調査したい場合とかがぼちぼちあると思います。

Dockerの中に入る時にSSHを入れなくても、ECS Execという仕組みを使うと、Fargateの専用タスクを起動して、その瞬間だけECS Execで入るかたちをとれるので、常時メンテナンスサーバーを上げておくのではなく、必要な時に専用のタスクを起動してECS Execの中に入るという使い方ができます。

One-offタスクが終わったらFargateのタスクも終了させればいいので、踏み台サーバーをその場で立ち上げて使って、終わったら落とすような使い方をする方も多いと思うのですが、そういうノリでOne-offタスクも作れちゃいます。

(スライドを示して)タスクの定義的にはこんな感じですね。サーバーレスフレームワークを使うと、こういうところはだいぶシンプルに記述できるのでおすすめです。

One-offタスクを起動するやつ(について)は、(これは)「例えばシェルスクリプトで起動用のやつを組むとこんな感じよ」というサンプルみたいなものです。「実際になにを実行するの?」というものを持ってきて、実際にそのタスクを実行して、タスクが起動するのを待って、ECS ExecをするためのManaged Agentが要るので、そのあたりの起動待ちをします。

そこからECS Execで入って、処理が終わったらタスクを落とすのも、ババッとシェルスクリプトでもこんなレベルで書けるので、意外と簡単に手前(の)実装ができてしまいます。

そんなこんなで、今話したのが、LambdaとFargateを使ってWebサーバーやOne-offやJobなどを実装しようという話でした。

ほぼ普通のMySQLなのにコネクション数の足枷がないPlanetScale

(今日話すこととして)残っているのがPlanetScaleによるスケーラブルなRDB(Relational Database)で、ある意味今日はこの布教をしに来たといっても過言ではないサービスです。

(スライドを示して)PlanetScaleはなかなか素敵なサービスです。トップページの説明などを後でググってぜひ見てほしいのですが、「Serverless MySQL Platform」と書かれていて。

「『MySQL』なのにサーバーレスってどういうことやねん?」ってなります。これはなかなかぶっ飛んでいて、多少の癖はあるのですが、サーバーレスと言っているのに、データベースにコネクションをつないでクエリを投げられるんですね。

一昔前に流行った「(Amazon)Aurora Serverless V1」は、専用のAPIがあってSQLをRESTで投げないといけなかった時代があったりしたのですが、これはただ普通にDBにコネクションがつなげられるんですね。Webアプリから見ると、ほぼほぼ普通のMySQLに見えます。

それなのに、恐ろしいことにコネクション数という足枷がなくて、数千とか数万コネクションが普通につながるんですよ。普通にRDBを使うと一番問題になるのはこのコネクションで、一気に数百とかつなぐとメモリがあふれて死ぬとかがあるのですが、PlanetScaleはそれがないんですね。

プラン一覧を見てもいろいろバグっています。無料で5GBのストレージが使えて、10億レコード読み込めてみたいな感じで規模感もバグっているのですが、そもそもコネクション上限とか(については)なにも書かれていません。

確か1年くらい前はそれぞれのプランでコネクション上限があったのですが、いつの間にかなくなっていたので、裏側でたぶんそのあたりが進化したんでしょうね。

というわけで、一昔前は「サーバーレスとRDBはそもそも相性が悪い」という話がいろいろささやかれていたのですが、もはやPlanetScaleがあれば、Lambdaがスケールしてもなにも怖くないなという世界が来ています。

というわけで、PlanetScaleはほぼ普通のMySQLで(ありながら)コネクション数という足枷がないので、サーバーレス系との相性が良くて。(また)課金も容量や読み書きの量ベースで、10万円とかですごく大きいインスタンスをあらかじめ立てなくちゃ(いけない)とかもないので、すごく気軽に始められるところがとても便利です。

ただ、何点か注意点があります。1トランザクションあたり20秒までみたいな時間制限があったり、クエリあたりの時間制限もあったりします。あとは、カラムとテーブルのリネームが不可能で、「新しいカラムを足す時はこういう手順でやってね」みたいなのが公式のドキュメントで書いてあるので、そのあたりを見ながらやってほしいという注意点はあるのですが、とても便利です。

というわけで、LambdaやFargateを組み合わせると最強のデータストアになります。

まとめです。今日話したのは、LambdaやFargateを使うと1つのDockerイメージでWebサーバーやJobやOne-offタスクが全部できちゃうよということと、そういうサーバーレスのものにPlanetScaleをつなぐと、なんとリレーショナルデータベースがサーバーレスで余裕で使えちゃうという話でした。

ちょっと時間オーバーしましたが、ご清聴ありがとうございました。