SkyPilot Sandboxes 实战指南在自有 Kubernetes 集群上按需创建秒级隔离计算环境【免费下载链接】skypilotThe AI Compute Platform for frontier teams. SkyPilot turns fragmented AI compute into one AI supercomputer, so frontier AI teams build custom intelligence faster.项目地址: https://gitcode.com/GitHub_Trending/sk/skypilotSkyPilot Sandboxes 是 SkyPilot 提供的一种快速、隔离的计算环境每个 sandbox 就是一个轻量级 Kubernetes Pod可以在你自己的集群上按需创建、执行命令、随时销毁无需预置整个集群。它专为 AI 编码代理AI coding agents、RL 训练 rollout 和并行评测parallel evals等需要大量短生命周期隔离环境的工作负载设计预热的 warm pool 可将启动时间压缩到1 秒以内并在创建时自动注入卷volumes与密钥secrets。读完本文你将掌握sky sandboxCLI 与sky.sandboxPython SDK 的完整用法包括批量创建、异步并发分发、密钥/卷注入、sandbox 间网络、快照恢复、warm pool 预热池、Docker-in-Docker 以及 GKE gVisor 加固等生产级能力。注意Sandboxes 属于SkyPilot Platform的一部分目前处于限量早期访问limited early access阶段。使用sky.sandboxSDK 需要 API server 开启 Sandbox 功能可通过SKYPILOT_API_SERVER_ENDPOINT指定。为什么选择 SkyPilot Sandboxes与直接开一台虚拟机或预置整个集群相比Sandboxes 的核心价值来自其 Kubernetes 原生的设计取舍亚秒级启动Sub-second launches预热池pre-warmed pools让空闲环境保持就绪状态create时直接认领一个已在运行的 Pod而不是等待镜像拉取与调度单个 sandbox 的启动时间可缩短50% 以上。每 Pod 天然隔离Isolated per pod每个 sandbox 都是独立的 Kubernetes Pod拥有专属镜像、CPU 与内存。这是运行 Agent 生成的、或任何不可信代码的天然边界——代码无法触碰你的其他工作负载。密钥不进入代码Secrets stay out of your code凭据在启动时由 SkyPilot Secrets Manager 以环境变量的形式注入token 永远不会被写进镜像或硬编码进 Agent 运行的命令里。大规模并行Massively parallel一次调用即可创建数千个 sandbox 用于 RL rollout 与并行评测并可并发分发命令。运行在你的基础设施上Runs on your infrasandbox 运行在你自己的 Kubernetes 集群上代码与数据永不离开你的环境容量就是现有集群的容量。快照与恢复Snapshot restore把 sandbox 的整个文件系统捕获成快照镜像之后从快照恢复出全新 sandbox——昂贵的环境准备只做一次之后直接续用无需重复执行。Sandbox 间网络Sandbox-to-sandbox networking默认情况下 sandbox 之间互不可达只有显式用ports暴露端口的 sandbox 才能被对端通过稳定端点访问且该端点可经受 Pod 替换。Docker-in-Docker传入enable_dockerTrue即可在 sandbox 内运行docker build、docker run与docker compose支持任意基础镜像守护进程运行在特权 sidecar 中而你代码所在的容器保持非特权。gVisor 更强的隔离Stronger isolation with gVisor在 GKE 上可将 sandbox Pod 调度到 gVisor runtime为不可信代码在默认的每 Pod 隔离之上再增加一层内核级隔离边界。典型使用场景AI 编码代理为每个代理如 Claude Code分配独立的可抛弃环境来读写和运行代码与你的其他工作、以及其他代理相互隔离。RL 训练 rollout一次性拉起数千个 sandbox 并行运行 rollout收集结果后全部销毁全程由单个进程驱动。并行评测Parallel evals在大量隔离环境中同时跑完一个大型评测集而不是在一台机器上串行执行。临时构建与 CI 任务在干净环境中执行短生命周期的构建、测试或脚本无需预置完整集群。快速上手CLI 与 SDK一个 sandbox 就是一个隔离 Pod创建它、在里面跑命令、然后终止它。只要安装好 SkyPilot CLI 与随附的 Sandbox SDK完整闭环就是如此。CLI 方式sky sandbox create会预置一个 sandbox 并直接带你进入交互式 shell退出 shell 即销毁 sandbox# 创建 sandbox 并进入 shell退出即销毁。 $ sky sandbox create -n dev ✓ Sandbox dev is ready. Connecting via bash... # 或者用 --detach 保持后台运行再按名字管理。 $ sky sandbox create --detach -n dev $ sky sandbox ls $ sky sandbox terminate devPython SDK 方式import sky.sandbox # 从内置的 default 池创建一个 sandbox。 sb sky.sandbox.create(namedev) # 运行命令argv 令牌无隐式 shell。exec 返回一个句柄 # 用 wait() 等待退出码再读取 stdout / stderr。 proc sb.exec(python, -c, print(2 ** 10)) proc.wait() print(proc.stdout.read()) # 1024 # 销毁。 sb.terminate()几个需要牢记的 SDK 语义命令是 argv 令牌直接在 Pod 内运行没有隐式 shell。如果需要管道、通配符、环境变量展开等 shell 特性请显式调用 shellsb.exec(sh, -c, echo $HOME | wc -c)。通过env参数可以为单条命令设置环境变量会覆盖创建时的 env且不会持久化到后续 execsb.exec(printenv, STAGE, env{STAGE: ci})。也可以使用上下文管理器实现自动销毁import sky.sandbox with sky.sandbox.create(namedev) as sb: sb.exec(python, train.py).wait() # 退出即自动终止 sandbox。深入 SDK批量、异步、密钥/卷与网络除了 create / exec / terminatesky.sandboxSDK 还覆盖批量与异步并发分发、密钥/卷注入、sandbox 间网络以及文件系统快照与恢复。批量创建传入num_sandboxes即可一次调用创建一批 sandbox名字根据前缀自动生成rollout-0001、rollout-0002、……import sky.sandbox sandboxes sky.sandbox.create(namerollout, num_sandboxes1000) for i, sb in enumerate(sandboxes): sb.exec(python, rollout.py, str(i))异步并发分发Async fan-out每个入口函数都有一个位于.aio属性上的异步孪生版本。单个事件循环即可驱动数百个并发的exec调用import asyncio import sky.sandbox async def main(): sandboxes await sky.sandbox.create.aio( namerollout, num_sandboxes100) try: results await asyncio.gather( *(sb.exec.aio(python, rollout.py, str(i)) for i, sb in enumerate(sandboxes))) finally: # 即使 exec 抛异常也要销毁。 await asyncio.gather(*(sb.terminate.aio() for sb in sandboxes)) await sky.sandbox.aclose() # 释放共享会话 asyncio.run(main())密钥与卷注入在创建时注入密钥、挂载卷import sky.sandbox sb sky.sandbox.create( namejob, # 从密钥管理器注入密钥作为同名环境变量。 secrets[HF_TOKEN], # 普通非密钥环境变量。 env{PROJECT: demo}, # 挂载已有卷键为挂载路径先用 sky volumes apply 创建卷。 # 值可以是卷名挂载整个卷 # 或 VolumeMount 用于子目录 / 只读挂载。 volumes{ /data: shared-data, /work: sky.sandbox.VolumeMount(team-fs, sub_pathjob-123), }, )其中持久卷是 SkyPilot 提供的独立能力参见卷文档卷相比云存储桶性能更高目前支持 Kubernetes 集群与 RunPod 上使用适合挂载进 sandbox 作为数据与共享文件系统。Sandbox 间网络默认情况下 sandbox 之间互不可达。一个server用ports声明其暴露的端口每个端口都会出现在它的endpoints映射中作为对端可拨号的稳定地址import sky.sandbox # Server向 peer sandbox 暴露 8080 端口。 server sky.sandbox.create(nameapi, imagepython:3.12, ports[8080]) print(server.endpoints[8080]) # api.default.svc.cluster.local:8080 # Client不暴露任何端口所以对端无法访问它 # 但可以访问 server 暴露的端口。 worker sky.sandbox.create(nameworker, imagepython:3.12) worker.exec(curl, -sf, fhttp://{server.endpoints[8080]}/healthz)该地址在 Pod 替换后依然有效在启用 NetworkPolicy 的集群上未暴露的端口保持被阻断。快照与恢复将 sandbox 的文件系统快照为容器镜像之后从快照恢复出全新 sandbox——昂贵的准备只做一次之后直接续用import sky.sandbox # 配置一个 sandbox然后快照它的文件系统。 sb sky.sandbox.create(namedev, imagepython:3.12) sb.exec(pip, install, numpy, pandas).wait() image sb.snapshot() # 之后恢复出全新 sandbox——numpy/pandas 已经装好。 restored sky.sandbox.create(namedev2, imageimage)快照功能需要在 Dashboard 的Sandboxes安装对话框中配置一个容器镜像仓库container registry。SDK 入口一览SDK 暴露的入口包括create、exec、terminate、snapshot、ls、create_pool、set_pool_size和delete_pool。每个按次调用的入口都有.aio属性上的异步孪生版本sky.sandbox.create.aio(...)、sb.exec.aio(...)因此在事件循环代码中可以使用相同的名字。你也可以在 Dashboard 的Sandboxes页面通过 UI 管理池与运行中的 sandbox。实战示例一RL 代码执行训练sandbox 奖励仓库中的llm/rl-code-execution-sandbox是一个完整的端到端示例用 GRPOGroup Relative Policy Optimization训练 LLM 做代码生成而奖励来自真正运行模型生成的代码——策略模型生成一个 Python 函数代码在 SkyPilot Sandbox 中针对隐藏测试用例执行全部通过奖励 1.0否则 0.0。每个 rollout 都隔离在自己的 Pod 中因此崩溃、死循环或恶意代码都无法影响 trainer 或其他 rollout。整个任务由 5 类组件通过 HTTP 通信构成该架构与rl-post-training-jobgroup相同只是把数学答案匹配的奖励服务器换成了 sandbox 支撑的代码执行奖励服务器data-serverauxiliaryFastAPI 服务提供 MBPP 风格的代码题面每个问题包含任务描述与一组隐藏测试用例assert 语句题面中只给出一条示例测试作为签名提示。rollout-serverauxiliaryx2带原生负载均衡的 SGLang 推理服务num_nodes: 2创建两个 GPU 实例rank 0 节点同时跑 SGLang server 与 SGLang router端口 30000router 提供对 KV 缓存友好的 cache-aware 负载均衡。sandbox-reward-serverauxiliary本示例的核心。对每个 rollout 从模型响应中提取代码块在隔离的 SkyPilot Sandbox 中运行code setup hidden tests进程退出码为 0 则返回 1.0 否则 0.0。整个批次通过异步 sandbox SDK 并发评分每个 rollout 一个 sandbox从预热池认领以实现亚秒级启动。replay-bufferauxiliary存储题面、响应、奖励经验元组供训练采样支持按高奖励优先采样。ppo-trainerprimary多节点训练编排器实现 GRPO每--policy-sync-interval步把最新权重通过 SGLang 的update_weights_from_disk接口推回 rollout-server。rollout → sandbox → reward 闭环┌─────────────┐ prompts hidden tests │>async def score_batch(items): # 一次 create 调用返回一组 sandbox从预热池认领。 sandboxes await sky.sandbox.create.aio( namereward, num_sandboxeslen(items), poolPOOL_NAME) try: # 并发评分每个 rollout每个 sandbox 一个。 rewards await asyncio.gather( *(score_one(sb, item) for sb, item in zip(sandboxes, items))) finally: # 即使 exec 抛异常也一定销毁。 await asyncio.gather(*(sb.terminate.aio() for sb in sandboxes), return_exceptionsTrue) return list(rewards) async def score_one(sb, item): # 奖励 模型生成的代码是否通过测试 # exec 返回句柄timeout_seconds 在服务端限制命令时长 #超时会在 Pod 内被杀并返回非零退出码因此客户端无需保持长连接。 proc await sb.exec.aio(python, -c, item.script, timeout_secondsEXEC_TIMEOUT_SECONDS) code await proc.wait() return 1.0 if code 0 else 0.0注意score_one中exec返回的是一个句柄wait()时才拿到退出码——连接只在启动 每次轮询时保持而不是覆盖命令的整个运行时长这正是大规模并发评分的吞吐关键。奖励函数也保证坏 rollout 不会向上抛异常崩溃、超时、非零退出码一律映射为奖励 0.0。预热池在服务器启动时创建一次sky.sandbox.create_pool(...)共享会话在关闭时释放一次sky.sandbox.aclose()。启动训练# 1. 先创建共享卷用于策略权重同步 sky volume apply llm/rl-code-execution-sandbox/rl-code-volume.yaml # 2. 启动 job group 训练 sky jobs launch llm/rl-code-execution-sandbox/rl-code-jobgroup.yaml # 3. 监控 sky jobs queue sky jobs logs job-id>import anthropic import sky.sandbox # Claude 运行在 sandbox 之外通过这两个工具按需创建 sandbox 并运行代码。 # 一场从不运行代码的对话永远不会创建 Pod。 sb None tools [ {name: start_skypilot_sandbox, description: Provision a fresh sandbox. Call the first time you need to run code., input_schema: {type: object, properties: {}}}, {name: run_shell, description: Run a shell command in the sandbox. State persists across calls., input_schema: {type: object, properties: {command: {type: string}}, required: [command]}}, ] def dispatch(name, args): global sb if name start_skypilot_sandbox: # 从池中认领一个预热 Pod。 sb sky.sandbox.create(namechat) return Sandbox ready. # run_shell。exec 返回句柄因此连接只在启动 每次轮询时保持 # 而非命令的整个运行时长长的 agent 命令构建、测试套件、训练任务 # 可以完整跑完而不会触发边缘超时。 # timeout_seconds 是服务端预算超时后命令在 Pod 内被杀—— # 请按你最长的一次工具调用来设置而不是保留 60 秒默认值。 proc sb.exec(sh, -c, args[command], timeout_seconds3600) proc.wait() return proc.stdout.read() or proc.stderr.read() client anthropic.Anthropic() messages [ {role: user, content: Compute the 100th Fibonacci number with Python.}] while True: resp client.messages.create(modelclaude-opus-4-8, max_tokens4096, toolstools, messagesmessages) messages.append({role: assistant, content: resp.content}) tool_uses [b for b in resp.content if b.type tool_use] if not tool_uses: break messages.append({role: user, content: [ {type: tool_result, tool_use_id: tu.id, content: dispatch(tu.name, tu.input)} for tu in tool_uses]}) if sb is not None: sb.terminate()每个 agent 拥有自己的 Pod因此可以并行工作而不会共享文件系统或互相干扰。在create时用secrets[...]注入每个 agent 的凭据token 就不会出现在 agent 运行的命令中。进阶Warm Pool 预热池与快速预置没有池时create会在需要时预置全新 Pod等待 Kubernetes 调度与容器镜像拉取。而一个**池pool**会保持一组预热、已预置的 Pod 就绪create改为认领一个已在运行的 Pod可将单个 sandbox 的启动时间缩短 50% 以上。池还固定了 sandbox 的形态容器镜像、CPU 与内存。SkyPilot 自带内置的default池python镜像所以上面的快速上手无需任何配置需要不同镜像或不同规格时再自建池即可。创建池、随时调整大小import sky.sandbox # 创建池保持 10 个空闲 Pod 预热就绪。 sky.sandbox.create_pool( nameml-gpu, imagenvcr.io/nvidia/pytorch:24.05-py3, cpus8, memory_gb64, replicas10, ) # 随时上下扩缩容。 sky.sandbox.set_pool_size(ml-gpu, replicas50) # 从池中启动 sandbox。 sb sky.sandbox.create(nametrain, poolml-gpu)SDK 还提供delete_pool用于删除不再使用的池。Docker-in-Docker在 Sandbox 内构建与运行镜像在 sandbox内部运行docker build、docker run和docker compose支持任意基础镜像。这是一个一行开关的 opt-in传入enable_dockerTrue。Docker 守护进程运行在独立的特权 sidecar 中dockerCLI 自动注入因此你代码所在的容器保持非特权镜像也无需任何改动。import sky.sandbox # 临时启动全新 Pod冷启动。 sb sky.sandbox.create(namedev, imageubuntu:22.04, enable_dockerTrue) sb.exec(docker, run, --rm, hello-world).wait() sb.exec(docker, build, -t, app, /src).wait() # 或者把 Docker 直接烤进预热池保持亚秒级启动。 sky.sandbox.create_pool(namedocker-pool, imageubuntu:22.04, replicas3, enable_dockerTrue) sky.sandbox.create(namedev2, pooldocker-pool)注意两点create()上的enable_docker只对临时启动生效需传image预热池的 Docker 支持在池创建时就已固定所以要用create_pool时传enable_dockerTrue。此外目标集群必须允许特权 Pod供 Docker daemon sidecar 使用强制无特权策略的集群如 GKE Autopilot会拒绝启动。在 GKE 上使用 gVisor 强化隔离在 GKE 上可以用 gVisor 进一步加固 sandbox Pod。gVisor 得到 GKE 官方支持通过 SkyPilot Sandboxes 使用它只需两步创建一个 GKE Sandbox 节点池带--sandbox typegvisorgcloud container node-pools create sandbox-pool \ --cluster cluster-name \ --sandbox typegvisor注意已有节点池无法转换为支持 gVisor必须新建一个。让 sandbox 指向该 runtime class在~/.sky/config.yaml的kubernetes.pod_config下添加runtimeClassName: gvisor。SkyPilot 据此确保 sandbox 使用 gVisor 创建# ~/.sky/config.yaml kubernetes: pod_config: spec: runtimeClassName: gvisor若要只对部分集群启用 gVisor把同样的pod_config嵌套到kubernetes.context_configs.context下即可# ~/.sky/config.yaml kubernetes: context_configs: gke_my-project_us-central1_my-cluster: pod_config: spec: runtimeClassName: gvisor这与 SkyPilot Kubernetes 文档中描述的pod_config机制一致其值遵循 Kubernetes Pod API 规范将应用到 SkyPilot 创建的所有 Pod 上参见 kubernetes-getting-started.rst 中关于~/.sky/config.yaml的pod_config覆盖说明。需要注意如果已经使用预热池来加速启动之后再启用 gVisor那么从预热池后续启动的 sandbox不会遵循 gVisor——需要重建预热池才能生效。此外gVisor runtime 上目前不支持快照与恢复Snapshot restore。与相邻能力的配合持久卷Volumes参见卷文档卷是可挂载进 sandbox 的持久存储。Job Groups参见 job-groups 示例可将大量并行 job 与 sandbox 一起运行用于 RL 训练。SkyPilot Platform参见 skypilot-platform.rst其中包含负责向 sandbox 注入凭据的 Secrets Manager。小结SkyPilot Sandboxes 把Kubernetes 上快速创建、用完即焚的隔离 Pod封装成一行 CLI 命令或一个 SDK 调用预热池解决冷启动延迟密钥/卷注入解决配置分发ports 稳定端点解决沙箱间通信snapshot()解决昂贵环境的复用enable_docker与 gVisor 则分别扩展了能力边界与安全边界。无论是给编码代理一个安全的代码执行沙箱还是为 RL rollout 与并行评测铺开上千个隔离环境这套机制都能在你的自有集群上按需伸缩、随用随销。【免费下载链接】skypilotThe AI Compute Platform for frontier teams. SkyPilot turns fragmented AI compute into one AI supercomputer, so frontier AI teams build custom intelligence faster.项目地址: https://gitcode.com/GitHub_Trending/sk/skypilot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考