为Agent Sandbox挂载共享存储

更新时间:
复制为 MD 格式

本文介绍如何在创建Agent Sandbox时为沙箱挂载OSSNAS静态存储卷。

前提条件

  1. 已完成Agent Sandbox的基础环境搭建,具体操作,请参见创建Agent Sandbox

  2. 在集群组件管理中,确认ack-agent-sandbox-controller组件版本为v0.5.12及以上。

    安装组件时,在sandbox-system命名空间下会自动创建名为sandbox-injection-configConfigMap,包含agent-runtimecsi两个配置项。

    如需特殊定制或配置修改,请在修改前联系阿里云技术支持评估配置的完备性。
  3. 在集群组件管理中,确认ack-sandbox-manager组件版本为v0.5.2及以上。

启用动态存储挂载功能,需要为容器开放特权容器(Privileged Container)和宿主机路径(hostPath,/var/run/csi)的容器安全验证,可以提交工单放开限制,但由此带来的安全风险需要用户承担一定责任,相关机制请参见安全责任共担模型

使用限制

  • 支持基于E2BCreate接口、休眠/唤醒功能以及原地升级镜像后的运行时存储挂载,但目前不支持基于Checkpoint机制创建快照后恢复存储挂载。

  • 目前OSS静态存储挂载仅支持AccessKey鉴权方式。

  • 在配置网络策略或流量策略时,请务必确保已放行访问 OSS/NAS 管控端点的出方向流量。

挂载共享存储

ACS支持在Sandbox运行时为其挂载存储卷(PV),如阿里云OSS、NAS等。此功能依赖agent-runtime组件,您可以通过E2B SDK(如Sandbox.createSandbox.beta_create接口)或SandboxClaim对象两种方式触发挂载。

步骤一:配置存储挂载能力

ACS提供动态注入Sidecar的配置方案。您只需在SandboxSetSandbox对象上设置spec.runtimes参数,框架会在Sandbox被创建时自动注入所需的CSI配置,包括agent-runtime和存储相关的CSI Sidecar配置。

以下为SandboxSet配置示例:

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxSet
metadata:
  name: code-interpreter-inject-test
  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
      terminationGracePeriodSeconds: 30

以下为Sandbox对象的配置示例:

apiVersion: agents.kruise.io/v1alpha1
kind: Sandbox
metadata:
  name: code-interpreter-inject-test-xxx
  namespace: default
spec:
  runtimes:
  - name: csi           # 提供CSI挂载能力
  - name: agent-runtime # 注入envd等环境管理工具
  ...

步骤二:创建存储卷

根据您的存储需求,在集群中创建对应的PV对象。以下分别介绍OSSNAS静态存储卷的创建方法。

创建OSS存储卷

创建一份描述OSSPersistentVolume对象和对应的访问密钥Secret对象。更多信息,请参见使用OSS静态存储卷

apiVersion: v1
kind: Secret
metadata:
  name: oss-secret
  # 密钥对象必须创建在sandbox-system命名空间
  namespace: sandbox-system
stringData:
  akId: <YOUR_ACCESS_KEY_ID>       # 访问OSS的AccessKey ID
  akSecret: <YOUR_ACCESS_KEY_SECRET> # 访问OSS的AccessKey Secret
---
apiVersion: v1
kind: PersistentVolume
metadata:
  labels:
    alicloud-pvname: oss-pv-sandbox-system
  name: oss-pv-sandbox-system
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 50Gi
  csi:
    driver: ossplugin.csi.alibabacloud.com
    nodePublishSecretRef:
      name: oss-secret
      namespace: sandbox-system
    volumeAttributes:
      bucket: <OSS_BUCKET>               # 替换为OSS中实际的Bucket名称
      otherOpts: -o umask=022 -o allow_other
      url: <OSS_ENDPOINT>               # OSS访问端点,请替换为实际OSS Endpoint地址
    volumeHandle: oss-pv-sandbox-system
  persistentVolumeReclaimPolicy: Retain
  storageClassName: test
  volumeMode: Filesystem

创建NAS存储卷

进入NAS存储接入点页面,复制接入点域名,替换以下<YOUR_NAS_ACCESS_POINT>。更多信息,请参见使用NAS静态存储卷

apiVersion: v1
kind: Secret
metadata:
  name: ap-secret
  # 密钥对象必须创建在sandbox-system命名空间
  namespace: sandbox-system
stringData:
  akId: <YOUR_ACCESS_KEY_ID>       # 访问NAS的AccessKey ID
  akSecret: <YOUR_ACCESS_KEY_SECRET> # 访问NAS的AccessKey Secret
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nas-pv-sandbox-system
spec:
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 50Gi
  csi:
    nodePublishSecretRef:
      name: ap-secret
      namespace: sandbox-system
    driver: nasplugin.csi.alibabacloud.com
    volumeHandle: nas-pv-sandbox-system
    volumeAttributes:
      accessPoint: <YOUR_NAS_ACCESS_POINT>  # 接入点域名
      path: /                               # 需要挂载的接入点子目录,最终挂载的路径为 [接入点根目录]/[path]
  mountOptions:
    - nolock,tcp,noresvport,tls,ram         # 默认配置 accessPoint 需要开启 RAM 鉴权
    - vers=3                                # 暂不支持vers=4.0配置

步骤三:挂载存储卷

根据您的使用场景,选择以下任一方式将存储卷挂载到Sandbox。

通过E2B SDK挂载

挂载单个存储卷

您可以参考以下Python代码,从预热池中获取Sandbox后,将存储卷挂载到沙箱内的指定目录。

为了获得更好的扩展性及对未来新特性的持续支持,建议优先使用挂载多个存储卷方式进行存储挂载,后续新特性将不再支持单存储卷挂载方式(e2b.agents.kruise.io/csi-volume-name)。

挂载OSS存储卷示例

from e2b_code_interpreter import Sandbox

sbx = Sandbox.create(template="code-interpreter-inject-test", timeout=300, metadata={
    "e2b.agents.kruise.io/csi-volume-name": "oss-pv-sandbox-system", # OSS的PersistentVolume名称
    "e2b.agents.kruise.io/csi-mount-point": "/data-oss", # 挂载路径必须为一个空目录,否则将导致挂载失败。
    "e2b.agents.kruise.io/csi-subpath": "data-subPath"  # 相对路径,表示在OSS Bucket内的相对子目录
})

挂载NAS存储卷示例

from e2b_code_interpreter import Sandbox

sbx = Sandbox.create(template="code-interpreter-inject-test", timeout=300, metadata={
    "e2b.agents.kruise.io/csi-volume-name": "nas-pv-sandbox-system",
    "e2b.agents.kruise.io/csi-mount-point": "/data-nas", # 挂载路径必须为一个空目录,否则将导致挂载失败。
    "e2b.agents.kruise.io/csi-subpath": "data-subPath"   # 相对路径,必须为已存在的 NAS 目录
})
如遇504响应问题,请前往配置管理 > 配置项修改sandbox-injection-config,将csi-agent 镜像地址替换为registry-cn-zhangjiakou-vpc.ack.aliyuncs.com/acs/csi-agent:v1.35.4-3c34d4a-aliyun,再重新创建Sandbox即可。

metadata参数说明如下:

参数

说明

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

指定PersistentVolume对象的名称。

e2b.agents.kruise.io/csi-mount-point

指定存储卷在容器内的挂载目录。

重要

挂载路径必须为一个空目录,否则将导致挂载失败。

e2b.agents.kruise.io/csi-subpath

指定存储卷在远端存储内的子目录名(相对路径)。

挂载多个存储卷

如果需要一次挂载多个存储卷,可以使用e2b.agents.kruise.io/csi-volume-config参数,通过JSON数组格式指定多个挂载配置。

若同时配置了e2b.agents.kruise.io/csi-volume-config(新协议)和单卷挂载参数(旧协议),新协议的优先级高于旧协议。

以下为同时挂载多个存储卷的Python代码示例:

from e2b_code_interpreter import Sandbox

sbx = Sandbox.create(template="code-interpreter-inject-test", timeout=600, metadata={
    "e2b.agents.kruise.io/csi-volume-config": '[{"pvName":"nas-pv-sandbox-system","mountPath":"/data-nas","subPath":"data-subPath"},{...}]'
})
print(f"sandbox id: {sbx.sandbox_id}")

csi-volume-config相关配置说明如下:

字段

类型

说明

pvName

String

PersistentVolume对象名称。

mountPath

String

期望挂载到容器内的目录路径。

subPath

String

远端存储的子目录名(相对路径),可选。

readOnly

Boolean

是否以只读方式挂载,可选,默认为false。

通过SandboxClaim挂载

SandboxClaim方式适用于通过Claim对象从预热的SandboxSet中分配Sandbox的场景。您可以在SandboxClaim对象上直接声明动态挂载的存储卷配置,被分配的Sandbox将自动按该配置完成挂载。

创建SandboxClaim对象

SandboxClaim对象的spec.dynamicVolumesMount字段中声明需要挂载的存储卷。Claim完成后,被分配的Sandbox将自动按照该配置挂载存储卷。以下为同时挂载多个存储卷的YAML示例:

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
  name: code-interpreter-claim          # SandboxClaim名称
  namespace: default                    # 命名空间
spec:
  templateName: code-interpreter-inject-test  # 关联的SandboxSet名称
  replicas: 1                           # 期望从SandboxSet内Claim的Sandbox数量
  claimTimeout: 5m                      # Claim超时时间
  ttlAfterCompleted: 15m                # Claim完成后的TTL
  dynamicVolumesMount:                  # 动态挂载的存储卷列表
  - pvName: oss-pv-sandbox-system       # 对应的PersistentVolume名称
    mountPath: "/data-oss"              # 容器内期望挂载的目录路径
    subPath: "data-subPath"             # 远端存储的子目录,替换为实际的目录名称
    readOnly: true                      # 是否以只读方式挂载
  - pvName: nas-pv-sandbox-system
    mountPath: "/data-nas"
    subPath: "data-subPath"
    readOnly: false

dynamicVolumesMount字段说明如下:

字段

类型

说明

pvName

String

PersistentVolume对象名称。

mountPath

String

期望挂载到容器内的目录路径。

subPath

String

远端存储的子目录名(相对路径),可选。

readOnly

Boolean

是否以只读方式挂载,可选,默认为false。

验证挂载结果

SandboxClaim创建成功后,其status状态变为Completed即表示Claim与挂载流程已完成。

您可以通过以下命令查询SandboxClaim分配出的Sandbox。每个被ClaimSandbox会自动带上agents.kruise.io/claim-name标签,标签值为SandboxClaim的名称。

kubectl get sandbox -n default -l agents.kruise.io/claim-name=code-interpreter-claim

预期输出:

NAME                                 STATUS    AGE   SHUTDOWN_TIME   PAUSE_TIME   MESSAGE
code-interpreter-inject-test-6vh94   Running   22h

替换以下<POD_NAME>查看dynamicVolumesMount中配置的OSS挂载目录。

kubectl exec -it <POD_NAME> -- ls -al / | grep oss

预期输出:

lrwxrwxrwx   1 root root   56 Apr 21 11:15 data-oss -> /run/csi/mount-root/oss/f69ed0682da41xxxxxxx80bf6fe851d69