前回の記事からだいぶ期間が空いたけど・・・
Minecraft統合版サーバをAWS ECS環境に実装したときの話。
以前は概要編で、今回は構築編。
実際にAWSで操作する手順を書きます。
前回の話は↓
その0:必要なAWSリソース
構築の前に必要なAWSリソースを説明。
構成図を再掲。
- Route53
- CloudWatch
- SNS
- Lambda
- ECS/Fargate
- EFS
- Backup
- S3(オプション)
- DataSync(オプション)
サーバの構成はECS/Fargate、永続ストレージにEFS、
あとはサーバ起動/停止にLambda、
起動トリガー用にRoute53、Cloudwatch、起動停止の通知にSNS。
S3とDatasyncはオプションなので必須じゃない。
その1:VPC作成
ECS/EFSを配置するためにVPCを作成する。
デフォルトVPCがあるのなら、それでもOK。
ここでは適当に以下のように。
CIDR:適当
パブリックサブネット:2つ
プライベートサブネット:2つ
NATゲートウェイ:無し
EFSもパブリックサブネットにおいてもいいのなら、プライベートサブネットは不要かな。
個人利用ならAZも1つでいいんじゃないかと。
その2:EFS作成
データを置くためのストレージ(EFS)を作成。
EFSにて「ファイルシステムの作成」をクリック。
名前:適当
ストレージクラスもここでは「標準」にしているけど、さらに低コストにするのなら「1ゾーン」でもいいかも。
他はそのままで「次へ」をクリック。
マウントターゲットをどのサブネットに置くかを指定。
ここではプライベートにしている。
あ、セキュリティグループを作成してないのなら、あとでNFSを許可するセキュリティグループに変更w
ファイルシステムポリシーはそのままで「次へ」をクリック。
確認して作成。
ファイルシステム作成。
続けてアクセスポイントを作成する。
「アクセスポイント」に移動して、「アクセスポイントを作成」をクリック。
ファイルシステムは先ほど作成したファイルシステム、
名前は適当、ルートディレクトリは「/minecraft」にする。
POSIXユーザーID・グループIDは「1000」を指定する。
次の所有者ユーザーID・グループIDも「1000」、
アクセス許可は「0755」を指定して「アクセスポイントを作成」をクリック。
アクセスポイント作成完了。
先ほどのファイルシステム作成でEFSのセキュリティグループをデフォルト(any/any)にしてしまったので、
新たにEFS用のセキュリティグループを作成。
VPCからセキュリティグループ作成画面に移り、以下のように作成。
タイプ:NFS(2049/tcp)
ソース:最低でもパブリックサブネットを含むように
作成したセキュリティグループに変更する。
EFSのファイルシステム画面に戻って、対象のファイルシステムを選択して、「詳細の表示」をクリック。
「ネットワーク」タブの「管理」をクリック。
セキュリティグループがデフォルトになっているのを・・・
作成したセキュリティグループに変更する。
最後に作成したアクセスポイントARNとファイルシステムIDを控える。
次のIAMポリシー作成に必要なため。
その3:Route53設定
DNSの設定。
まずはパブリックホストゾーンを作成する。
作成したゾーンのネームサーバをドメインのレジストラに登録する。
次に「クエリログの設定」をクリックする。
ロググループを新規作成する。
最後に作成したホストゾーンIDを控える。
その4:SNS設定
SNSの設定。
まずはSNSトピックを作成する。
名前は適当w
次にサブスクリプション(SNSの通知先)を作成する。
トピックARNは先ほど作成したSNSトピック。
プロトコルはEメールもしくはSMSかな。
その4:IAMポリシー、IAMロール設定
ECSタスクが実行するためのIAMポリシー、IAMロールを作成する。
まずはIAMポリシー。
ポリシー名:efs.rw.minecraft-data
EFSのファイルシステムIDとアクセスポイントのARNをここで入力。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "elasticfilesystem:ClientMount", "elasticfilesystem:ClientWrite", "elasticfilesystem:DescribeFileSystems" ], "Resource": "arn:aws:elasticfilesystem:ap-northeast-3:zzzzzzzzzzzz:file-system/fs-xxxxxxxx", "Condition": { "StringEquals": { "elasticfilesystem:AccessPointArn": "arn:aws:elasticfilesystem:ap-northeast-3:zzzzzzzzzzzz:access-point/fsap-xxxxxxxxxxxxxxxxx" } } } ] }
ポリシー名:ecs.rw.minecraft-service
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["ecs:*"], "Resource": [ "arn:aws:ecs:ap-northeast-3:zzzzzzzzzzzz:service/minecraft/minecraft-server", "arn:aws:ecs:ap-northeast-3:zzzzzzzzzzzz:task/minecraft/*" ] }, { "Effect": "Allow", "Action": ["ec2:DescribeNetworkInterfaces"], "Resource": ["*"] } ] }
ポリシー名:route53.rw.yourdomainname
ここでは作成したRoute53のホストゾーンIDを記入。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "route53:GetHostedZone", "route53:ChangeResourceRecordSets", "route53:ListResourceRecordSets" ], "Resource": "arn:aws:route53:::hostedzone/XXXXXXXXXXXXXXXXXXXXX" }, { "Effect": "Allow", "Action": ["route53:ListHostedZones"], "Resource": "*" } ] }
ポリシー名:sns.publish.minecraft-notifications
ここでは作成したSNSトピックのARNを記入。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sns:Publish", "Resource": "arn:aws:sns:ap-northeast-3:zzzzzzzzzzzz:minecraft-notifications" } ] }
次にIAMロールを作成する。
信頼されたエンティティは「Elastic Container Service Task」を選ぶ。
ポリシーは先ほど作成した4つを設定。
名前はなんでもいいけど、「ecs.task.minecraft-server」とした。
その5:ECSクラスター作成
次にコンテナを動かすための基盤、ECSクラスターを作る。
ECSより「今すぐ始める」をクリック。
「クラスターの作成」をクリック。
クラスター名:minecraft
VPC:その1で作成したVPC
サブネット:パブリックサブネット2つ
で、作成する。
作成完了。
その6:タスク設定
コンテナを動かす実行環境(タスク)の設定。
「タスク定義」をクリックし、「新しいタスク定義の作成」をクリックする。
タスク定義ファミリー:minecraft-server
コンテナ名:minecraft-server
イメージURI:itgz/minecraft-bedrock-server
コンテナポート:19132
プロトコル:UDP
キー:EULA
値:TRUE
OS/アーキテクチャ:Linux/X86_64
CPU:1vCPU
メモリ:6GB
タスクロール:ecs.task.minecraft-server
タスク実行ロール:ecsTaskExecutionRole
次にボリュームの設定。
ボリュームタイプ:EFS
ボリューム名:data
ファイルシステムID:EFSで作成したファイルシステム
ルートディレクトリ:/
アクセスポイントID:-(何も指定しない)
コンテナマウントポイント:/data
ログ収集は任意だけど、CloudWatchにしておくとコンテナのログが表示される。
同じ要領で監視用のコンテナを設定する。
コンテナ名:minecraft-ecsfargate-watchdog
イメージURI:doctorray/minecraft-ecsfargate-watchdog
環境変数:
CLUSTER:minecraft(ECSクラスタ名)
DNSZONE:XXXXXXXX(Route53のゾーンID)
SERVERNAME:サーバのFQDN名(minecraft.hogehoge.comとか)
SERVICE:minecraft-server(上記で設定したコンテナ名)
SNSTOPIC:XXXXXX(SNSトピックのARN)
次に作成した定義にチェックを入れ、デプロイ→「サービスの作成」をクリックする。
既存のクラスター:minecraft
コンピューティングオプション:キャパシティープロバイダー戦略
キャパシティープロバイダー:FARGATE_SPOT
を選ぶ。
サービス名:minecraft-server
必要なタスク:0
を選ぶ。
VPC:作成したVPC
サブネット:パブリック
セキュリティグループ:19132/UDPを許可
パブリックIP:オン
これでサービスが作成された。
まだこの状態ではコンテナ(=タスク)は起動していない。
その7:Lambda作成
タスクを起動するためのLambda関数を作成する。
この関数はRoute53からイベントをトリガーにしてCloudWatchが起動する関数でもあるから、
バージニア北部リージョンで作成すること。
コードは以下の通り。
import boto3 REGION = 'ap-northeast-3' CLUSTER = 'minecraft' SERVICE = 'minecraft-server' def lambda_handler(event, context): """Updates the desired count for a service.""" ecs = boto3.client('ecs', region_name=REGION) response = ecs.describe_services( cluster=CLUSTER, services=[SERVICE], ) desired = response["services"][0]["desiredCount"] if desired == 0: ecs.update_service( cluster=CLUSTER, service=SERVICE, desiredCount=1, ) print("Updated desiredCount to 1") else: print("desiredCount already at 1")
リージョンとクラスタ名とサービス名を指定するだけ。
ちなみに"if desired == 0"と"desiredCount=1"の数字をそれぞれ逆にすると
サーバを停止する関数になる。
API Gatewayを挟むなり、関数URLを作成して関数化するなりすれば、APIで起動停止ができるようになる。
その8:CloudWatch設定
先ほど作成したLambda関数を実行するためのトリガーを作成する。
つまり、Route53のクエリログが出力されたら、Lambdaを実行するようにする。
バージニア北部のCloudWatchに移動して、Route53のクエリログをチェックする。
アクションから「サブスクリプションフィルター」→「Lambdaサブスクリプションフィルターを作成」をクリックする。
Lambda関数:先ほど作成したLambda関数
サブスクリプションフィルターのパターン:"<サーバのFQDN名>"
サブスクリプションフィルター名:任意
作成後、Lambda関数に戻り、トリガーに「CloudWatch Logs」が追加されていればOK。
その9:動作確認
以上で一通りの設定は完了。
Lambdaを実行するなり、サーバのFQDNにcurl等でアクセスを行ってみる。
すると、ECSサービスのタスクが"実行中"になる。
タスクを確認すると、実行中となっていることがわかる。
ログを確認すると、コンテナが起動していることがわかる。
パブリックIPも割り当てられている。
このパブリックIPはタスクが起動するたびにコロコロ変わるので、
Route53にゾーン登録できるドメインを持っていなければ、ここで逐次IPアドレスを確認する必要がある。
あとはMinecraftのクライアントから接続すればOK。
おまけ:いくらかかった?
10月はこんな感じ。約$6ということで900円くらい。
おそらく数時間程度しか使っていないと思う。
EFSのマウント確認にEC2を立てたりしたので、余計なコストも混じっているかもしれないw
x86ベースになっているのか、OCIのコンテナ環境よりも遥かに快適になった。
起動停止スクリプトをLambdaの関数URLに設定して、
iPhoneのショートカットからcurlするようにすれば
起動に時間がかかるものの普通に遊べるレベル。
AWSクレジットがいくらを登録しているので、多少費用が発生しても問題無し。
今のところは大きな課金も発生しておらず安定して動かしている。
この仕組みを考えた人天才だわ〜。
0 件のコメント:
コメントを投稿