yangxt65535

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安装

  1. 创建命名空间

注意在当前版本只支持sandbox-system

kubectl create ns sandbox-system
  1. 按顺序安装组件

本地构建上述镜像后,可以直接使用。

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镜像,同样需要重新构建。

  1. 拉取code-interpreter仓库
git clone https://github.com/e2b-dev/code-interpreter.git
  1. 运行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服务配置

  1. 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
  1. 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
  1. 网络

由于配置了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管理与使用沙箱

  1. 安装SDK依赖
pip install e2b_code_interpreter
  1. 下载kruise-agent补丁文件patch_e2b.py到当前目录。

  2. 运行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)
  1. 示例功能
  • 创建沙箱,模板名称与前面的SandboxSet名称一致。由于预热池机制,可以看到拉起了一个新的Sandbox

    sbx = Sandbox.create(template="code-interpreter", timeout=600)
    
  • 暂停沙箱,在另一个终端执行kubectl get sbx可见对应的Sandbox状态变为Paused

    sbx.beta_pause()
    
    code-interpreter-sslbv   Paused    80m     2026-04-27T02:57:34Z
    
  • 恢复沙箱,在另一个终端执行kubectl get sbx可见对应的Sandbox状态先变为Resuming,再变为Running

    sbx.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

问题

  1. 在部分实验环境中,创建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后解决。