
OpenSandbox 在 AKS 上的 Kata VM 隔离实战从部署到凭据注入的完整路径【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox本文以仓库内的docs/examples/aks-kata.md文档为主体完整覆盖在 Azure AKS 集群上部署 OpenSandbox配合 Kata VM 隔离的全部步骤Helm 安装 controller 与 server、port-forward 联调、凭据库Credential Vault配置、基于main.py的逐步骤沙箱操作以及 Pause/Resume 快照到 ACR 的可选流程。读完并动手后你将掌握如何在 Kata 安全运行时上创建隔离沙箱并通过 OpenSandbox 的 egress 侧车与 ingress 网关实现沙箱内只见假密钥、出站仅放行白名单域名、入站全部经过鉴权的端到端安全闭环。前置条件开始前需确认环境满足以下条件一个 AKS 集群且kubectl get runtimeclass输出中包含kata-vm-isolation即节点池已启用 Kata VM 隔离节点带kubernetes.azure.com/kata-vm-isolation标签Helm 3Python 3.10并已pip install opensandbox requests一个 Azure OpenAI 资源endpoint API key用于演示凭据注入场景。示例文件构成整个示例位于仓库的examples/aks-kata目录由 4 个文件组成见 示例目录文件用途main.pyCLI 工具——逐步创建、检查、操作沙箱controller-values.yamlOpenSandbox controller 的 Helm valuesserver-values.yaml生命周期 server 与 ingress 网关的 Helm valuesbatchsandbox-template-configmap.yaml将沙箱 Pod 固定到 Kata 节点的 BatchSandbox 模板其中 batchsandbox-template-configmap.yaml 的核心内容是Pod 模板通过nodeSelector: kubernetes.azure.com/kata-vm-isolation: true确保落到 Kata 节点池并以tolerations: [{operator: Exists}]容忍节点上的污点restartPolicy: Never表明每个沙箱 Pod 是一次性工作负载。该模板以 ConfigMap 形式挂载进 server 容器配合下文 server 配置中的batchsandbox_template_file生效。1. 安装 OpenSandbox从仓库根目录执行kubectl create namespace opensandbox-system --dry-runclient -o yaml | kubectl apply -f - kubectl create namespace opensandbox --dry-runclient -o yaml | kubectl apply -f - kubectl apply -f examples/aks-kata/batchsandbox-template-configmap.yaml helm upgrade --install opensandbox-controller ./kubernetes/charts/opensandbox-controller \ --namespace opensandbox-system \ -f examples/aks-kata/controller-values.yaml helm upgrade --install opensandbox-server ./kubernetes/charts/opensandbox-server \ --namespace opensandbox-system \ -f examples/aks-kata/server-values.yaml等待部署就绪kubectl rollout status deploy/opensandbox-controller-manager -n opensandbox-system --timeout180s kubectl rollout status deploy/opensandbox-server -n opensandbox-system --timeout180s kubectl rollout status deploy/opensandbox-ingress-gateway -n opensandbox-system --timeout180s2. 建立两条 port-forward打开两个独立终端# 终端 1 — 生命周期 server kubectl port-forward -n opensandbox-system svc/opensandbox-server 18080:80 # 终端 2 — ingress 网关 kubectl port-forward -n opensandbox-system svc/opensandbox-ingress-gateway 28080:803. 设置环境变量export SANDBOX_DOMAINhttp://127.0.0.1:18080 export SANDBOX_API_KEYaks-kata-demo-key export AZURE_OPENAI_ENDPOINThttps://your-resource.openai.azure.com export AZURE_OPENAI_API_KEYyour-real-key # 可选 # export AZURE_OPENAI_DEPLOYMENTgpt-4o-mini4. 可选启用 Pause/ResumePause 会把沙箱的容器 rootfs 提交为 OCI 镜像并推送到镜像仓库Resume 则从该镜像重建沙箱。如果没有配置仓库pause和resume步骤会记录错误并跳过main.py all流程中该阶段被 try/except 捕获后继续。下面以 Azure Container RegistryACR为例任意 OCI 仓库均可完整指南见 Pause / Resume 指南。步骤 1给 kubelet 身份授予 AcrPushKUBELET_ID$(az aks show \ -g resource-group -n cluster-name \ --query identityProfile.kubeletidentity.clientId -o tsv) ACR_ID$(az acr show --name acr-name --query id -o tsv) az role assignment create --assignee $KUBELET_ID --role AcrPush --scope $ACR_ID步骤 2创建 push/pull 镜像密钥ACR_PASSWORD$(az acr credential show --name acr-name \ --query passwords[0].value -o tsv) kubectl create secret docker-registry acr-snapshot-push-secret \ --docker-serveracr-name.azurecr.io \ --docker-usernameacr-name \ --docker-password$ACR_PASSWORD \ --namespaceopensandbox步骤 3升级 controllerhelm upgrade opensandbox-controller ./kubernetes/charts/opensandbox-controller \ --namespace opensandbox-system \ --reuse-values \ --set controller.snapshot.registryacr-name.azurecr.io/opensandbox-snapshots \ --set controller.snapshot.snapshotPushSecretacr-snapshot-push-secret \ --set controller.snapshot.resumePullSecretacr-snapshot-push-secret kubectl rollout status deploy/opensandbox-controller-manager \ -n opensandbox-system --timeout90s提示controller.snapshot.containerdSocketPath在 chart 中默认为表示 controller 使用内置默认值/var/run/containerd/containerd.sock无需显式传递--containerd-socket-path参数除非节点使用了非默认 socket 且镜像支持该参数。示例中的 controller-values.yaml 正是把这个值显式置为空字符串。5. 使用 main.py 逐步操作以下所有main.py命令都在示例目录下运行见 main.py 的模块 docstring 对命令清单的说明cd examples/aks-kata端到端一键执行python3 main.py all该命令会创建沙箱、依次执行全部演示步骤并在最后删除沙箱。从源码看run_all()按create → credentials → llm → http → exec → (pause/resume) → delete的顺序串联各步骤且delete放在finally块中保证即使中途失败沙箱也会被清理。逐步执行创建沙箱python3 main.py create预期输出Creating Kata-isolated sandbox on AKS... OpenSandbox API: http://127.0.0.1:18080 Sandbox image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/code-interpreter:v1.1.0 SANDBOX_ID96045ee2-6614-435c-9fa8-d4b6f9592598 Use --sandbox-id 96045ee2-6614-435c-9fa8-d4b6f9592598 for subsequent steps.记下 ID 供后续步骤使用export SANDBOX_ID96045ee2-6614-435c-9fa8-d4b6f9592598验证 Pod 确实运行在 Kata 节点上kubectl get pod -n opensandbox -o wide # NODE 列应显示 aks-sandboxagent-* kubectl get pod -n opensandbox -o jsonpath{.items[0].spec.runtimeClassName} # 预期: kata-vm-isolation python3 main.py exec --sandbox-id $SANDBOX_ID -c uname -r # 预期: 6.6.137.mshv1-1.azl3mshv Microsoft Hypervisor Kata VM 客户机内核这里有一个值得注意的实现细节main.py中step_create()通过SandboxSync.create()下发沙箱时同时携带了三个安全关键参数——network_policy默认拒绝的出站策略见下文出站隔离、credential_proxyCredentialProxyConfig(enabledTrue)启用凭据代理侧车、secure_accessTrue启用 ingress 网关的签名鉴权路由。此外CONNECTION_CONFIG把request_timeout提升到 180 秒因为 Kata VM 沙箱的创建涉及镜像拉取往往超过默认 30 秒。配置 Credential Vaultpython3 main.py credentials --sandbox-id $SANDBOX_ID预期输出[credentials] Credential Vault configured.从 main.py 的step_credentials()可以看到完整的绑定结构真实密钥以Credential(nameazure-openai-key, source{value: ...})存入凭据库再通过CredentialBinding声明匹配规则——仅当出站请求同时满足https方案、443端口、目标 host 为 Azure OpenAI 资源域名、方法为GET/POST、路径匹配/openai/*时才由 egress 侧车注入api-key请求头auth{type: apiKey, name: api-key, credential: azure-openai-key}。向 LLM 提问python3 main.py llm --sandbox-id $SANDBOX_ID -q What is the capital of France? Reply in one word.预期输出[llm] Question: What is the capital of France? Reply in one word. [llm] Model: gpt-4o-mini [llm] Answer: Paris关键点在于沙箱内部只持有假密钥fake-key-inside-sandbox真实密钥由 egress 侧车通过 Credential Vault 注入。可以直接验证python3 main.py exec --sandbox-id $SANDBOX_ID -c echo \$AZURE_OPENAI_API_KEY # 预期: fake-key-inside-sandbox从step_llm()的实现看沙箱内执行的curl命令故意不设置api-key头命令体完全无密请求经 egress 侧车出站时命中绑定规则后真实密钥才作为api-key头被追加。这也是该示例安全模型的核心演示点Agent 与宿主人都无法在沙箱内窥探到真实凭据。在沙箱内执行命令python3 main.py exec --sandbox-id $SANDBOX_ID -c uname -a # [exec][stdout] Linux ...-0 6.6.137.mshv1-1.azl3 ... x86_64 GNU/Linux python3 main.py exec --sandbox-id $SANDBOX_ID -c cat /etc/os-release | head -3 # [exec][stdout] PRETTY_NAMEUbuntu 24.04.4 LTS # [exec][stdout] NAMEUbuntu # [exec][stdout] VERSION_ID24.04 python3 main.py exec --sandbox-id $SANDBOX_ID -c ls -la /tmp/www/ # 显示 HTTP 服务根目录内容通过沙箱 HTTP 服务拉取文件沙箱以python3 -m http.server 8080提供/tmp/www/目录这是step_create()中entrypoint指定的启动命令。流量经 ingress 网关并以 secure-access 请求头转发# 先写入文件再经网关拉取 python3 main.py exec --sandbox-id $SANDBOX_ID -c echo hello /tmp/www/greeting.txt python3 main.py http --sandbox-id $SANDBOX_ID -p /greeting.txt # [http] GET /greeting.txt - 200 (6 bytes) # hello # 目录列表 python3 main.py http --sandbox-id $SANDBOX_ID -p / # 显示 HTML 目录列表 # 缺失文件返回 404 python3 main.py http --sandbox-id $SANDBOX_ID -p /nonexistent.txt # [http] GET /nonexistent.txt - 404不带-p时http步骤会跑完整演示写入index.html/data.json、拉取目录列表、解析 JSON、请求缺失文件验证 404。_ingress()辅助函数展示了网关调用方式——sandbox.get_endpoint(HTTP_PORT)返回 endpoint 与需要携带的请求头调用方无需手工构造签名。查看沙箱状态python3 main.py status --sandbox-id $SANDBOX_ID # Sandbox: 96045ee2-6614-435c-9fa8-d4b6f9592598 # State: Running # Image: ...code-interpreter:v1.1.0暂停与恢复Pause 将容器 rootfs 快照推送至仓库约 1–5 分钟Resume 从快照重建。依赖上文第 4 节的仓库配置。python3 main.py pause --sandbox-id $SANDBOX_ID # [lifecycle] pausing sandbox... # [lifecycle] sandbox is PAUSED python3 main.py status --sandbox-id $SANDBOX_ID # State: Paused # Pod 已消失但 BatchSandbox CR 与快照保留 kubectl get pods -n opensandbox # No resources found kubectl get sandboxsnapshot -n opensandbox # 显示 phase 为 Succeed 的快照 python3 main.py resume --sandbox-id $SANDBOX_ID # [lifecycle] resuming sandbox... # [setup] sandbox state: Resuming, waiting... # [lifecycle] state after resume: Running # [http] GET /index.html - 200 (文件系统被完整保留!) python3 main.py status --sandbox-id $SANDBOX_ID # State: Running从源码看step_pause()会持续轮询状态直至PAUSED一旦 controller 上报FAILED例如缺少controller.snapshot.registry或推送密钥错误会立即抛出错误避免静默超时后误判成功step_resume()复用同一个 sandbox IDID 在 pause/resume 间保持稳定并重新等待就绪后验证/index.html可访问——证明 rootfs 文件系统内容被快照完整保留。删除沙箱python3 main.py delete --sandbox-id $SANDBOX_ID # [lifecycle] sandbox 96045ee2-... deleted. kubectl get pods -n opensandbox # No resources found补充一点exec、llm、http三个步骤在不带-c、-q、-p参数时会各自执行内置的完整演示序列。安装后的组件一览组件命名空间职责opensandbox-controlleropensandbox-systemKubernetes operator——管理 BatchSandbox CRD、资源池与快照opensandbox-serveropensandbox-system生命周期 API——创建/删除沙箱代理 SDK 调用opensandbox-ingress-gatewayopensandbox-system将外部 HTTP 流量带鉴权路由进沙箱 PodBatchSandbox 模板opensandbox-system通过nodeSelector把沙箱 Pod 固定到具备 Kata 能力的 AKS 节点server-values.yaml 中的关键配置configToml段如下每个配置项都值得对照理解[server] host 0.0.0.0 port 80 api_key aks-kata-demo-key max_sandbox_timeout_seconds 86400 [runtime] type kubernetes execd_image sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.1.0 [kubernetes] namespace opensandbox informer_enabled true workload_provider batchsandbox batchsandbox_template_file /etc/opensandbox/aks-kata.batchsandbox-template.yaml [egress] image sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/egress:v1.1.7 mode dnsnft disable_ipv6 true [secure_runtime] type kata k8s_runtime_class kata-vm-isolationHelm values 部分还开启了 ingress 网关gateway.enabled true路由模式header数据面命名空间opensandbox并配置了secureAccess签名密钥演示用的固定 base64 值同时把 BatchSandbox 模板 ConfigMap 以只读 subPath 挂载到 server 容器内与上面batchsandbox_template_file路径对应。安全模型解析警告server-values.yaml内置的均为仅演示用途的凭据api_key aks-kata-demo-key与固定的 base64secureAccess签名密钥。它们存在的唯一目的是让本地 port-forward 演练开箱即用。在把 server 或网关暴露到127.0.0.1以外的任何环境之前必须替换两者例如随机 api_key 和openssl rand -base64 32生成的签名密钥。Kata VM 隔离每个沙箱运行在专属 Kata VM 中runtimeClassName: kata-vm-isolation落在带kubernetes.azure.com/kata-vm-isolation: true标签的 AKS Kata 节点池上。沙箱看到的是自己的客户机内核6.6.137.mshv1之类而非宿主机内核。从源码看这一映射由 server 的安全运行时解析器完成runtime_resolver.py 中的get_k8s_runtime_class()优先返回配置里显式指定的k8s_runtime_class否则回退到类型映射表kata→kata-qemu。本示例显式指定了kata-vm-isolation正是命中显式配置优先的分支。此外server 启动时会执行 fail-fast 校验若集群中不存在该 RuntimeClassAPI 返回 404server 会直接拒绝启动并提示请先创建 RuntimeClass见 validate_secure_runtime_on_startup。config.py 中的SecureRuntimeConfig字段定义也明确了三种可选类型gvisor/kata/firecracker其中firecracker仅与 Kubernetes 运行时兼容。出站隔离创建请求step_create()设置了默认拒绝的出站策略只有显式放行的 host——Azure OpenAI 资源域名、pypi.org、files.pythonhosted.org——可达。这与[egress] mode dnsnft的侧车配置配合工作egress 侧车以 DNS 策略 nftables 规则实施域名级控制。Credential Vault沙箱内只能看到假的AZURE_OPENAI_API_KEY值为fake-key-inside-sandbox。真实密钥存放在 Credential Vault 中仅当出站请求匹配绑定规则目标为https://your-resource.openai.azure.com/openai/*时才由 egress 侧车以api-key头注入。凭据库的完整设计可进一步参考 凭据库指南 与 OSEP-0012。Ingress 网关 secureAccess所有发往沙箱服务的外部流量都经由 ingress 网关。网关校验OpenSandbox-Secure-Access令牌并依据OpenSandbox-Ingress-To头完成路由。两个值都由 SDK 的get_endpoint()调用返回——调用方永远不需要手工构造它们。从源码看OpenSandbox-Ingress-To就是网关路由层的标准请求头常量见 header.go 中的SandboxIngress配套的签名校验逻辑位于 ingress 签名包。逐服务鉴权兜底即便有人绕过网关直连 Podexecd44772 端口要求独立的 access token 头egress 侧车18080 端口要求OPENSANDBOX-EGRESS-AUTH头只有用户的 HTTP 服务8080 端口没有内建鉴权——这正是 secureAccess 所保护的最后一环。三层防线网关签名 逐服务 token 沙箱内假密钥叠加 Kata VM 的硬件级隔离边界共同构成该示例的安全模型。清理删除本示例安装的全部内容# 1) 删除所有运行中的沙箱 kubectl delete batchsandbox --all -n opensandbox # 2) 卸载 Helm release helm uninstall opensandbox-server -n opensandbox-system helm uninstall opensandbox-controller -n opensandbox-system # 3) 删除 BatchSandbox 模板 kubectl delete configmap aks-kata-batchsandbox-template -n opensandbox-system # 4) 删除快照推送/拉取密钥如已创建 kubectl delete secret acr-snapshot-push-secret -n opensandbox --ignore-not-found # 5) 删除命名空间 kubectl delete namespace opensandbox kubectl delete namespace opensandbox-system小结这个示例的价值在于把 OpenSandbox 的三大安全能力串成了一条可在真实云上复现的链路secure_runtime配置让 server 把沙箱 Pod 落到 Kata RuntimeClassruntime_resolver.py 保证启动期校验通过network_policy egress 侧车实施默认拒绝的域名级出站白名单Credential Vault 让真实 API 密钥只在出站侧车处注入、沙箱内全程只存在假值ingress 网关的OpenSandbox-Secure-Access/OpenSandbox-Ingress-To签名机制则守护着入站流量。所有步骤均可按本文顺序在 AKS 集群上直接执行验证。【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考