当开始使用Kubernetes时,通常会忘记配置容器资源。此时,您只需要确保Docker映像正常工作并且可以将其部署到Kubernetes集群即可。
但是稍后,该应用程序需要与其他应用程序一起部署到生产集群。为此,您需要为容器分配资源,并确保有足够的资源来启动和运行该应用程序,并且在其他正在运行的应用程序中将没有问题。Mail.ru
的Kubernetes aaS团队翻译了一篇有关容器资源(CPU和MEM),请求和资源限制的文章。您将了解这些设置的好处以及如果不安装它们会发生什么。
计算资源
我们有两种资源,具有以下单位:
- 中央处理器(CPU)-核心;
- 内存(MEM)-字节。
为每个容器指定资源。在以下YAML荚文件中,您将看到一个资源部分,其中包含请求的资源和限制资源:
- 请求的Pod资源=所有Pod的请求资源之和;
- 限制容器资源=所有容器的边际资源之和。
apiVersion: v1
kind: Pod
metadata:
name: backend-pod-name
labels:
application: backend
spec:
containers:
— name: main-container
image: my-backend
tag: v1
ports:
— containerPort: 8080
resources:
requests:
cpu: 0.2 # REQUESTED CPU: 200m cores
memory: "1Gi" # REQUESTED MEM: 1Gi
limits:
cpu: 1 # MAX CPU USAGE: 1 core
memory: "1Gi" # MAX MEM USAGE: 1Gi
— name: other-container
image: other-app
tag: v1
ports:
— containerPort: 8000
resources:
requests:
cpu: "200m" # REQUESTED CPU: 200m cores
memory: "0.5Gi" # REQUESTED MEM: 0.5Gi
limits:
cpu: 1 # MAX CPU USAGE: 1 core
memory: "1Gi" # MAX MEM USAGE: 1Gi
请求和限制资源的示例Pod规范中的
字段
resources.requested
是用于查找所需节点的元素之一。现在,您可以安排Pod部署。您如何找到合适的节点?
Kubernetes由几个组件组成,包括主节点或主节点(Kubernetes控制平面)。主节点中有几个进程:kube-apiserver,kube-controller-manager和kube-scheduler。
kube-scheduler进程负责查看新创建的模块,并查找与所有模块请求(包括请求的资源数量)匹配的可能的工作程序节点。由kube-scheduler找到的节点列表将排名。该广告连播计划用于得分最高的网站。
紫色豆荚会放在哪里?
图片显示kube-scheduler应该安排一个新的紫色Pod。 Kubernetes集群包含两个节点:A和B。如您所见,kube-scheduler无法将Pod调度到节点A-可用(未经请求)的资源与紫色Pod的请求不匹配。例如,紫色Pod请求的1GB内存将不适合节点A,因为可用内存为0.5GB。但是节点B有足够的资源。结果,kube-scheduler决定紫色Pod的目的地是NodeB。
现在我们知道请求的资源如何影响启动Pod的节点的选择。但是边际资源如何影响?
限制资源是CPU / MEM无法跨越的边界。但是,CPU是灵活的,因此达到CPU限制的容器不会导致Pod关闭。相反,CPU节流将开始。如果达到了MEM使用限制,则容器将由于OOM-Killer而停止,并在RestartPolicy设置允许的情况下重新启动。
请求和详细限制资源
Docker和Kubernetes之间的资源关系
解释请求的资源和限制资源的工作方式的最好方法是代表Kubernetes和Docker之间的关系。在上图中,您可以看到Kubernetes字段与Docker启动标志之间的关系。
内存:请求和限制
containers:
...
resources:
requests:
memory: "0.5Gi"
limits:
memory: "1Gi"
如上所述,内存以字节为单位。根据Kubernetes文档,我们可以将内存指定为数字。通常,它是一个整数,例如2678-即2678个字节。您也可以使用后缀
G
和Gi
,最重要的是,记住,他们是不等价的。第一个是十进制,第二个是二进制。作为一个例子,在文档K8S提到:128974848
,129e6
,129M
,123Mi
-它们是实质上相等。
Kubernetes参数
limits.memory
与--memory
来自Docker的标志匹配。的情况下request.memory
Docker没有箭头,因为Docker不使用此字段。您可能会问这是否有必要?是的如我之前所说,该领域对Kubernetes至关重要。根据从中获得的信息,kube调度程序决定要为其调度Pod的节点。
如果没有足够的内存用于查询,该怎么办?
如果容器达到请求的内存限制,则将Pod放置在Pod组中,当节点中没有内存时该Pod组停止。
如果将内存限制设置得太低会怎样?
如果容器超出内存限制,则由于OOM-Killed而终止。并且将在可能的情况下根据RestartPolicy重新启动,默认值为
Always
。
如果不指定请求的内存会怎样?
Kubernetes将采用该限制并将其设置为默认值。
如果不指定内存限制会怎样?
容器没有限制,它可以根据需要使用尽可能多的内存。如果他开始使用该节点的所有可用内存,则OOM将杀死他。然后,如果可能,将根据RestartPolicy重新启动容器。
如果不指定内存限制会怎样?
这是最坏的情况:调度程序不知道容器需要多少资源,这会在节点上引起严重的问题。在这种情况下,最好具有默认的名称空间约束(由LimitRange设置)。默认情况下没有限制-Pod没有限制,它可以使用任意数量的内存。
如果请求的内存超出节点可提供的内存,则不会调度Pod。重要的是要记住,这
Requests.memory
不是最小值。这是足以使容器连续运行的内存量的说明。
通常建议为
request.memory
和设置相同的值limit.memory
... 这样可以防止Kubernetes在具有足够内存来运行Pod但又不足以运行Pod的节点上调度Pod。注意事项:安排Pod时,Kubernetes仅计算requests.memory
,limits.memory
不计算在内。
CPU:请求和限制
containers:
...
resources:
requests:
cpu: 1
limits:
cpu: "1200m"
使用CPU,一切都变得有些复杂。回到Kubernetes与Docker之间的关系图,您可以看到它
request.cpu
与匹配--cpu-shares
,而limit.cpu
与cpus
Docker中的标志匹配。
Kubernetes请求的CPU乘以1024,即CPU周期的比例。如果要请求1个完整内核,则必须
cpu: 1
如上所述添加。
请求完整内核(比例= 1024)并不意味着您的容器将收到它。如果您的主机只有一个内核,并且您使用的容器不止一个,则所有容器之间必须共享可用的CPU。这是怎么发生的?让我们看一下图片。
CPU请求-单核系统
假设您有一个运行容器的单核主机系统。妈妈(Kubernetes)已烤制一个馅饼(CPU),并希望在孩子(容器)之间共享。三个孩子想要整个蛋糕(比例= 1024),另一个孩子想要一半的蛋糕(512)。妈妈想公平一点,做一个简单的计算。
# ?
# 3
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# :
3 (/) * 1 ( / ) + 1 (/) * 0.5 ( / )
# ?
availableCakesNumber = 1
# () ?
newMaxRequest = 1 / 3.5 =~ 28%
根据计算,三个孩子将获得28%的内核,而不是整个内核。第四个孩子将获得完整内核的14%,而不是一半。但是,如果您有多核系统,情况将有所不同。
CPU请求-多核(4)系统
在上图中,您可以看到三个孩子想要整个馅饼,一个想要一半。由于妈妈烤了四个蛋糕,她的每个孩子都会得到他们想要的东西。在多核系统中,处理器资源分布在所有可用的处理器核上。如果一个容器限制为少于一个完整的CPU内核,则仍可以100%使用它。
简化了以上计算,以了解如何在容器之间分配CPU。当然,除了容器本身之外,还有其他进程也使用CPU资源。当一个容器中的进程处于空闲状态时,其他容器可以使用其资源。
CPU: "200m"
对应CPU: 0,2
,这表示一个核心的20%
现在让我们谈谈
limit.cpu
... 限制Kubernetes的CPU乘以100。结果是容器每100μs(cpu-period
)可使用的时间。
limit.cpu
匹配Docker标志--cpus
。这是旧--cpu-period
与旧的新结合--cpu-quota
。通过设置它,我们指示容器在开始节流之前可以使用多少可用CPU资源:
- 的CPU是的组合
cpu-period
,是cpu-quota. cpus = 1.5
等同于设置cpu-period = 100000
和cpu-quota = 150000
; - cpu-period - CPU CFS调度程序周期,默认为100微秒;
- cpu-quota-
cpu-period
容器内部限制的微秒数。
如果请求的CPU不足会怎样?
如果容器需要的容量超过安装的容量,那么它将从其他进程中窃取CPU。
如果您设置的CPU限制不足会怎样?
由于CPU资源是可调的,因此节流将打开。
如果不指定CPU请求会怎样?
与内存一样,请求值等于限制。
如果不指定CPU限制会怎样?
容器将使用所需的CPU。如果在命名空间中定义了默认的CPU策略(LimitRange),则此限制也将用于容器。
如果不指定请求或CPU限制,会发生什么情况?
与内存一样,这是最坏的情况。调度程序不知道您的容器需要多少资源,这会在节点上引起严重的问题。为避免这种情况,您需要设置名称空间的默认限制(LimitRange)。
请记住,如果您请求的CPU数量超过节点可以提供的数量,则不会安排Pod。
Requests.cpu
-不是最小值,而是足以启动Pod并正常工作的值。如果您的应用程序不执行复杂的计算,则最佳选择是安装request.cpu <= 1
并运行所需数量的副本。
理想的请求资源量或资源限制
我们了解了计算资源的局限性。现在是时候回答这个问题了,“我的Pod要运行应用程序而没有问题,需要多少资源?理想的量是多少?”
不幸的是,对于这些问题没有确切的答案。如果您不知道应用程序的性能如何,需要多少CPU或内存,最好的选择是为应用程序分配大量的内存和CPU,然后运行基准测试。
除了性能测试外,还应观察应用程序一周的监视行为。如果这些图表明您的应用程序消耗的资源少于请求的资源,则可以减少请求的CPU或内存量。
请参阅此Grafana仪表板作为示例。... 它显示请求的资源或资源限制与当前资源使用之间的差异。
结论
查询和限制资源有助于保持Kubernetes集群的健康。正确配置限制可以最大程度地降低成本,并使应用程序始终保持运行状态。
简而言之,请记住以下几点:
- 请求的资源是启动期间(当Kubernetes计划托管应用程序时)要考虑的配置。相反,在应用程序已经在节点上运行时,限制资源在运行时很重要。
- 与内存相比,CPU是受管制的资源。如果CPU不足,您的Pod不会关闭,它将开始节流。
- 请求的资源和资源限制不是最小值和最大值!通过标识请求的资源,可以确保您的应用程序将平稳运行。
- 优良作法是将内存请求设置为等于内存限制。
CPU <=1
如果应用程序不执行复杂的计算,则可以按要求设置。- 如果您请求的资源多于节点的资源,则永远不会为该节点调度Pod。
- 使用负载测试和监视来确定请求的资源/资源限制的正确数量。
希望本文能帮助您了解资源限制的基本概念。您将能够在工作中应用这些知识。
祝好运!
还有什么要读的: