全部產品
Search
文件中心

Container Compute Service:使用Checkpoint功能複製Agent Sandbox

更新時間:Apr 01, 2026

在開發複雜 AI Agent 需要儲存運行狀態時,為實現沙箱環境的快速複用,可通過 E2B SDK 調用 Checkpoint 功能對運行中容器建立快照並執行複製,確保檔案系統與記憶體資料一致並降低環境初始化成本。

準備工作

  1. 升級acs-virtual-node組件至 v2.17.0 及以上版本。

  2. 安裝相關組件

使用限制

  1. 當前僅支援ACS通用算力使用 Checkpoint 功能。

  2. Pod狀態為 Running 且 Ready 之後才可提交 Checkpoint。

  3. 同一個Pod,只能同時存在一個運行中的 Checkpoint。Checkpoint 達到終態(成功或失敗)後,可再次提交 Checkpoint。

  4. Checkpoint 任務進入 Running 狀態後,無法通過刪除 Checkpoint 資源來中斷任務。

配置 Checkpoint 保留內容

Checkpoint 支援保留以下內容:

  • 檔案系統(filesystem):預設保留。

  • 記憶體(memory):可選保留。

預設情況下,通過 E2B 介面建立的 Checkpoint 將繼承原始 Sandbox 的spec.persistentContents欄位配置,並自動忽略ip保留配置。

樣本 1:繼承檔案系統與記憶體保留配置

# 原始 Sandbox 配置
apiVersion: agents.kruise.io/v1alpha1
kind: Sandbox
spec:
  persistentContents:
    - filesystem
    - memory
  ...
---
# 最終產生的 Checkpoint 配置
apiVersion: agents.kruise.io/v1alpha1
kind: Checkpoint
spec:
  persistentContents: # 自動繼承原始配置
    - filesystem
    - memory
  ...

樣本 2:自動過濾 IP 保留配置

# 原始 Sandbox 配置
apiVersion: agents.kruise.io/v1alpha1
kind: Sandbox
spec:
  persistentContents:
    - ip
    - filesystem
  ...
---
# 最終產生的 Checkpoint 配置
apiVersion: agents.kruise.io/v1alpha1
kind: Checkpoint
spec:
  persistentContents: # 自動去除 ip,僅保留 filesystem
    - filesystem
  ...

此外,可以通過 SandboxSet 批量控制該模板下所有 Sandbox 的保留內容:

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxSet
metadata:
  name: code-interpreter-fs
  namespace: default
spec:
  replicas: 2
  persistentContents:
    - filesystem # 僅保留檔案系統,不保留記憶體
  ...

建立沙箱快照並複製沙箱

E2B SDK方式

建立原始沙箱

以下樣本通過兩個不同的 SandboxSet 模板(分別配置為“保留記憶體”和“不保留記憶體”)示範復原。

  1. 部署 SandboxSet,將以下內容儲存為YAML檔案,然後執行kubectl apply -f <YAML_FILE>命令。

    code-interpreter-mem.yaml

    apiVersion: agents.kruise.io/v1alpha1
    kind: SandboxSet
    metadata:
      name: code-interpreter-mem
      namespace: default
    spec:
      # 預熱池的大小,建議比預估的請求突發量略大
      replicas: 2
      persistentContents: # 記憶體保留
        - memory
        - filesystem
      template:
        metadata:
          labels:
            # 可選,用於在 ACK 叢集中將沙箱 Pod 調度到 ACS
            alibabacloud.com/acs: "true"
        spec:
          initContainers:
            # 以 sidecar 容器形式聲明 agent-runtime,實現向沙箱容器自動注入 envd 等運行時組件
            - name: runtime
              image: registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/agent-runtime:v0.0.2
              command: [ "sh", "/workspace/entrypoint_inner.sh" ]
              volumeMounts:
                # 與主容器的共用目錄
                - name: envd-volume
                  mountPath: /mnt/envd
              env:
                - name: ENVD_DIR
                  value: /mnt/envd
                # 這個環境變數使得 sidecar 共用主容器的資源,不產生額外費用
                - name: __IGNORE_RESOURCE__
                  value: "true"
              restartPolicy: Always
          containers:
          - name: sandbox
            # 官方維護的 e2b code-interpreter 鏡像,支援全地區、vpc 拉取
            image: registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/code-interpreter:v1.6
            imagePullPolicy: IfNotPresent
            # 推薦設定資源需求,否則在 ACS 環境下會被設定成超小規格影響運行
            resources:
              limits:
                cpu: 1
                memory: 1Gi
              requests:
                cpu: 1
                memory: 1Gi
            startupProbe:
              failureThreshold: 10
              httpGet:
                path: /health
                port: 49999
              initialDelaySeconds: 1
              periodSeconds: 2
              timeoutSeconds: 1
            env:
              # 指定 runtime 注入的 envd 組件位置
              - name: ENVD_DIR
                value: /mnt/envd
            volumeMounts:
              # 與 runtime 的共用目錄
              - name: envd-volume
                mountPath: /mnt/envd
            lifecycle:
              postStart:
                exec:
                  command: [ "/bin/bash", "-c", "/mnt/envd/envd-run.sh" ]
          # 保證容器快速銷毀,提高複用的機率
          terminationGracePeriodSeconds: 1
          volumes:
            - name: envd-volume
              emptyDir: { }

    code-interpreter-no-mem.yaml

    apiVersion: agents.kruise.io/v1alpha1
    kind: SandboxSet
    metadata:
      name: code-interpreter-no-mem
      namespace: default
    spec:
      # 預熱池的大小,建議比預估的請求突發量略大
      replicas: 2
      persistentContents: # 記憶體不保留
        - filesystem
      template:
        metadata:
          labels:
            # 可選,用於在 ACK 叢集中將沙箱 Pod 調度到 ACS
            alibabacloud.com/acs: "true"
        spec:
          initContainers:
            # 以 native-sidecar 形式聲明 agent-runtime,自動給沙箱容器注入 envd 等運行時組件
            - name: runtime
              image: registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/agent-runtime:v0.0.2
              command: [ "sh", "/workspace/entrypoint_inner.sh" ]
              volumeMounts:
                # 與主容器的共用目錄
                - name: envd-volume
                  mountPath: /mnt/envd
              env:
                - name: ENVD_DIR
                  value: /mnt/envd
                # 這個環境變數使得 sidecar 共用主容器的資源,不產生額外費用
                - name: __IGNORE_RESOURCE__
                  value: "true"
              restartPolicy: Always
          containers:
          - name: sandbox
            # 官方維護的 e2b code-interpreter 鏡像,支援全地區、vpc 拉取
            image: registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/code-interpreter:v1.6
            imagePullPolicy: IfNotPresent
            # 推薦設定資源需求,否則在 ACS 環境下會被設定成超小規格影響運行
            resources:
              limits:
                cpu: 1
                memory: 1Gi
              requests:
                cpu: 1
                memory: 1Gi
            startupProbe:
              failureThreshold: 10
              httpGet:
                path: /health
                port: 49999
              initialDelaySeconds: 1
              periodSeconds: 2
              timeoutSeconds: 1
            env:
              # 指定 runtime 注入的 envd 組件位置
              - name: ENVD_DIR
                value: /mnt/envd
            volumeMounts:
              # 與 runtime 的共用目錄
              - name: envd-volume
                mountPath: /mnt/envd
            lifecycle:
              postStart:
                exec:
                  command: [ "/bin/bash", "-c", "/mnt/envd/envd-run.sh" ]
          # 保證容器快速銷毀,提高複用的機率
          terminationGracePeriodSeconds: 1
          volumes:
            - name: envd-volume
              emptyDir: { }
  2. 通過 E2B SDK建立沙箱,詳細操作請參考建立Agent Sandbox

    # Import the E2B SDK
    from e2b_code_interpreter import Sandbox
    
    # 建立開啟記憶體保留的沙箱
    sbx_with_mem = Sandbox.create("code-interpreter-mem")
    print(f"mem-sandbox id: {sbx_with_mem.sandbox_id}")
    # 建立僅保留檔案系統的沙箱
    sbx_no_mem = Sandbox.create("code-interpreter-no-mem")
    print(f"fs-sandbox id: {sbx_no_mem.sandbox_id}")
  3. 初始化狀態:在沙箱中寫入記憶體變數和檔案系統資料。

    def init_mem_fs(sbx):
      sbx.run_code("a = 1") # 寫入記憶體變數
      sbx.files.write("/my-file", "hello") # 寫入檔案
      
      # 驗證資料寫入成功
      print(sbx.run_code("print(a)"))
      print(sbx.files.read("/my-file"))
    
    init_mem_fs(sbx_with_mem)
    init_mem_fs(sbx_no_mem)

建立 Checkpoint

將以下<YOUR_SANDBOX_XXX_ID>替換成實際沙箱id,為沙箱建立目前狀態的快照。

sbx_with_mem = Sandbox.connect("<YOUR_SANDBOX_WITH_MEMORY_ID>")
sbx_no_mem = Sandbox.connect("<YOUR_SANDBOX_WITHOUT_MEMORY_ID>")

snapshot_with_mem = sbx_with_mem.create_snapshot()
snapshot_no_mem = sbx_no_mem.create_snapshot(headers={
  "x-e2b-kruise-snapshot-keep-running": "true",                 # Checkpoint 建立後 Sandbox 是否繼續運行。如果是 false,對應 Pod 狀態將會變為 Succeeded。預設為 true。
  "x-e2b-kruise-snapshot-ttl": "30m",                           # 建立的 Checkpoint 存在時間,超期後自動刪除。預設不配置,除非手動刪除,永久存在。
  "x-e2b-kruise-snapshot-persistent-contents": "filesystem",    # Checkpoint 的保留內容,預設繼承 Sandbox 的保留內容。目前只支援 filesystem 與 memory,filesystem 兩種組合。
  "x-e2b-kruise-snapshot-wait-success-seconds": "60",           # 建立 Checkpoint 時,服務端等待其完成的逾時時間。預設為 60。
})

print(f"Snapshot ID with memory: {snapshot_with_mem.snapshot_id}")
print(f"Snapshot ID without memory: {snapshot_no_mem.snapshot_id}")

# Checkpoint 建立完成後,可安全刪除原始沙箱
sbx_with_mem.kill()
sbx_no_mem.kill()

Header參數說明

ack-sandbox-manager 支援通過自訂 Header 擴充 Checkpoint 能力:

Header 參數

說明

預設值

x-e2b-kruise-snapshot-keep-running

Checkpoint 建立後 Sandbox 是否繼續運行。若為 false,Pod 狀態將變為 Succeeded。

true

x-e2b-kruise-snapshot-ttl

Checkpoint 存活時間,到期自動刪除(如 30m)。若不配置則永久存在。

x-e2b-kruise-snapshot-persistent-contents

手動覆蓋 Checkpoint 保留內容。支援 filesystem 或 memory,filesystem。

繼承 Sandbox 配置

x-e2b-kruise-snapshot-wait-success-seconds

服務端等待 Checkpoint 完成的逾時時間(秒)。

60

從 Checkpoint 複製沙箱

  1. 複製時,將上一步返回的Snapshot ID作為 template 參數傳入 create 介面。標準的 timeout、auto_pause 及 CSI 掛載等擴充參數在複製介面中依然有效。

    # 使用快照 ID 作為模板建立新沙箱
    clone_with_mem = Sandbox.create("<YOUR_SNAPSHOT_WITH_MEMORY_ID>")
    clone_no_mem = Sandbox.create("<YOUR_SNAPSHOT_WITHOUT_MEMORY_ID>")
  2. 檢查複製後的沙箱資料,驗證復原。

    # 驗證開啟記憶體保留的複製
    print(clone_with_mem.run_code("print(a)"))     
    print(clone_with_mem.files.read("/my-file"))    
    print(clone_no_mem.run_code("print(a)")) 
    print(clone_no_mem.files.read("/my-file"))

    預期輸出:

    Execution(Results: [], Logs: Logs(stdout: ['1\n'], stderr: []), Error: None)
    hello
    Execution(Results: [], Logs: Logs(stdout: [], stderr: []), Error: ExecutionError(name='NameError', value="name 'a' is not defined", traceback="---------------------------------------------------------------------------NameError                                 Traceback (most recent call last)Cell In[1], line 3\n      1 import os; os.environ['E2B_SANDBOX'] = 'true'\n----> 3 print(a)\nNameError: name 'a' is not defined"))
    hello
    • 兩個複製沙箱均能正確恢複檔案系統中的 /my-file

    • clone_with_mem成功恢複了記憶體變數 a。

Sandbox CR方式

建立沙箱

將以下內容儲存為sandbox.yaml檔案,然後執行kubectl apply -f sandbox.yaml命令。

apiVersion: agents.kruise.io/v1alpha1
kind: Sandbox
metadata:
  name: code-demo
spec:
  template: 
    metadata:
      labels:
        agent: code-demo
        # 使用ACS算力
        alibabacloud.com/acs: "true"
    spec:
      automountServiceAccountToken: false
      containers:
      - name: my-session
        image: registry-ap-southeast-1.ack.aliyuncs.com/acs/code-interpreter:v1.6
        env:
        - name: GODEBUG
          value: multipathtcp=0
        resources:
          requests:
            cpu: 1
            memory: 1Gi
            ephemeral-storage: "30Gi" #聲明儲存空間為30 GiB
        ports:
        - containerPort: 49999
          name: interpreter

建立Checkpoint

  1. 通過建立 Checkpoint CR 對目標沙箱建立快照,將以下內容儲存為sandbox-checkpoint.yaml檔案,然後執行kubectl apply -f sandbox-checkpoint.yaml命令。

    apiVersion: agents.kruise.io/v1alpha1
    kind: Checkpoint
    metadata:
      name: checkpoint-code-demo
      namespace: default
    spec:
      # 目標Pod Name
      podName: code-demo
      # 建立 Checkpoint 後,是否要求 Pod 保持 Running 狀態。如果配置 false ,Pod狀態變為 Succeeded
      keepRunning: true
      # Checkpoint 回收時間,系統在 ttlAfterFinished 逾時後將自動回收 Checkpoint 資源
      # 如果不配置,系統預設不會回收,使用者主動刪除 Checkpoint CR 時回收底層 checkpoint 資源
      ttlAfterFinished: 30h # 格式,例如 30m, 30h, 30d
      persistentContents: # 目前僅支援 filesystem以及 memory,filesystem 兩種組合。預設啟用 memory,filesystem
      - memory
      - filesystem
  2. 查看checkpointId

    kubectl get checkpoint checkpoint-code-demo -n default -o jsonpath='{.status.checkpointId}'

複製新沙箱

  1. 替換以下<CHECKPOINT_ID>為上一步的checkpointId,將以下內容儲存為sandbox-clone.yaml檔案,然後執行kubectl apply -f sandbox-clone.yaml命令。

    apiVersion: agents.kruise.io/v1alpha1
    kind: Sandbox
    metadata:
      name: code-demo-clone
    spec:
      template:
        metadata:
          labels:
            agent: code-demo-clone
            # 使用ACS算力
            alibabacloud.com/acs: "true"
          annotations:
            # 必須配置此註解,才允許對 Pod 建立 Checkpoint
            ops.alibabacloud.com/pause-enabled: "true"
            # 需替換為正確的 Checkpoint ID
            checkpoint.alibabacloud.com/restore-from: "<CHECKPOINT_ID>"
        spec: # 複製沙箱的 spec 需與原始 Pod 的 spec 保持一致
          automountServiceAccountToken: false
          containers:
          - name: my-session
            image: registry-ap-southeast-1.ack.aliyuncs.com/acs/code-interpreter:v1.6
            env:
            - name: GODEBUG
              value: multipathtcp=0
            resources:
              requests:
                cpu: 1
                memory: 1Gi
                ephemeral-storage: "30Gi" #聲明儲存空間為30 GiB
            ports:
            - containerPort: 49999
              name: interpreter
  2. 查看 Sandbox 資源及對應的 Pod 狀態。

    kubectl get sandbox/code-demo-clone pod/code-demo-clone -o wide

    預期輸出:

    NAME                                       STATUS    AGE   SHUTDOWN_TIME   PAUSE_TIME   MESSAGE
    sandbox.agents.kruise.io/code-demo-clone   Running   71m
    
    NAME                  READY   STATUS    RESTARTS   AGE   IP            NODE                            NOMINATED NODE   READINESS GATES
    pod/code-demo-clone   1/1     Running   0          71m   172.16.x.xx   virtual-kubelet-cn-hangzhou-h   <none>           <none>

相關文檔

建立Agent Sandbox