Skip to content

Commit

Permalink
更新 k8s 资源
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Jun 20, 2024
1 parent b52a032 commit 8fcdd12
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
7 changes: 7 additions & 0 deletions container/conclusion.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# 7.8 小结

从 Google 的 Brog 到如今的 Kubernetes,容器化技术的最大益处早就超越了单纯的提高硬件资源使用率的范畴。

Kubernetes 通过无数的扩展/接口,变成外部可扩展的功能,通过 CNI 插件,实现容器间通信,通过 CSI,所有的存储生态。通过 Device Plugin 又把资源扩展到 GPU、FPGA 这类物理设备,正是这种开放性的设计,Kubernetes 乘着整个开源社区的力量不断向前。

最关键的是,Kubernetes 以统一的方式抽象以上资源/基础设施的能力,并将这些抽象以声明式 API 的方式对外暴露,用户只需要关心应用的最终状态,而不是去关注底层的基础设施哪来的、如何实现、如何配置。

通过 API 框架屏蔽底层细节,为用户提供一种简单/一致/跨平台的方式来管理和部署应用,正是 Kubernetes 设计哲学的精髓所在。

本章参考内容:

Expand Down
11 changes: 7 additions & 4 deletions container/kube-scheduler.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Kubernetes 默认调度器(kube-scheduler)双循环架构如下所示。

Kubernetes 的调度器还要负责对调度器缓存(即 Scheduler Cache)进行更新,缓存的目的主要是对调度部分进行性能优化,将集群信息 cache 化,以便提升 Predicate 和 Priority 调度算法的执行效率。

第二个控制循环,是调度器负责 Pod 调度的主循环,被称之为 Scheduling Path。
第二个控制循环是调度器负责 Pod 调度的主循环,被称之为 Scheduling Path。

Scheduling Path 主要逻辑是不断地从调度队列里出队一个 Pod。然后调用 Predicates 算法对所有的 Node 进行“过滤”。“过滤”得到的一组可以运行这个 Pod 的 Node 列表。当然,Predicates 算法需要的 Node 信息,也都是 Scheduler Cache 里直接拿到的,这是调度器保证算法执行效率的主要手段之一。

Expand All @@ -48,16 +48,19 @@ Kubernetes 调度器的上述设计思想,也是在集群规模不断增长的

**解决以上问题的思想是将调度单元从 Pod 修改为 PodGroup,以组的形式进行调度,实现“Gang Scheduling”**

实现 Gang Scheduling 的第一步,便是要干预 Pod 的调度逻辑。

Kubernetes 从 v1.15 版本起,为 kube-scheduler 设计了可插拔的扩展机制 —— Scheduling Framework。

:::center
![](../assets/scheduling-framework-extensions.png)<br/>
Pod 的调度上下文以及调度框架公开的扩展点
:::

有了 Scheduling Framework,在保持调度“核心”简单且可维护的同时,用户可以编写自己的调度插件注册到 Scheduling Framework 的扩展点来实现自己想要的调度逻辑。

最开始是社区催化 kube-batch,能够将一个训练任务的多个 Pod 当做一个整体进行调度,只有当任务所有 Pod 的资源都满足,才会将容器在节点上启动;kube-batch 还提供了 Queue 的机制(其实就是多租户),不同队列之间可以设置优先级,优先级高的队列中的任务会优先得到调度
比如,你可以扩展调度队列的实现,控制每个调度的时机,然后 Predicates 选择满足某一组 Pod 资源的节点,实现多个 Pod 被统一调度

但仅有调度器还不足以支持相应的批量计算作业,作为一个批量计算系统还需要其它很多组件的支持,例如 作业管理,数据管理,资源规划等等。
但仅有调度器还不足以支持相应的批量计算作业,作为一个批量计算系统还需要其它很多组件的支持,例如作业管理,数据管理,资源规划等等。

后续社区中又陆续出现 Volcano、Koordinator 项目,这些项目虽然功能上有些差异,但总体而言核心依靠基本的 Gang Scheduling,提供主流架构的 CPU、GPU 在内的异构设备混合调度能力,再补齐 MPI 等辅助功能,最终构造出以 Kubernetes 为基础的通用的计算系统/平台。
社区中陆续出现 Volcano、Koordinator 项目,这些项目虽然功能上有些差异,但总体而言核心依靠基本的 Gang Scheduling,提供主流架构的 CPU、GPU 在内的异构设备混合调度能力,再补齐 MPI 等辅助功能,最终构造出以 Kubernetes 为基础的通用的计算系统/平台。
32 changes: 20 additions & 12 deletions container/resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
```
注意 Mebibyte 和 Megabyte 的区分,123 Mi = `123*1024*1024 B` 、123 M = `1*1000*1000 B`,显然使用带小 i 的更准确。

## 2. 扩展资源
## 2. Extended Resource 与 Device Plugin

当容器运行需要一些特殊资源,Kubernetes 就无能为力了。
Kubernetes 在 Pod 中并没有专门为 GPU 设置一个专门的资源类型,而是使用了一个特殊字段(Extended Resource),来负责传递 GPU 资源。

为了能让调度器知道这个扩展资源在每台节点的可用量信息,节点本身就要通过 APIServer 汇报自身的资源情况。如下所示,通过发送 PATCH 请求,为节点增加自定义的资源类型。

```bash
PATCH /api/v1/nodes/<your-node-name>/status HTTP/1.1
Expand All @@ -25,25 +27,25 @@ Host: k8s-master:8080
[
{
"op": "add",
"path": "/status/capacity/example.com~1dongle",
"path": "/status/capacity/nvidia.com~1gpu",
"value": "4"
}
]
```

输出展示了刚才扩展的 dongle 资源:
输出展示了刚才扩展的 nvidia.com/gpu 资源:

```bash
$ kubectl describe node <your-node-name>
...
Capacity:
cpu: 2
memory: 2049008Ki
example.com/dongle: 4
nvidia.com/gpu: 4
...
```

接下来就可以在 Pod 中使用扩展资源了。
接下来就可以在 Pod 中使用扩展资源了,比如下面这个例子

```yaml
apiVersion: v1
Expand All @@ -59,17 +61,23 @@ spec:
nvidia.com/gpu: 1
```

Kubernetes 在 1.8 版本中引入了 Device Plugin 机制,支持以插件化的方式将第三方的设备接入到 kubernetes 体系中,类似 CPU、MEM 方式进行调度、使用。例如 GPU 设备,设备厂商只需要开发一个配套的 Device Plugin 组件,并且以 DaemonSet 的方式将其运行在集群当中,Kubelet 通过 gRPC 接口与 Device Plugin 组件交互,实现设备发现、状态更新、资源上报等
可以看到,上面 Pod resources 中,GPU 的资源名称为 nvidia.com/gpu。也就是说这个 Pod 声明了要使用 nvidia 类型的 GPU。容器启动的时候,再通过挂载宿主机的 GPU 驱动,就能直接使用 GPU 资源了

最后,应用通过 resource request、limit 显示声明使用即可,如同 CPU、MEM 一样
在 Kubernetes 支持的 GPU 方案中,你并不需要去操作上述 Extended Resource 的逻辑,Kubernetes 中,所有的硬件加速设备的管理都通过 Device Plugin 插件来支持,也包括对该硬件的 Extended Resource 进行汇报的逻辑

就像存储资源,存储有读写方式、存储空间大小、回收策略等等,而这些异构资源 GPU、FPGA、ASIC、智能网卡设备等,也肯定不能仅用一个增减的数字代表。而且这些设备在系统拓扑层面是紧密协作的,这就要求在分配扩展资源时,还需要感知硬件拓扑,尽可能就近分配这种设备
各个硬件设备商开发的 Device Plugin 插件以 DaemonSet 方式运行在集群当中,Kubelet 通过 gRPC 接口与 Device Plugin 插件交互,实现设备发现、状态更新、资源上报等

在这些特殊场景的催化下,Nvidia、Intel 等头部厂商联合推出了 DRA(Dynamic Resource Allocation,动态资源分配)机制,用于解决现有 Device Plugin 的不足。
最后,Pod 通过 resource request、limit 显示声明使用即可,如同 CPU、MEM 一样。

:::tip 问题

你注意到 Device Plugin 的问题了么?

DRA 借鉴了 StoreClass 的设计,更加开放和自主,
Pod 只能过"nvidia.com/gpu:2" 这种简单的“计数形式”,来申请 2 块 GPU,但是关于 2 块卡分别是什么型号、是否拓扑最优、是否共享/独享等等内容,都没有能力进行选择。

现在,NVIDIA、Intel 这些设备厂商也基于 DRA 开放了自己下一代 Device Plugin,以期满足更复杂的业务场景。
在这些特殊场景的催化下,Nvidia、Intel 等头部厂商联合推出了 DRA(Dynamic Resource Allocation,动态资源分配)机制,用于解决现有 Device Plugin 的不足。

:::

## 3. 节点资源分配控制

Expand Down

0 comments on commit 8fcdd12

Please sign in to comment.