本文发布于Cylon的收藏册,转载请著名原文链接~


原作者 Javier Martínez

背景

在学习 Kubernetes 调度时,有两个重要的概念,“request “与 “limit”,而对应的资源就是“内存” 与 “CPU” ,而这两个决定了 Pod 将如何调度;“request “与 “limit” 也是整个调度系统中的基数因子。

什么是 request 和 limit

在 Kubernetes 中,Limit 是容器可以使用的最大资源量,这表示 “容器” 的内存或 CPU 的使用,永远不会超过 Limit 配置的值。

而另一方面,Request 则是为 “容器” 保留的最低资源保障;换句话来说,Request 则是在调度时,容器被允许所需的配置。

img

图:Kubernetes 中Limit 和 Request 图示
Source:https://sysdig.com/blog/kubernetes-limits-requests/

如何配置 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 节点。此时可以提取出的信息如下:

  1. Pod Request 是 400 MiB 内存和 600 毫核 CPU (Redis+busybox)。而调度需要一具有足够可用可分配空间的Node

    来调度 Pod。

  2. redis的 CPU 为 512,busybox 容器的 CPU 份额为 102,Kubernetes 为每个核心分配 1024 个份额,因此 redis:1024 * 0.5 个核心 ≅ 512 与 busybox:1024 * 0.1 个核心 ≅ 102

  3. 如果 Redis 容器尝试分配超过 600MB 的内存,则它会被 OOM 终止

  4. 如果 Redis 每 100 毫秒超过超过 100 毫秒时的 CPU,(Node有 4 个核,可用时间为每 100 毫秒 400 毫秒时),Redis 将受到 CPU 限制,从而导致性能下降**。**

  5. 如果 Busybox 容器试图分配超过 200MB 的内存,它将被 OOM 终止

  6. 如果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 。

如何设置良好的 CPU 请求

图:如何最佳的分配资源
Source:https://sysdig.com/blog/kubernetes-limits-requests/

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 国际」 许可协议进行许可。