文章

instabox 云沙盒保活:为什么在机器里做什么都没用

instabox 云沙盒保活:为什么在机器里做什么都没用

这篇文章针对 instabox 这类「一段时间不操作就把整台 VM 冻结」的沙盒平台。下面的结论和脚本都在 instabox 上实测过;同类平台思路通用,但端口映射规则和网关地址要按实际情况改。

先说结论

云沙盒这类「一段时间不操作就整台 VM 冻结」的平台,判定发生在宿主机层。

这意味着:

做法结果
沙盒内制造 CPU 负载无效,照样被冻
沙盒内定时发网络请求无效
从外部访问沙盒的端口映射地址有效

沙盒里跑什么,宿主机根本不看。要续命只能从外面碰它。

这条结论不是猜的,是跑了 45 小时后拿数据换来的。

三条证据

一、心跳在跑,机器照样被冻

沙盒内每分钟执行一次心跳脚本,日志显示断档:

1
2
3
04:17:44 → 04:18:49 → 04:19:54 → 04:20:59
SUSPENDED_GAP: 941s          ← 被冻结 15 分 41 秒
04:36:40 → 04:37:42 → 04:38:46

断档前后都是准点条目。进程没死,是整台机器被冻住了。

二、平台自己的 agent 也被冻

沙盒内的 guest agent 每 5 分钟向宿主机上报一次,同一时间窗口一起断档。连平台自己的组件都停了,说明冻结在 VM 层,不在应用层。

三、恢复时出现 VM 级动作

1
2
3
04:36:34  op=sync_clock       ← 重新校时
04:36:34  op=configure        ← 重新下发配置
04:36:35  op=configure_ipv6

只有 VM 从挂起状态恢复才会走这套流程。

三条同时成立,就可以定性了:继续在沙盒内部研究「制造什么活动」是浪费时间。

一个很容易踩的坑

对 guest agent 做 strings,能看到一堆看着像开关的符号:

1
2
3
4
5
internal/guestagent/activity.go
guestagent.(*Agent).activity
guestagent.activityTimeout
guestagent.ActivityProbes
guestagent.RunProbe / probeSignal / probeTimeout

看起来像在检测 CPU busy、服务状态,很容易得出「造 CPU 负载就能保活」的结论。

但这是错的。 如果 CPU busy 真能续命,第一条证据里的 941 秒冻结就不可能发生。

这些探针只是使用统计,不参与暂停决策。

教训:二进制里有 activity 相关符号,不等于找到了控制开关。必须用行为验证,不能靠符号推断。

怎么搭

前提是先拿到端口映射地址。平台通常把沙盒端口映射成 <端口>-<机器ID>.<通配域>,注意裸域往往不解析,只有子域指向统一网关。

1
2
3
4
5
# 机器 ID,在沙盒内执行
cat /etc/instabox/identity | sed 's/^m_//'

# 验证网关可达
curl -sS -m 10 https://3000-<MACHINE_ID>.instabox.tech

返回 Nothing is listening on this port in the sandbox 说明网关通了、沙盒该端口空着。这个 URL 不需要登录态,比控制台 API 好自动化得多。

第一步:沙盒内起监听

1
curl -fsSL https://raw.githubusercontent.com/poisonhs/instabox-keepalive/main/scripts/sandbox-side.sh | sh -s -- 3000

脚本装一个 systemd 服务,用 python3 在指定端口常驻。验证:

1
2
systemctl is-active ka-http
ss -tlnp | grep ':3000'

第二步:外部机器定时敲门

必须是另一台机器。 沙盒自己访问自己,流量没离开机器,网关看不到,等于没做。

1
curl -fsSL https://raw.githubusercontent.com/poisonhs/instabox-keepalive/main/scripts/outside-side.sh | sh -s -- 3000-<MACHINE_ID>.instabox.tech

装一个 5 分钟一次的 systemd timer。

不一定要公网 VPS——家里的树莓派、路由器 cron、另一台云主机都行,关键是常开且不能是沙盒自己。

第三步:可选的长连接加固

定时任务是「新建连接、请求完就断」,长连接则是一次 TLS 握手后复用同一 TCP,每 60 秒打一次,网关看到的是持续会话。

两种可以同时挂,但那样就无法区分哪条在起作用。验收按整体判就行。

怎么算通过

不要凭「现在能通」下结论。 单次 200 什么都证明不了,必须等过了平台的空闲窗口再看。

指标合格线
uptime连续不少于 2 天
心跳日志 SUSPENDED_GAP0 条
敲门日志 5020 条

三条同时成立才算保活成立。

状态码怎么读

码含义动作
200链路通,沙盒活着正常
502沙盒内该端口没服务先查沙盒侧进程
429请求太密,网关限流间隔拉到 60 秒以上
000DNS / 网络 / 超时查域名拼写和 DNS

关键一条:429 和 000 都不代表沙盒挂了,只有 502 指向沙盒侧。 报告问题时这点要说清楚,否则容易把限流当故障。

实测

指标数值
连续运行45.6 小时
系统 uptime2 天 24 分
SUSPENDED_GAP0 次
敲门成功511 / 521
502 出现次数0

对照组:只跑内部心跳时,停止操作 941 秒即被冻结。

一点想法

这个项目里最值得抄的不是脚本,是诊断顺序:先用行为数据排除层级,再去猜实现细节。反过来做的话,很容易被二进制里几个像样的符号骗着走上岔路。

仓库:poisonhs/instabox-keepalive,MIT 许可。仅用于自己拥有或经授权管理的沙盒实例。

本文由作者按照 CC BY 4.0 进行授权