拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OpenSandbox Code Interpreter 实战:在安全沙箱中执行多语言代码与 Kubernetes Pool 预热模式

OpenSandbox Code Interpreter 实战在安全沙箱中执行多语言代码与 Kubernetes Pool 预热模式【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox本文基于 OpenSandbox 官方示例文档完整讲解 Code Interpreter 沙箱的落地全流程拉取预构建镜像、启动本地或 Kubernetes 版 OpenSandbox 服务端、使用 Python SDK 在沙箱内执行 Python/Java/Go/TypeScript 代码并捕获 stdout 与执行结果以及通过 Pool 资源池实现免冷启动的按需分配。读完本文你可以复制仓库中的 main.py 与 main_use_pool.py 直接在本地或 k8s 集群上跑通多语言代码解释器并理解服务端 entrypoint 注入与 task-executor 的底层工作机制。整体架构Sandbox CodeInterpreter 的分层设计Code Interpreter 并非独立的运行时而是构建在 OpenSandbox 通用沙箱能力之上的 SDK 层。从源码结构看分层关系非常清晰Sandbox 层opensandbox SDK负责沙箱基础设施——容器/Pod 生命周期、网络、文件系统、命令执行CodeInterpreter 层code_interpreter SDK包裹一个已存在的 Sandbox 实例在其之上提供多语言代码执行、执行上下文Context管理与变量持久化沙箱内运行时code-interpreter 镜像内置 Jupyter kernel gateway由 execd 守护进程统一对外提供代码执行 API默认 execd 端口经sandbox.get_endpoint(DEFAULT_EXECD_PORT)获取服务端opensandbox-server接收 SDK 的创建请求按 ProviderDocker 或 Kubernetes BatchSandbox实际拉起工作负载。CodeInterpreter.create(sandboxsandbox)是唯一的工厂入口它会先解析 execd 端点然后执行双重严格健康检查见下文“源码实现”一节确认沙箱内 Jupyter 运行时真正就绪后才返回可用实例。这种“Sandbox 管基础设施、CodeInterpreter 管代码执行”的关注点分离也是 code_interpreter.py 模块文档中明确的设计原则。获取 Code Interpreter 镜像Code Interpreter 依赖一个专用的预构建容器镜像镜像中预装了 Python、Java、Go、Node.js 等多语言运行时。官方镜像源与环境定义维护在独立的 sandbox-images 仓库中。从镜像仓库拉取即可docker pull sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/code-interpreter:v1.1.0 # use docker hub # docker pull opensandbox/code-interpreter:v1.1.0注意Code Interpreter SDK README 强调必须使用opensandbox/code-interpreter镜像或其衍生镜像普通python:3.11之类的裸镜像不含 Jupyter 运行时无法通过 CodeInterpreter 的严格健康检查。语言版本可以通过创建沙箱时注入环境变量选择未设置时使用镜像默认版本语言环境变量示例值PythonPYTHON_VERSION3.11JavaJAVA_VERSION17Node.jsNODE_VERSION20GoGO_VERSION1.24启动本地 OpenSandbox 服务端Docker Provider在 Docker 环境下启动本地服务端只需三步uv pip install opensandbox-server opensandbox-server init-config ~/.sandbox.toml --example docker opensandbox-serverinit-config --example docker会生成一份基于 Docker 运行时的示例配置~/.sandbox.toml随后opensandbox-server启动并监听示例脚本默认连接localhost:8080。创建并访问 Code Interpreter 沙箱安装 SDK 后运行仓库内置示例# Install OpenSandbox packages uv pip install opensandbox opensandbox-code-interpreter # Run the example (requires SANDBOX_DOMAIN / SANDBOX_API_KEY) uv run python examples/code-interpreter/main.py示例脚本环境变量变量默认值说明SANDBOX_DOMAINlocalhost:8080沙箱服务地址SANDBOX_API_KEY(可选)服务端开启鉴权时必填的 API keySANDBOX_IMAGEsandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/code-interpreter:v1.1.0使用的沙箱镜像示例代码逐段解析main.py 的完整流程分为四步核心代码结构如下import asyncio import os from datetime import timedelta from code_interpreter import CodeInterpreter, SupportedLanguage from opensandbox import Sandbox from opensandbox.config import ConnectionConfig async def main() - None: domain os.getenv(SANDBOX_DOMAIN, localhost:8080) api_key os.getenv(SANDBOX_API_KEY) image os.getenv( SANDBOX_IMAGE, sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/code-interpreter:v1.1.0, ) # 1. 连接配置域名 可选 API Key 请求超时 config ConnectionConfig( domaindomain, api_keyapi_key, request_timeouttimedelta(seconds60), ) # 2. 创建沙箱entrypoint 指向镜像内的 code-interpreter 启动脚本 sandbox await Sandbox.create( image, connection_configconfig, entrypoint[/opt/code-interpreter/code-interpreter.sh] ) try: # 3. 包裹 CodeInterpreter内部含 execd ping Jupyter 端口探活 interpreter await CodeInterpreter.create(sandboxsandbox) # 4. 以 language 参数使用各语言的“默认上下文”状态跨 run 持久化 py_exec await interpreter.codes.run( import platform\n print(Hello from Python!)\n result {py: platform.python_version(), sum: 2 2}\n result, languageSupportedLanguage.PYTHON, ) print(\n Python example ) for msg in py_exec.logs.stdout: print(f[Python stdout] {msg.text}) if py_exec.result: for res in py_exec.result: print(f[Python result] {res.text}) # ... Java / Go / TypeScript 示例同理 finally: # 5. 无论成功与否都销毁远端实例避免资源泄漏 await sandbox.destroy()几个关键实现点entrypoint[/opt/code-interpreter/code-interpreter.sh]这是镜像内启动 Jupyter 运行时的入口脚本缺少它沙箱内的解释器运行时不会启动CodeInterpreter.create的严格健康检查会超时抛出SandboxReadyTimeoutExceptionlanguageSupportedLanguage.PYTHON而不是create_context从 services/code.py 的run协议定义可知当只传language而不传context时execd 会为该语言创建或复用一个默认会话因此同一语言多次run的变量状态可以跨执行持久化models/code.py 中SupportedLanguage枚举定义了六种语言PYTHON、JAVA、GO、TYPESCRIPT、BASH、JAVASCRIPT结果结构Execution对象区分logs.stdout/logs.stderr标准输出流与result代码最后一个表达式的求值结果。Python 示例最后单独写一行result正是为了让解释器捕获{py: 3.14.2, sum: 4}这个值而print的内容进入 stdoutfinally中await sandbox.destroy()官方文档特别指出即使解释器初始化或代码执行抛异常清理逻辑仍会执行保证远端实例被终止。运行后的典型输出为 Python example [Python stdout] Hello from Python! [Python result] {py: 3.14.2, sum: 4} Java example [Java stdout] Hello from Java! [Java stdout] 2 3 5 [Java result] 5 Go example [Go stdout] Hello from Go! 3 4 7 TypeScript example [TypeScript stdout] Hello from TypeScript! [TypeScript stdout] sum 6该示例还附带了 test_main.py 作为测试入口可结合 SDK 自身测试如 test_code_service_adapter_streaming.py理解流式输出与请求适配层的实现。扩展用法上下文隔离、流式输出与同步 API除示例脚本外SDK README 还覆盖了以下能力均为同一套interpreter.codes服务显式上下文await interpreter.codes.create_context(SupportedLanguage.PYTHON)创建独立会话不同语言上下文相互隔离多语言互不串状态流式输出通过ExecutionHandlers(on_stdout..., on_stderr...)实时处理逐行输出适合长任务同步 APISandboxSyncCodeInterpreterSyncConnectionConfigSync组合提供非 asyncio 的等价实现运行时安装依赖await sandbox.commands.run(pip install pandas numpy)可直接在沙箱内装包随后在代码中 import 使用。从 Pool 池获取 Code Interpreter 沙箱Kubernetes在 Kubernetes 场景下冷启动一个 Pod 需要拉镜像、起容器。OpenSandbox 提供 Pool 资源池机制预先创建并保活一批“热 Pod”生命周期 API 直接从池中分配跳过容器冷启动。启动 k8s OpenSandbox 服务端uv pip install opensandbox-server # replace with your k8s cluster config, kubeconfig etc. opensandbox-server init-config ~/.sandbox.toml --example k8s curl -o ~/batchsandbox-template.yaml https://raw.githubusercontent.com/opensandbox-group/OpenSandbox/main/server/opensandbox_server/examples/example.batchsandbox-template.yaml opensandbox-serverBatchSandbox 模板文件在仓库中同样有本地副本example.batchsandbox-template.yaml可直接查看而非依赖远程下载。服务端 k8s 示例配置可参考 example.config.k8s.toml。创建 Pool 资源以下 Pool 声明来自官方示例文档它定义了池容量水位bufferMin/bufferMax与poolMin/poolMax以及一个三阶段启动模板。Pool CRD 的另一种样例见 sandbox_v1alpha1_pool.yamlapiVersion: sandbox.opensandbox.io/v1alpha1 kind: Pool metadata: labels: app.kubernetes.io/name: sandbox-k8s app.kubernetes.io/managed-by: kustomize name: pool-sample namespace: opensandbox spec: template: metadata: labels: app: example spec: volumes: - name: sandbox-storage emptyDir: { } - name: opensandbox-bin emptyDir: { } initContainers: - name: task-executor-installer image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/task-executor:v0.1.0 command: [ /bin/sh, -c ] args: - | cp /workspace/server /opt/opensandbox/task-executor chmod x /opt/opensandbox/task-executor volumeMounts: - name: opensandbox-bin mountPath: /opt/opensandbox - name: execd-installer image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.1.0 command: [ /bin/sh, -c ] args: - | cp ./execd /opt/opensandbox/execd cp ./bootstrap.sh /opt/opensandbox/bootstrap.sh chmod x /opt/opensandbox/execd chmod x /opt/opensandbox/bootstrap.sh volumeMounts: - name: opensandbox-bin mountPath: /opt/opensandbox containers: - name: sandbox image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/code-interpreter:v1.1.0 command: - /bin/sh - -c - | /opt/opensandbox/task-executor \ -listen-addr0.0.0.0:5758 \ -log-dir/tmp env: - name: SANDBOX_MAIN_CONTAINER value: main - name: EXECD_ENVS value: /opt/opensandbox/.env - name: EXECD value: /opt/opensandbox/execd volumeMounts: - name: sandbox-storage mountPath: /var/lib/sandbox - name: opensandbox-bin mountPath: /opt/opensandbox tolerations: - operator: Exists capacitySpec: bufferMax: 3 bufferMin: 1 poolMax: 5 poolMin: 0Pool 模式的 entrypoint 注入机制这是 Pool 方案中最容易误解的部分官方文档给出了明确的机制说明生命周期 API 分配的是 Pool 中已经在运行的 Pod因此它不会替换该 Pod 的command、args或env。当创建请求携带entrypoint或环境变量时服务端把它们记录到BatchSandbox.spec.taskTemplate中Controller 随后再通过 Pod IP 的5758 端口把任务下发给 Pod 内的 task-executor 执行。因此 Pool 模板必须自行提供完整执行链路安装并前台运行 task-executor监听0.0.0.0:5758并显式指定-log-dir使排查路径确定示例写/tmp日志落在/tmp/task-executor.log在 Pod 启动前安装 execd 与 bootstrap.sh到共享卷/opt/opensandbox由上面的两个 initContainer 完成bootstrap.sh必须保持在/opt/opensandbox/bootstrap.sh因为服务端生成的任务会调用这个固定路径execd 二进制可以用其他路径前提是 task-executor 环境中通过EXECD变量正确指向分配后由 bootstrap.sh 启动 execd这样EXECD_ACCESS_TOKEN等请求级变量才可用——这正是示例把 task-executor 而非业务进程留作热 Pod 前台进程的原因。由此可以推断Pod YAML 里始终显示 Pool 模板是预期行为排查时应该看BatchSandbox资源与 task-executor而不是 Pod 定义。官方给出的排查命令序列# Confirm that the server injected the requested process and environment. kubectl get batchsandbox sandbox-name -n namespace \ -o jsonpath{.spec.taskTemplate}{\n} # Find the allocated Pod. The annotation value contains a JSON pods array. kubectl get batchsandbox sandbox-name -n namespace \ -o jsonpath{.metadata.annotations.sandbox\.opensandbox\.io/alloc-status}{\n} # Replace pool-pod with the first Pod name from that array. kubectl exec pool-pod -n namespace -- \ sh -c test -x /opt/opensandbox/task-executor test -x /opt/opensandbox/bootstrap.sh kubectl exec pool-pod -n namespace -- \ tail -n 100 /tmp/task-executor.log # Check the executor health endpoint from a second terminal while this runs. kubectl port-forward pod/pool-pod -n namespace 5758:5758 curl http://127.0.0.1:5758/health curl http://127.0.0.1:5758/getTasks # The lifecycle server uses sandbox-name-0 as the task name. Check the tasks # captured output (adjust the path if task-executor uses a custom data directory). kubectl exec pool-pod -n namespace -- \ sh -c tail -n 100 /var/lib/sandbox/tasks/sandbox-name-0/stdout.log; tail -n 100 /var/lib/sandbox/tasks/sandbox-name-0/stderr.log # Check controller logs for delivery failures between the controller and port 5758. kubectl logs -n opensandbox-system -l control-planecontroller-manager --tail100一个关键的故障排查提示如果taskTemplate已存在但健康检查连不上 5758 端口先确认 task-executor 已安装且仍在运行。由于生成的任务是在后台启动bootstrap.sh的即使bootstrap.sh缺失或请求的 entrypoint 后续失败任务包装器也可能报告成功——所以不要仅依赖taskFailed或taskLastErrorMessage判断这类失败应直接检查任务的stderr.log/stdout.log并核实 execd 或应用进程本身。运行 Pool 示例main_use_pool.py 与单实例版本的关键差异在于Sandbox.create的三个参数sandbox await Sandbox.create( image, connection_configconfig, extensions{poolRef:pool-sample}, # 引用上面创建的 Pool entrypoint[/opt/code-interpreter/code-interpreter.sh], env{TEST_ENV: test}, # 请求级环境变量经 taskTemplate 注入 )随后脚本先用一段 Python 代码验证TEST_ENV是否成功注入到沙箱内再依次执行 Java、Go、TypeScript 示例最后调用await sandbox.kill()归还池资源。运行方式uv pip install opensandbox opensandbox-code-interpreter uv run python examples/code-interpreter/main_use_pool.pyPool 示例的典型输出注意第一段是环境变量验证 Verify Environment Variable [ENV Check] TEST_ENV value: test [ENV Result] test Java example [Java stdout] Hello from Java! [Java stdout] 2 3 5 [Java result] 5 Go example [Go stdout] Hello from Go! 3 4 7 TypeScript example [TypeScript stdout] Hello from TypeScript! [TypeScript stdout] sum 6源码实现佐证结合服务端源码可以对上述机制做三点印证poolRef仅 Kubernetes Provider 支持。docker_service.py 中明确校验请求携带extensions.poolRef时Docker provider 会直接拒绝并提示 poolRef is not supported by the Docker provider. Use Kubernetes BatchSandbox provider insteadkubernetes_service.py 则负责校验 Pool 是否存在并限制 pooled 场景不能与networkPolicy同时使用因为池 Pod 是预创建的。这也解释了为什么 Pool 示例必须走 k8s 服务端。严格健康检查的实现。code_interpreter.py 中定义了RUNTIME_PROCESS_CHECK_COMMANDL52-L55CodeInterpreter.create的健康检查包含两步——execd 守护进程响应GET /ping且通过 execd 命令 API 探测沙箱内 Jupyter 监听端口127.0.0.1:${JUPYTER_PORT:-44771}默认 44771是否可连接。注释解释得很直接execd 在 entrypoint 启动 Jupyter 之前就开始服务/ping仅凭守护进程 ping 无法证明解释器运行时就绪默认ready_timeout为 30 秒、轮询间隔 200 毫秒可用skip_health_checkTrue关闭。执行上下文的数据模型。models/code.py 中CodeContext只含id与language两个字段语言字段经校验器保证非空省略context.id即触发 execd 侧的“默认会话”语义这与示例脚本只传language的写法一一对应。适用前提与参考本地Docker路径要求宿主机可运行 Docker且能拉取上述 code-interpreter 镜像k8s 路径要求已部署 OpenSandbox operatorPool/BatchSandbox CRD 与 controllerSANDBOX_DOMAIN指向的服务端必须与沙箱 Provider 匹配Docker 服务端走--example docker配置Pool 场景必须走--example k8s配置镜像中各语言的具体版本以 sandbox-images 仓库的环境文档为准本文涉及的v1.1.0镜像版本以仓库文档与示例代码为准。关键参考路径本文档原始来源docs/examples/code-interpreter.md示例脚本main.py、main_use_pool.pyPython Code Interpreter SDKcode_interpreter.py、README.md服务端 Pool 校验逻辑kubernetes_service.py、docker_service.pyBatchSandbox 模板示例example.batchsandbox-template.yaml【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门