🤖

素人が何もわからずAWSにマイクラサーバを立ててみた(続編)- 自動起動と自動停止編

に公開

はじめに

前回の記事では、AWSでMinecraftサーバーを立ち上げ、Javaのインストール、サーバーの初期設定、そしてチートの有効化までを行いました。今回は、サーバー運用におけるコスト削減と利便性向上に直結する重要な設定、すなわち「サーバーの自動起動」と「プレイヤーがいなくなったら自動で停止する」仕組みについて、Geminiと二人三脚で挑戦した記録をお届けします。

今回の目標

  1. EC2インスタンスを立ち上げたら、自動でMinecraftサーバーが立ち上がるようにする
  2. プレイヤーが0人になったら、自動でEC2インスタンスを停止する
  3. サーバー設定など、EC2を操作したいだけの時に自動停止を防ぐ方法を知る

1. EC2を立ち上げたら自動でMinecraftサーバーが立ち上がる設定

手動でEC2を起動するたびに、SSHでログインしてMinecraftサーバーを起動するのは面倒ですよね。ここでは、LinuxのSystemdというサービス管理ツールを使って、OS起動時に自動でMinecraftサーバーが立ち上がるように設定します。

Minecraft起動スクリプトの作成

まず、Minecraftサーバーを起動するためのシンプルなシェルスクリプトを作成します。

  1. EC2インスタンスにSSH接続します。

  2. Minecraftサーバーのディレクトリとは別に、例えばホームディレクトリ直下に起動スクリプトを作成します。ここでは/home/ec2-user/start_minecraft.shとします。

    vi /home/ec2-user/start_minecraft.sh
    

    ここでviエディタが開きます。

    ここでちょっと寄り道:viエディタの基本的な使い方

    viは慣れるまで少し独特な操作感がありますが、基本的な操作を覚えれば大丈夫です。

    • 起動時:コマンドモード
      viを開くと、最初はコマンドモードという状態です。ここでは文字を直接入力することはできません。カーソル移動やコマンドの実行などを行います。

    • 文字を入力したい:挿入モード
      文字を入力するには、コマンドモードから挿入モードに切り替える必要があります。

      • カーソルがある位置から入力開始:iキーを押す
      • カーソルがある位置の次から入力開始:aキーを押す
      • カーソルがある行の下に新しい行を追加して入力開始:oキーを押す
        挿入モードになると、画面の左下あたりに -- INSERT -- と表示されます。これで通常のテキストエディタのように文字を入力できます。
    • 入力終了:コマンドモードに戻る
      文字の入力が終わったら、Escキーを押すとコマンドモードに戻ります。-- INSERT -- の表示が消えます。

    • ファイルを保存して終了:最終行モード
      コマンドモードで :(コロン)キーを押すと、画面の左下にカーソルが移動し、コマンド入力待ちになります(最終行モード)。

      • 変更を保存して終了::wq と入力して Enter
      • 変更を保存せずに終了::q! と入力して Enter
      • 保存だけする::w と入力して Enter

    上記viの操作方法を参考に、以下の内容をファイルに貼り付けてください。cd /home/ec2-user/minecraft/java ...のパスや設定は、あなたのサーバーの実際のパスや起動コマンドに合わせてください。

    #!/bin/bash
    cd /home/ec2-user/minecraft/
    java -Xmx512M -Xms512M -jar server.jar nogui
    

    変更したら、Escキーを押してコマンドモードに戻り、:wqと入力してEnterでファイルを保存して閉じます。

  3. スクリプトに実行権限を付与します。

    chmod +x /home/ec2-user/start_minecraft.sh
    

Systemd ユニットファイルの作成

次に、Systemdがこのスクリプトをサービスとして管理するための設定ファイル(ユニットファイル)を作成します。

  1. 以下の内容で/etc/systemd/system/minecraft.serviceファイルを作成します。sudo権限が必要です。

    sudo vi /etc/systemd/system/minecraft.service
    

    ここでもviエディタが開きますので、上記「viエディタの基本的な使い方」を参考に操作してください。

    [Unit]
    Description=Minecraft Server
    After=network.target
    
    [Service]
    User=ec2-user
    Group=ec2-user
    WorkingDirectory=/home/ec2-user/minecraft/
    ExecStart=/home/ec2-user/start_minecraft.sh
    Restart=always       # サービスが停止した場合に常に再起動
    RestartSec=10s       # 10秒後に再起動
    StandardOutput=journal # ログをjournaldに転送
    StandardError=journal
    
    [Install]
    WantedBy=multi-user.target
    
    • UserGroupはMinecraftサーバーを実行するユーザーに合わせてください(通常はec2-user)。
    • WorkingDirectoryExecStartは、先ほど作成したスクリプトとMinecraftサーバーのディレクトリの正確なパスを指定します。
    • Restart=alwaysを設定することで、万が一Minecraftサーバーがクラッシュしても自動的に再起動されるようになります。
  2. ファイルを保存してエディタを閉じます(Escキー → :wqEnter)。

Systemdの設定をリロードし、サービスを有効化・起動

新しいサービスファイルをSystemdに認識させ、OS起動時に自動で起動するように設定します。

  1. Systemdの設定をリロードします。
    sudo systemctl daemon-reload
    
  2. minecraft.serviceをOS起動時に自動起動するよう有効化します。
    sudo systemctl enable minecraft.service
    
  3. サービスを今すぐ起動します(テスト)。
    sudo systemctl start minecraft.service
    
  4. サービスのステータスを確認し、Active: active (running)と表示されていることを確認します。
    sudo systemctl status minecraft.service
    

これで、EC2インスタンスが起動するたびに、Minecraftサーバーが自動的に立ち上がるようになりました。


2. プレイヤーが0人になったら自動でEC2を停止する設定

これはコスト削減の要となる設定です。誰もプレイしていないときにEC2インスタンスを自動停止させることで、無駄な料金発生を防ぎます。

CloudWatch エージェントのインストールと設定

Minecraftサーバーのログを監視するために、CloudWatch エージェントをEC2インスタンスにインストールし、ログをAWSのCloudWatch Logsに送信するように設定します。

  1. エージェントのダウンロードとインストール:

    sudo yum install -y amazon-cloudwatch-agent
    
  2. 設定ファイルの作成 (config.json):
    config.jsonを作成し、Minecraftサーバーのログファイル(通常はlogs/latest.log)を監視するように設定します。

    sudo vi /opt/aws/amazon-cloudwatch-agent/bin/config.json
    

    ここでもviエディタが開きますので、上記「viエディタの基本的な使い方」を参考に操作してください。

    {
        "logs": {
            "logs_collected": {
                "files": {
                    "collect_list": [
                        {
                            "file_path": "/home/ec2-user/minecraft/logs/latest.log",
                            "log_group_name": "/aws/ec2/minecraft-server-log",
                            "log_stream_name": "{instance_id}",
                            "timestamp_format": "%H:%M:%S"
                        }
                    ]
                }
            }
        }
    }
    
    • file_pathはあなたのMinecraftサーバーのログファイルの正確なパスに設定してください。
    • log_group_nameはCloudWatch Logsでログが保存されるグループ名です。
      変更したら、Escキーを押してコマンドモードに戻り、:wqと入力してEnterでファイルを保存して閉じます。
  3. CloudWatch エージェントの起動:

    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json -s
    

    これでエージェントが起動し、MinecraftサーバーのログがCloudWatch Logsにリアルタイムで送られるようになります。

CloudWatch メトリクスフィルターとアラームの設定

CloudWatch Logsに送られたログの中から「プレイヤーのログイン」と「プレイヤーのログアウト」の情報を抽出し、現在のプレイヤー数をカウントするカスタムメトリクスを作成します。そして、そのプレイヤー数が0になったら発動するアラームを設定します。

  1. CloudWatch Logsでメトリクスフィルターを作成:
    • AWSマネジメントコンソールでCloudWatchサービスに移動します。
    • 左のナビゲーションペインで「ロググループ」を選択し、/aws/ec2/minecraft-server-logをクリックします。
    • メトリクスフィルター」タブを選択し、「メトリクスフィルターを作成」をクリックします。
    • プレイヤーログイン用フィルター:
      • フィルターパターン: [INFO] logged in
      • メトリクス名: PlayerLoggedInCount
    • プレイヤーログアウト用フィルター:
      • フィルターパターン: [INFO] left the game
      • メトリクス名: PlayerLeftCount
  2. カスタムメトリクス(プレイヤー数)の作成:
    • CloudWatchの左ナビゲーションペインで「メトリクス」を選択し、「すべてのメトリクス」タブをクリックします。
    • 数式と可視化されたメトリクス」タブを選択し、「数式を追加」をクリックします。
    • PlayerLoggedInCountm1PlayerLeftCountm2として、数式に m1 - m2 と入力し、エイリアスをPlayerCountなどと設定します。これが現在のプレイヤー数を表すメトリクスになります。
  3. CloudWatch アラームの作成:
    • 先ほど作成したPlayerCountメトリクスを選択し、「アラームの作成」をクリックします。
    • アラームの条件:
      • 「期間」: 1分
      • 「条件」: PlayerCount0 より小さいまたは等しい (<= 0)
      • 「データポイントのしきい値」: 1
    • アクションの設定:
      • 「通知」: 新しいSNSトピックを作成するか、既存のトピックを選択します。このSNSトピックが、後述するLambda関数をトリガーします。例えばminecraft-server-stop-snsという名前で作成します。

Lambda関数によるEC2の自動停止

CloudWatchアラームが「ALARM」状態になったら、それをトリガーとしてLambda関数が実行され、MinecraftサーバーのEC2インスタンスを停止します。

  1. Lambda 関数の作成:
    • AWSマネジメントコンソールでLambdaサービスに移動します。
    • 関数の作成」をクリックし、以下の設定を行います。
      • 関数名: stop-minecraft-server
      • ランタイム: Python 3.9 (または最新のサポートされているバージョン)
      • 実行ロール: 「基本的な Lambda アクセス権限で新しいロールを作成する」を選択し、後で権限を最小化します。
    • 関数を作成したら、コードエディタに以下のPythonコードを貼り付けます。
    import boto3
    import os
    
    ec2 = boto3.client('ec2')
    
    def lambda_handler(event, context):
        # 環境変数からEC2インスタンスIDを取得
        instance_id = os.environ.get('INSTANCE_ID')
    
        if not instance_id:
            print("Error: INSTANCE_ID environment variable is not set.")
            return
    
        try:
            # EC2インスタンスを停止
            response = ec2.stop_instances(InstanceIds=[instance_id])
            print(f"Stopping instance {instance_id}: {response}")
        except Exception as e:
            print(f"Error stopping instance {instance_id}: {e}")
            raise e
    
  2. 環境変数の設定:
    • Lambda関数の設定タブで、「環境変数」セクションを見つけ、「編集」をクリックします。
    • キー: INSTANCE_ID
    • 値: あなたのMinecraftサーバーのEC2インスタンスID (例: i-0abcdef1234567890)
  3. トリガーの設定:
    • Lambda関数の「トリガーを追加」をクリックします。
    • トリガーとして「SNS」を選択し、CloudWatchアラームで設定したSNSトピック(例: minecraft-server-stop-sns)を選択します。

権限の最小化とセキュリティ強化

Lambda関数がEC2インスタンスを停止するための権限は、必要最小限に抑えるべきです。

  1. カスタムIAMポリシーの作成:
    • AWSマネジメントコンソールでIAMサービスに移動します。
    • 左ナビゲーションペインで「ポリシー」を選択し、「ポリシーを作成」をクリックします。
    • 「JSON」タブを選択し、以下のポリシーを貼り付けます。
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:StopInstances",
                    "ec2:DescribeInstances"
                ],
                "Resource": "arn:aws:ec2:YOUR_REGION:YOUR_ACCOUNT_ID:instance/YOUR_INSTANCE_ID"
            }
        ]
    }
    
    • YOUR_REGIONはあなたのEC2インスタンスが存在するリージョン(例: ap-northeast-1)、YOUR_ACCOUNT_IDはあなたのAWSアカウントID、YOUR_INSTANCE_IDはMinecraftサーバーのEC2インスタンスIDに置き換えてください。
    • ポリシーにMinecraftServerStopPolicyなどの分かりやすい名前をつけ、作成します。
  2. Lambda関数の実行ロールにアタッチ:
    • Lambda関数の設定タブに戻り、「アクセス権限」セクションで実行ロールのリンクをクリックします。
    • ロールのページで、「アクセス権限を追加」をクリックし、先ほど作成したMinecraftServerStopPolicyをアタッチします。
    • 初期に付与された広範なポリシー(例: AWSLambdaBasicExecutionRole以外でEC2操作に関わるもの)があれば、デタッチして削除します。

これで、プレイヤーがいなくなったら自動でEC2が停止する、セキュアな自動停止システムが完成です!


2-2. EC2を動かしたいだけの時はCloudWatchをオフにすること

サーバーの設定変更やメンテナンス作業中など、プレイヤーがいない状態でEC2を起動しておきたい場合、上記で設定した自動停止機能が作動してしまい、作業が中断されてしまいます。これを防ぐために、作業中は一時的に CloudWatch アラームを無効化する必要があります。

  1. AWSマネジメントコンソールでCloudWatchサービスに移動します。
  2. 左側のナビゲーションペインで「アラーム」の下の「すべてのアラーム」を選択します。
  3. MinecraftServerEmptyAlarm (アラーム作成時に自分で設定した名前) を見つけて選択します。
  4. アクション」ドロップダウンメニューから「アラームを無効にする」を選択します。
    これで、アラームの状態が「ALARM」になっても、EC2インスタンスの停止アクションはトリガーされなくなります。

重要: 作業が完了したら、忘れずに同じ手順で「アラームを有効にする」に戻してください。


まとめ

今回の続編では、Minecraftサーバーをさらに便利でコスト効率よく運用するための重要なステップを学びました。Systemdによる自動起動、そしてCloudWatchとLambdaを組み合わせた自動停止機能は、サーバー管理の手間を大幅に削減してくれます。

AWSの学習は一歩ずつですが、GeminiのようなAIアシスタントの助けを借りることで、私のような初心者でも複雑な設定に挑戦し、成功体験を積むことができました。

AWSでのMinecraftサーバー運用は、クラウドの基礎を学ぶ素晴らしいサンドボックスになります。ぜひあなたも、AIアシスタントと一緒にこの挑戦を楽しんでみてください!

Discussion