はじめに
さくらのクラウドには、コンテナの動作基盤としてAppRunというサービスがあります。
AppRun共用型は、コンテナ化されたアプリケーションを簡単にデプロイし、自動的にスケーリングを行うサービスです。インフラ管理の複雑さを気にすることなく、開発者が本来の業務であるアプリケーション開発に集中できる環境を提供します。
AppRunがどのような感じなのか知りたかったので、マイクラサーバーを管理するDiscord Botを作成し、AppRun上で動かしてみることにしました。
アーキテクチャ
作ったものは以下のリポジトリで公開しています。
構成は以下のようになります。
Discord Botには、スラッシュコマンドでサーバーの起動・停止ができる機能を実装しています。
Discord Bot が AppRun にデプロイしたコマンドのAPIを叩き、AppRun のアプリケーションがさくらのクラウドのAPIを叩くことで、サーバーの起動・停止を実現しています。
なお、スラッシュコマンドを使ったアプリの作り方については、以前記事にまとめています。
アプリが動作するまでの流れは以下の通りです。
- Discord Bot を作成してサーバーに招待
- コマンドの登録用スクリプトを実行
- 構成図のアプリケーションをデプロイ
- アプリケーションのURLをDiscord Botに登録する
ここまですると、Discordからスラッシュコマンドでサーバーの起動・停止ができるようになります。
サーバーの電源周りのロジック
現在、マイクラサーバーにはシンプル監視の設定が入っています。このサービスは、特定のIP・ポートに対する外形監視を行ってくれるサービスです。
この監視設定が入った状態でサーバーの電源を落とすと、シンプル監視が異常として検知してしまいます。
毎回電源を落とすたびに死活監視のアラートが来るのは煩わしいので、サーバーの停止と同時に、シンプル監視の無効化も行うようにしました。
ちなみに、シンプル監視のwebhook通知はslack向けでDiscordには対応していないですが、Discord側がslackのwebhookに対応したエンドポイントを提供してくれています。
利用方法も簡単で、発行したwebhook URL の末尾に /slack をつけるだけです。
こちらの記事に詳しい解説が書かれていました。
Discord周りのロジック
AppRun側のアプリケーションはFastAPIで実装しています。ここではDiscord Bot のスラッシュコマンドを受け取る部分と、そのコマンドを読み取ってさくらのクラウドの操作を行うバックエンドを実装しています。
Discordへのレスポンス部分は非同期で実装しています。
サーバーの起動と停止には若干時間がかかるため、まずは「起動中」や「停止中」といったメッセージをユーザーに返すようにしています。
その裏側では、5秒おきにサーバーのステータスを確認し、起動や停止が完了したことを検知したら、完了メッセージを送る仕組みにしています。
AppRunの設定
インフラは一部を除いてTerraformで管理しています。
コンテナ側は8080ポートでhttpレスポンスを受け付けているので、AppRunのルーティングも8080に向けます。
resource "sakura_apprun_shared" "this" {
depends_on = [terraform_data.push_image]
name = var.name
timeout_seconds = 30
port = 8080
min_scale = 1
max_scale = 1
components = [{
name = "bot"
max_cpu = "0.5"
max_memory = "1Gi"
deploy_source = {
container_registry = {
image = "${var.container_registry_fqdn}/${var.name}:${var.image_tag}"
server = var.container_registry_fqdn
username = "deploy"
password_wo = var.container_registry_password
password_wo_version = 1
}
}
# まだ検証中のため環境変数に入れているが、将来的にシークレットマネージャーに移したい
env = [
{ key = "DISCORD_PUBLIC_KEY", value = var.discord_public_key },
{ key = "DISCORD_APPLICATION_ID", value = var.discord_application_id },
{ key = "DISCORD_BOT_TOKEN", value = var.discord_bot_token },
{ key = "SAKURA_ZONE", value = var.sakura_zone },
{ key = "SAKURA_SERVER_ID", value = var.sakura_server_id },
{ key = "SAKURA_ACCESS_TOKEN", value = var.sakura_access_token },
{ key = "SAKURA_ACCESS_TOKEN_SECRET", value = var.sakura_access_token_secret },
{ key = "SAKURA_SIMPLE_MONITOR_IDS", value = var.simple_monitor_ids },
]
probe = {
http_get = {
path = "/health"
port = 8080
}
}
}]
}
課題点
AppRunの0スケール運用
Discordのスラッシュコマンドには、イベント受信後3秒以内に最初のレスポンスを返さなければならないという制約があります。
Interaction tokens are valid for 15 minutes and can be used to send followup messages but you must send an initial response within 3 seconds of receiving the event. If the 3 second deadline is exceeded, the token will be invalidated.
インタラクショントークンは15分間有効で、フォローアップメッセージの送信に使用できますが、イベント受信後3秒以内に最初の応答を送信する必要があります。3秒の期限を過ぎると、トークンは無効になります。
コスト最適化のためにAppRunのコンテナ最小数を0に設定しておきたいところですが、コンテナの起動に時間がかかってしまい(それでも十分高速ですが)、Discord からの最初のレスポンスに失敗するようになります(2回目以降は時間内にレスポンスされますが、あまり使い勝手の良いものではありません)。
前回AWS Lambdaで同様の仕組みを試した際は、Lambdaの起動時間が非常に高速だったためこの問題は発生しませんでした。この問題を料金を抑えつつ回避する方法が思いつかなかったので、今回はスケーリングの最小数を1に設定しています。
将来的に、さくらのクラウドにもLambdaのようなサーバーレスサービスが登場してくれると嬉しいですね。
コンテナレジストリ
さくらのクラウドのコンテナレジストリは月額課金制で、作成した時点から料金が発生する方式になっています。私は検証時にTerraformでスクラップアンドビルドを繰り返すことが多いため、この課金方式だと少し痛手です(作り直されるたびに課金されてしまうので…)。
現状では、月額課金のリソースのみ手動で作成し、Terraformからはdataソースで参照するという運用にしていますが、やや管理が煩雑になっています。
これはコンテナレジストリに限った話ではなく、オブジェクトストレージやモニタリングスイートなど月額課金制のサービス全般に言えることです。
今回はさくらのクラウドで完結させてみたいという要件があったためコンテナレジストリを使用しましたが、もし自由に選択ができるのであれば、GitHub Container RegistryやDocker Hubといった外部サービスの利用も視野に入ってくるかもしれません。
まとめ
今回は、さくらのクラウドのAppRunを使って、マイクラサーバーを管理するDiscord Botを動かしてみました。
AppRunはコンテナベースのアプリケーションを手軽にデプロイできるサービスで、FastAPIで実装したDiscord Botも問題なく動作させることができました。
LambdaではWebアプリを動かすためにWeb Adapterを噛ませる必要があったり、ECSは設定項目が多くインフラ周りの準備に手間がかかりますが、AppRunはそういった煩雑な設定をせずにWebアプリをデプロイできるので、ちょうど良い塩梅のサービスだと思いました。
一方で、課題もいくつか見つかりました。
特に、0スケール運用ができない点はコスト面で気になるポイントです。
Discordのインタラクションの3秒レスポンス制限との兼ね合いで最小インスタンス数を1にせざるを得ず、常時稼働のコストが発生してしまいます。この点は、今後さくらのクラウドに一時受けに特化した、よりサーバーレスなサービスが登場することに期待したいところです。
また、コンテナレジストリの月額課金制も、Terraformで頻繁にリソースの作成・削除を行う検証スタイルとは相性が悪く、運用に工夫が必要でした。
新しいサービスを使ったり、限られた制約の中で工夫をするのはとても楽しいので、今後もしばらくの間、さくらのクラウド縛りを続けていきたいと思います(笑。


