cover

验证目的

验证阿里云 ACS(ECI)沙箱环境下,ESSD 持久卷(PVC)在以下操作中的数据持久性,以及 OpenClaw Web UI 在各升级路径下的可用性:

  • E2B SDK pause/resume(休眠/唤醒)
  • kubectl patch pod 原地换镜像
  • kubectl patch pod 原地调整 CPU/内存
  • SandboxUpdateOps 声明式升级

环境信息

集群阿里云 ACS(ECI),节点 x86_64
命名空间default
SandboxSetopenclaw
基础镜像registry-cn-hangzhou-vpc.ack.aliyuncs.com/ack-demo/openclaw:2026.3.23-2
升级镜像registry.cn-hangzhou.aliyuncs.com/fclaw/fclaw:1.2(amd64)
存储类alicloud-disk-essd,20Gi
E2B SDKe2b==2.24.0,e2b-code-interpreter==2.7.0
ALB 地址121.43.128.121

前置准备

SandboxSet YAML

文件 openclaw-sandboxset-essd.yaml

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxSet
metadata:
  name: openclaw
  namespace: default
spec:
  replicas: 1
  persistentContents:
    - filesystem
  runtimes:
    - name: csi
    - name: agent-runtime
  volumeClaimTemplates:
    - metadata:
        name: workspace-pvc
      spec:
        accessModes:
          - ReadWriteOnce
        storageClassName: alicloud-disk-essd
        resources:
          requests:
            storage: 20Gi
  template:
    metadata:
      labels:
        alibabacloud.com/acs: "true"
        alibabacloud.com/compute-class: agent-sandbox
        alibabacloud.com/compute-qos: default
      annotations:
        scaling.alibabacloud.com/enable-inplace-resource-resize: "true"
    spec:
      automountServiceAccountToken: false
      terminationGracePeriodSeconds: 30
      securityContext:
        fsGroup: 1000
      containers:
        - name: openclaw
          image: registry-cn-hangzhou-vpc.ack.aliyuncs.com/ack-demo/openclaw:2026.3.23-2
          imagePullPolicy: IfNotPresent
          env:
            - name: OPENCLAW_SKIP_ONBOARDING
              value: "1"
            - name: OPENCLAW_TZ
              value: Asia/Shanghai
          ports:
            - containerPort: 18789
              name: http-ui
              protocol: TCP
          resources:
            limits:
              cpu: "2"
              memory: 4Gi
            requests:
              cpu: "2"
              ephemeral-storage: 30Gi
              memory: 4Gi
          volumeMounts:
            - name: workspace-pvc
              mountPath: /app/workspace

OpenClaw 配置模板

文件 e2b-test/openclaw_template.json,关键字段 gateway.bind: "lan" 使 gateway 监听 0.0.0.0,外部可通过 ALB 访问:

{
    "gateway": {
        "port": 18789,
        "bind": "lan",
        "controlUi": {
            "allowedOrigins": ["*"],
            "dangerouslyAllowHostHeaderOriginFallback": true,
            "allowInsecureAuth": true,
            "dangerouslyDisableDeviceAuth": true
        },
        "auth": {
            "mode": "token",
            "token": "${GATEWAY_TOKEN}"
        }
    }
}

E2B 配置注入脚本

文件 e2b-test/create_openclaw.py,创建沙箱后通过 SDK 写入配置文件,等待 gateway 重启:

from e2b_code_interpreter import Sandbox
from string import Template

sbx = Sandbox.create("openclaw", metadata={"e2b.agents.kruise.io/never-timeout": "true"})

with open("openclaw_template.json") as f:
    template = Template(f.read())
rendered = template.safe_substitute(
    GATEWAY_TOKEN="openclaw-sandbox-token",
    DASHSCOPE_API_KEY="sk-fake-test-key-12345",
)
sbx.files.write("/home/node/.openclaw/openclaw.json", rendered, user="node")

time.sleep(30)  # 等待 gateway 重启

验证步骤与结果

创建 SandboxSet

kubectl create --validate=false -f openclaw-sandboxset-essd.yaml

结果:

SandboxSet: openclaw, replicas=1, available=1
Sandbox CR:  openclaw-bvgr2, Running, claimed=false
Pod:        openclaw-bvgr2, 4/4 Running
PVC:        workspace-pvc-openclaw-bvgr2, Bound, 20Gi, alicloud-disk-essd
annotation:  scaling.alibabacloud.com/enable-inplace-resource-resize=true

E2B SDK 领取沙箱 + 配置注入

运行 create_openclaw.py

sandbox_id: default--openclaw-bvgr2  耗时: 0.09s
配置已写入 /home/node/.openclaw/openclaw.json
等待 30s gateway 重启

验证 Web UI 外部访问

r = requests.get("https://18789-default--openclaw-bvgr2.openclaw-sandbox.infra/?token=openclaw-sandbox-token", verify=False)
print(r.status_code)  # 200

结果:HTTP 200,返回 <title>OpenClaw Control</title> 页面,body 2732 bytes。

gateway 监听地址确认:

/proc/net/tcp: 00000000:4965  -> 0.0.0.0:18789 (全接口监听)

写入测试数据

通过 E2B SDK 向三个位置写入数据:

数据位置存储类型
pvc-test.txt/app/workspace/PVC (ESSD)
pvc-hello.txt/app/workspace/PVC (ESSD)
pvc-5mb.bin (5MB)/app/workspace/PVC (ESSD)
tmp-test.txt/tmp/容器可写层
app-test.txt/app/容器可写层

Pause/Resume 验证

sbx = Sandbox.connect("default--openclaw-bvgr2")
sbx.beta_pause()        # 休眠
sbx = Sandbox.connect("default--openclaw-bvgr2")  # connect 隐式唤醒

结果:

数据位置pause/resume 后
pvc-test.txt/app/workspace/ (PVC)保留
pvc-hello.txt/app/workspace/ (PVC)保留
pvc-5mb.bin/app/workspace/ (PVC)保留
tmp-test.txt/tmp/ (可写层)保留
app-test.txt/app/ (可写层)保留

kubectl patch 镜像升级

kubectl patch pod openclaw-bvgr2 -n default \
  -p '{"spec":{"containers":[{"name":"openclaw","image":"registry.cn-hangzhou.aliyuncs.com/fclaw/fclaw:v1.3"}]}}'

ECI 检测到镜像层发生变化(imageID 不同),在 Pod 内重建容器(containerID 变更),Pod 不删除。

状态变化:

patch 前patch 后
imageopenclaw:2026.3.23-2fclaw/fclaw:v1.3
imageIDsha256:dda9f4...sha256:ca6fd1...
containerID093a2184...833fbbb... (变更)
restartCount35

结果:

数据位置patch 后
pvc-test.txt/app/workspace/ (PVC)保留
pvc-hello.txt/app/workspace/ (PVC)保留
pvc-5mb.bin/app/workspace/ (PVC)保留
tmp-test.txt/tmp/ (可写层)丢失
app-test.txt/app/ (可写层)丢失

Web UI:HTTP 503,gateway 退回 127.0.0.1:18789(配置文件随可写层销毁,同 SandboxUpdateOps)。

kubectl patch CPU/内存原地扩容

SandboxSet YAML 中 Pod 模板已包含 annotation scaling.alibabacloud.com/enable-inplace-resource-resize: "true",Pod 创建时即携带,ECI 允许原地调整资源。

kubectl patch pod openclaw-bvgr2 -n default \
  -p '{"spec":{"containers":[{"name":"openclaw","resources":{"limits":{"cpu":"4","memory":"8Gi"},"requests":{"cpu":"4","memory":"8Gi","ephemeral-storage":"30Gi"}}}]}}'

ECI 直接调整 cgroup 限制,不重建容器(containerID 不变),不杀进程。

结果:

patch 前patch 后
CPU (spec)24
CPU (实际 nproc)24
Memory (spec)4Gi8Gi
Memory (实际 cgroup)4096 MiB8192 MiB
containerIDe2476b85...e2476b85... (不变)
restartCount11 (不变)
数据位置patch 后
pvc-test.txt/app/workspace/ (PVC)保留
pvc-hello.txt/app/workspace/ (PVC)保留
pvc-5mb.bin/app/workspace/ (PVC)保留
tmp-test.txt/tmp/ (可写层)保留
app-test.txt/app/ (可写层)保留

Web UI:HTTP 200,gateway 仍监听 0.0.0.0:18789。

注意:该 annotation 必须在 Pod 创建时存在,后补不生效。未携带此 annotation 的 Pod 执行资源 patch 时,ECI 后端返回 400 错误:

The operation of in-place resource resizing has been denied.
pod should created with annotation key:[scaling.alibabacloud.com/enable-inplace-resource-resize] and value:[true]

SandboxUpdateOps 镜像升级

先 patch 回基础镜像,再通过 SandboxUpdateOps 声明式升级:

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxUpdateOps
metadata:
  name: upgrade-bvgr2
  namespace: default
spec:
  selector:
    matchLabels:
      agents.kruise.io/sandbox-template: openclaw
      agents.kruise.io/sandbox-claimed: "true"
  updateStrategy:
    maxUnavailable: 100%
  patch:
    spec:
      containers:
        - name: openclaw
          image: registry.cn-hangzhou.aliyuncs.com/fclaw/fclaw:v1.3
kubectl create --validate=false -f sandbox-updateops.yaml

状态变化:

[1] ops=Updating  pod=Running    ready=true   img=2026.3.23-2
[4] ops=Updating  pod=Succeeded  ready=false              <- 旧 Pod 终止
[6] ops=Updating  pod=Pending    ready=false  img=fclaw:1.2  <- 新 Pod 创建
[8] ops=Completed pod=Running    ready=true   img=fclaw:1.2  <- 新 Pod 就绪

结果:

数据位置SandboxUpdateOps 后
pvc-test.txt/app/workspace/ (PVC)保留
pvc-hello.txt/app/workspace/ (PVC)保留
pvc-5mb.bin/app/workspace/ (PVC)保留
tmp-test.txt/tmp/ (可写层)丢失
app-test.txt/app/ (可写层)丢失

Web UI:HTTP 503(配置文件随可写层销毁,gateway 退回默认 bind=localhost,ALB 无法访问)。

配置重注入

SandboxUpdateOps 后需重新执行配置注入步骤(同 4.2):

sbx = Sandbox.connect("default--openclaw-bvgr2")
sbx.files.write("/home/node/.openclaw/openclaw.json", rendered, user="node")
time.sleep(30)

结果:HTTP 200,<title>OpenClaw Control</title>,gateway 恢复 0.0.0.0:18789 监听。

数据持久性总结

数据位置存储类型pause/resumepatch 镜像patch CPU/内存SandboxUpdateOps
/app/workspace/PVC (ESSD)保留保留保留保留
/tmp/容器可写层保留丢失保留丢失
/app/ (非 PVC)容器可写层保留丢失保留丢失

原因:patch CPU/内存走 ECI cgroup 热更新,不重建容器;patch 镜像(不同镜像层)在 Pod 内重建容器,可写层随旧容器销毁;SandboxUpdateOps 删除重建整个 Pod,同样丢失可写层。PVC 是独立卷,独立于 Pod 生命周期。

Web UI 可用性总结

操作Web UI原因
配置注入后HTTP 200gateway.bind=lan, 监听 0.0.0.0
pause/resume 后HTTP 200Pod 未删除,配置保留
patch 镜像后(未重注入)HTTP 503容器重建,配置丢失,gateway 退回 localhost
patch CPU/内存后HTTP 200不重建容器,配置保留
SandboxUpdateOps 后(未重注入)HTTP 503Pod 删除重建,配置丢失,gateway 退回 localhost
SandboxUpdateOps 后(重注入配置)HTTP 200配置恢复,gateway 重新监听 0.0.0.0

结论:patch 镜像(不同镜像层)和 SandboxUpdateOps 均会重建容器,导致可写层丢失,升级后必须重新执行配置注入步骤,否则 Web UI 不可用。仅 patch CPU/内存走 cgroup 热更新,不重建容器,无需重注入配置。

相关文件

文件说明
openclaw-sandboxset-essd.yamlSandboxSet 定义(含 ESSD PVC)
sandbox-updateops-fclaw12.yamlSandboxUpdateOps 升级定义
e2b-test/create_openclaw.py沙箱创建与配置注入脚本
e2b-test/openclaw_template.jsonOpenClaw 配置模板
e2b-test/.envE2B 环境变量
OpenClaw on 阿里云ACK Agent Sandbox:ESSD 持久卷与镜像升级验证
转载前请阅读本站 版权协议,文章著作权归 饼铛 所有,转载请注明出处。
评论

目录