Skip to content

Commit

Permalink
更新容器配置
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Sep 24, 2024
1 parent 7bf38b5 commit 0f40f64
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 26 deletions.
2 changes: 1 addition & 1 deletion consensus/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
一个篮子装不下所有的鸡蛋,那么就多用几个篮子来装。

:::right
—— 分布式容错系统设计的基本思想
—— 分布式处理系统的基本思想
:::

本章我们讨论如何在无序、冲突和不可靠的网络环境下实现分布式共识,共识是确保所有节点对某个决策达成一致的关键,如何实现共识是软件工程领域中最具挑战的难题之一。
Expand Down
25 changes: 14 additions & 11 deletions container/auto-scaling.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,25 @@

## 7.8.3 基于事件驱动的弹性伸缩

HPA 虽然能基于外部指标实现弹性伸缩,但缺点是仅与 Prometheus 指标关联
HPA 虽然能基于外部指标实现弹性伸缩,但缺点指标有限且粒度太粗。为了根据外部事件实现更细粒度的自动扩展,微软和红帽联合开发一种基于事件触发的 Kubernetes 自动伸缩器 KEDA(Kubernetes Event-driven Autoscaling)

为了更好地降低资源成本,微软和红帽联合开发一种基于事件触发的 Kubernetes 自动伸缩器 KEDA(Kubernetes Event-driven Autoscaling)。KEDA 的出现并非取代 HPA,它们实际上是一种组合配合关系。KEDA 通过内置几十种常见的 Scaler 或者用户自定义的 Scaler,来增强 HPA 的功能。例如,KEDA 可以根据消息队列的排队深度、每秒请求数、调度的 Cron 作业数等事件指标,驱动 HPA 动态调整工作负载,从 0 扩展到 1,或从 1 缩减到 0。

KEDA 的工作原理如图 7-35 所示,核心的组件如下:

- Scaler:连接到外部组件(如 Prometheus、RabbitMQ)以获取相关指标(如待处理消息队列的大小)。这些指标用于判断是否需要进行扩缩容操作。
- Metrics Adapter:将 Scaler 获取到的指标转化为 HPA(Horizontal Pod Autoscaler)能够使用的格式,并将这些指标传递给 HPA,使其能够基于这些数据进行自动扩缩容。
- Controller:负责创建和维护 HPA 对象资源,同时管理 HPA 的激活和停止。在没有事件触发时,Controller 会将副本数降低为 0(如果 minReplicaCount 未设置的话),以节省资源。
KEDA 的出现并非取代 HPA,它们实际上是一种组合配合关系。KEDA 的工作原理如图 7-35 所示,用户通过配置 ScaledObject(缩放对象)来定义 Scaler 的工作方式,Scaler(KEDA 内部的组件)持续从外部系统获取实时数据,并将这些数据与配置的扩展条件进行比较。当条件满足时,Scaler 将触发扩展操作,调用 Kubernetes 的 Horizontal Pod Autoscaler(HPA)调整对应工作负载的 Pod 副本数。

:::center
![](../assets/keda-arch.png)<br/>
图 7-35 KADA 架构图
:::

以下是一个 Kafka 的伸缩配置示例。minReplicaCount 和 maxReplicaCount 分别定义了伸缩对象的最小和最大副本数量。其中,minReplicaCount 可以设置为 0,这意味着在没有新消息的情况下,Kafka 的副本数量可以缩减至 0,实现完全缩容。当 Kafka 队列中有新消息到达时,KEDA 会自动触发扩容操作,确保系统能够及时处理消息负载。
KEDA 通过内置几十种常见的 Scaler 用来处理特定的事件源或指标源,笔者列举常见的 Scaler 供你参考:

- 消息队列 Scaler:如 Kafka、RabbitMQ、Azure Queue、AWS SQS 等消息队列的消息数量。
- 数据库 Scaler:如 SQL 数据库的连接数、数据库查询延迟等。
- HTTP 请求 Scaler:基于 Web API 的请求数量或响应时间。
- Prometheus Scaler:通过 Prometheus 获取的自定义指标来触发扩展,如队列长度、CPU 使用率等业务特定指标。
- 时间 Scaler:根据特定的时间段触发扩展逻辑,例如每日的高峰期或夜间低峰期。


以下是一个 Kafka Scaler 配置示例,它监控某个 Kafka 主题中的消息数量。当消息数量超过设定的阈值时,它会触发 Kubernetes 集群中的工作负载自动扩展以处理更多的消息;当消息处理完毕,消息队列变空时,Scaler 会触发缩减操作,减少 Pod 的副本数(可以缩减至 0,minReplicaCount)。

```yaml
apiVersion: keda.sh/v1alpha1
Expand All @@ -76,9 +79,9 @@ spec:
offsetResetPolicy: latest
```
## 7.8.4 集群节点自动伸缩
## 7.8.4 节点自动伸缩
随着业务的发展,应用数量和资源需求都会逐渐增加,最终可能导致集群资源不足。动态伸缩的范畴应该扩展到整个集群范围,也就是说能根据资源利用率情况自动增/减节点。
随着业务的增长(也有可能萎缩),应用数量和资源需求相应的变化,可能导致集群资源不足或者资源过度冗余。为了有效控制成本,动态伸缩的范畴应该扩展到整个集群范围,也就是说能根据资源利用率情况自动增/减节点。
在 Kubernetes 中,Cluster AutoScaler 是专门用于自动扩展和缩减集群节点的组件。它的主要功能如下:
- 自动扩展(Scale Up):当集群中的节点资源不足以满足当前的 Pod 请求时,Cluster AutoScaler 会自动向云服务提供商(如 GCE、GKE、Azure、AKS、AWS 等)请求创建新的节点,从而扩展集群容量,确保应用能够获得所需的资源。
Expand Down
23 changes: 9 additions & 14 deletions container/resource.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
# 7.7.1 资源模型


在 JAVA 的世界中一切皆对象,而在 Kubernetes 的世界中一切皆资源。

在 Kubernetes 中,“资源”是一个定义相当广泛的概念,下到物理资源(CPU、内存、磁盘空间),API 资源(Node、Pod、Service、Volume),以及 API 资源的属性或动作,如标签(Label)、命名空间(Namespace)、部署(Depoyment)、HPA 等等。然后使用 yaml 文件(也成资源清单)组织资源层级、调用关系。

在本节的“资源”指狭义上的物理资源,它们与调度有密切的关系。

## 1. 资源的分类

根据资源不足时应用表现的差异,Kubernetes 物理资源又可分为两类:
根据物理资源不足时应用表现的差异,Kubernetes 物理资源又可分为两类:

- **可压缩的资源**:此类资源匮乏时,容器内的进程会被限制,应用表现变得卡顿,业务延迟明显增加,但**容器进程不会被杀掉**。可压缩的资源典型代表是 CPU,CPU 资源其实准确来讲,指的是 CPU 时间。它的基本单位为 millicores,1 个核等于 1000 millicores。也代表了 kubernetes 可以将单位 CPU 时间细分为 1000 份。

Expand All @@ -23,9 +16,11 @@

## 2. 资源扩展

Kubernetes 在 Pod 中并没有专门为 GPU 设置一个专门的资源类型,而是使用了一个特殊字段(Extended Resource),来负责传递 GPU 资源。
在 Kubernetes 中,标准资源(如 CPU、内存、存储等)是由 Kubelet 自动报告的。但在某些情况下,节点可能会有一些特定的资源(如 GPU、FPGA、某些硬件加速器),Kubernetes 本身并没有识别和管理。

为了解决这个问题,Kubernetes 使用了一个特殊的机制(Extended Resource,扩展资源),用于让集群管理员声明、管理和使用除标准资源(如 CPU 和内存)之外的自定义资源。

为了能让调度器知道这个扩展资源在每台节点的可用量信息,节点本身就要通过 APIServer 汇报自身的资源情况。如下所示,通过发送 PATCH 请求,为节点增加自定义的资源类型
为在一个节点上发布一种新的扩展资源,需要发送一个 HTTP PATCH 请求到 Kubernetes API server。例如:假设你的一个节点上带有四个 gpu 资源。下面是一个 PATCH 请求的示例,该请求为`/<your-node-name>`节点发布 4 个 gpu 资源

```bash
PATCH /api/v1/nodes/<your-node-name>/status HTTP/1.1
Expand All @@ -41,8 +36,9 @@ Host: k8s-master:8080
}
]
```
需要注意的是,Kubernetes 并不了解 gpu 资源的含义和用途。前面的 PATCH 请求只是告诉 Kubernetes `<your-node-name>`节点拥有 4 个称之为 gpu 的东西。

输出展示了刚才扩展的 nvidia.com/gpu 资源:
然后,使用 kubectl describe node 命令查看节点资源配置情况。可以看到命令输出了刚才扩展的 nvidia.com/gpu 资源容量(capacity)为 4。

```bash
$ kubectl describe node <your-node-name>
Expand All @@ -54,7 +50,7 @@ Capacity:
...
```

接下来就可以在 Pod 中使用扩展资源了,比如下面这个例子
在定义 Pod 时,可以像请求标准资源(如 CPU 和内存)一样,请求这些自定义的 Extended Resource。以下是一个示例 Pod 的配置

```yaml
apiVersion: v1
Expand All @@ -69,8 +65,7 @@ spec:
limits:
nvidia.com/gpu: 1
```
可以看到,上面 Pod resources 中,GPU 的资源名称为 nvidia.com/gpu。也就是说这个 Pod 声明了要使用 nvidia 类型的 GPU。容器启动的时候,再通过挂载宿主机的 GPU 驱动,就能直接使用 GPU 资源了。
可以看到,上面 Pod resources 中,GPU 的资源名称为 nvidia.com/gpu,并且限制了它只能使用 1 个该资源。这意味着调度器会将这个 Pod 分配到一个有足够 nvidia.com/gpu 资源的节点上。当容器启动时,再通过挂载宿主机的 GPU 驱动,就能直接使用 GPU 资源了。
在 Kubernetes 支持的 GPU 方案中,你并不需要去操作上述 Extended Resource 的逻辑,Kubernetes 中,所有的硬件加速设备的管理都通过 Device Plugin 插件来支持,也包括对该硬件的 Extended Resource 进行汇报的逻辑。
Expand Down

0 comments on commit 0f40f64

Please sign in to comment.