简介
为了降低闲置云服务器的费用,我尝试使用 Scaleway Serverless Jobs 配合 Scaleway CLI,按照 Cron 定时启动和关闭 Instance。
这套方案本身并不复杂,但我在管理荷兰区域的服务器时遇到了一个非常容易误判的问题:服务器 ID 明明正确,CLI 却一直提示找不到资源。
最终确认,问题不在服务器 ID、Jobs 所在区域或启动命令本身,而在于 Scaleway Instance 是按 Availability Zone 定位的资源,仅配置 SCW_DEFAULT_REGION 并不足够。必须设置 SCW_DEFAULT_ZONE,或者在每一条 Instance 命令中显式传入 zone=。
本文记录完整的现象、原因、解决办法,以及如何用一个 Job 跨区域管理多台服务器。
本文中的服务器 ID、Project ID、Organization ID、Access Key 和 Secret Key 均已替换为占位符,请勿直接照抄。
一、最初的配置
我按照 Scaleway 官方的自动化资源管理文档,在 Serverless Jobs 中使用 Scaleway CLI 镜像,并配置以下环境变量:
SCW_ACCESS_KEY=YOUR_ACCESS_KEY
SCW_SECRET_KEY=YOUR_SECRET_KEY
SCW_DEFAULT_PROJECT_ID=YOUR_PROJECT_ID
SCW_DEFAULT_ORGANIZATION_ID=YOUR_ORGANIZATION_ID
SCW_DEFAULT_REGION=fr-par
随后执行类似下面的命令:
/scw instance server start YOUR_FR_SERVER_ID
定时启动和关闭法国区域的实例都能正常完成:
/scw instance server start YOUR_FR_SERVER_ID
/scw instance server stop YOUR_FR_SERVER_ID
因此,我一开始认为只要把 Region 改成目标区域,再替换正确的服务器 ID,就可以管理其他区域的实例。
二、令人困惑的错误
当我使用相同方式管理荷兰区域的服务器时,执行:
/scw instance server start YOUR_NL_SERVER_ID
Jobs 日志却一直返回:
Cannot find resource 'instance_server' with ID 'YOUR_NL_SERVER_ID'
我反复检查了以下内容:
- 服务器 ID 正确;
- Project ID 正确;
- Organization ID 正确;
- API Access Key 和 Secret Key 正确;
- 同一套凭据可以正常管理其他实例;
- 服务器确实位于荷兰区域。
问题仍然存在。
这类错误很容易让人怀疑服务器 ID、IAM 权限或 Project 配置,但实际原因是:命令缺少具体的 Zone。
三、Region 和 Zone 不是一回事
Scaleway 的资源 API 分为 Regional API 和 Zonal API。Instance 属于按 Zone 管理的资源。
以荷兰为例:
Region: nl-ams
Zones:
nl-ams-1
nl-ams-2
nl-ams-3
法国区域同样包含多个 Zone:
Region: fr-par
Zones:
fr-par-1
fr-par-2
fr-par-3
因此,下面这组信息并不能唯一定位一台 Instance:
Region + Server ID
Instance API 实际需要的是:
Zone + Server ID
换句话说,SCW_DEFAULT_REGION=nl-ams 只指定了 Region,并没有告诉 Instance API 应该去 nl-ams-1、nl-ams-2 还是 nl-ams-3 查找服务器。
如果命令没有显式指定 Zone,Scaleway CLI 就会使用默认 Zone。我的法国实例之所以能够成功,是因为 CLI 当时使用的默认 Zone 恰好与法国实例所在的 Zone 一致。到了荷兰区域,同样的默认值自然无法找到目标实例。
这也解释了为什么:
- 一个区域成功;
- 另一个区域失败;
- 服务器 ID 明明正确,却仍然提示资源不存在。
四、解决方案一:配置 SCW_DEFAULT_ZONE
如果一个 Job 只负责管理某一个 Zone 中的服务器,可以增加:
SCW_DEFAULT_REGION=nl-ams
SCW_DEFAULT_ZONE=nl-ams-1
完整环境变量示例:
SCW_ACCESS_KEY=YOUR_ACCESS_KEY
SCW_SECRET_KEY=YOUR_SECRET_KEY
SCW_DEFAULT_PROJECT_ID=YOUR_PROJECT_ID
SCW_DEFAULT_ORGANIZATION_ID=YOUR_ORGANIZATION_ID
SCW_DEFAULT_REGION=nl-ams
SCW_DEFAULT_ZONE=nl-ams-1
配置完成后,原来的命令即可正常工作:
/scw instance server start YOUR_NL_SERVER_ID
关闭实例:
/scw instance server stop YOUR_NL_SERVER_ID
在我的实际测试中,增加 SCW_DEFAULT_ZONE=nl-ams-1 后,之前一直提示找不到资源的命令立即恢复正常。
这种方式适合什么场景
适合:
- 一个 Job 只管理一个 Zone;
- 所有目标服务器都位于同一个 Zone;
- 希望命令尽量简短。
不太适合:
- 一个 Job 同时管理多个 Zone;
- 一个 Job 同时管理法国、荷兰等多个 Region;
- 后续可能新增其他区域的服务器。
五、解决方案二:在命令中显式指定 zone
更明确、也更推荐的方式,是在每一条 Instance 命令末尾添加具体 Zone:
/scw instance server start YOUR_NL_SERVER_ID zone=nl-ams-1
在 Serverless Jobs 的命令和参数配置中,可以写成:
"/scw" "instance" "server" "start" "YOUR_NL_SERVER_ID" "zone=nl-ams-1"
关闭服务器:
/scw instance server stop YOUR_NL_SERVER_ID zone=nl-ams-1
对应的参数形式:
"/scw" "instance" "server" "stop" "YOUR_NL_SERVER_ID" "zone=nl-ams-1"
在我的实际测试中,即使不依赖默认 Zone,只要显式传入:
zone=nl-ams-1
命令也能正常执行。
为什么更推荐显式指定 Zone
显式传入 Zone 有几个明显优点:
- 命令本身包含完整的资源定位信息;
- 不依赖 CLI 镜像、配置文件或环境变量中的默认值;
- 查看 Job 日志时能直接确认目标 Zone;
- 同一个 Job 可以操作不同 Zone 的实例;
- 避免
SCW_DEFAULT_REGION与SCW_DEFAULT_ZONE配置不一致; - 日后新增服务器时更不容易误操作。
因此,即使已经配置了 SCW_DEFAULT_ZONE,我仍然建议在自动化脚本中为每台服务器显式填写 zone=。
六、如何确认服务器的真实 Zone
不要只确认服务器位于 nl-ams,还需要确认它具体位于:
nl-ams-1
nl-ams-2
nl-ams-3
方法一:通过控制台查看
打开 Scaleway Console 中对应 Instance 的详情页面,查看 Zone 或 Availability Zone 字段。
方法二:使用 CLI 跨 Zone 查询
instance server list 支持使用 zone=all 查询所有 Zone。可以通过服务器 ID 过滤:
/scw -o json instance server list \
zone=all \
servers=YOUR_SERVER_ID
找到返回结果中的 Zone 后,再进行单独验证:
/scw instance server get YOUR_SERVER_ID zone=nl-ams-1
如果 get 能够正常返回实例信息,再执行:
/scw instance server start YOUR_SERVER_ID zone=nl-ams-1
需要注意:zone=all 适合资源列表查询,但启动和关闭实例时仍然应该使用一个明确的 Zone,例如:
zone=nl-ams-1
而不是:
zone=all
七、一个 Serverless Job 能否管理所有区域
答案是:可以。
Serverless Job 自身创建在哪个 Region,与它通过 Scaleway API 管理哪个 Zone 的 Instance,不是同一个概念。
例如,一个运行在 fr-par 的 Job,可以依次操作:
/scw instance server start YOUR_FR_SERVER_ID zone=fr-par-1
/scw instance server start YOUR_NL_SERVER_ID zone=nl-ams-1
/scw instance server start YOUR_PL_SERVER_ID zone=pl-waw-1
前提是:
- API 凭据有权访问这些服务器;
- Project 和 Organization 配置正确;
- 每台实例都使用正确的服务器 ID;
- 每一条命令都传入目标实例的真实 Zone。
因此,不必为了不同 Region 的服务器分别在每个 Region 部署一套完全相同的 Job。一个 Job 可以通过脚本管理多个 Zone 和多个 Region。
不过,Job 自己仍然是区域型资源。Job 运行区域与被管理服务器的 Zone 应该作为两个独立概念理解。
八、用一个脚本管理多区域服务器
可以创建一个统一的脚本,根据参数执行启动或关闭操作:
#!/usr/bin/env bash
set -euo pipefail
ACTION="${1:-}"
case "$ACTION" in
start|stop)
;;
*)
echo "Usage: $0 start|stop" >&2
exit 2
;;
esac
SERVERS=(
"fr-par-1:YOUR_FR_SERVER_ID"
"nl-ams-1:YOUR_NL_SERVER_ID"
"pl-waw-1:YOUR_PL_SERVER_ID"
)
for TARGET in "${SERVERS[@]}"; do
ZONE="${TARGET%%:*}"
SERVER_ID="${TARGET#*:}"
echo "Running action=${ACTION}, zone=${ZONE}, server=${SERVER_ID}"
/scw instance server "$ACTION" "$SERVER_ID" "zone=$ZONE"
done
启动全部实例:
bash /manage-instances.sh start
关闭全部实例:
bash /manage-instances.sh stop
正式使用时,可以将脚本存放在 Scaleway Secret Manager 中,再以文件方式挂载到 Serverless Job,避免为了修改服务器列表而重新制作容器镜像。
是否应该用一个 Job 同时负责开机和关机
技术上可以让一个脚本同时支持 start 和 stop,但定时任务层面更推荐建立两个 Job Definition:
start-all-instances
stop-all-instances
它们可以共用:
- 同一个 Scaleway CLI 镜像;
- 同一份服务器清单;
- 同一个脚本;
- 同一套 Secret 和 IAM 凭据。
区别仅在于启动参数和 Cron 时间:
bash /manage-instances.sh start
以及:
bash /manage-instances.sh stop
这样日志、失败重试和权限排查都会更加直观。
九、安全配置建议
使用 Serverless Jobs 自动管理服务器时,应注意以下几点。
1. 不要把密钥写入命令或脚本
以下信息应该使用 Scaleway 的 Secret 或受保护环境变量保存:
SCW_ACCESS_KEY
SCW_SECRET_KEY
不要把真实密钥提交到 Git 仓库,也不要出现在博客、截图或 Job 日志中。
2. 博客和公开日志中隐藏资源标识
公开内容中应替换以下信息:
- Server ID;
- Project ID;
- Organization ID;
- Access Key;
- Secret Key;
- 可能包含账户信息的完整 API 响应。
虽然服务器 UUID 通常不能单独用于登录服务器,但仍然不建议公开真实资源标识。
3. 使用最小权限 IAM Policy
用于定时开关机的 API 凭据不应获得不必要的管理权限。建议只授予目标 Project 和 Instance 自动化所需的权限。
4. 为脚本启用错误退出
脚本开头建议加入:
set -euo pipefail
避免某条命令失败后,Job 仍然以成功状态结束。
如果希望某台服务器失败时继续操作其他服务器,则应自行记录失败状态,并在所有命令执行完后统一返回非零退出码。
十、排查清单
如果显式指定 Zone 后仍然失败,可以按照以下顺序检查。
1. 查询所有 Zone
/scw -o json instance server list zone=all servers=YOUR_SERVER_ID
如果完全没有返回结果,再检查 Project、Organization 和 API 凭据。
2. 使用 get 验证定位
/scw instance server get YOUR_SERVER_ID zone=YOUR_REAL_ZONE
如果 get 都无法找到资源,说明还没有必要继续排查 start 或 stop,应优先检查 Zone 和身份配置。
3. 检查默认值
确认 Job 中是否存在旧的或错误的配置:
SCW_DEFAULT_REGION
SCW_DEFAULT_ZONE
SCW_DEFAULT_PROJECT_ID
SCW_DEFAULT_ORGANIZATION_ID
4. 检查 IAM 权限
如果 get 成功,但 start 或 stop 失败,则更可能是:
- IAM Policy 不允许执行对应操作;
- 实例当前状态不允许执行该动作;
- API 凭据属于其他 Organization;
- Job 使用了错误版本的 Secret。
5. 在日志中打印目标信息,但不要打印密钥
可以打印:
action=start
zone=nl-ams-1
server=脱敏后的服务器标识
不要打印:
SCW_SECRET_KEY
完整 Access Key
Secret 内容
十一、最终推荐配置
如果只管理一个 Zone,可以同时配置:
SCW_DEFAULT_REGION=nl-ams
SCW_DEFAULT_ZONE=nl-ams-1
并执行:
/scw instance server start YOUR_SERVER_ID
但对于正式自动化任务,我更推荐始终显式指定 Zone:
/scw instance server start YOUR_SERVER_ID zone=nl-ams-1
/scw instance server stop YOUR_SERVER_ID zone=nl-ams-1
跨区域管理时,则为每台服务器保存一组明确的:
Zone + Server ID
而不是只保存:
Region + Server ID
十二、总结
这次问题的核心并不是服务器 ID 错误,而是 Scaleway 官方自动化教程只强调了:
SCW_DEFAULT_REGION
却没有在 Instance 定时开关机的场景中明确提醒还需要:
SCW_DEFAULT_ZONE
或者在命令中添加:
zone=具体可用区
最终,以下两种方式都验证有效。
方式一,设置默认 Zone:
SCW_DEFAULT_ZONE=nl-ams-1
方式二,命令显式指定 Zone:
/scw instance server start YOUR_SERVER_ID zone=nl-ams-1
在多区域、多 Zone 的自动化环境中,第二种方式更清晰,也更不容易因为默认配置而操作失败。
一句话概括:
Scaleway Instance 是 Zonal Resource。管理实例时,不能只告诉 CLI 它在哪个 Region,还必须告诉它具体在哪个 Zone。
