华为云开放能力闯关挑战 —— 2048 游戏部署全流程
华为云开放能力闯关挑战 —— 2048 游戏部署全流程
活动代码:
open-capability-2026-1024
区域:cn-north-4
日期:2026-10-22
最终积分:3000 分
一、整体流程概览
本次挑战包含两个里程碑:
| 里程碑 | 难度 | 目标 | 积分 |
|---|---|---|---|
| beginner(沙箱部署) | ⭐ | 将作品部署到华为云沙箱,通过 DevBridge 隧道获取公网访问地址 | 1000 分 |
| intermediate(ECS 持久化部署) | ⭐⭐ | 将作品部署到 ECS 服务器,通过 EIP 获取持久公网访问地址 | 2000 分 |
完整流程分为五个阶段:
环境准备 → 2048 游戏开发 → 沙箱部署(beginner)→ ECS 持久化部署(intermediate)→ 资源释放
二、环境准备
2.1 工具清单
| 工具 | 版本 | 用途 |
|---|---|---|
| HuaweiCloud DevKit | v1.1.10 | AI 编码代理工具包,提供 MCP Server |
| KooCLI (hcloud) | v7.3.12 | 华为云命令行工具,调用 OpenAPI |
| Node.js | v20+ | 运行 MCP Client 脚本 |
| Python 3 | 3.11 | 数据处理与 JSON 解析 |
2.2 凭证配置
使用 AK/SK(Access Key / Secret Key)方式认证,通过环境变量传入,避免明文写入配置文件:
# 配置 hcloud 凭证
hcloud cli config set --cli-access-key=HST****2KF --cli-secret-key=**** --cli-region=cn-north-4
# 获取 Project ID
hcloud IAM KeystoneListAuthDomains --cli-region=cn-north-4
# → Project ID: 0eb34d2afb0090132f22c0086aa70c03
2.3 DevKit 安装
DevKit 是华为云为 AI 编码代理提供的工具包,包含 MCP Server,可让 AI 代理安全地操作华为云资源。
# 安装 DevKit(选择安装到所有目标)
npx huaweicloud-devkit@latest install
# 安装 KooCLI
npx huaweicloud-devkit@latest install-cli
# 自检
npx huaweicloud-devkit@latest doctor
安装完成后,DevKit 自动检测到环境中的 9 个安装目标(包括 OpenCode、VS Code 等),全部完成配置。
2.4 MCP 通信架构
DevKit 的沙箱操作能力通过 MCP(Model Context Protocol)Server 暴露。由于运行环境没有原生 MCP 客户端,编写了自定义 MCP Client 脚本通过 JSON-RPC over stdio 与 Server 通信:
┌─────────────┐ JSON-RPC/stdio ┌──────────────────┐
│ MCP Client │ ←─────────────────→ │ DevKit MCP Server│
│ (Node.js) │ │ (mcp-server.mjs) │
└─────────────┘ └──────────────────┘
│
▼
┌──────────────┐
│ 华为云沙箱 │
│ (DevStation) │
└──────────────┘
核心 MCP 工具调用链:
| MCP 工具 | 作用 |
|---|---|
sandbox_check_user |
检查沙箱用户协议签署状态 |
sandbox_connect |
创建并连接沙箱实例 |
sandbox_upload_file |
上传文件到沙箱 |
sandbox_exec |
在沙箱中执行命令 |
三、2048 游戏开发
3.1 设计要求
- 单文件 HTML,CSS 和 JS 全部内联
- 无构建工具依赖,无外部 CDN
- 4×4 网格经典 2048 玩法
- 支持键盘方向键 / WASD 操作
- 支持手机触摸滑动操作
- PC 和移动端响应式适配
- 文件大小控制在 10KB 以内
3.2 实现要点
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2048</title>
<style> /* 内联样式:网格布局、动画、响应式 */ </style>
</head>
<body>
<!-- 游戏界面:分数板 + 4×4 网格 -->
<script> /* 内联脚本:游戏逻辑、键盘/触摸控制 */ </script>
</body>
</html>
核心游戏逻辑:
init():初始化 4×4 矩阵,随机生成两个数字方块move(direction):处理上下左右四个方向的滑动合并merge(row):单行合并算法(相邻相同数字翻倍)spawn():在空白位置随机生成 2 或 4checkGameOver():检测无可移动步骤时游戏结束render():渲染网格,根据数值映射颜色和字号
触摸控制:监听 touchstart / touchend 事件,计算滑动方向(水平/垂直位移 > 阈值),触发对应方向的 move()。
3.3 最终产物
| 属性 | 值 |
|---|---|
| 文件路径 | /root/workspace/index.html |
| 文件大小 | 6810 字节 |
| 代码行数 | 156 行 |
| 外部依赖 | 无 |
四、沙箱部署(beginner 里程碑)
4.1 流程图
sandbox_check_user → sandbox_connect → sandbox_upload_file → 配置 Nginx → DevBridge 隧道 → curl 验证
4.2 详细步骤
步骤 1:检查用户协议
// MCP 调用
sandbox_check_user → { signed: true }
步骤 2:连接沙箱
// MCP 调用,创建 Linux 容器沙箱
sandbox_connect → {
sandbox_id: "136eb6071c4c433dbf5960acb219ce23",
region: "cn-north-4"
}
沙箱启动可能遇到 “No available node pool” 错误,需重试(最多 5 次,每次间隔 10 秒)。
步骤 3:上传游戏文件
// MCP 调用,上传 index.html 到沙箱
sandbox_upload_file({
path: "/workspace/2048/index.html",
content: "<base64 编码的文件内容>"
})
// → MD5 校验通过
步骤 4:配置 Nginx 静态托管
# 在沙箱中执行
sandbox_exec("mkdir -p /workspace/2048")
sandbox_exec("nginx -c /etc/nginx/nginx.conf") # 启动 Nginx 监听 8080
步骤 5:DevBridge 隧道
DevBridge 自动为沙箱服务创建公网隧道,无需额外配置:
沙箱内 8080 端口 → https://fxrmr5b3-8080.devbridge-s2.hwtunnel.com
步骤 6:验证
$ curl -sI https://fxrmr5b3-8080.devbridge-s2.hwtunnel.com
HTTP/1.1 200 OK
Content-Length: 6810
Content-Type: text/html
✅ HTTP 200,Content-Length 6810 与源文件完全匹配。
4.3 提交闯关
curl -X POST \
"https://open-dataset.huaweicloud.com/api/v1/hdopenservice/agent/submit-activity-work" \
-H "X-HW-AK: $AK" -H "X-HW-SK: $SK" \
-H "X-HW-PROJECT-ID: $PROJECT_ID" -H "X-HW-REGION: cn-north-4" \
-d '{
"activity_code": "open-capability-2026-1024",
"milestone": "beginner",
"work_link": "https://fxrmr5b3-8080.devbridge-s2.hwtunnel.com",
"summary": "2048 单文件HTML小游戏,纯CSS/JS内联,适配PC和移动端"
}'
# → {"message":"作品提交成功","code":"success"}
4.4 结果
| 项目 | 值 |
|---|---|
| 公网地址 | https://fxrmr5b3-8080.devbridge-s2.hwtunnel.com |
| 有效期 | 72 小时 |
| HTTP 状态 | 200 OK |
| Content-Length | 6810 |
| 积分 | +1000 分 |
五、ECS 持久化部署(intermediate 里程碑)
5.1 架构图
┌─────────────────────────────────┐
│ 华为云 cn-north-4a │
│ │
用户 ──── 公网 ────→ │ EIP (1.94.230.36) │
│ │ │
│ ▼ │
│ ECS (s6.medium.2) │
│ Rocky Linux 9.8 │
│ Nginx 1.20.1 │
│ /usr/share/nginx/html/ │
│ hc-activity/index.html │
│ │ │
│ ▼ │
│ VPC test001-vpc │
│ 子网 subnet-test001 │
│ 安全组 sg-2048-ecs │
└─────────────────────────────────┘
5.2 资源规划
复用已有资源
| 资源 | ID | 说明 |
|---|---|---|
| VPC | 2371a903-cb0d-4e46-a868-a7d1606909e6 |
test001-vpc,CIDR 10.13.0.0/16 |
| 子网 | bcfd1a86-8c18-470d-a995-8939a0cfdf03 |
subnet-test001,CIDR 10.13.0.0/24 |
新建资源
| 资源 | 规格 | 说明 |
|---|---|---|
| 安全组 | sg-2048-ecs | SSH 22 仅本机出口 IP,HTTP 80 放通 0.0.0.0/0 |
| ECS | s6.medium.2 (1vCPU/2GB) | Rocky Linux 9.8,按量付费 |
| 系统盘 | 40GB SAS | SAS 类型优先于 SATA(SATA 常售罄) |
| EIP | 5Mbps 5_bgp | 按带宽计费,动态 BGP |
选型依据
- Flavor:s6.medium.2(1vCPU/2GB),通用型 s6 规格,按量付费 ¥0.34/h
- 镜像:Rocky Linux 9.8 64bit(
dd7fba37-0ce2-465b-bae3-73319fcb64f0),yum/dnf 系,cloud-init 原生支持 - 磁盘:SAS 类型(高 IO),SATA 在部分 AZ 常售罄
- AZ:cn-north-4a,已确认可用
5.3 安全组配置
入站规则:
规则 1:TCP 22 ← 114.116.242.127/32 (SSH,仅本机出口 IP,用于调试)
规则 2:TCP 80 ← 0.0.0.0/0 (HTTP,全放通,供公网访问)
出站规则:
默认允许全部出站(安装软件包需要)
安全说明:SSH 仅放通本机出口 IP,不暴露到公网。HTTP 80 端口全放通是静态站点的常规做法,Nginx 仅提供只读静态文件,无注入风险。
5.4 Cloud-Init 自动化
ECS 创建时通过 user_data 传入 cloud-init 脚本,一次性完成所有配置,无需手动 SSH 登录:
#!/bin/bash
# 1. 设置 root 密码
echo 'root:Huawei@2048!' | chpasswd
# 2. 安装 Nginx
dnf install -y nginx
# 3. 创建目录并写入游戏文件
mkdir -p /usr/share/nginx/html/hc-activity
echo '<base64>' | base64 -d > /usr/share/nginx/html/hc-activity/index.html
# 4. 配置 Nginx
cat > /etc/nginx/conf.d/hc-activity.conf << 'EOF'
server {
listen 80;
server_name _;
location /hc-activity/ {
alias /usr/share/nginx/html/hc-activity/;
index index.html;
}
}
EOF
# 5. 启动 Nginx
systemctl enable nginx
systemctl start nginx
user_data 编码:整个脚本 Base64 编码后约 13KB,在 ECS user_data 32KB 限制内。index.html 本身也以 Base64 内嵌在脚本中,避免依赖外部下载。
5.5 ECS 创建命令
hcloud ECS CreateServers --cli-region=cn-north-4 \
--X-Client-Token="<UUID>" \
--server.flavorRef=s6.medium.2 \
--server.imageRef=dd7fba37-0ce2-465b-bae3-73319fcb64f0 \
--server.name=ecs-2048 \
--server.root_volume.volumetype=SAS \
--server.root_volume.size=40 \
--server.vpcid=2371a903-cb0d-4e46-a868-a7d1606909e6 \
--server.nics.1.subnet_id=bcfd1a86-8c18-470d-a995-8939a0cfdf03 \
--server.security_groups.1.id=744fc2f2-9725-4147-a7e9-648f5c33a8c1 \
--server.adminPass='Huawei@2048!' \
--server.availability_zone=cn-north-4a \
--server.publicip.eip.iptype=5_bgp \
--server.publicip.eip.bandwidth.size=5 \
--server.publicip.eip.bandwidth.sharetype=PER \
--server.extendparam.chargingMode=postPaid \
--server.user_data="<Base64 编码的 cloud-init 脚本>"
注意:hcloud 数组参数下标从 1 开始,不是 0。
--server.nics.1.subnet_id而非--server.nics.0.subnet_id。
5.6 创建与验证过程
T+0s 提交创建请求 → job_id: ff808081..., serverId: 0fd205c7...
T+10s ECS 状态: ACTIVE,EIP: 1.94.230.36
T+10s 开始轮询 http://1.94.230.36/hc-activity/index.html
T+70s HTTP 200 OK ← cloud-init 完成(Nginx 安装 + 文件写入 + 服务启动)
验证结果:
$ curl -sI http://1.94.230.36/hc-activity/index.html
HTTP/1.1 200 OK
Server: nginx/1.20.1
Content-Type: text/html
Content-Length: 6810
ETag: "6ad99f3a-1a9a"
Accept-Ranges: bytes
✅ HTTP 200,Content-Length 6810 与源文件完全匹配。
5.7 提交闯关
curl -X POST \
"https://open-dataset.huaweicloud.com/api/v1/hdopenservice/agent/submit-activity-work" \
-H "X-HW-AK: $AK" -H "X-HW-SK: $SK" \
-H "X-HW-PROJECT-ID: $PROJECT_ID" -H "X-HW-REGION: cn-north-4" \
-d '{
"activity_code": "open-capability-2026-1024",
"milestone": "intermediate",
"api_link": "http://1.94.230.36/hc-activity/index.html",
"summary": "2048游戏部署到ECS(Rocky Linux 9.8 + Nginx),s6.medium.2按量付费"
}'
# → {"message":"作品提交成功","code":"success"}
5.8 结果
| 项目 | 值 |
|---|---|
| Server ID | 0fd205c7-d560-45d9-a59f-a459b4ff82a2 |
| EIP | 1.94.230.36 |
| 公网地址 | http://1.94.230.36/hc-activity/index.html |
| HTTP 状态 | 200 OK |
| Content-Length | 6810 |
| Nginx 版本 | 1.20.1 |
| 积分 | +2000 分 |
六、资源释放
任务完成后,为节省费用,释放所有新建资源:
# 删除 ECS(同时释放 EIP 和系统盘)
hcloud ECS DeleteServers --cli-region=cn-north-4 \
--servers.1.id="0fd205c7-d560-45d9-a59f-a459b4ff82a2" \
--delete_publicip=true \
--delete_volume=true
# 删除安全组
hcloud VPC DeleteSecurityGroup --cli-region=cn-north-4 \
--security_group_id=744fc2f2-9725-4147-a7e9-648f5c33a8c1
验证释放结果:
ECS NovaShowServer → 404 Not Found ✅
ECS NovaListServers → 空 ✅
curl http://1.94.230.36 → 连接不通 ✅
七、遇到的问题与解决方案
| # | 问题 | 原因 | 解决方案 |
|---|---|---|---|
| 1 | DevKit 安装时"No AI agents detected" | 环境中未检测到已知 AI 代理 | 选择"A"安装到所有目标,DevKit 自动检测 9 个目标 |
| 2 | DevSpace 默认账号冲突 | 已有其他 AK/SK 配置 | 用 hcloud cli config set 覆盖为用户凭证 |
| 3 | MCP 工具不可直接调用 | DevKit MCP Server 非命名工具 | 编写自定义 MCP Client(JSON-RPC over stdio) |
| 4 | huaweicloud-devkit-mcp npm 包 404 |
非公开发布的 npm 包 | 使用本地 MCP Server 路径 |
| 5 | 沙箱连接 “No available node pool” | 节点池资源紧张 | 重试 5 次,每次间隔 10 秒 |
| 6 | GitCode raw URL 404 | SKILL.md 不在 raw 路径 | git clone 整个仓库到本地 |
| 7 | 活动提交缺少 X-HW-PROJECT-ID | API 更新,所有步骤均需 Project ID | 直接用 curl 附加请求头提交 |
| 8 | hcloud 数组参数下标从 0 报错 | hcloud 数组下标从 1 开始 | --server.nics.1.subnet_id 而非 .0. |
| 9 | VPC v3 API 参数名不同 | v3 使用嵌套命名 | --security_group.name 而非 --name |
| 10 | 端口参数无 port_range_min | v3 API 使用 multiport |
--security_group_rule.multiport=80 |
八、两种部署方式对比
| 维度 | 沙箱部署 (beginner) | ECS 部署 (intermediate) |
|---|---|---|
| 部署方式 | MCP sandbox_upload_file | cloud-init 自动化 |
| 运行环境 | DevStation 容器 | Rocky Linux ECS 虚机 |
| Web 服务器 | Nginx(沙箱预装) | Nginx(cloud-init 安装) |
| 公网暴露 | DevBridge 隧道(自动) | EIP(手动绑定) |
| 持久性 | 72 小时自动回收 | 持久运行,手动释放 |
| 费用 | 免费 | ≈ ¥0.40/小时 |
| 适用场景 | 快速预览、开发调试 | 生产环境、长期托管 |
| 提交字段 | work_link |
api_link |
| 积分 | 1000 分 | 2000 分 |
九、关键技术决策
9.1 为什么选择 Rocky Linux 而非 EulerOS?
- Rocky Linux 使用 dnf/yum 包管理器,
dnf install -y nginx一条命令搞定 - EulerOS 虽为华为官方镜像,但包仓库中不一定有 nginx,可能需额外配置 repo
- Rocky Linux 9.8 完全兼容 RHEL 9 生态,软件包丰富
9.2 为什么用 cloud-init 而非 SSH 手动配置?
- cloud-init 在 ECS 首次启动时自动执行,无需 SSH 连接
- 避免在安全组临时开放 22 端口给 0.0.0.0/0
- 全流程声明式,可重复、可版本管理
- index.html 以 Base64 内嵌在 user_data 中,无需外部下载依赖
9.3 为什么 SSH 安全组仅放通本机 IP?
- SSH 仅用于调试,不需要对公网开放
- 限制源 IP 到
114.116.242.127/32,减少攻击面 - HTTP 80 端口全放通是静态站点的常规做法,Nginx 只提供只读文件
9.4 为什么磁盘选 SAS 而非 SATA?
- SATA(普通 IO)在部分 AZ 经常售罄
- SAS(高 IO)可用性更高,且对 1vCPU 小规格 ECS 价格差异极小
- GPSSD(通用型 SSD)也是好选择,但 SAS 更稳妥
十、最终成果总结
10.1 积分
| 里程碑 | 状态 | 积分 |
|---|---|---|
| 沙箱部署 (beginner) | ✅ 已完成 | 1000 分 |
| ECS 持久化部署 (intermediate) | ✅ 已完成 | 2000 分 |
| 合计 | 3000 分 |
10.2 产出物清单
| 文件 | 路径 | 说明 |
|---|---|---|
| 2048 游戏 | /root/workspace/index.html |
6810 字节,单文件 HTML |
| MCP Client | /tmp/mcp-client.js |
自定义 MCP 通信脚本 |
| Cloud-Init 脚本 | /tmp/cloud-init.sh |
ECS 自动化部署脚本 |
| 部署报告 | /root/workspace/2048-deployment-report.md |
本文档 |
| 沙箱二维码 | /root/workspace/qr-code.png |
沙箱地址二维码 |
| ECS 二维码 | /root/workspace/qr-code-ecs.png |
ECS 地址二维码 |
10.3 公网访问地址
- 沙箱(72h 有效):
https://fxrmr5b3-8080.devbridge-s2.hwtunnel.com - ECS(已释放):
http://1.94.230.36/hc-activity/index.html
10.4 资源状态
| 资源 | 状态 |
|---|---|
| 沙箱 | 有效(72h 内自动回收) |
| ECS | 已释放 |
| EIP | 已释放 |
| 安全组 sg-2048-ecs | 已删除 |
| VPC / 子网 | 保留(已有资源,未创建) |
附录:活动提交 API
接口
POST https://open-dataset.huaweicloud.com/api/v1/hdopenservice/agent/submit-activity-work
请求头
| Header | 说明 |
|---|---|
| Content-Type | application/json |
| X-HW-AK | Access Key |
| X-HW-SK | Secret Key |
| X-HW-PROJECT-ID | 项目 ID |
| X-HW-REGION | 区域(如 cn-north-4) |
请求体
{
"activity_code": "open-capability-2026-1024",
"milestone": "beginner | intermediate",
"work_link": "https://...", // beginner 步骤用
"api_link": "http://...", // intermediate 步骤用
"summary": "作品描述"
}
响应
{"message": "作品提交成功", "code": "success"}
10.5 3段提示词
请阅读https://github.com/huaweicloud/huaweicloud-devkit/blob/main/README.md文档,按照步骤为我安装并配置 HuaweiCloud DevKit。
我想要生成一个 2048 小游戏,纯单文件 HTML(CSS/JS 全部内联在 index.html 中,不依赖 npm、Vite 或任何构建工具)。直接编写一个经典 2048 游戏(4×4 网格、方向键操作、合并得分、游戏结束判定,需适配PC和移动端),用 HuaweiCloud DevKit 沙箱部署,上传 index.html 时用sandbox_upload_file 工具一次调用方式,通过 DevBridge 隧道暴露到公网,最后给我一个公开沙箱域名 URL。部署后用 curl -sI <公网URL> 验证返回 200,读取 https://gitcode.com/huaweicloud/huaweicloud-skills.git 里面的 huawei-cloud-activity-submit 技能,使用此 skill 提交沙箱链接,最后给我一个可直接在对话中预览的沙箱地址二维码。
使用 HuaweiCloud DevKit 在华为云 cn-north-4 区域部署 ECS,把上一步生成的 index.html 用 Nginx 托管为静态站点,得到可公网 HTML 地址。先查询当前区域是否已有可用 ECS 实例,有则直接复用(通过 SSH 上传文件并配置 Nginx),无则按量付费新建 1 核 2G ECS(优先 s6.medium.2/sn3.medium.2)。创建前先读 API help 列出必填参数,并查目标 AZ 的 flavor 和磁盘类型售卖状态(磁盘优先 SAS/GPSSD,SATA 常售罄)。完整流程:1) 复用或新建 VPC/子网(DNS 100.125.1.250,100.125.129.250)与安全组(SSH 22 放通本机出口 IP 仅用于调试、HTTP 80 放通 0.0.0.0/0);2) 新建 ECS 时选用 yum/dnf 系镜像(如 Rocky Linux),必须用 cloud-init(user_data 用 shell 执行 hcloud 命令)一次性完成:设置 root 密码、安装 Nginx、将 index.html 写入 /usr/share/nginx/html/hc-activity/index.html 并启动 Nginx;同时绑定 EIP;3) ECS ACTIVE 后轮询等待 cloud-init 完成,验证 curl -sI http://{ECS_EIP}/hc-activity/index.html 返回 200。读取 https://gitcode.com/huaweicloud/huaweicloud-skills.git 里面的 huawei-cloud-activity-submit 技能,使用此 skill 提交公网地址(http://{ECS_EIP}/hc-activity/index.html),最后给我一个可直接在对话中预览的 ECS 地址二维码并告知我已获得的积分。
- 点赞
- 收藏
- 关注作者
评论(0)