实验范围
kind 把 Kubernetes 节点运行在容器里,适合本地开发和 CI。本实验在 kind 中部署调用 E2B 的 Worker,配置 Secret、Job 生命周期和日志采集。Sandbox 由 E2B 托管服务创建。
本文不部署 E2B 自托管基础设施。官方自托管方案包含 Terraform、Packer、Nomad、PostgreSQL、对象存储和 Firecracker orchestrator;AWS 参考架构要求裸金属或支持嵌套虚拟化的实例。
- kind 验证:Kubernetes Job、配置注入、SDK 调用、失败重试、日志和清理。
- E2B 验证:Sandbox 创建、命令执行、文件和生命周期 API。
- 不验证:本地 Firecracker、嵌套虚拟化、E2B 自托管控制面与容量调度。
实验链路
执行链路包括:将本地镜像加载到 kind,Kubernetes Job 从 Secret 读取 API Key,Python Worker 创建 Sandbox、运行固定命令、输出结果,并在 finally 中回收资源。
- 入口:Kubernetes Job。
- 凭据:仅通过 Secret 注入,不写进镜像或 Git。
- 执行:E2B Python SDK 的 create → commands.run → kill。
- 证据:Job 日志、Sandbox ID、stdout、exit code 和清理结果。
在 finally 中回收 Sandbox
Smoke Test 使用固定命令,不允许模型生成任意 Shell。Worker 输出 Sandbox ID、退出码和 stdout,便于 CI 判断结果。
无论命令成功还是异常,都在 finally 中调用 kill。生产系统还需要 TTL 回收器和控制面补偿任务,不能只依赖客户端正常退出。
import json
from e2b import Sandbox
sandbox = Sandbox.create(
timeout=300,
metadata={"lab": "goclaw-kind", "purpose": "smoke"},
)
try:
result = sandbox.commands.run(
"python -c 'import platform; print(platform.platform())'"
)
print(json.dumps({
"sandbox_id": sandbox.sandbox_id,
"exit_code": result.exit_code,
"stdout": result.stdout.strip(),
}, ensure_ascii=False))
finally:
sandbox.kill()固定 Worker 镜像与 SDK 版本
示例固定 SDK 主版本范围,实际仓库应锁定经过验证的精确版本并记录升级证据。Worker 使用非 root 用户运行;API Key 只在 Pod 启动时注入。
FROM python:3.12-slim
WORKDIR /app
RUN pip install --no-cache-dir "e2b>=2.3,<3"
COPY worker.py /app/worker.py
USER 65532:65532
CMD ["python", "/app/worker.py"]用 Kubernetes Job 约束单次调用
backoffLimit 设为 0,避免认证错误或 Provider 故障触发无意识的重复创建。Job 完成五分钟后自动清理 Kubernetes 对象,但这不会替代 E2B Sandbox 的 kill/TTL。
生产环境应进一步配置 NetworkPolicy、Workload Identity 或外部 Secret 管理,并把请求幂等键、预算和审计字段传给 GoClaw 控制面。
apiVersion: batch/v1
kind: Job
metadata:
name: e2b-smoke
namespace: agent-lab
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 300
template:
spec:
restartPolicy: Never
containers:
- name: worker
image: goclaw/e2b-kind-lab:0.1.0
imagePullPolicy: IfNotPresent
env:
- name: E2B_API_KEY
valueFrom:
secretKeyRef:
name: e2b-credentials
key: E2B_API_KEY
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 250m
memory: 256Mi用 Makefile 固定实验入口
Makefile 提供 make lab-up、make lab-image、make lab-secret、make lab-run、make lab-logs 和 make lab-down。开发环境与 CI 使用相同入口。
kind 官方支持将本地镜像加载到命名集群;镜像不要使用 latest,并在 Job 中设置 IfNotPresent,避免 kubelet 再次尝试从远端拉取。
LAB_CLUSTER ?= goclaw-e2b
LAB_IMAGE ?= goclaw/e2b-kind-lab:0.1.0
.PHONY: lab-up lab-image lab-secret lab-run lab-logs lab-down
lab-up:
kind create cluster --name $(LAB_CLUSTER) --wait 90s
kubectl create namespace agent-lab --dry-run=client -o yaml | kubectl apply -f -
lab-image:
docker build -t $(LAB_IMAGE) .
kind load docker-image $(LAB_IMAGE) --name $(LAB_CLUSTER)
lab-secret:
@test -n "$(E2B_API_KEY)" || (echo "E2B_API_KEY is required"; exit 1)
kubectl -n agent-lab create secret generic e2b-credentials \
--from-literal=E2B_API_KEY="$(E2B_API_KEY)" \
--dry-run=client -o yaml | kubectl apply -f -
lab-run:
kubectl -n agent-lab delete job e2b-smoke --ignore-not-found
kubectl apply -f deploy/e2b-smoke-job.yaml
kubectl -n agent-lab wait --for=condition=complete job/e2b-smoke --timeout=180s
lab-logs:
kubectl -n agent-lab logs job/e2b-smoke
lab-down:
kind delete cluster --name $(LAB_CLUSTER)通过条件
至少保存一次结构化日志,确认 sandbox_id 非空、exit_code 为 0、stdout 包含 Linux 内核信息,并确认 Job 完成。随后在 E2B Dashboard 或 CLI 中验证 Sandbox 已终止。
- 认证失败时,Job 必须失败且不能无限重试。
- 命令非零退出时,仍然必须执行 kill。
- 删除 kind 集群不会自动删除远端 Sandbox。
- 任何输出都不能包含 E2B_API_KEY。
官方来源与继续阅读
文中的技术信息来自以下官方文档和开源仓库。实施前请核对所用版本的最新说明。