/ kubernetes / README-ZH.md
README-ZH.md
  1  # OpenSandbox Kubernetes 控制器
  2  
  3  [English](README.md) | [中文](README-ZH.md)
  4  
  5  OpenSandbox Kubernetes 控制器,通过自定义资源管理沙箱环境。它在 Kubernetes 集群中提供**自动化沙箱生命周期管理**、**资源池化以实现快速供应**、**批处理沙箱创建**和**可选的任务编排**功能。
  6  
  7  ## 关键特性
  8  
  9  - **灵活的沙箱创建**:在池化和非池化沙箱创建模式之间选择
 10  - **批处理和单个交付**:支持单个沙箱(用于真实用户交互)和批处理沙箱交付(用于高吞吐量智能体强化学习场景)
 11  - **可选任务调度**:集成任务编排,支持可选的分片任务模板以实现异构任务分发和定制化沙箱交付(例如,进程注入)
 12  - **资源池化**:维护预热的资源池以实现快速沙箱供应
 13  - **全面监控**:实时跟踪沙箱和任务状态
 14  
 15  ## 功能特性
 16  
 17  ### 批处理沙箱管理
 18  BatchSandbox 自定义资源允许您创建和管理多个相同的沙箱环境。主要功能包括:
 19  - **灵活的创建模式**:支持池化(使用资源池)和非池化沙箱创建
 20  - **单个和批处理交付**:根据需要创建单个沙箱(replicas=1)或批处理沙箱(replicas=N)
 21  - **可扩展的副本管理**:通过副本配置轻松控制沙箱实例数量
 22  - **自动过期**:设置 TTL(生存时间)以自动清理过期沙箱
 23  - **可选任务调度**:内置任务执行引擎,支持可选任务模板
 24  - **详细状态报告**:关于副本、分配和任务状态的综合指标
 25  
 26  ### 资源池化
 27  Pool 自定义资源维护一个预热的计算资源池,以实现快速沙箱供应:
 28  - 可配置的缓冲区大小(最小和最大)以平衡资源可用性和成本
 29  - 池容量限制以控制总体资源消耗
 30  - 基于需求的自动资源分配和释放
 31  - 实时状态监控,显示总数、已分配和可用资源
 32  
 33  ### Pod 驱逐
 34  Pool 支持优雅的 Pod 驱逐,适用于节点维护或资源回收等场景:
 35  
 36  **工作原理:**
 37  - 用户通过给 Pod 打上 `pool.opensandbox.io/evict` 标签请求驱逐
 38  - 控制器会跳过已分配给 BatchSandbox 的 Pod(保护使用中的工作负载)
 39  - 空闲 Pod 将被删除,触发池补充容量
 40  - 标记驱逐的 Pod 不会被分配给新的 BatchSandbox
 41  
 42  **自定义驱逐行为:**
 43  您可以通过以下方式实现自定义驱逐策略:
 44  1. 在 Pool 上设置 `pool.opensandbox.io/eviction-handler` 标签选择您的处理器
 45  2. 实现 `EvictionHandler` 接口,包含 `NeedsEviction()` 和 `Evict()` 方法
 46  3. 在工厂函数中注册您的处理器
 47  
 48  ### 任务编排
 49  集成的任务管理系统,在沙箱内执行自定义工作负载:
 50  - **可选执行**:任务调度完全可选 - 可以在不带任务的情况下创建沙箱
 51  - **基于进程的任务**:支持在沙箱环境中执行基于进程的任务
 52  - **异构任务分发**:使用 shardTaskPatches 为批处理中的每个沙箱定制单独的任务
 53  
 54  ### 高级调度
 55  智能资源管理功能:
 56  - 最小和最大缓冲区设置,以确保资源可用性同时控制成本
 57  - 池范围的容量限制,防止资源耗尽
 58  - 基于需求的自动扩展
 59  
 60  ## 运行时 API 支持说明
 61  
 62  - Kubernetes 运行时当前**不支持** `pause` / `resume` 生命周期 API。
 63  - 对 Kubernetes 运行时调用这两个 API 会返回 `501 Not Implemented`。
 64  - OpenSandbox 的 pause/resume 语义是保留容器进程内存态后再恢复;当前 Kubernetes provider 主要覆盖 create/get/list/delete/renew 流程。
 65  
 66  
 67  ## 与 [kubernates-sigs/agent-sandbox](kubernates-sigs/agent-sandbox) 的关系
 68  
 69  BatchSandbox 并非重复实现 Agent-Sandbox 的基础功能,而是作为其补充,提供了额外的增强能力:
 70  
 71  1. **批量 Sandbox 语义**:在强化学习(RL)训练等场景下,显著提升 Sandbox 的交付吞吐量
 72  2. **Task 调度能力**:通过 Task 调度实现差异化 Sandbox 交付,例如在交付 Sandbox 之前向容器内注入自定义进程
 73  
 74  因此,您可以根据具体应用场景选择合适的项目作为 Sandbox 底层运行时。
 75  
 76  ### 性能测试
 77  
 78  BatchSandbox 与 Sig Agent-Sandbox 在吞吐量方面的性能对比测试。
 79  
 80  **测试环境**
 81  
 82  **Controller 组件配置**
 83  - 资源规格:request: 12C32G, limit: 16C64G
 84  - 并发配置:
 85    - **Sig Agent-Sandbox**:共 3 个 controller(sandbox、sandboxclaim、sandboxwarmppool),代码中未提供并发度配置,默认值为 1
 86    - **BatchSandbox**:共 2 个 controller,batchsandbox controller 并发度为 32,pool controller 并发度为 1
 87  
 88  **Pool 配置**
 89  - 镜像:busybox:latest
 90  - 资源规格:0.1C256MB
 91  
 92  > **补充说明**:虽然 BatchSandbox 的 batchsandbox-controller 并发度为 32,但测试用例中仅创建了一个 BatchSandbox 对象,实际等价于并发度为 1。因此在并发度方面,BatchSandbox 与 SIG Agent-Sandbox 保持一致。
 93  
 94  **性能对比结果**
 95  
 96  在都使用资源池的情况下,交付 100 个 Sandbox 的总耗时对比:
 97  
 98  | 测试场景 | 总耗时 (秒) |
 99  |---------|------------|
100  | SIG Agent-Sandbox (创建并发=1) | 76.35 |
101  | SIG Agent-Sandbox (创建并发=10) | 23.17 |
102  | SIG Agent-Sandbox (创建并发=50) | 33.85 |
103  | BatchSandbox | 0.92 |
104  
105  **原因分析**
106  
107  核心差异:Sig Agent-Sandbox 和 BatchSandbox 批量交付 N 个 Sandbox 的时间复杂度分别为 O(N) 和 O(1)。
108  
109  **Sig Agent-Sandbox 原理**
110  - 每个 Sandbox 的交付流程需要执行以下写操作(写操作总数与 Sandbox 规模成正比):
111    1. 创建一个 SandboxClaim
112    2. 创建一个 Sandbox
113    3. 更新 Pod 一次(从资源池中接管 Pod)
114    4. 更新 Sandbox Status 一次
115    5. 更新 SandboxClaim Status 一次
116  
117  **BatchSandbox 原理**
118  - 每批 Sandbox 的交付流程需要执行以下写操作(写操作总数与 Sandbox 规模无关):
119    1. 创建一个 BatchSandbox
120    2. 更新 BatchSandbox annotation 一次(写入批分配结果)
121    3. 更新 BatchSandbox status 一次
122  
123  ## 入门指南
124  
125  ![](images/deploy-example.gif)
126  
127  ### 先决条件
128  - go 版本 v1.24.0+
129  - docker 版本 17.03+
130  - kubectl 版本 v1.11.3+
131  - 访问 Kubernetes v1.21.1+ 集群
132  
133  如果您没有 Kubernetes 集群的访问权限,可以使用 [kind](https://kind.sigs.k8s.io/) 创建一个本地 Kubernetes 集群进行测试。Kind 在 Docker 容器中运行 Kubernetes 节点,使得设置本地开发环境变得容易。
134  
135  安装 kind:
136  - 从[发布页面](https://github.com/kubernetes-sigs/kind/releases)下载适用于您操作系统的发布二进制文件并将其移动到 `$PATH` 中
137  - 或使用包管理器:
138    - macOS (Homebrew):`brew install kind`
139    - Windows (winget):`winget install Kubernetes.kind`
140  
141  安装 kind 后,使用以下命令创建集群:
142  ```sh
143  kind create cluster
144  ```
145  
146  此命令默认创建单节点集群。要与其交互,请使用生成的 kubeconfig 运行 `kubectl`。
147  
148  **Kind 用户的重要说明**:如果您使用的是 kind 集群,在使用 `make docker-build` 构建镜像后,需要将控制器和任务执行器镜像加载到 kind 节点中。这是因为 kind 在 Docker 容器中运行 Kubernetes 节点,无法直接访问本地 Docker 守护进程中的镜像。
149  
150  使用以下命令将镜像加载到 kind 集群中:
151  ```sh
152  kind load docker-image <controller-image-name>:<tag>
153  kind load docker-image <task-executor-image-name>:<tag>
154  ```
155  
156  例如,如果您使用 `make docker-build CONTROLLER_IMG=my-controller:latest` 构建镜像,则使用以下命令加载:
157  ```sh
158  kind load docker-image my-controller:latest
159  ```
160  
161  完成后使用以下命令删除集群:
162  ```sh
163  kind delete cluster
164  ```
165  
166  有关使用 kind 的更多详细说明,请参阅[官方 kind 文档](https://kind.sigs.k8s.io/docs/user/quick-start/)。
167  
168  ### 部署
169  
170  此项目需要两个独立的镜像 - 一个用于控制器,另一个用于任务执行器组件。
171  
172  #### 方式 1:使用 Helm 部署(推荐)
173  
174  **从 GitHub Release 安装:**
175  
176  您可以直接从 GitHub Releases 安装 OpenSandbox Controller。查看 [Releases 页面](https://github.com/alibaba/OpenSandbox/releases?q=helm%2Fopensandbox-controller&expanded=true) 了解所有可用版本。
177  
178  ```sh
179  # 将 <version> 替换为所需版本(例如:0.1.0)
180  helm install opensandbox-controller \
181    https://github.com/alibaba/OpenSandbox/releases/download/helm/opensandbox-controller/<version>/opensandbox-controller-<version>.tgz \
182    --namespace opensandbox-system \
183    --create-namespace
184  ```
185  
186  具体版本示例:
187  ```sh
188  helm install opensandbox-controller \
189    https://github.com/alibaba/OpenSandbox/releases/download/helm/opensandbox-controller/0.1.0/opensandbox-controller-0.1.0.tgz \
190    --namespace opensandbox-system \
191    --create-namespace
192  ```
193  
194  您也可以先下载 chart 然后再安装:
195  ```sh
196  # 下载 chart
197  wget https://github.com/alibaba/OpenSandbox/releases/download/helm/opensandbox-controller/<version>/opensandbox-controller-<version>.tgz
198  
199  # 从本地文件安装
200  helm install opensandbox-controller ./opensandbox-controller-<version>.tgz \
201    --namespace opensandbox-system \
202    --create-namespace
203  ```
204  
205  **自定义安装:**
206  
207  使用 `--set` 参数自定义配置:
208  
209  ```sh
210  # 示例:自定义资源限制
211  helm install opensandbox-controller \
212    https://github.com/alibaba/OpenSandbox/releases/download/helm/opensandbox-controller/0.1.0/opensandbox-controller-0.1.0.tgz \
213    --namespace opensandbox-system \
214    --create-namespace \
215    --set controller.replicaCount=2 \
216    --set controller.resources.limits.cpu=1000m \
217    --set controller.resources.limits.memory=512Mi
218  
219  # 示例:自定义日志级别
220  helm install opensandbox-controller \
221    https://github.com/alibaba/OpenSandbox/releases/download/helm/opensandbox-controller/0.1.0/opensandbox-controller-0.1.0.tgz \
222    --namespace opensandbox-system \
223    --create-namespace \
224    --set controller.logLevel=debug
225  ```
226  
227  或使用 values 文件进行复杂配置:
228  
229  ```sh
230  # 创建自定义 values 文件
231  cat > custom-values.yaml <<EOF
232  controller:
233    replicaCount: 2
234    resources:
235      limits:
236        cpu: 1000m
237        memory: 512Mi
238      requests:
239        cpu: 100m
240        memory: 128Mi
241    logLevel: debug
242  EOF
243  
244  # 使用自定义 values 安装
245  helm install opensandbox-controller \
246    https://github.com/alibaba/OpenSandbox/releases/download/helm/opensandbox-controller/0.1.0/opensandbox-controller-0.1.0.tgz \
247    --namespace opensandbox-system \
248    --create-namespace \
249    -f custom-values.yaml
250  ```
251  
252  **从源码安装(用于开发):**
253  
254  如果您正在进行开发或需要自定义 chart:
255  
256  1. **构建和推送您的镜像:**
257     ```sh
258     # 构建和推送控制器镜像
259     make docker-build docker-push CONTROLLER_IMG=<some-registry>/opensandbox-controller:tag
260     
261     # 构建和推送任务执行器镜像
262     make docker-build-task-executor docker-push-task-executor TASK_EXECUTOR_IMG=<some-registry>/opensandbox-task-executor:tag
263     ```
264  
265  2. **使用 Helm 安装:**
266     ```sh
267     helm install opensandbox-controller ./charts/opensandbox-controller \
268       --set controller.image.repository=<some-registry>/opensandbox-controller \
269       --set controller.image.tag=<tag> \
270       --namespace opensandbox-system \
271       --create-namespace
272     ```
273  
274  **验证安装:**
275  
276  检查控制器是否运行:
277  ```sh
278  kubectl get pods -n opensandbox-system
279  kubectl get deployment -n opensandbox-system
280  
281  # 查看日志
282  kubectl logs -n opensandbox-system -l control-plane=controller-manager -f
283  ```
284  
285  **升级:**
286  
287  ```sh
288  # 升级到新版本
289  helm upgrade opensandbox-controller \
290    https://github.com/alibaba/OpenSandbox/releases/download/helm/opensandbox-controller/<new-version>/opensandbox-controller-<new-version>.tgz \
291    --namespace opensandbox-system
292  ```
293  
294  **卸载:**
295  
296  ```sh
297  helm uninstall opensandbox-controller -n opensandbox-system
298  ```
299  
300  有关更多配置选项和高级用法,请参阅 [Helm Chart README](charts/opensandbox-controller/README.md)。
301  
302  #### 方式 2:使用 Kustomize 部署
303  
304  1. **构建和推送您的镜像:**
305     ```sh
306     # 构建和推送控制器镜像
307     make docker-build docker-push CONTROLLER_IMG=<some-registry>/opensandbox-controller:tag
308     
309     # 构建和推送任务执行器镜像
310     make docker-build-task-executor docker-push-task-executor TASK_EXECUTOR_IMG=<some-registry>/opensandbox-task-executor:tag
311     ```
312  
313     **注意:** 这些镜像应该发布在您指定的个人注册表中。需要能够从工作环境中拉取镜像。如果上述命令不起作用,请确保您对注册表具有适当的权限。
314  
315  2. **将 CRD 安装到集群中:**
316     ```sh
317     make install
318     ```
319  
320  3. **将管理器部署到集群:**
321     ```sh
322     make deploy CONTROLLER_IMG=<some-registry>/opensandbox-controller:tag TASK_EXECUTOR_IMG=<some-registry>/opensandbox-task-executor:tag
323     ```
324  
325     **注意**:您可能需要授予自己集群管理员权限或以管理员身份登录以确保您在运行命令之前具有集群管理员权限。
326  
327  **Kind 用户的重要说明**:如果您使用的是 kind 集群,需要在构建镜像后将两个镜像都加载到 kind 节点中:
328  ```sh
329  kind load docker-image <controller-image-name>:<tag>
330  kind load docker-image <task-executor-image-name>:<tag>
331  ```
332  
333  ### 创建 BatchSandbox 和 Pool 资源
334  
335  #### 基础示例
336  创建一个简单的非池化沙箱,不带任务调度:
337  
338  ```yaml
339  apiVersion: sandbox.opensandbox.io/v1alpha1
340  kind: BatchSandbox
341  metadata:
342    name: basic-batch-sandbox
343  spec:
344    replicas: 2
345    template:
346      spec:
347        containers:
348        - name: sandbox-container
349          image: nginx:latest
350          ports:
351          - containerPort: 80
352  ```
353  
354  应用批处理沙箱配置:
355  ```sh
356  kubectl apply -f basic-batch-sandbox.yaml
357  ```
358  
359  检查批处理沙箱状态:
360  ```sh
361  kubectl get batchsandbox basic-batch-sandbox -o wide
362  ```
363  
364  示例输出:
365  ```sh
366  NAME                   DESIRED   TOTAL   ALLOCATED   READY   EXPIRE   AGE
367  basic-batch-sandbox    2         2       2           2       <none>   5m
368  ```
369  
370  状态字段说明:
371  - **DESIRED**:请求的沙箱数量
372  - **TOTAL**:创建的沙箱总数
373  - **ALLOCATED**:成功分配的沙箱数量
374  - **READY**:准备使用的沙箱数量
375  - **EXPIRE**:过期时间(未设置时为空)
376  - **AGE**:资源创建以来的时间
377  
378  沙箱准备好后,您可以在注解中找到端点信息:
379  ```sh
380  kubectl get batchsandbox basic-batch-sandbox -o jsonpath='{.metadata.annotations.sandbox\.opensandbox\.io/endpoints}'
381  ```
382  
383  这将显示交付沙箱的 IP 地址。
384  
385  #### 高级示例
386  
387  ##### 不带任务的池化沙箱
388  首先,创建一个资源池:
389  
390  ```yaml
391  apiVersion: sandbox.opensandbox.io/v1alpha1
392  kind: Pool
393  metadata:
394    name: example-pool
395  spec:
396    template:
397      spec:
398        containers:
399        - name: sandbox-container
400          image: nginx:latest
401          ports:
402          - containerPort: 80
403    capacitySpec:
404      bufferMax: 10
405      bufferMin: 2
406      poolMax: 20
407      poolMin: 5
408  ```
409  
410  应用资源池配置:
411  ```sh
412  kubectl apply -f pool-example.yaml
413  ```
414  
415  **可选:配置扩容速率控制** - 添加 `scaleStrategy` 限制扩容节奏:
416  ```yaml
417    scaleStrategy:
418      maxUnavailable: "20%"  # 或绝对数量如 5
419  ```
420  
421  该配置控制扩容过程中允许不可用的 Pod 数量。例如,当 `poolMax=50` 且 `maxUnavailable=20%` 时,每次最多扩容 10 个 Pod。
422  
423  使用资源池创建一批沙箱:
424  
425  ```yaml
426  apiVersion: sandbox.opensandbox.io/v1alpha1
427  kind: BatchSandbox
428  metadata:
429    name: pooled-batch-sandbox
430  spec:
431    replicas: 3
432    poolRef: example-pool
433  ```
434  
435  应用批处理沙箱配置:
436  ```sh
437  kubectl apply -f pooled-batch-sandbox.yaml
438  ```
439  
440  ##### 带异构任务的池化沙箱
441  创建一批带有基于进程的异构任务的沙箱。为了使任务执行正常工作,任务执行器必须作为 sidecar 容器部署在资源池模板中,并与沙箱容器共享进程命名空间:
442  
443  首先,创建一个带有任务执行器 sidecar 的资源池:
444  
445  ```yaml
446  apiVersion: sandbox.opensandbox.io/v1alpha1
447  kind: Pool
448  metadata:
449    name: task-example-pool
450  spec:
451    template:
452      spec:
453        shareProcessNamespace: true
454        containers:
455        - name: sandbox-container
456          image: ubuntu:latest
457          command: ["sleep", "3600"]
458        - name: task-executor
459          image: <task-executor-image>:<tag>
460          securityContext:
461            capabilities:
462              add: ["SYS_PTRACE"]
463    capacitySpec:
464      bufferMax: 10
465      bufferMin: 2
466      poolMax: 20
467      poolMin: 5
468  ```
469  
470  使用我们刚刚创建的资源池创建一批带有基于进程的异构任务的沙箱:
471  
472  ```yaml
473  apiVersion: sandbox.opensandbox.io/v1alpha1
474  kind: BatchSandbox
475  metadata:
476    name: task-batch-sandbox
477  spec:
478    replicas: 2
479    poolRef: task-example-pool
480    taskTemplate:
481      spec:
482        process:
483          command: ["echo", "Default task"]
484    shardTaskPatches:
485    - spec:
486        process:
487          command: ["echo", "Custom task for sandbox 1"]
488    - spec:
489        process:
490          command: ["echo", "Custom task for sandbox 2"]
491          args: ["with", "additional", "arguments"]
492  ```
493  
494  应用批处理沙箱配置:
495  ```sh
496  kubectl apply -f task-batch-sandbox.yaml
497  ```
498  
499  检查带任务的批处理沙箱状态:
500  ```sh
501  kubectl get batchsandbox task-batch-sandbox -o wide
502  ```
503  
504  示例输出:
505  ```sh
506  NAME                   DESIRED   TOTAL   ALLOCATED   READY   TASK_RUNNING   TASK_SUCCEED   TASK_FAILED   TASK_UNKNOWN   EXPIRE   AGE
507  task-batch-sandbox     2         2       2           2       0              2              0             0              <none>   5m
508  ```
509  
510  任务状态字段说明:
511  - **TASK_RUNNING**:当前正在执行的任务数
512  - **TASK_SUCCEED**:成功完成的任务数
513  - **TASK_FAILED**:失败的任务数
514  - **TASK_UNKNOWN**:状态未知的任务数
515  
516  当您删除带有运行任务的 BatchSandbox 时,控制器将首先停止所有任务,然后删除 BatchSandbox 资源。一旦所有任务都成功终止,BatchSandbox 将被完全删除,沙箱将返回到资源池中以供重用。
517  
518  删除 BatchSandbox:
519  ```sh
520  kubectl delete batchsandbox task-batch-sandbox
521  ```
522  
523  您可以通过观察 BatchSandbox 状态来监控删除过程:
524  ```sh
525  kubectl get batchsandbox task-batch-sandbox -w
526  ```
527  
528  ### 监控资源
529  检查资源池和批处理沙箱的状态:
530  ```sh
531  # 查看资源池状态
532  kubectl get pools
533  
534  # 查看批处理沙箱状态
535  kubectl get batchsandboxes
536  
537  # 获取特定资源的详细信息
538  kubectl describe pool example-pool
539  kubectl describe batchsandbox example-batch-sandbox
540  ```
541  
542  ## 项目结构
543  
544  ```
545  ├── api/
546  │   └── v1alpha1/          # 自定义资源定义(BatchSandbox, Pool)
547  ├── cmd/
548  │   ├── controller/         # 主控制器管理器入口点
549  │   └── task-executor/     # 任务执行器二进制文件
550  ├── config/
551  │   ├── crd/               # 自定义资源定义清单
552  │   ├── default/           # 控制器部署的默认配置
553  │   ├── manager/           # 控制器管理器配置
554  │   ├── rbac/              # 基于角色的访问控制清单
555  │   └── samples/           # 资源的示例 YAML 清单
556  ├── hack/                  # 开发脚本和工具
557  ├── images/                # 文档图片
558  ├── internal/
559  │   ├── controller/        # 核心控制器实现
560  │   ├── scheduler/         # 资源分配和调度逻辑
561  │   ├── task-executor/     # 任务执行引擎内部实现
562  │   └── utils/             # 实用函数和助手
563  ├── pkg/
564  │   └── task-executor/     # 共享的任务执行器包
565  └── test/                  # 测试套件
566  ```
567  
568  ## 贡献
569  欢迎为 OpenSandbox Kubernetes 控制器项目做出贡献。请随时提交问题、功能请求和拉取请求。
570  
571  **注意:** 运行 `make help` 以获取所有潜在 `make` 目标的更多信息
572  
573  更多信息请参见 [Kubebuilder 文档](https://book.kubebuilder.io/introduction.html)
574  
575  ## 许可证
576  此项目在 Apache 2.0 许可证下开源。
577  
578  您可以将 OpenSandbox 用于个人或商业项目,只要遵守许可证条款即可。