以低成本实现24小时MineCraft服务器

引发因素。因为和朋友一起玩Minecraft的事,我决定准备一个服务器。
我总是被指派去做这个麻烦的工作,而且每个人的登录时间都不一样,还要求我们运行一个全天候的服务器。
偶尔也希望你能给我买下愿望清单上的一两样东西作为礼物。

メインPCでサーバーを構築するとリソースを食いすぎて支障なので、使っていないベアボーンPCをサーバーにすることにしたが、故障していて自宅サーバーは断念。
結局お金を出し合ってVPS借りる話になり、ちょうど私がAWS-SAAの勉強中だったのでAWSで構築することにした。

这次的要求

    1. 可以参加24小时游戏

 

    1. 由于参与人数可能增加,必须具备可扩展性

 

    尽可能地降低成本。

アーキテクチャ在需要进行成本最优化时启动实例,并在游戏活动为0时停止EC2实例。

由于每次启动和停止都需要我在控制台上操作,这很麻烦,所以我使用Lambda的URL函数让参与者自己启动实例。

每次启动时,向Discord发送新的IP地址通知,因为如果在实例停止期间分配弹性IP地址,则会产生费用。

在实例中运行cron来监控参与人数,并在没有人参与时触发关闭脚本。

根据需要手动升级实例类型。

追加功能方案备忘录(折叠)
在关机壳中备份世界数据到S3。
停机时也通知Discord。通过EventBridge->Lambda。
充分利用Spot实例。
AWS.png

有关成本因此,在本次構築階段中,我們以免費方案來組建,所以如果規模較小的話,可以完成一個零元伺服器。
如果伺服器規格不足,則可以進行逐次付費的升級。

环境

EC2 OSAmazon Linux 2023EC2 タイプt4g.small (Arm系)LambdaPython 3.11Tera Term5.0 beta1DiscordStable 235476 (a7cb1d5)MineCraftJAVA版 1.20.2

作業手順假设您对Linux和AWS有一定的了解。
以下内容不会详细描述。

    • Linuxの操作コマンド

 

    AWSサービスの機能説明、料金等

请自行适当命名各种事物,只需您自己理解即可。

创建EC2实例

AMI

 

Amazon Linux 2023 : Arm

 

インスタンスタイプ

 

t4g.small

 

キーペア

 

RSAのpem形式 SSH接続で使用

 

VPC

 

デフォルト

セキュリティグループ
SSH と TCP: 25565 すべて許可
ストレージ
8GB gp3 足りなければ後から足せる

 

创建一个用于附加到Lambda的IAM角色。为了能够从Lambda中操作EC2,需要创建IAM角色。

制定政策

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:DescribeInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*"
        }
    ]
}

ロール作成ユースケースはLambda

使用客户管理筛选并添加之前创建的策略。

创建Lambda函数

运行时

 

Python3.11

 

架构

 

x86_64

 

执行角色

 

之前创建的内容

 

详细设置

 

启用函数URL

认证类型

如果将认证类型设置为NONE,任何人都可以执行Lambda函数,这会降低安全性。
如果设置为AWS_IAM,需要使用AWS-SDK添加签名并发起请求。
考虑到本次需方便地通过浏览器发起请求,因此将设置为NONE。

代码 mǎ)

import boto3
import time
import requests

def lambda_handler(event, context):
    # EC2インスタンスID
    instance_id = 'i-#########'

    # EC2インスタンスを起動するためのパラメータ
    ec2 = boto3.client('ec2')
    response = ec2.start_instances(InstanceIds=[instance_id])

    # EC2インスタンスが起動するのを待つ
    instance_running = False
    while not instance_running:
        instance = ec2.describe_instances(InstanceIds=[instance_id])
        state = instance['Reservations'][0]['Instances'][0]['State']['Name']
        if state == 'running':
            instance_running = True
        else:
            time.sleep(5)

    # EC2インスタンスのパブリックIPアドレスを取得する
    instance = ec2.describe_instances(InstanceIds=[instance_id])
    public_ip = instance['Reservations'][0]['Instances'][0]['PublicIpAddress']
    
    #DiscordにWebhookを送信
    webhook_url = 'https://discord.com/api/webhooks/################'
    data = {
        'content': f'インスタンス【{instance_id}】は起動しました\r{public_ip}'
    }
    requests.post(webhook_url, json=data)
    
    return public_ip

instance_idとwebhook_urlを書き換えて、Deployを忘れずにしてください。

レイヤー追加
因为无法使用requests模块,所以需要添加一个层,即使按照现有代码仍无法执行。

参考

 

arn:aws:lambda:ap-northeast-1:770693421928:layer:Klayers-p311-requests:2

超时为了避免在实例启动等待时发生超时问题,将超时时间延长。
常规设置
超时时间为3分钟。

确认动作ブラウザから関数URLにアクセス
1分くらい待っていると起動したインスタンスのIPアドレスがレスポンスされる。
DiscordにもWebhookが送信される。

インスタンスの中を設定设置一个脚本,在SSH上启动一个实例,并构建和停止Minecraft服务器。

要连接到Amazon Linux 2023时,只能使用Tera Term的5.0 beta1版本才能进行连接。

补充说明
由于TeraTerm的重大5.0版本已经在10月15日发布,所以我们应该使用该版本。
此外,我还了解到从Win10起,cmd默认支持SSH。ユーザー名:ec2-user
パスフレーズ:なし
RSAキーを使う:キーペア作成でダウンロードした.pem

Minecraft服务器设置如果希望使用其他版本,请从下方网站下载链接中替换wget版本1.20.2。

 

#Java17をインストール
sudo yum install java-17-amazon-corretto-headless

#サーバー設置のディレクトリを作成
mkdir minecraft
cd minecraft

#サーバーjar(1.20.2)をダウンロード
wget https://piston-data.mojang.com/v1/objects/5b868151bd02b41319f54c8d4061b8cae84e665c/server.jar

#jarを実行
java -Xmx1G -Xms1G -jar server.jar nogui

#eulaを編集
vim eula.txt

#もう一度実行
java -Xmx1G -Xms1G -jar server.jar nogui

#下のログ表示で起動完了
[Server thread/INFO]: Done (70.809s)! For help, type "help"

如果可以的话,试着在实际的客户端进行连接。
如果可以的话,用stop命令来停止。

通过更改运行jar时的选项数值,可以调整内存分配量(堆大小)。

实例启动时自动启动Minecraft服务器。请参考以下内容,尽量保持相似度高

 

$ sudo vim /etc/systemd/system/minecraft.service

[Unit]
Description=Minecraft Server
After=network-online.target

[Service]
WorkingDirectory=/home/ec2-user/minecraft
User=ec2-user

ExecStart=/bin/bash -c '/bin/screen -DmS minecraft /bin/java -server -Xms1G -Xmx1G -jar ./server.jar nogui'

ExecReload=/bin/screen -p 0 -S minecraft -X eval 'stuff "reload"\\015'

ExecStop=/bin/screen -p 0 -S minecraft -X eval 'stuff "say Server Shutdown. Saving map..."\\015'
ExecStop=/bin/screen -p 0 -S minecraft -X eval 'stuff "save-all"\\015'
ExecStop=/bin/screen -p 0 -S minecraft -X eval 'stuff "stop"\\015'
ExecStop=/bin/sleep 10

Restart=on-failure
RestartSec=60s

[Install]
WantedBy=network-online.target


$ sudo systemctl daemon-reload
$ sudo systemctl enable minecraft

当使用此方法启动实例时,Minecraft服务器将自动启动,并在实例停止时保存世界并正常关闭。

监控登录并自动停止
创建一个cron任务来监视/home/ec2-user/minecraft/logs/latest.log文件,当活跃数为0时自动停止。

考虑要写什么样的代码时,发现有人已经做了同样的事情,于是借鉴了一下。
但是直接复制粘贴也不有趣,所以我尝试了一下将不熟悉的Ruby代码大致转换成Python。

仅提供一个选项,以下是对“参考”的中文本土释义:参考

 

import datetime
import os

file_path='/home/ec2-user/minecraft/logs/latest.log'
f=open(file_path)
in_cnt=0
out_cnt=0
starting=True

#起動後15分はシャットダウンしない
for i, l in enumerate(f.readlines()):
    line = l.strip()
    if i==0:
        hms=line.split()[0][1:-1].split(':')
        before=int(hms[0])*3600+int(hms[1])*60+int(hms[2])
        now=datetime.datetime.now()
        after=now.hour*3600+now.minute*60+now.second
        diff = after - before
        diff+=24*3600 if diff<0
        starting=False if diff >= 15*60
    if 'joined the game' in line:
        in_cnt+=1
    if 'left the game' in line:
        out_cnt+=1

if starting:
    print('server is starting')
elif in_cnt > out_cnt:
    print('someone is login')
else:
    print('shutdown now')
    os.system('sudo shutdown -h now')

注册cron
每10分钟运行一次

sudo yum install cronie -y
sudo systemctl enable crond.service
sudo systemctl start crond.service
sudo crontab -e
*/10 * * * * /usr/bin/python3 /home/ec2-user/ActiveMonitoring.py
sudo systemctl restart cron

个人看法或者印象通过使用AWS,可以考虑和构建各种不同的组合,这一过程非常有趣。
虽然我本想尝试使用更多不同的服务,但出于成本考虑,我只使用了EC2和Lambda这两个服务。

ググるとEC2でマイクラサーバーを立てる人は意外とたくさんいたし、自動化をする人もいて考えることは同じなんだなーと思った。
自分自身、特にコーディング技術力がなくて自動停止の実装が遅れたがRubyをPythonに書き換えるいい経験ができた。

最后
根据使用方式而定,由于AWS的费用以美元计算,当前相对于日元的汇率非常低(149日元),所以在国内的VPS上建立一个24小时运行的服务器可能更简单且更便宜。明年也将开始收费使用IPv4,所以应该学习IPv6。

bannerAds