理解Kubernetes中的CPU请求和限制
在本文中,我们将探讨「请求」和「限制」的含义,以及它们如何转化为操作系统原语并如何执行,读者如果有Kubernetes和Linux的相关经验,这将会对你有所帮助。
资源管理基础
Kubernetes允许指定单个Pod需要多少CPU/RAM,并且如何限制给定Pod对这些资源的使用。这是通过资源部分下的请求和限制来实现的。
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: app
image: my.private.registry/my-app
resources:
requests:
memory: "64M"
cpu: "250m"
limits:
memory: "128M"
cpu: "500m"
在研究如何执行请求和限制之前,让我们先熟悉一下它们所衡量的单位。上面的例子中,容器应用程序的请求被指定为250毫核心和64兆字节,而限制则为500毫核心/120兆字节。
内存单元
内存以字节为单位进行测量,单位非常直观。Kubernetes允许使用SI后缀,如k、M、G、T,分别表示千字节、兆字节、千兆字节和太字节。同时,还可以使用Ki、Mi、Gi、Ti表示基比字节、米比字节、吉比字节和太比字节,这是2的幂单位。
CPU 单元
CPU资源的度量单位,你猜对了,就是CPU单位。1个CPU单位等同于1个物理核心(或虚拟核心,取决于集群运行的位置)。要指定CPU的分数,可以使用毫核单位,其中1个CPU = 1000m。
由于CPU是一种可压缩的资源,因此很难直观地确定这个单位对应的是什么,而且更令人困惑的是,请求和限制的含义略有不同。
CPU是一个绝对的单位,意味着无论一个节点有多少个核心,1个CPU始终是相同的。
请求和安排
Kubernetes使用资源的请求部分来在节点上调度Pod,并确保Pod将获得所请求的资源量。
实际上,Pod中的每个容器都有指定的资源,但为了简单起见,我们假设我们的Pod只有一个容器。当Pod在节点上进行调度时,Kubernetes使用总值来进行调度。
例如,假设我们有以下3个Pods:
- 应用程序1:250兆CPU和512兆内存
- 应用程序2:300兆CPU和512兆内存
- 应用程序3:350兆CPU和768兆内存
当Kubernetes尝试将Pod调度到具有1个vCPU和2G RAM的节点上时,所有的Pod都将适应,因为它们有足够的资源
但是如果我们改变对于App 3的请求,现在需要1G的内存呢?现在Kubernetes将无法将该Pod调度到节点上,因为资源不足
这很简单,有了RAM,我们很容易明白内存是如何根据Pod的请求分配的。但是CPU呢?250m到底是什么意思?好吧,让我们一起来探索一下Linux CPU调度器的深渊吧。
CPU请求、CPU份额和CFS
为了将资源分配给Pod的容器,Kubernetes在Linux上使用Cgroups和CFS(完全公平调度器)。简单来说,容器的所有进程/线程都在一个独立的Cgroup中运行,CFS根据指定的资源请求将CPU资源分配给这些Cgroups(稍等,很快就会清楚的……)。
然而,CFS使用的是CPU份额(CPU Shares),而不是Kubernetes的CPU单位(CPU Units)。为了将CPU单位转换为CPU份额,Kubernetes将1个CPU等同于1024个CPU份额。这意味着一个请求500m CPU的Pod将被分配512个CPU份额。而一个具有6个CPU的节点总共有6144个CPU份额。
好的。但是CPU份额是什么意思呢?一个Pod拥有512份额意味着什么呢?如果没有任何上下文,这些都毫无意义。份额是CFS用来在CPU资源争用时分配的相对单位。
当Pod几乎不工作或工作很少,CPU大部分时间处于空闲状态时,CFS并不关心每个Cgroup拥有多少份额。但是当多个Cgroup有可运行的任务,并且CPU资源不足时,CFS确保每个Cgroup相对于其拥有的份额获得CPU时间。而且,由于Kubernetes从CPU单位计算份额,它保证了Pod获得所请求的CPU资源。
...>_ 0