CDKでMinecraftサーバを作ってみた
目次
はじめに
こんにちは、スカイアーチHRソリューションズのsugawaraです。
先日公開されたAWS公式ブログにて、「Amazon EC2 に Java 版 Minecraft サーバーをセットアップ」という記事を見つけました。自分は普段あまりゲームをやらないため、自前のサーバでプレイすることがゲームができるとは知りませんでした。いい機会だと思ったので、実際に構築してみました。
※実際にプレイするにはライセンスの購入が必要なため、上記の記事と同様にサーバのセットアップまでとなります(サーバを用意すれば無料でできると勘違いしていました。。。)
なお、マネジメントコンソールでの手動構築だと、ブログ記事と同じになってしまうため、今回はCDK(TypeScript)で書いてみました。
環境
WSL2
CDK 2.121.1
Node.js 18.18.1
流れ
まずWSL上に作業フォルダMinecaftを作成し、そのディレクトリにてCDKの準備をします。
$ mkdir Minecraft
$ cd Minecraft
$ cdk init app --language typescript
作成されたフォルダは下記のような構成になっています。
├── bin
│ └── minecraft.ts // ここにenvを定義
├── cdk.json
├── jest.config.js
├── lib
│ └── minecraft-stack.ts // ここにAWSリソースを定義
├── package.json
├── package-lock.json
├── README.md
├── test
│ └── minecraft.test.ts
└── tsconfig.json
bin/minecraft.tsファイルにて、デプロイするアカウントとリージョンを指定します。今回はGithubなどにはpushしないため、シンプルにハードコーディングします。
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { MinecraftStack } from '../lib/minecraft-stack';
const app = new cdk.App();
new MinecraftStack(app, 'MinecraftStack', {
env: {
account: 'YOUR_AWS_ACCOUNT',
region: 'ap-northeast-1'
}
});
なお、ハードコーディングしないデプロイ先の指定方法は下記の記事にまとめていますのでご参照ください。
そしてlib/minecraft-stack.tsは下記のように定義します。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as fs from 'fs';
export class MinecraftStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// デフォルトVPCの取得
const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
isDefault: true,
});
// セキュリティグループの作成
const securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
vpc,
securityGroupName: 'Minecraft Security Group',
description: 'Security group with ports open for Minecraft Server & SSH.',
allowAllOutbound: true
});
// SSHとカスタムポートのルールを追加(東京リージョンを想定)
securityGroup.addIngressRule(ec2.Peer.ipv4('3.112.23.0/29'), ec2.Port.tcp(22), 'ap-northeast-1 EC2 Instance Connect');
securityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(25565), 'Allow Minecraft connections');
// キーペアの作成
const keyPair = new ec2.KeyPair(this, 'KeyPair', {
keyPairName: 'MinecraftKey',
type: ec2.KeyPairType.RSA
})
// ユーザデータファイルの読み込み
const userDataScript = fs.readFileSync('./lib/userdata.sh', 'utf8');
// EC2インスタンスを作成
const instance = new ec2.Instance(this, 'Instance', {
vpc,
vpcSubnets: {
subnetType: ec2.SubnetType.PUBLIC
},
instanceType: new ec2.InstanceType('t4g.small'),
machineImage: new ec2.AmazonLinuxImage({
generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2023,
cpuType: ec2.AmazonLinuxCpuType.ARM_64
}),
securityGroup: securityGroup,
keyPair: keyPair,
userData: ec2.UserData.custom(userDataScript),
});
// EIPをインスタンスに割り当て
const eip = new ec2.CfnEIP(this, 'EIP', {
instanceId: instance.instanceId,
});
}
}
また、lib配下にはuserdata.shを追加で作成します。内容はブログ記事からそのまま転載しております。
#!/bin/bash
# *** INSERT SERVER DOWNLOAD URL BELOW ***
# Do not add any spaces between your link and the "=", otherwise it won't work. EG: MINECRAFTSERVERURL=https://urlexample
MINECRAFTSERVERURL=https://piston-data.mojang.com/v1/objects/8dd1a28015f51b1803213892b50b7b4fc76e594d/server.jar
# Download Java
sudo yum install -y java-17-amazon-corretto-headless
# Install MC Java server in a directory we create
adduser minecraft
mkdir /opt/minecraft/
mkdir /opt/minecraft/server/
cd /opt/minecraft/server
# Download server jar file from Minecraft official website
wget $MINECRAFTSERVERURL
# Generate Minecraft server files and create script
chown -R minecraft:minecraft /opt/minecraft/
java -Xmx1300M -Xms1300M -jar server.jar nogui
sleep 40
sed -i 's/false/true/p' eula.txt
touch start
printf '#!/bin/bash\njava -Xmx1300M -Xms1300M -jar server.jar nogui\n' >> start
chmod +x start
sleep 1
touch stop
printf '#!/bin/bash\nkill -9 $(ps -ef | pgrep -f "java")' >> stop
chmod +x stop
sleep 1
# Create SystemD Script to run Minecraft server jar on reboot
cd /etc/systemd/system/
touch minecraft.service
printf '[Unit]\nDescription=Minecraft Server on start up\nWants=network-online.target\n[Service]\nUser=minecraft\nWorkingDirectory=/opt/minecraft/server\nExecStart=/opt/minecraft/server/start\nStandardInput=null\n[Install]\nWantedBy=multi-user.target' >> minecraft.service
sudo systemctl daemon-reload
sudo systemctl enable minecraft.service
sudo systemctl start minecraft.service
# End script
CDKコードが完成したら、minecraftディレクトリにて下記のコマンドを実行します。
$ cdk diff
$ cdk deploy
問題なくデプロイされたら、マネジメントコンソール上でインスタンスを確認します。
次に、作成されたEC2インスタンスへ、EC2 Instance Connectを使って接続します。
下記の画面が出ればリソースが正しく作成されています。
最後に、ブログ記事にあるコマンドでサーバの停止と起動を実行して、オペレータを追加してみます。
まずはサーバの停止と起動です。起動には多少時間がかかります。
[ec2-user@ip-172-31-44-196 ~]$ cd /opt/minecraft/server/
[ec2-user@ip-172-31-44-196 server]$ sudo ./stop
[ec2-user@ip-172-31-44-196 server]$ sudo ./start
Starting net.minecraft.server.Main
[23:15:59] [ServerMain/INFO]: Environment: Environment[sessionHost=https://sessionserver.mojang.com, servicesHost=https://api.minecraftservices.com, name=PROD]
[23:16:01] [ServerMain/INFO]: Loaded 7 recipes
[23:16:02] [ServerMain/INFO]: Loaded 1271 advancements
[23:16:03] [Server thread/INFO]: Starting minecraft server version 1.20.4
[23:16:03] [Server thread/INFO]: Loading properties
[23:16:03] [Server thread/INFO]: Default game type: SURVIVAL
[23:16:03] [Server thread/INFO]: Generating keypair
[23:16:03] [Server thread/INFO]: Starting Minecraft server on *:25565
[23:16:03] [Server thread/INFO]: Using epoll channel type
[23:16:03] [Server thread/INFO]: Preparing level "world"
[23:16:11] [Server thread/INFO]: Preparing start region for dimension minecraft:overworld
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:16] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:17] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:17] [Worker-Main-1/INFO]: Preparing spawn area: 0%
[23:16:18] [Server thread/INFO]: Time elapsed: 6650 ms
[23:16:18] [Server thread/INFO]: Done (14.870s)! For help, type "help"
Doneが表示されたら、Minecraft コマンドが実行できるようになりますので、プレイヤーをオペレータとして追加します。
$ op sugawara
以上でブログ記事の内容を終わっていますが、ライセンスをお持ちの方はJava版のMinecraftを起動し、[サーバを追加]を選択することで、構築したEC2インスタンスを利用したMinecraftがプレイできるようです。今回はあくまでサーバのセットアップまでとなります。
最後に後片付けとして、下記のコマンドもしくはCloudFormationの画面からスタックの削除をしてください。
$ cdk destroy
おわりに
今回はブログ記事の通り、MinecraftサーバのセットアップまでをCDK化してみました。
このブログのためだけにライセンス購入はしなかったため、実際にMinecraftの表示はしていません。興味がある人はライセンス購入をした上でやってみてください!