如何在 AKS 集群上用 Kata VM 隔离部署 OpenSandbox 并验证沙箱端到端可用
【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox
本文的目标是:在一个已有 Kata 节点池的 AKS 集群上部署 OpenSandbox(controller、生命周期 server、ingress 网关),创建一个运行在独立 Kata VM 内的沙箱,并逐步验证命令执行、出站白名单、Credential Vault 密钥注入、ingress 网关访问这几条链路端到端可用。仓库中的完整示例位于 examples/aks-kata,配套说明文档见 docs/examples/aks-kata.md。
开始前注意:示例中的 Helm values 使用不安全、公开的演示凭据(api_key = "aks-kata-demo-key"和固定的secureAccess签名密钥),这样本地kubectl port-forward可以开箱即用。在把 server 或网关暴露到127.0.0.1以外的环境之前,必须先替换这两个值(例如随机 api_key,签名密钥可用openssl rand -base64 32生成)。
准备条件
- 一个 AKS 集群,满足
kubectl get runtimeclass能看到kata-vm-isolation这个 RuntimeClass - Helm 3
- Python 3.10+,执行
pip install opensandbox requests安装 SDK 与依赖 - 一个 Azure OpenAI 资源(endpoint + API key),用于验证 Credential Vault 链路
示例由以下文件组成(都在 examples/aks-kata 下):
| 文件 | 用途 |
|---|---|
| main.py | CLI 工具——按步骤创建、检查、操作沙箱 |
| controller-values.yaml | OpenSandbox controller 的 Helm values |
| server-values.yaml | 生命周期 server 与 ingress 网关的 Helm values |
| batchsandbox-template-configmap.yaml | 通过nodeSelector把沙箱 Pod 固定到 Kata 节点的 BatchSandbox 模板 |
1. 安装 OpenSandbox
以下命令在仓库根目录执行:
kubectl create namespace opensandbox-system --dry-run=client -o yaml | kubectl apply -f - kubectl create namespace opensandbox --dry-run=client -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等三个 Deployment 滚动完成:
kubectl rollout status deploy/opensandbox-controller-manager -n opensandbox-system --timeout=180s kubectl rollout status deploy/opensandbox-server -n opensandbox-system --timeout=180s kubectl rollout status deploy/opensandbox-ingress-gateway -n opensandbox-system --timeout=180s安装完成后集群中各组件的分工:opensandbox-controller(opensandbox-system命名空间)是 Kubernetes operator,管理 BatchSandbox CRD、池和快照;opensandbox-server提供生命周期 API;opensandbox-ingress-gateway带鉴权地把外部 HTTP 流量路由进沙箱 Pod;BatchSandbox 模板负责通过nodeSelector: kubernetes.azure.com/kata-vm-isolation: "true"把沙箱 Pod 钉到支持 Kata 的 AKS 节点。
server 的关键配置(见 server-values.yaml):workload_provider = "batchsandbox"、secure_runtime.type = "kata"/k8s_runtime_class = "kata-vm-isolation"、egress sidecar 使用dns+nft模式、ingress 网关使用header路由加secureAccess。
2. 启动 port-forward
开两个独立终端,分别转发生命周期 server 和 ingress 网关:
# 终端 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_DOMAIN=http://127.0.0.1:18080 export SANDBOX_API_KEY=aks-kata-demo-key # 下面两行替换为你自己的 Azure OpenAI 资源信息 export AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com export AZURE_OPENAI_API_KEY=your-real-key # 可选: # export AZURE_OPENAI_DEPLOYMENT=gpt-4o-miniSANDBOX_DOMAIN和SANDBOX_API_KEY对应本地 port-forward 端口与 demo values 中的api_key;AZURE_OPENAI_ENDPOINT/AZURE_OPENAI_API_KEY是你自己的真实值,文档中的your-resource、your-real-key是占位写法。
4. 可选:启用 Pause/Resume
Pause 会把沙箱 rootfs 提交为 OCI 镜像推送到 registry,Resume 从该镜像重建沙箱;没有 registry 时pause和resume步骤会记录错误并继续(python3 main.py all会打印跳过信息并照常走完全流程)。本节以 Azure Container Registry(ACR)为例,任意 OCI registry 均可,完整说明见 Pause / Resume 指南。
以下命令中的<resource-group>、<cluster-name>、<acr-name>三个占位符分别替换为你的 AKS 资源组名、集群名和 ACR 实例名。
Step 1:给 kubelet 身份授予 AcrPush
KUBELET_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"Step 2:创建推送/拉取 Secret
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-server=<acr-name>.azurecr.io \ --docker-username=<acr-name> \ --docker-password="$ACR_PASSWORD" \ --namespace=opensandboxStep 3:升级 controller 并注入快照配置
helm upgrade opensandbox-controller ./kubernetes/charts/opensandbox-controller \ --namespace opensandbox-system \ --reuse-values \ --set controller.snapshot.registry=<acr-name>.azurecr.io/opensandbox-snapshots \ --set controller.snapshot.snapshotPushSecret=acr-snapshot-push-secret \ --set controller.snapshot.resumePullSecret=acr-snapshot-push-secret kubectl rollout status deploy/opensandbox-controller-manager \ -n opensandbox-system --timeout=90schart 中controller.snapshot.registry、snapshotPushSecret、resumePullSecret默认都是空字符串(见 controller chart values),所以不执行本步时快照功能不可用。另外controller.snapshot.containerdSocketPath默认为"",表示 controller 使用内置默认值/var/run/containerd/containerd.sock;如果你的节点使用非默认 containerd socket,需要显式设置该值。
5. 用 main.py 逐步验证
以下命令都在示例目录下执行:
cd examples/aks-kata想一次性跑通全流程(创建 → 全部步骤 → 删除)可以直接执行:
python3 main.py all下面按单步执行讲解验证逻辑。
创建沙箱
python3 main.py create文档示例输出(sandbox ID 每次不同):
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_ID=96045ee2-6614-435c-9fa8-d4b6f9592598 Use --sandbox-id 96045ee2-6614-435c-9fa8-d4b6f9592598 for subsequent steps.把输出的 ID 存下来供后续步骤使用(下面用示例值演示):
export SANDBOX_ID=96045ee2-6614-435c-9fa8-d4b6f9592598创建请求会带上 deny-by-default 的出站策略,只放行 Azure OpenAI、pypi.org、files.pythonhosted.org(见 main.py 中的network_policy与credential_proxy配置)。
验证 Pod 确实跑在 Kata VM 上
这是判断“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.azl3 (mshv = Microsoft Hypervisor = Kata VM 客户机内核)三个检查分别确认:Pod 调度到 Kata 节点池、Pod 的runtimeClassName是kata-vm-isolation、沙箱内看到的是独立客户机内核而不是宿主机内核。
配置 Credential Vault 并验证 LLM 链路
python3 main.py credentials --sandbox-id $SANDBOX_ID预期输出:
[credentials] Credential Vault configured.再让沙箱里的 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能拿到回答说明出站白名单和密钥注入都工作正常。可以进一步验证密钥只存在于 egress 侧:
python3 main.py exec --sandbox-id $SANDBOX_ID -c "echo \$AZURE_OPENAI_API_KEY" # 预期: fake-key-inside-sandbox沙箱内看到的只是假 key,真实的 Azure OpenAI key 存在 Credential Vault 中,由 egress sidecar 仅对发往https://<your-resource>.openai.azure.com/openai/*的匹配出站请求以api-key头注入。
在沙箱内执行命令
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_NAME="Ubuntu 24.04.4 LTS"(文档示例)不带-c时exec会运行内置演示序列。
通过 ingress 网关访问沙箱内 HTTP 服务
沙箱入口进程是python3 -m http.server 8080,根目录为/tmp/www/;外部流量经过 ingress 网关并携带 secure-access 头(由 SDK 的get_endpoint()返回,调用方不需要手工构造OpenSandbox-Secure-Access与OpenSandbox-Ingress-To头):
# 向沙箱写入文件,再经网关取回 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 / # 不存在的文件 python3 main.py http --sandbox-id $SANDBOX_ID -p /nonexistent.txt # [http] GET /nonexistent.txt -> 404(文档示例)/greeting.txt返回 200、不存在的文件返回 404,说明经网关的入站路由和鉴权链路可用。
查看状态、暂停/恢复、删除
python3 main.py status --sandbox-id $SANDBOX_ID # 文档示例: # Sandbox: 96045ee2-6614-435c-9fa8-d4b6f9592598 # State: Running # Image: ...code-interpreter:v1.1.0如果执行了第 4 节的 ACR 配置,可以继续验证暂停/恢复(快照推送约 1–5 分钟):
python3 main.py pause --sandbox-id $SANDBOX_ID # [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] state after resume: Running(文档示例)验证完成后删除沙箱:
python3 main.py delete --sandbox-id $SANDBOX_ID # [lifecycle] sandbox 96045ee2-... deleted.(文档示例) kubectl get pods -n opensandbox # No resources found安全模型要点
- Kata VM 隔离:每个沙箱运行在专用 Kata VM(
runtimeClassName: kata-vm-isolation)中,落在带kubernetes.azure.com/kata-vm-isolation: "true"标签的 AKS Kata 节点池上,沙箱看到的是自己的客户机内核而非宿主机内核。 - 出站隔离:创建请求设置了 deny-by-default 出站策略,只放行显式允许的域名。
- 逐服务鉴权:即使绕过网关直连 Pod,execd(端口 44772)需要自己的 access token 头,egress sidecar(端口 18080)需要
OPENSANDBOX-EGRESS-AUTH头;只有用户 HTTP 服务(端口 8080)没有内置鉴权,这正是 secureAccess 要保护的部分。
清理
执行以下命令删除本示例安装的全部内容。注意第 1 步会删除opensandbox命名空间下所有BatchSandbox(沙箱),第 5 步会删除整个命名空间,请确认没有混用其他工作负载:
# 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 模板 ConfigMap kubectl delete configmap aks-kata-batchsandbox-template -n opensandbox-system # 4) 删除快照推送/拉取 Secret(如果创建过) kubectl delete secret acr-snapshot-push-secret -n opensandbox --ignore-not-found # 5) 删除命名空间 kubectl delete namespace opensandbox kubectl delete namespace opensandbox-system相关文档
- 完整场景说明:docs/examples/aks-kata.md
- 安全容器运行时(Kata/gVisor/Firecracker)原理与验证方式:docs/guides/secure-container.md
- 示例代码与 values:examples/aks-kata
【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考