Kruise Agent 部署流程
尝试使用 Kruise Agent 调度在鲲鹏 ARM 环境上的 Kata Container 沙箱实例。
实验环境:openEuler(ARM64)
安装 openkruise
openKruise 本体不包含沙箱管理,但是有沙箱管理所依赖的能力
使用官方helm方式安装。本次实验时版本为1.8.3。
helm repo add openkruise https://openkruise.github.io/charts/
helm repo update
helm search repo openkruise
helm install kruise openkruise/kruise --version 1.8.3
将在kruise-system命名空间拉起2个manager副本,以及与节点数一致的daemon守护进程。
安装 Kruise Agents
构建 Kruise Agent 镜像
openKruise官方未提供Kruise Agents的arm镜像,需要先手动构建。
Kruise Agents官方仓库代码相比发布版本有更新,应当使用helm对应的版本分支,当前最新的版本分支为v0.1.0。在docerfiles文件夹下有提供Dockerfile,可以用于构建镜像。
git clone https://github.com/openkruise/agents.git -b v0.1.0
cd agents
使用nerdctl直接在k8s.io命名空间构建chart中的同名镜像。Helm chart中均使用IfNotPresent的拉取策略,可以直接使用本地镜像。
注意:agent-runtime.Dockerfile中,go build写死了amd64,需要先手动修改为arm64
nerdctl -n k8s.io built -t openkruise/sandbox-manager:v0.1.0
nerdctl -n k8s.io build -t openkruise/agent-sandbox-controller:v0.1.0
nerdctl -n k8s.io build -t openkruise/agent-runtime:preview-v0.0.2
helm安装Kruise Agents
实验时,Kruise Agents最新版本为0.1.0,可直接通过helm安装。
- 创建命名空间
注意在当前版本只支持sandbox-system
kubectl create ns sandbox-system
- 按顺序安装组件
本地构建上述镜像后,可以直接使用。
helm install agents-sandbox-controller openkruise/kruise-agents-sandbox-controller -n sandbox-system --version 0.1.0
helm install agents-sandbox-manager openkruise/kruise-agents-sandbox-manager -n sandbox-system --version 0.1.0
构建 code-interpreter 镜像
这里使用E2B官方code-interpreter镜像demo,由于E2B官方也没有提供code-interpreter的arm镜像,同样需要重新构建。
- 拉取code-interpreter仓库
git clone https://github.com/e2b-dev/code-interpreter.git
- 运行
template文件夹中的脚本生成Dockerfile,并构建镜像
cd template
pip install e2b dotenv
python3 build_docker.py
nerdctl -n k8s.io build -t e2b-dev/code-interpreter:latest
提示:build_docker.py默认构建支持python与ts/js的镜像,另外还支持多种运行时:r, deno, bash, java,编辑文件以增加镜像支持的运行时:
# 默认
tmp = make_template(kernels=["python", "javascript"], is_docker=True)
# 新增
tmp = make_template(kernels=["python", "javascript", "java"], is_docker=True)
通过CRD管理沙箱
创建code interpreter沙箱demo
创建sandboxset-demo.yaml
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxSet
metadata:
name: code-interpreter
namespace: default
annotations:
e2b.agents.kruise.io/should-init-envd: "true"
spec:
replicas: 2
template:
spec:
initContainers:
- name: init
image: openkruise/agent-runtime:preview-v0.0.2
imagePullPolicy: IfNotPresent
volumeMounts:
- name: envd-volume
mountPath: /mnt/envd
env:
- name: ENVD_DIR
value: /mnt/envd
restartPolicy: Always
containers:
- name: sandbox
image: e2bdev/code-interpreter:latest
imagePullPolicy: IfNotPresent
env:
- name: PORT
value: "49999"
- name: ENVD_DIR
value: /mnt/envd
volumeMounts:
- name: envd-volume
mountPath: /mnt/envd
lifecycle:
postStart:
exec:
command:
- bash
- /mnt/envd/envd-run.sh
startupProbe:
failureThreshold: 20
httpGet:
path: /health
port: 49999
initialDelaySeconds: 1
periodSeconds: 2
timeoutSeconds: 1
terminationGracePeriodSeconds: 1
volumes:
- name: envd-volume
emptyDir: { }
执行kubectl apply -f sandboxset-demo.yaml将创建一个副本数为2的预热池。查看集群中的sandbox,应当创建了两个沙箱
$ kubectl get sbx
NAME STATUS AGE SHUTDOWN_TIME PAUSE_TIME MESSAGE
code-interpreter-6gbkd Running 13h
code-interpreter-9qb47 Running 13h
通过SandboxClaim申领沙箱
创建sandboxclaim-demo.yaml
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
name: code-interpreter-claim-demo
namespace: default
spec:
templateName: code-interpreter
执行kubectl apply -f sandboxclaim-demo.yaml,会从沙箱池中申领一个沙箱,沙箱池将新创建一个待申领的沙箱。可以通过label筛选获取当前claim申领的沙箱
$ kubectl get sandbox
NAME STATUS AGE SHUTDOWN_TIME PAUSE_TIME MESSAGE
code-interpreter-6gbkd Running 13h
code-interpreter-9qb47 Running 13h
code-interpreter-gnxbm Running 25s
$ kubectl get sandbox -l agents.kruise.io/code-interpreter-claim-demo
NAME STATUS AGE SHUTDOWN_TIME PAUSE_TIME MESSAGE
code-interpreter-6gbkd Running 13h
通过E2B SDK管理沙箱
Sandbox-manager对外暴露E2B API,允许用户通过E2B官方SDK进行沙箱的生命周期管理与功能调用。对于sandbox-manager暴露的E2B需要进行以下配置。
E2B服务配置
- Ingress
需要修改sandbox-system中默认提供的Ingress:
- demo状态下可不提供证书,删除`spec.tls`字段
- 根据匹配规则中的host不同,分别修改为`sandbox.example.com`或`*.sandbox.example.com`
集群还需提供一个ingress controller。若没有,由于kruise agents默认指定nginx类型,推荐下面的命令快速安装ingress-nginx-controller。
helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace ingress-nginx --create-namespace
若集群已预置 nginx-ingress-controller,可按需编辑其 Service,开放 HTTP 端口(示例如下,nodePort 按环境调整)。
ports:
- appProtocol: http # 新增 http 80端口
name: http
nodePort: 30080
port: 80
protocol: TCP
targetPort: http
- appProtocol: https
name: https
nodePort: 30443
port: 443
protocol: TCP
targetPort: https
- E2B服务配置
注意:文档说可以通过helm values进行,但是截至0.1.0版本,该功能并不可用。需要通过sandbox-manager命令行启动参数配置,字段与默认值参见源码。
编辑agents-sandbox-manager Deployment,在spec.containers[].args中添加参数,env没用可以不改:
- args
-v=3
- --zap-log-level=3
- --peer-selector=agents.kruise.io/sandbox-manager-peer-finder=agents-sandbox-manager-1
# 新增
- --e2b-domain=sandbox.example.com
- --e2b-enable-auth=true
- --e2b-admin-key=your-secure-api-key
- 网络
由于配置了E2B域名,需要在节点 /etc/hosts 中添加 127.0.0.1 sandbox.exmaple.com。
配置kubectl端口转发,允许请求转发到Ingress Controller
kubectl port-forward -n ingress-nginx services/ingress-nginx-controller 80:80 &
使用E2B SDK管理与使用沙箱
- 安装SDK依赖
pip install e2b_code_interpreter
下载kruise-agent补丁文件patch_e2b.py到当前目录。
运行
python3打开交互式环境
from e2b_code_interpreter import Sandbox
import os
os.environ["E2B_DOMAIN"] = "sandbox.example.com"
os.environ["E2B_API_KEY"] = "your-secure-api-key"
from patch_e2b import patch_e2b
patch_e2b(False)
- 示例功能
创建沙箱,模板名称与前面的SandboxSet名称一致。由于预热池机制,可以看到拉起了一个新的Sandbox
sbx = Sandbox.create(template="code-interpreter", timeout=600)暂停沙箱,在另一个终端执行
kubectl get sbx可见对应的Sandbox状态变为Pausedsbx.beta_pause()code-interpreter-sslbv Paused 80m 2026-04-27T02:57:34Z恢复沙箱,在另一个终端执行
kubectl get sbx可见对应的Sandbox状态先变为Resuming,再变为Runningsbx.connect()code-interpreter-sslbv Resuming 83m # 等待几秒 code-interpreter-sslbv Running 84m删除沙箱,可见对应的Sandbox已不存在
sbx.kill()创建Sandbox对象后,执行
run_code方法下发代码运行请求。目前支持python、JS/TS、bash。>>> sbx.run_code("print('Hello, world!'')") Execution(Results: [], Logs: Logs(stdout: ['Hello, world!\n'], stderr: []), Error: None) >>> sbx.run_code("console.log('hello world')", language="ts") Execution(Results: [], Logs: Logs(stdout: ['hello world\n'], stderr: []), Error: None) >>> sbx.run_code("!uname -r") Execution(Results: [], Logs: Logs(stdout: ['6.x.x\r\n'], stderr: []), Error: None)
接入Kata-conteiners
在K8s上,推荐通过helm方式安装,文档
export VERSION=$(curl -sSL https://api.github.com/repos/kata-containers/kata-containers/releases/latest | jq .tag_name | tr -d '"')
export CHART="oci://ghcr.io/kata-containers/kata-deploy-charts/kata-deploy"
# 在demo环境中,只启用qemu vmm
helm install kata-deploy "${CHART}" --version "${VERSION}" \
--set shims.disableAll=true
--set shims.qemu.enabled=true
helm安装完成后,将在集群中创建kata-qemu的RuntimeClass,并部署一个DaemonSet在各节点上执行软件安装、containerd配置更新等工作。可查看Daemon的日志来确认Kata-containers安装是否完成。
修改上文sandboxset-demo.yaml,添加 runtime类配置,并重新创建SandboxSet。
spec:
runtimeClassName: kata-qemu
观察到Sandbox均为running状态即为创建成功,执行ctr以确认容器通过kata-containers启动:
$ ctr -n k8s.io c ls | grep code-interpreter
<container-id> docker.io/library/E2Bdev/code-interpreter:latest io.containerd.kata-qemu.v2
问题
在部分实验环境中,创建Pod失败,报错不支持 CPU 热插拔:
Error: failed to create containerd task: failed to create shim task: failed to query hotpluggable CPUs: QMP command failed: machine does not support hot-plugging CPUs修改kata配置文件
/opt/kata/share/defaults/kata-containers/runtimes/qemu/configuration-qemu.toml,设置default_maxvcpus=1,限制最大CPU与default_vcpus相等,从而禁用热插拔。重启containerd后解决。