
前言
对于许多技术爱好者和玩家而言,拥有一个私人Minecraft服务器是件极具吸引力的事。它不仅是与朋友共建数字世界的乐园,也是一个绝佳的技术实践平台。在寻求低成本解决方案时,各大云服务商提供的“云原生开发环境”成为了一个理想的备选项。这些平台通常提供配置尚可的容器化Linux环境,对于运行一个中小型MC服务器来说绰绰有余。
我的探索也由此开始。起初,一切都非常顺利:注册账户,选择环境,上传服务端文件,执行启动命令。几分钟内,一个崭新的Minecraft世界便在云端诞生。然而,喜悦并没有持续太久。次日我便发现,辛苦搭建的服务器已然消失无踪。
md这服务器比我养的电子宠物死得还快。
经过一番仔细研究,我终于在平台的文档中找到了原因——一套严格的资源回收机制:
- 闲置回收:环境创建后,若10分钟内没有活跃的VSCode会话连接,系统将自动回收。
- 会话超时:用户断开连接后,闲置超过10分钟,环境同样会被回收。
- 生命周期上限:单个环境的最长连续运行时间不能超过16小时。
- 周期性强制回收:为优化资源调度,运行超过8小时的环境会在凌晨4点至6点被强制回收。
这些规则使得常规的部署方式变得毫无意义。一个频繁下线、数据无法保存的服务器,几乎不具备任何实用价值。挑战也因此变得明确:能否在不违反平台核心规则的前提下,通过技术手段,实现服务器的稳定、持续运行?
破局思路:自动化对抗“熵增”
直接对抗平台的回收机制是行不通的,但规则本身也揭示了其运行逻辑。系统的“回收”行为是基于“闲置”状态的判断。如果我们能通过程序模拟持续的“活跃”状态,并设计一套机制应对必然到来的周期性重启,问题便迎刃而解。
由此,我构思了一个自动化运维方案,其核心由两部分构成: 由于cnb具有openapi调用方式
-
外部编排器 (External Orchestrator):
- 角色:一个独立的、始终在线的低配服务器(例如廉价VPS或树莓派)。
- 任务:作为总调度中心,负责在每天固定时间(如上午9点),通过调用平台的API,自动创建或唤醒MC服务器环境。
-
内部保活与数据同步脚本 (Internal Keep-Alive & Sync Scripts):
- 角色:运行在CNB环境内部的一系列自动化脚本。
- 任务:
- 心跳维持:模拟用户活动,防止环境因“闲置”而被回收。
- 数据持久化:在环境被销毁前,将世界存档等关键数据备份至外部持久化存储;在环境重启后,再自动恢复这些数据。
整个工作流形成了一个完美的闭环:每日由外部编排器“重生”服务器,再由内部脚本维持其“生命体征”并确保“记忆”得以延续,周而复始。
自动化核心:构建外部“编排器”
实现外部编排器的关键在于与CNB平台的API进行交互。通过阅读API文档,我锁定了三个核心接口:
- 启动接口 (
POST /.../workspace/start
): 作用是触发一个开发环境的启动流程。这是每日“唤醒”操作的起点。 - 列表接口 (
GET /workspace/list
): 用于查询用户下所有环境的状态。通过它,我们可以筛选出正在运行的环境,并获取其唯一标识符sn
。 - 详情接口 (
GET /.../workspace/detail/{sn}
): 利用sn
,获取环境的详细连接信息,其中包含了我们需要的公网地址(IP或域名)。
基于这三个接口,我编写了以下的Bash脚本,配合cron
定时任务,即可实现服务器的每日自动启动。
start_cnb_mc_server.sh
(编排器脚本)
#!/bin/bash# CNB Minecraft Server Orchestrator Script# 负责每日定时启动服务器,并广播其最新地址
# --- 配置区 ---API_BASE_URL="https://example.com" # 平台API地址PRIVATE_TOKEN="YOUR_PRIVATE_TOKEN" # 个人访问令牌,请妥善保管REPO_PATH="your-group%2Fminecraft-server-repo" # 项目仓库路径 (URL编码)GIT_BRANCH="main"DISCORD_WEBHOOK_URL="YOUR_DISCORD_WEBHOOK_URL" # 用于发送开服通知
# --- 日志函数 ---log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] - $1"}
# 1. 调用API,请求启动环境log "Step 1: Requesting to start the CNB workspace..."curl -s -X POST "${API_BASE_URL}/${REPO_PATH}/-/workspace/start" \ --header "Authorization: Bearer ${PRIVATE_TOKEN}" \ --header "Content-Type: application/json" \ --data "{\"branch\": \"${GIT_BRANCH}\"}"
# 2. 等待环境初始化log "Step 2: Waiting 60 seconds for workspace initialization..."sleep 60
# 3. 获取正在运行环境的SN标识符log "Step 3: Fetching the SN of the running workspace..."SN=$(curl -s "${API_BASE_URL}/workspace/list?status=running" \ --header "Authorization: Bearer ${PRIVATE_TOKEN}" | \ jq -r '.list[0].sn') # 简化处理,取列表的第一个
if [[ -z "$SN" ]]; then log "Error: Could not find a running workspace SN. Aborting." exit 1filog "Success: Found running workspace SN: ${SN}"
# 4. 根据SN获取详细连接信息log "Step 4: Fetching workspace details..."DETAIL_RESPONSE=$(curl -s "${API_BASE_URL}/${REPO_PATH}/-/workspace/detail/${SN}" \ --header "Authorization: Bearer ${PRIVATE_TOKEN}")VSCODE_URL=$(echo "$DETAIL_RESPONSE" | jq -r '.vscode')
# 5. 解析出服务器公网地址log "Step 5: Parsing the server host address..."SERVER_HOST=$(echo "$VSCODE_URL" | grep -oP 'ssh-remote\+\w+@\K[^?]+')SERVER_ADDRESS="${SERVER_HOST}:25565"log "Success: Server address for today is: ${SERVER_ADDRESS}"
# 6. 通过Webhook发送通知log "Step 6: Sending notification..."JSON_PAYLOAD="{\"content\": \"Minecraft服务器已启动!今日地址为:\`${SERVER_ADDRESS}\`\"}"curl -X POST -H "Content-Type: application/json" -d "$JSON_PAYLOAD" "$DISCORD_WEBHOOK_URL"
log "Orchestration complete."
将此脚本配置到crontab
中,即可实现每日无人值守的自动唤醒。
内部心跳:维持环境的“生命体征”
为防止服务器在日间因无VSCode连接而“休眠”,我们需要一个内部的心跳脚本。其原理是周期性地创造系统活动,以重置平台的闲置计时器。一个简单有效的方案是利用SSH客户端连接localhost
,模拟一次新的终端会话。
keep_alive.sh
(心跳维持脚本)
#!/bin/bash# 该脚本在后台运行,通过周期性创建SSH会话来维持环境活跃
INTERVAL=180 # 180秒(3分钟)
while true; do echo "[Keep-Alive] - $(date): Sending heartbeat to prevent idle shutdown." # 通过SSH连接localhost制造系统活动 ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 localhost 'echo "Heartbeat session successful"'
sleep $INTERVALdone
这个脚本将在环境启动后,由主启动脚本在后台运行,为服务器的持续在线提供保障。
关键挑战:解决数据的“无状态”问题
CNB环境的“无状态”(Stateless)特性是本项目最大的挑战。每次重启都意味着环境被重置,若不处理,所有游戏进度都将丢失。
最初我考虑使用Git来同步世界存档,但很快发现此路不通。MC的地图文件体积庞大且更新频繁,使用Git进行版本控制会迅速导致仓库臃肿,同步效率低下。
最终,我选择了更为健壮的方案:Rclone + 外部对象存储(S3兼容)。Rclone是一款强大的云存储管理工具,能轻松实现本地文件与云端存储的同步。
- 数据恢复:在服务器每日启动时,首先执行
rclone sync
命令,将云端存储的最新存档完整地同步到本地。 - 数据备份:在服务器内部设置一个定时任务,周期性地(例如每30分钟)执行
rclone sync
,将本地的游戏存档增量同步到云端。
这套方案不仅解决了数据持久化的问题,而且将数据丢失的风险控制在了两次备份的间隔之内,实现了成本和可靠性之间的良好平衡。
整合与部署:定义最终启动流程
最后,需要一个主启动脚本来协调内部的所有任务。这个脚本将作为CNB环境的启动入口(Entrypoint)。
将CNB项目的启动命令配置为执行此脚本,整个自动化部署便宣告完成。
总结与注意事项
通过结合外部API调度和内部自动化脚本,我们成功地将一个具有严格生命周期限制的免费开发环境,改造为了一个能近似7x24小时服务的“半永久”Minecraft服务器。这个项目不仅实现了零成本的游戏服务器部署,更是一次关于自动化运维、IaC(基础设施即代码)和逆向思考的有趣实践。看看我的使用量(
官方看不到…官方看不到…(其实话又说回来,这个大部分情况下cpu负载不会很高的)