在ACS集群中创建Agent Sandbox

更新时间:
复制为 MD 格式

本文介绍如何在ACS集群中创建 Agent Sandbox(沙箱),完成组件安装、预热池创建、SDK 接入以及生产环境域名和证书配置。

准备工作

  1. 创建ACS集群,并开通Agent Sandbox服务

  2. 如已有集群,开通服务后还需升级以下组件版本。

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

    2. 升级Kube Scheduler组件版本。

      集群版本

      Kube Scheduler组件版本

      v1.28

      v1.28.12-aliyun-1.4.6及以上

      v1.30

      v1.30.3-aliyun-1.6.2及以上

      v1.31

      v1.31.0-aliyun-1.5.2及以上

      v1.32

      v1.32.0-apsara.6.11.11.3187ac8f及以上

安装组件

说明

如已安装组件,请升级ack-agent-sandbox-controller组件版本至v0.5.14-release.1及以上,升级ack-sandbox-manager组件版本至v0.6.0及以上。

  1. 登录容器计算服务控制台,在左侧导航栏选择集群列表

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择组件管理

  3. 安装 Ingress Controller 和 Sandbox 相关组件。

    1. 安装Ingress Controller组件。

      安装ACS支持的任一Ingress Controller组件,用于从集群外部访问sandbox-manager服务。后续步骤以安装ALB Ingress Controller为例,新建一个公网类型的ALB实例。

    2. 安装ack-agent-sandbox-controller组件。

      首次安装需要先授权AliyunCSManagedAgentSandboxRole角色访问您的云资源,参数可先按照默认设置,如有额外并发需求,可再提升对应资源规格。

      关于该组件功能的详细说明,请参见ack-agent-sandbox-controller

    3. 安装ack-sandbox-manager组件。

      1. 准备E2B域名。

        准备域名、域名解析和申请证书的详细操作,请参见应用于生产环境

      2. 配置组件参数。

        修改classNamealb(即安装Ingress Controller组件中自动创建的IngressClass),修改domain为实际域名,修改adminApiKey为自定义API Key,其他配置保持默认。组件安装完成后会在sandbox-system命名空间中创建一个名为sandbox-manager的路由。

        详细参数说明

        配置项

        参数

        说明

        sandboxManager

        replicaCount

        sandbox-manager 实例个数,默认值为 3。

        E2B

        domain

        E2B域名,请参考准备E2B域名

        Enable E2B_API_KEY verification

        是否开启 API_KEY 鉴权,默认开启。

        adminApiKey

        开启鉴权后,首次安装时通过该配置项来指定最初的 Key。请替换为自定义的API Key。

        Controller

        logLevel

        controller日志等级,默认为 1。

        resources.requests.cpu

        controller CPU资源请求,默认为 2。

        resources.requests.memory

        controller 内存资源请求,默认为 4Gi。

        Proxy

        resources.requests.cpu

        proxy CPU资源请求,默认为 2。

        resources.requests.memory

        proxy 内存资源请求,默认为 4Gi。

        Ingress

        className

        集群中已配置的 IngressClass 名称,如 albmse

      3. 若使用ALB Ingress Controller,还需同时为ALB实例和Ingress新增HTTPS:443监听配置。

        更新AlbConfig,为ALB实例新增HTTPS:443监听。

        1. 在左侧导航栏,选择工作负载 > 自定义资源。在资源对象浏览器页签中,搜索AlbConfig,然后单击搜索结果。

        2. AlbConfig资源对象列表中,找到目标资源alb,单击其右侧操作列下的YAML 编辑

        3. 新增spec.listeners.port: 443spec.listeners.protocol: HTTPS字段,然后单击确定

          image

        更新Ingress,关联HTTPS:443监听。

        1. 在左侧导航栏,选择网络 > 路由。在sandbox-manager路由右侧操作栏中,单击更新

        2. 添加以下配置,单击确定

          • 注解alb.ingress.kubernetes.io/listen-ports: [{"HTTP": 80}, {"HTTPS": 443}]

创建Agent Sandbox

步骤一:通过 SandboxSet 创建预热池

预热池是一组预先创建的 Sandbox 副本,由 SandboxSet CR 管理。应用从预热池中直接获取已就绪的 Sandbox,可显著提高交付效率。
  1. 单击左侧导航栏自定义资源,选择资源定义(CustomResourceDefinition)页签,单击使用YAML创建资源

  2. 使用以下 YAML 创建 SandboxSet 资源。ack-sandbox-manager 会自动监听并识别该资源,同步初始化名为 code-interpreter 的沙箱模板配置。

    启用动态存储挂载功能,需要为容器开放特权容器(Privileged Container)和宿主机路径(hostPath,/var/run/csi)的容器安全验证,可以提交工单放开限制,但由此带来的安全风险需要用户承担一定责任,相关机制请参见安全责任共担模型
    apiVersion: agents.kruise.io/v1alpha1
    kind: SandboxSet
    metadata:
      name: code-interpreter
      namespace: default
    spec:
      runtimes:
      - name: csi           # 支持CSI挂载能力,新建的Sandbox会被注入对应的Sidecar
      - name: agent-runtime # 注入envd等环境管理工具
      replicas: 4
      template:
        metadata:
          labels:
            alibabacloud.com/acs: "true"
            alibabacloud.com/compute-class: agent-sandbox # Agent Sandbox 实例类型 
            alibabacloud.com/compute-qos: default # 算力质量 default/best-effort
        spec:
          automountServiceAccountToken: false
          containers:
          - image: registry-cn-zhangjiakou-vpc.ack.aliyuncs.com/acs/code-interpreter:v1.6 # 替换成实际集群所在的地域
            imagePullPolicy: IfNotPresent
            name: sandbox
            resources:
              limits:
                cpu: "1"
                memory: 1Gi
              requests:
                cpu: "1"
                memory: 1Gi
                ephemeral-storage: 30Gi
          terminationGracePeriodSeconds: 30

    code-interpreter镜像使用说明

    • 镜像拉取registry-cn-zhangjiakou-vpc.ack.aliyuncs.com/acs/code-interpreter镜像是 ACS 基于 e2b-code-interpreter 项目制作的示例镜像,兼容 E2B 客户端的run_code接口,推荐直接使用。可将镜像地址中的地域修改为实际的地域以提高拉取速度,或去除-vpc通过公网拉取。

    • 使用自定义镜像:如需使用 E2B code-interpreter(直接使用或作为 base 镜像),推荐选择 ACS 提供的版本化镜像。ACS 不保证运行时与 E2B 官方 latest 镜像的兼容性。如需要使用自定义镜像,请确保镜像满足以下条件:

      1. 包含 cp、mv、mkdir 等基础指令。

      2. 包含 bash 且可执行文件位于/bin/bash

      使用自定义镜像时,E2B 的run_code方法暂时无法使用。

  3. 单击左侧导航栏容器组,选择对应的命名空间,查看已创建的code-interpreter Sandbox。

    可通过kubectl get sbs命令查看 SandboxSet 资源,其中AVAILABLE表示已就绪的 Sandbox 数量。

当一个 Sandbox 被分配后,SandboxSet 会自动触发补充流程,以维持预热池实例数量。

步骤二:获取Agent Sandbox

E2B SDK方式

  1. 在本地环境中安装Python

  2. 安装E2B Python SDK(仅支持小于v2.25.0的版本)。

    pip install "e2b-code-interpreter==2.7.0" "e2b==2.24.0"
  3. 配置环境变量。

    # 使用安装ack-sandbox-manager组件时默认的域名,不需要带*,可按实际配置修改
    export E2B_DOMAIN=your.domain.com
    # 使用安装ack-sandbox-manager组件时默认的API Key,可按实际配置修改
    export E2B_API_KEY=admin-987654321
  4. 将以下代码保存为main.py文件。

    # Import the E2B SDK
    from e2b_code_interpreter import Sandbox
    
    sbx: Sandbox = Sandbox.create(template="code-interpreter")
    print(f"sandbox id: {sbx.sandbox_id}")
    result = sbx.run_code("print('hello, world')")
    print(f"run code result: {result}")
    text = input("enter some text to be saved to file 'text.txt' inside sandbox:  ")
    sbx.files.write("text.txt", text)
    print(f"read file from sandbox via files api: [{sbx.files.read('text.txt')}]")
    print(f"read file from sandbox via commands api: [{sbx.commands.run('cat text.txt')}]")
    input("press ENTER to kill the sandbox")
    print(sbx.kill())
    

    create 接口 metadata 参数说明

    create 接口的 metadata 参数的使用方式,请参见使用示例

    key

    含义

    value

    e2b.agents.kruise.io/never-timeout

    是否为Sandbox配置自动清理时间。配置true则不会使用超时时间自动清理此Sandbox。

    • false

    • true

    e2b.agents.kruise.io/image

    是否为申请的Sandbox指定运行时镜像,如果镜像与预热池中声明的镜像不一致会主动原地升级镜像。

    特定镜像名,例如ghcr.io/openclaw/openclaw:****

    e2b.agents.kruise.io/wait-ready-timeout-seconds

    主要用于申请时,镜像更新场景。最长等待多久让镜像更新完成。

    整数,默认为60。

    e2b.agents.kruise.io/csi-volume-config

    支持申请Sandbox时,动态挂载NAS/OSS,格式为JSON字符串,支持细粒度配置多挂载点。每个挂载点支持配置:

    1. pvName:上述 OSS/NASPersistentVolume名称。

    2. mountPath:沙箱内的挂载目录。

    3. subPath:OSS/NAS 的 BucketPath,表示绝对地址。

    volume_config = [

    {"pvName": "oss-pv-sandbox-system", "mountPath": "/home/data-oss1", "subPath": "data-subPath1","readOnly": true}]

    e2b.agents.kruise.io/claim-timeout-seconds

    本次获取到可用沙箱最长等待多久,超过此时间直接置为申请失败。

    整数,默认为60。

    e2b.agents.kruise.io/create-on-no-stock

    默认总是会从预热池中获取沙箱,如果预热池中没有可用沙箱则会等待沙箱补充与就绪。通过配置此项可以直接基于预热池模板创建沙箱,减少等待时间。

    • false

    • true

    默认:false

    e2b.agents.kruise.io/skip-init-runtime

    申请Sandbox实例时,是否对Sandbox实例中的Agent-runtime进行初始化。如果没有runtime进程或需要高度自定义则可以配置为false

    • false

    • true

    默认:true

    e2b.agents.kruise.io/reserve-failed-sandbox

    获取沙箱时,如果出现错误管理组件会直接清理异常沙箱。通过此字段可以让管理组件保留发生错误的Sandbox实例,用于问题排查。

    • false

    • true

    默认:false

    自定义元数据

    在获取沙箱时,可以通过自定义kv,为Sandbox实例添加注解。

    自定义value,例如{"userId": "alice"}

  5. 运行main.py文件,创建并验证Sandbox。

    在第一次出现提示后,输入文字如acs agent sandbox,然后按ENTER键,会在名为code-interpreter-29***Pod/home/user/text.txt文件中写入acs agent sandbox;若再次按ENTER键,则会删除当前 Sandbox。
    python main.py

    预期输出:

    sandbox id: default--code-interpreter-29***
    run code result: Execution(Results: [], Logs: Logs(stdout: ['hello, world\n'], stderr: []), Error: None)
    enter some text to be saved to file 'text.txt' inside sandbox:  acs agent sandbox
    read file from sandbox via files api: [acs agent sandbox]
    read file from sandbox via commands api: [CommandResult(stderr='', stdout='acs agent sandbox', exit_code=0, error='')]
    press ENTER to kill the sandbox
    True

SandboxClaim方式

预热池分配Sandbox后,将立即启动自动补足逻辑,快速回填预热实例。

  1. 单击左侧导航栏自定义资源,选择资源定义(CustomResourceDefinition)页签,单击使用YAML创建资源

  2. 使用以下YAML创建 SandboxClaim 资源获取Sandbox。

    apiVersion: agents.kruise.io/v1alpha1
    kind: SandboxClaim
    metadata:
      name: code-interpreter              # SandboxSet 的名字
      namespace: default                  # SandboxSet 的命名空间
    spec:  
      templateName: code-interpreter      # 指定 SandboxSet 的名字
      replicas: 1                         # 期望从 SandboxSet 中获取的沙箱数量
      claimTimeout: 5m                    # 指定 SandboxClaim 的超时时间 
      ttlAfterCompleted: 15m              # 指定 SandboxClaim 完成后的 TTL 时间。任务完成后,经过 TTL 时间,SandboxClaim 资源会被删除(获取到的沙箱不会被删除)。
  3. 单击左侧导航栏容器组,选择default命名空间,查看新获取的名为code-interpreter-xxxxx的 Sandbox。

    可通过kubectl get sbx -l agents.kruise.io/claim-name=code-interpreter命令获取 Sandbox状态。
开发者还可通过Kubernetes SDK方式来操作Sandbox资源。

替换Agent Sandbox容器镜像

E2B SDK方式

参考以下Python代码,替换<YOUR_IMAGE>为实际的镜像地址,从预热池中取出Sandbox后,通过metadata参数将容器镜像替换为指定镜像。

from e2b_code_interpreter import Sandbox

# timeout默认时长300秒
sbx = Sandbox.create(template="some-template", timeout=300, metadata={
    # 将沙箱容器的镜像原地替换为指定镜像
    "e2b.agents.kruise.io/image": "<YOUR_IMAGE>"
})

SandboxClaim方式

替换以下<YOUR_IMAGE>为实际的镜像地址。

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
  name: my-sandbox-claim
  namespace: default
spec:
  templateName: code-interpreter    # 指定SandboxSet预热池名称
  replicas: 1
  claimTimeout: 5m
  ttlAfterCompleted: 15m
  inplaceUpdate:
    # 期望升级的目标镜像
    image: <YOUR_IMAGE> # 请将 cn-zhangjiakou 替换为实际地域ID 

指定Agent Sandbox资源规格

从预热池分配 Sandbox 时支持容器原地垂直伸缩(VPA),将已预热的低规格沙箱实例升配至业务所需规格,无需重建 Pod,兼顾预热池的快速供给与业务侧的差异化资源诉求。

说明
  • 当前仅支持调整 CPU,内存和其他资源会被忽略,且仅调整主容器。详细的使用限制及使用说明,请参考基于CPU指标的容器原地垂直伸缩

  • 集群在1.32以下版本时,需在组件管理Kube API Server配置特性门控InPlacePodVerticalScaling=true,开启原地变配功能。

步骤一:为 SandboxSet 开启原地变配

在 SandboxSet 的 spec.template.metadata.annotations 中添加 scaling.alibabacloud.com/enable-inplace-resource-resize: "true",允许预热池中的 Sandbox 在被分配时执行原地 VPA。

以下示例仅创建一个较小规格的预热池,后续分配时可指定规格动态扩容。
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxSet
metadata:
  name: code-interpreter
spec:
  template:
    metadata:
      annotations:
        # 允许从预热池分配 Sandbox 时执行原地 VPA
        scaling.alibabacloud.com/enable-inplace-resource-resize: "true"
    spec:
      containers:
        - name: interpreter
          image: xxx
          resources:
            requests:
              cpu: 500m     
              memory: 1Gi 
            limits:
              cpu: 500m 
              memory: 1Gi
...

步骤二:分配时声明目标资源规格

从预热池中分配Agent Sandbox时,可通过以下两种方式将 CPU 动态扩容至指定规格:

E2B SDK方式

Sandbox.createmetadata 中通过约定的键声明目标 CPU 规格。

from e2b_code_interpreter import Sandbox

sbx = Sandbox.create(template="code-interpreter", metadata={
    "e2b.agents.kruise.io/cpu-request": "1000m",
    "e2b.agents.kruise.io/cpu-limit": "1000m"
})

SandboxClaim方式

在 SandboxClaim 的 spec.inplaceUpdate.resources 中声明目标资源规格。

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
  name: code-interpreter-vpa-claim
  namespace: default
spec:
  templateName: code-interpreter
  replicas: 1
  claimTimeout: 5m
  ttlAfterCompleted: 15m
  inplaceUpdate:  # 声明目标资源规格
    resources:
      requests:
        cpu: 1000m
      limits:
        cpu: 1000m

删除Agent Sandbox

如需彻底移除实例,可通过以下方式删除沙箱。

E2B SDK方式

通过E2B SDK删除沙箱实例:将以下<YOUR_SANDBOX_ID>替换成实际的沙箱id

from e2b_code_interpreter import Sandbox

sandbox = Sandbox.connect("<YOUR_SANDBOX_ID>")
sandbox.kill()

Sandbox CR方式

# 执行前请将 <NAMESPACE> 替换为资源对应的命名空间,<RESOURCE_NAME>替换为实际的CR名称
kubectl -n <NAMESPACE> delete sandbox <RESOURCE_NAME>

应用于生产环境

准备域名

可参考添加/删除内网权威域名 (Zone)配置域名your.domain.com*.your.domain.com,并解析到Ingress的地址;如果访问完全在ACS集群内部,也可以直接使用集群内Headless Service地址:sandbox-manager.sandbox-system.svc.cluster.local

申请证书

E2B 客户端可以通过 HTTPS 协议请求后端。在生产场景下,推荐使用以下方式申请证书。

(推荐)方式一: 使用 cert-manager 管理证书

以下步骤提供了一种使用 cert-manager 来管理和部署 sandbox-manager 自签证书的最佳实践。请确保具备 kubectl 命令行工具并有cert-manager API的操作权限。

步骤一:安装 cert-manager

请参考 官方文档 安装 v1.14 版本的cert-manager。

由于最新版本使用的是社区的镜像仓库(quay.io),推荐使用 v1.14 版本。
步骤二:通过 cert-manager 自动管理证书
  1. cert-manager.yaml 中的*.your.domain.comyour.domain.com替换为你的域名。

    示例YAML中使用了自签的CA证书,也可以使用自己的CA证书。
  2. 执行kubectl apply -f cert-manager.yaml命令,将配置添加到 ACS 集群中。

步骤三:验证证书状态
  1. 检查证书是否正确创建和颁发。

    kubectl get certificates -n sandbox-system
    kubectl describe certificate sandbox-manager-ingress-cert -n sandbox-system
    kubectl describe secret sandbox-manager-tls -n sandbox-system
  2. 检查 Ingress 状态。

    kubectl get ingress sandbox-manager -n sandbox-system
    kubectl describe ingress sandbox-manager -n sandbox-system
步骤四:配置客户端信任

若使用的是自签名证书,客户端需要信任根 CA 证书。

  1. 获取 CA 证书。

    kubectl get secret sandbox-ca-key-pair -n sandbox-system -o jsonpath='{.data.tls\.crt}' | base64 -d > ca.crt
  2. 配置客户端。客户端需要设置环境变量 SSL_CERT_FILE 为获取的 CA 证书路径或者将 CA 证书添加到系统的信任存储中。

    export SSL_CERT_FILE=/path/to/ca.crt

方式二:使用自签证书

步骤一:创建证书
  1. 通过脚本 generate-certificates.sh 创建自签名证书。可通过以下命令查看脚本的使用方法。

    bash generate-certificates.sh --help

    预期输出:

    Usage: generate-certificates.sh [OPTIONS]
    
    Options:
      -d, --domain DOMAIN     Specify certificate domain (default: example.com)
      -o, --output DIR        Specify output directory (default: .)
      -D, --days DAYS         Specify certificate validity days (default: 365)
      -h, --help              Show this help message
    
    Examples:
      generate-certificates.sh -d myapp.example.com
      generate-certificates.sh --domain api.example.com --days 730
  2. 执行generate-certificates.sh -d your.domain.com命令,生成证书。完成证书生成后,会创建以下文件:

    • fullchain.pem:服务器证书公钥

    • privkey.pem:服务器证书私钥

    • ca-fullchain.pem:CA 证书公钥

    • ca-privkey.pem:CA 证书私钥

    该脚本会同时生成单域名(your.domain.com)与泛域名(*.your.domain.com)证书,兼容原生 E2B 协议与 OpenKruise 定制 E2B 协议。

步骤二:安装证书

通过以下命令将服务器证书挂载到集群的 Ingress 上:

kubectl create secret tls sandbox-manager-tls \
        --cert=fullchain.pem \
        --key=privkey.pem -n sandbox-system
证书的生效可能会有一些延迟,具体生效时间由所用的 Ingress 控制器决定。
步骤三:配置客户端信任

客户端需要设置环境变量 SSL_CERT_FILE 为步骤一中生成的 CA 公钥(ca-fullchain.pem)文件路径:

export SSL_CERT_FILE=/path/to/ca-fullchain.pem
python main.py # 通过 python 调用 E2B SDK

方式三:采用正式证书(以 Let's Encrypt 为例)

步骤一:准备证书

E2B 客户端必须通过 HTTPS 协议请求后端。在生产场景下,推荐申请一个正式的域名证书。

以下示例通过 Let's Encrypt 申请一个免费的测试证书(Let's Encrypt证书需要强依赖公网域名)。

  1. 通过系统的包管理器(brew、snap 等)安装 certbot,更多安装信息请查看 官方文档

  2. 修改-d--email的参数为泛域名your.domain.com 申请证书。请根据命令的提示进行验证操作。

由于签发的证书同时包括泛域名和单域名,通过 TXT 解析鉴权的流程需要连续操作两次。
sudo certbot certonly \
  --manual \
  --preferred-challenges=dns \
  --email your-email@example.com \
  --server https://acme-v02.api.letsencrypt.org/directory \
  --agree-tos \
  -d "your.domain.com" \
  -d "*.your.domain.com"
步骤二:导出证书
sudo cp /etc/letsencrypt/live/your.domain.com/fullchain.pem ./fullchain.pem
sudo cp /etc/letsencrypt/live/your.domain.com/privkey.pem ./privkey.pem
步骤三:安装证书
kubectl create secret tls sandbox-manager-tls \
  --cert=fullchain.pem \
  --key=privkey.pem \
  --namespace=sandbox-system

域名解析

通过以下命令查看接入点信息:

kubectl get ingress sandbox-manager -o jsonpath='{range .status.loadBalancer.ingress[*]}{.hostname}{.ip}{"\n"}{end}' -n sandbox-system

根据输出的接入点信息,配置域名 your.domain.com 或者 *.your.domain.com 的解析。更多域名解析相关的操作,请参见快捷入口

  • 如果输出的是一个 IP 地址(如47.114.***.***),请将主机记录 *.your.domain.com 以 A 记录类型解析到该 IP。

  • 如果输出的是一个域名(如alb-*****62roo70i*****.cn-hangzhou.alb.aliyuncsslb.com),请将主机记录 *.your.domain.com 以 CNAME 记录类型解析到对应域名。

  • 如果输出多个接入点,将记录解析到其中任意一个接入点,或为所有接入点配置轮询均可。

常见问题

ack-agent-sandbox-controller组件安装失败,错误信息:[RAM Role AliyunCSManagedAgentSandboxRole is not granted]

  1. 进入RAM访问控制-角色页面,搜索AliyunCSManagedAgentSandboxRole,然后单击角色名称进入角色详情页。

  2. 在角色详情页,勾选AliyunCSManagedAgentSandboxRolePolicy,然后单击解除授权

  3. 重新进行授权,单击授权链接