blog.morishin.me

Minecraft のマルチプレイ用サーバをプレイ時だけ稼働させるための Lambda Function

三行#

  • Minecraft サーバはメモリ2GB以上のインスタンスが欲しいけど VPS を借りると月2000円ぐらいかかるところが多い
  • プレイ時だけ稼働させればよいので Slack からインスタンスを立てて遊び終わったらデータを退避させて壊せるようにした
  • $0.03 / hour で遊べる

minecraft-lambda-function#

Minecraft サーバをプレイ時だけ稼働させるために下記の機能を持つ AWS Lambda Function を作った。

  • create: DigitalOcean にサーバインスタンスの生成 → S3 からプレイデータ(worldディレクトリ)のダウンロード → Minecraft サーバの起動 → IP アドレスを Slack に通知
  • upload: S3 へプレイデータをアップロード
  • destroy: インスタンスの破壊
https://twitter.com/morishin127/status/818309827709411328

インターフェイス#

Slack の Slash Commands で対応する Function を呼び出す。

  • /minecraft create
  • /minecraft upload
  • /minecraft destroy

インターフェイスの図

アーキテクチャ#

Lambda Function は図のような構成で動いている。 Minecraft サーバアプリケーション自体は itzg/minecraft-server という Docker イメージを利用して動かしている。環境変数に S3 上の world.zip の URL を渡すだけでそのプレイデータで起動されて便利。

create⚒#

create

upload🚀#

upload

destroy💥#

destroy

Slack からの実行#

Slack の Slash Commands から Lambda Function を実行するために API Gateway を利用した。

  1. API Gateway にエンドポイントを作成して POST したら minecraft-lambda-function を実行するように設定。
  2. Lambda Function はパラメータを JSON で受け取りたいのだけど Slack Slash Commands は JSON で送ってくれないので API Gateway で Body Mapping Template を設定。 Body Mapping Template このようにした。
#set($httpPost = $input.path('$').split("&"))
{
\#foreach( $keyValue in $httpPost )
\#set($data = $keyValue.split("="))
"$data[0]" : "$data[1]"\#if( $foreach.hasNext ),\#end
\#end
}
  1. Slack Slash Commands を設定 URL に API Gateway のエンドポイントの URL を設定する。ここで設定する Token は Lambda Function に渡される JSON データに含まれる。(Lambda Function 側の環境変数にも同じ Token を設定しておいて Function 内で照合することで、Slack Slash Commands 以外からのリクエストを無視する) Slack Slash Commands
  2. Slack から /minecraft create を実行すると
{"token": "*****", "text": "create"}

というパラメータで Lambda Function が実行されるようになる 🎉

動作#

Slash Commands 自体のログは残らないけどこんな感じのログになる。

料金#

$0.03 / hour で遊んだ時間分しかかかってないのでお安い 💰

感想#

最高便利!!!!!!!!

余談#

Lambda のデプロイパッケージのビルドを macOS 上で行なっても Lambda 上で動かず苦戦した際の知見です。