我在 AWS Fargate 上构建了按需 Minecraft 主机,以停止支付月费
Source: Dev.to
请提供您希望翻译的正文内容,我将为您翻译成简体中文并保持原有的格式、Markdown 语法以及技术术语不变。
Introduction
大多数 Minecraft 服务器托管商都有一个根本缺陷:他们对一台空置 90 % 时间的服务器收取月度订阅费用。
我意识到我每月支付 €20 / month,而我的孩子和我只在大多数周末玩几个小时。这就是 ERGamesPRO 的灵感——一个基于 AWS 的按需 Minecraft 托管平台,目标很简单:
如果没有人在玩,我就不应该付费。
(所谓“无服务器”,指的是没有一直开启的计算资源:没有需要打补丁的 EC2 集群,CPU/RAM 的计费在服务器关闭时停止。存储/任务控制的费用仍然存在,但相较于 24/7 计算来说很小。)
架构:为何选择 Fargate?
我选择 AWS Fargate (ECS) 来实现 scale‑to‑zero(零规模)行为,而无需管理实例。
- Start – 在仪表板上点击 “Start” 即会为该特定服务器创建一个全新的 Fargate 任务。
- Stop – 点击 “Stop” 会终止任务,计算费用降至零。
高层架构
| 层级 | AWS 服务 |
|---|---|
| 计算 | AWS Fargate (ECS) – 基于 ARM64(Graviton)的 Docker 容器 |
| 存储 | Amazon EFS – 持久化世界数据 |
| 编排/计费 | AWS Lambda + EventBridge |
| 数据库 | DynamoDB – 用户配置文件和服务器元数据 |
| 身份验证 | Amazon Cognito |
| DNS | Amazon Route 53 – 每个服务器的主机名 |
Stable Join Address (No Load Balancer)
我没有使用 NLB/ALB 或 Cloud Map。ECS 任务运行在 public subnets 并获取公共 IP。
当服务器启动时,控制平面会自动更新位于域 ergamespro.click 下的 Route 53 记录,将自定义主机名(例如 myserver.ergamespro.click)映射到该任务的公共 IP。
- TTL: 60 秒
- Connection method: 玩家始终通过主机名进行连接,即使底层 IP 在重启后可能会变化。
“Scale to Zero”问题
按需主机最难的部分是何时安全地关闭灯光。
我使用 AWS Lambda + EventBridge 构建了一个调和循环:
- Watchdog Lambda 每隔几分钟运行一次。
- 它使用基于 TCP 的 Minecraft Server List Ping 对每个运行中的服务器进行 ping,以读取实时玩家数量。
- 如果玩家数量 > 0 → 保持服务器运行。
- 如果玩家数量 = 0 且持续 10 分钟 → 触发关机事件。
如果 ping 失败或超时,watchdog 失效打开 并重试,以避免误关机。当关机事件触发时,Fargate 任务停止,计算费用立即结束。对于空闲时间较多的使用场景(例如周末会话),相比 24/7 托管,可将成本降低 约 70–80 %。
途中遇到的挑战
1️⃣ 500 资源限制(CDK)
- 问题:使用 AWS CDK(Python)时,我触及了 CloudFormation 的硬性限制——每个堆栈最多 500 个资源。
- 解决方案:将单体拆分为 七个独立堆栈(Foundation、Data、Compute 等)。部署变得更快、更安全,也更易于理解。
2️⃣ 启动时间与金色镜像
- 问题:Fargate 并非瞬时启动。运行时拉取约 1 GB 的镜像会导致令人痛苦的冷启动延迟。
- 解决方案:构建一个流水线,为每个 Minecraft 版本(Vanilla、Paper、Forge)预先构建“金色镜像”,目标平台为 ARM64(Graviton)。
- Graviton 更便宜。
- 对于典型的基于 Java 的 Minecraft 工作负载,它的表现非常出色。
注意:拥有 100 + 插件的高度模组化服务器可能更适合时钟频率更高的 x86,但对于 Vanilla 和轻量模组包,ARM 是极佳选择。
3️⃣ 使用 EFS 的持久存储
- 问题:Fargate 任务是短暂的;容器文件系统在任务停止时会消失。
- 解决方案:使用 Amazon EFS 并配合专用 访问点。每个服务器获得一个独立目录,挂载到
/data,这样世界、配置和备份在重启之间得以持久化。- EFS 默认采用 突发吞吐量(可配置为弹性或预置)。
- 在小规模时突发模式表现极佳;预置吞吐量成本可能过高,因此默认使用突发模式。
4️⃣ 在短暂环境中的文件访问(SFTP)
- 问题:在 VPS 上你可以 SSH 并上传模组。而在 Fargate 中,当服务器停止时根本没有“可 SSH 的机器”。
- 解决方案:Sidecar 模式——当用户启动服务器时,同时启动 Minecraft 容器和一个 SFTP sidecar。
| 功能 | 细节 |
|---|---|
| 卷 | 两个容器挂载同一 EFS 卷 |
| 服务 | 锁定、chroot 的 SFTP 服务器 |
| 凭证 | 动态生成,短期有效 |
| 端点 | 同一 DNS 名称,固定端口 2222 |
| 生命周期 | 任务停止时即消失 |
由于客户端 IP 不可预测,SFTP 并未基于源 IP 白名单。访问通过短期凭证和锁定的 SFTP 配置进行控制,既保持了文件管理的便利,又不破坏按需模型。
5️⃣ 实时控制台流式传输
- 问题:我想在网页仪表盘中实时查看日志。Kinesis Data Streams 对于刚起步的项目来说成本太高。
- 解决方案:CloudWatch Logs + WebSockets
- Fargate 将日志流入 CloudWatch Logs。
- Lambda 轮询新日志条目。
- 通过 API Gateway WebSocket 连接将更新推送到前端。
延迟约为 1–2 秒——在大幅降低成本的前提下,这一延迟是可以接受的。
今日平台
结果感觉像是高级托管,但行为却像云原生应用:
- 启动时间:~50–90 s 从点击到轻量服务器可加入;~3–4 min 对于重度模组包。
- 隔离性:每个服务器在其自己的 Fargate 任务中运行(无噪声邻居)。
- 费用模型:仅为服务器运行的时间付费。
接下来是什么?
- 多区域支持 – 部署更靠近玩家。
- 每个服务器多个世界 – 在 EFS 上存储多个世界目录,让用户选择要启动的世界。
文档结束。
ETA 已上线 ergames.pro.
我还有一些邀请代码,供想要对架构进行压力测试的开发者和玩家使用——欢迎提供直接反馈。
如果想了解 AWS CDK 结构、Lambda 逻辑或 Fargate 调优的细节,请在评论中提问。
