在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.2 及以上,升级ack-sandbox-manager组件版本至v0.3.2 及以上。
  1. 登录容器计算服务控制台,在左侧导航栏选择集群列表

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

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

    安装Ingress Controller组件

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

    安装ack-agent-sandbox-controller组件

    使用默认配置安装组件。

    安装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域名,即步骤a中准备的域名。

      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 的沙箱模板配置。

    YAML中添加alibabacloud.com/compute-class: agent-sandbox标签即指定使用Agent Sandbox实例类型。
    apiVersion: agents.kruise.io/v1alpha1
    kind: SandboxSet
    metadata:
      name: code-interpreter
      namespace: default
    spec:
      scaleStrategy:
        maxUnavailable: 500
      # 预热池的大小,建议比预估的请求突发量略大
      replicas: 10
      # 可选,创建的沙箱在休眠、唤醒过程中需要保留的内容
      # persistentContents:
        # - ip
      # Sandbox 模板,与 Sandbox CRD 一致
      template:
        metadata:
          # annotations:
            # 可选,不填则使用acs-profile中的安全组配置,
            # 需确保对应安全组有足够的可用IP,至少需要大于replicas
            # IP不足会导致sandbox创建缓慢甚至失败
            # network.alibabacloud.com/security-group-ids: sg-8******
          labels:
            # 使用 ACS 算力
            alibabacloud.com/acs: "true"
            alibabacloud.com/compute-class: agent-sandbox # Agent Sandbox 实例类型 
            alibabacloud.com/compute-qos: default # 算力质量 default/best-effort
        spec:
          initContainers:
            # 以 native-sidecar 形式声明 agent-runtime,自动给Sandbox容器注入 envd 等运行时组件
            - name: runtime
              image: registry-cn-zhangjiakou-vpc.ack.aliyuncs.com/acs/agent-runtime:v0.0.5 # 请将 cn-zhangjiakou 替换为实际地域ID 
              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-zhangjiakou-vpc.ack.aliyuncs.com/acs/code-interpreter:v1.6 # 请将 cn-zhangjiakou 替换为实际地域ID
            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
            # 通过 post start hook 启动 envd 服务
            lifecycle:
              postStart:
                exec:
                  command: [ "/bin/bash", "-c", "/mnt/envd/envd-run.sh" ]
          # 保证容器快速销毁,提高复用的概率
          terminationGracePeriodSeconds: 1
          volumes:
            - name: envd-volume
              emptyDir: { }

    code-interpreter镜像使用说明

    • 镜像拉取registry-cn-hangzhou-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。

    pip install e2b-code-interpreter
  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

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

    整数

    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方式

  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

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 

删除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 记录类型解析到对应域名。

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