本文发布于Cylon的收藏册,转载请著名原文链接~
原作者 Javier Martínez
背景
在学习 Kubernetes 调度时,有两个重要的概念,“request “与 “limit”,而对应的资源就是“内存” 与 “CPU” ,而这两个决定了 Pod 将如何调度;“request “与 “limit” 也是整个调度系统中的基数因子。
什么是 request 和 limit
在 Kubernetes 中,Limit 是容器可以使用的最大资源量,这表示 “容器” 的内存或 CPU 的使用,永远不会超过 Limit 配置的值。
而另一方面,Request 则是为 “容器” 保留的最低资源保障;换句话来说,Request 则是在调度时,容器被允许所需的配置。
如何配置 request 和 limit
下列清单是 Deployment 的部署清单,他将部署一个 redis 与 一个 busybox
kind: Deployment
apiVersion: extensions/v1beta1
…
template:
spec:
containers:
- name: redis
image: redis:5.0.3-alpine
resources:
limits:
memory: 600Mi
cpu: 1
requests:
memory: 300Mi
cpu: 500m
- name: busybox
image: busybox:1.28
resources:
limits:
memory: 200Mi
cpu: 300m
requests:
memory: 100Mi
cpu: 100m
假设现有集群,具有 4 核CPU 和 16GB RAM 节点。此时可以提取出的信息如下:
-
Pod Request 是 400 MiB 内存和 600 毫核 CPU (Redis+busybox)。而调度需要一具有足够可用可分配空间的Node
来调度 Pod。
-
redis的 CPU 为 512,busybox 容器的 CPU 份额为 102,Kubernetes 为每个核心分配 1024 个份额,因此 redis:1024 * 0.5 个核心 ≅ 512 与 busybox:1024 * 0.1 个核心 ≅ 102
-
如果 Redis 容器尝试分配超过 600MB 的内存,则它会被 OOM 终止
-
如果 Redis 每 100 毫秒超过超过 100 毫秒时的 CPU,(Node有 4 个核,可用时间为每 100 毫秒 400 毫秒时),Redis 将受到 CPU 限制,从而导致性能下降**。**
-
如果 Busybox 容器试图分配超过 200MB 的内存,它将被 OOM 终止
-
如果Busybox尝试每 100 毫秒使用超过 30 毫秒的 CPU
Request
通过上面示例,可以下定义了,Kuberentes 将 Request 定义为容器的 最小资源量。
当一个 Pod 被调度时,kube-scheduler
将检查 Kubernetes 请求,以便将该 Pod 分配到最佳节点,该节点至少可以满足 Pod 中所有容器的数量。如果 Request 的数量高于可用资源,则 Pod 将不会被调度并保持在 Pending 状态。
例如下列例子
resources:
requests:
cpu: 0.1
memory: 4Mi
使用请求:
-
将 Pod 分配给 Node 时,满足 Pod 中容器指示的 Request 。
-
在运行时,指示的 Request 将保证为该 Pod 中的容器的最小 Request 。
Limit
Limit 在 Kubernetes 为定义容器可以使用的最大资源量。这代表容器永远不会超过 Limit 配置的 内存 或 CPU 。
resources:
limits:
cpu: 0.5
memory: 100Mi
- 在调度时,如果没有配置 Request,默认 Kubernetes 将设置 requests = limits。
- 调度后,运行时,kubelet 检查 Pod 中的容器是否消耗了比 Limit 中配置的更多的资源。
CPU 和 内存的特性
CPU 是一种 “可压缩资源”,这意味着它可以被拉伸以满足所有需求。如果进程申请了太多 CPU,其中一些将被限制。
- 可以使用 millicores (m) 来表示比1核心更小的数量
- CPU 最小量为 1m
内存是一种 “不可压缩的” 资源,这意味着内存资源不能像 CPU 资源那样被拉伸。如果一个进程没有足够的内存来工作,这个进程就会被 OOM。
内存资源在 Kubernetes 中的单位是以字节为单位,可以使用大写的 E、P、T、G、M、k 来表示 Exabyte、Petabyte、Terabyte、Gigabyte、Megabyte 和 kilobyte,例如 4G, 500M;也可以使用 Ei、Pi、Ti,例如 500Mi
**G 和 Gi ** 的区别:**G 和 Gi **区别主要在计算方式上,G是按照 2 的 n 次方进行计算,例如 1KB = $2^{10}$,而 Gi 计算方式是按照 10 的 n 次方,例如 1Mi = $10^3$
Note:不要使用小写的 “m” ,这代表 Millibytes
Resource/LimitQuota - 基于名称空间的资源限制
ResourceQuotas 在 Kubernetes 集群中提供了基于名称空间的资源隔离,我们可以将资源隔离到不同的名称空间中,也称为租户;例如可以 为整个命名空间设置内存或 CPU 限制,确保名称空间内的业务不能从使用更多的系统资源。
下列是一个 ResourceQuotas 的配置
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-demo
spec:
hard:
requests.cpu: 2
requests.memory: 1Gi
limits.cpu: 3
limits.memory: 2Gi
requests.cpu
:名称空间中所有 Request 的最低 CPU 数量requests.memory
:名称空间中所有 Request 的 最低内存数量limits.cpu
:名称空间中所有 Limit 最大 CPU 数量limits.memory
:名称空间中所有 Limit 最大内存量
ResourceQuotas 可限制名称空间的资源总量,如果我们想给里名称空间里的 Pod 配置限制可以使用 “LimitRange”
下列是一个 LimitRanges 的配置
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-resource-constraint
spec:
limits:
- default:
cpu: 500m
defaultRequest:
cpu: 500m
min:
cpu: 100m
max:
cpu: "1"
type: Container
default
: 如果未指定,创建的容器将具有此值。min
:创建的容器不能有小于此的限制或请求。max
: 创建的容器不能有比这更大的限制或请求。
Note: 在默认情况下,即使未设置
LimitRanges
,Pod 中的所有容器也会有效地请求 100m 的 CPU。
总结
- Request 和 Limit 是在 Kubernetes 集群中控制成本的关键配置
- 只有巧用 Request 和 Limit 才可以为集群提供最佳配额
- 专用的 容器不应该设置 Request 和 Limit,这将导致容器无法正常允许,甚至被驱逐
- 只有对 Request 和 Limit 进行精细的设置才可以使 Kubernetes 集群最佳化,否则 “弊大于利”
本文发布于Cylon的收藏册,转载请著名原文链接~
链接:https://www.oomkill.com/2023/06/kubernetes-limit-request/
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。