⛏️

AWSで立てたマイクラサーバにボタン起動と自動停止の仕組みを入れる

2021/06/15に公開

身内で遊ぶ用のJava版マイクラサーバを立てる機会がありました。
使いたい人が使いたいときだけサーバを起動して、使ってないときは自動で停止することで料金節約できないかなと思い、この構成を考えました。

  • この記事では、全体的な構成と主な作業について書きます。設定方法の詳細については書きません。あと、マイクラサーバの立て方については詳しく書きません。
  • 初心者向けの記事ではないと思います。知識がある人もしくは自力で調べて解決できる人向けな気がします。

概要

サーバをどこに立てるか?

  • クラウドサービス or VPS
    • 使いたいときだけ使うならクラウドサービスの方が安いと考えました。
    • VPSで有名なものにConoha VPSがあります。これは、使いたいときだけ課金ができるようですが、停止してサーバ消さないといけない(AWSだとEC2インスタンスの削除に相当する)ため面倒だなと思いました。

https://support.conoha.jp/common/faq/payment-q/billing-q/?btn_id=support_faq

  • どのクラウドサービスを使うか?
    • AWSを使いました。仕事で使っていて慣れているためです。

機能

  • ボタン起動:webページ上のサーバ起動ボタンでサーバを起動します。

  • 自動停止:マイクラに接続している人がいないときにサーバを停止します。

  • 定期停止:毎日決まった時間にサーバを停止します。接続放置対策も兼ねています。

詳細

前提

  • AWSのEC2でサーバを立て、マイクラを入れます。他の方が書いた記事がいくらでもあるので、ここでは割愛します。
    • 注意: 古い記事だとEC2のインスタンスタイプにt2系を選んでますが、こだわりがなければt3系を選ぶようにしましょう。こちらの方が安くて性能が良いです。

ボタン起動

herokuで作ったwebページにサーバ起動ボタンを置いて、これを押したら起動するようにしました。

この機能は、自分以外の人が自由にサーバを起動するために必要でした。IFTTTやwebhookとdiscordを連携する方法をいくつか試したのですが、どれも(無料では)うまく行かず、結局webページのボタンを押す方法にしました。

herokuを使ったのはサーバ費をケチるためです。サーバの性能が悪くてもよいため、herokuの無料枠のサーバで十分です。AWSの無料枠が使える場合は、こちらで立てても良いかもしれません。

仕組み

  • ユーザがherokuのwebページにアクセスします
  • 画面上のボタンを押します
  • AWS API GatewayのAPIをコールしてLambda関数を発火します
  • LambdaからEC2を起動します
  • EC2起動時にマイクラを起動します

主な作業

  • Lambda関数を作る
    • EC2を起動する関数です。
    • コード(js)
const instance_ids = ['Your EC2 instance id'];
const AWS = require('aws-sdk');
AWS.config.region = 'ap-northeast-1';

exports.handler = () => {
    const ec2 = new AWS.EC2();
    const params = {
      InstanceIds: instance_ids,
    };
    console.log('start script startEC2');
    ec2.startInstances(params, (err, data) => {
        if(err){
          console.log(err, err.stack);
        } else{
          console.log(JSON.stringify(data));
        }
    });
    console.log('end script startEC2');
};
  • AWS API Gatewayを設定しておく

    • 特定のURLにpostされたら上記のLambda関数を発火するようにします。
  • ボタンを押したら先ほどのAPIのURLへpostするwebページを作る

    • 私は得意なRailsで作りました。APIコールさえできれば何の言語/フレームワークでも良いとは思います。
  • herokuへデプロイする

    • (他の方が書いてるはずなので)手順は割愛します。
    • 身内用なのでBASIC認証をかけておきました。検索エンジンにクロールされないようにするため、知らない人にボタン押させないためです。
  • systemdを設定する

    • サーバ起動時にマイクラを起動するようにします。

自動停止

マイクラのログを5分おきにチェックし、接続人数0人ならサーバを停止する。

仕組み

  • cronで5分おきにスクリプトを実行します。
  • スクリプトでマイクラのログを参照して接続人数を判断します。
  • 接続人数が0人ならサーバを落とします。

主な作業

  • スクリプトの作成
    • マイクラのログを参照して、シャットダウンをするスクリプトです。
      • 他に接続人数判断する方法が思いつかなかったのでログを読み取ってます。
      • サーバ停止は、AWS管理画面から行うのが正規な手順な気がするのですが、サーバ内からshutdownコマンドで問題なさそうでした。
    • 私は得意なRubyで書きました。テキスト解析ができてOSコマンドが実行できる言語なら何でも良いと思います。
      • 起動後15分はshutdownコマンドを打たない
file_path='/home/ubuntu/minecraft/logs/latest.log'
f=File.open(file_path)
in_cnt=0
out_cnt=0
starting=true

f.readlines.each.with_index do |l,i|
  line = l.chomp
  if i==0
    hms=line.split()[0][1..-2].split(':').map(&:to_i)
    before=hms[0]*3600+hms[1]*60+hms[2]
    now=Time.now
    after=now.hour*3600+now.min*60+now.sec
    diff = after - before
    diff+=24*3600 if diff<0
    # 15min start up time
    starting=false if diff >= 15*60
  end
  if line.match(/joined the game/)
    in_cnt+=1
  end
  if line.match(/left the game/)
    out_cnt+=1
  end
end

if starting
  puts 'server is starting'
elsif in_cnt > out_cnt
  puts 'someone is login'
else
  puts 'shutdown now'
  system('sudo shutdown -h now')
end
  • cronの設定
    • 5分おきに上記スクリプトを実行するようにします

定期停止

毎日決まった時間にCloudWatch EventsでLambda経由でEC2を停止するようにします。

仕組み

  • CloudWatch Eventsで毎日朝2時にLambda関数を発火
  • LambdaからEC2を停止

主な作業

  • LambdaでEC2を停止する関数を作る。
    • 上記の起動の関数をコピペして作ります。startInstancesstopInstancesにしてコメントを変えるくらいです。
  • CloudWatch Eventsで毎日朝2時にLambda関数を発火するように設定する。
    • 時刻はGMTなので気を付ける。

料金

主にEC2関連で課金されます。Lambdaは使用回数が少なすぎて無料枠に収まってます。

この仕組みを入れないと、t3.mediumを1か月24H起動で40$(4000円)程度かかるでしょう。40$→10$に抑えられたのでよかったです。

感想

  • 思ったより複雑になってしまった気がします。構成検討から実際の作業で8-16時間かかりました。サーバ費節約分より作業費用の方が多くなりそうだが大丈夫か?
    まあ、ケチりたい精神を具現化できて満足できたのでいいかな。

Discussion