【.com快考】许多组织在Kubernetes集群中创建资源时可能会遇到以下情况:(1)没有为工作负载请求指定CPU资源请求或低CPU资源,这意味着更多的pod可以在同一个节点上工作。当流量激增时,服务器中的CPU会需要较长的延迟时间才能达到最大值,但部分服务器可能会出现CPU软锁的情况。(2)同样,没有为工作负载指定内存资源请求或更低的内存资源请求。某些pod(尤其是那些运行Java业务应用程序的pod)将重新启动,即使它们实际上在本地测试中运行良好。(3)在Kubernetes集群中,工作负载通常在节点之间分布不均。特别是,在大多数情况下内存资源分布不均,这意味着某些节点的内存利用率可能高于其他节点。作为容器编排的事实标准,Kubernetes应该有一个高效的调度器来保证资源的均匀分布。但事实真的如此吗?通常情况下,如果流量突然爆发,当服务器宕机导致SSH登录失败时,集群管理员只能重启集群。在本文中,我们将通过分析可能的问题并讨论当今解决这些问题的最佳实践,深入探讨Kubernetes资源请求和限制。如果对它的底层机制感兴趣,也可以找源码角度的分析。本文将帮助您了解Kubernetes资源请求和限制的工作原理以及它们按预期工作的原因。概念为了充分利用Kubernetes集群中的资源,提高调度效率,Kubernetes通过资源请求和限制来控制容器的资源分配。每个容器都有自己的要求和限制。这两个参数由resources.requests和resources.limits指定。一般来说,请求在调度上更重要,而限制在执行上更重要。请求定义容器所需的最少资源。例如,对于运行SpringBoot业务的容器,指定的请求必须是Java虚拟机(JVM)在容器镜像中需要消耗的最小资源量。如果您只是指定一个低内存请求,Kubernetes调度程序很可能会将pod调度到没有足够资源来运行JVM的节点。也就是说,Pod不能使用超过JVM启动过程所需的内存。从而导致Pod不断重启。另一方面,限制决定了容器可以使用的最大资源量,从而防止由于资源消耗过多而导致资源匮乏或服务器停机。如果设置为0,表示容器没有资源限制。特别是,如果在没有指定请求的情况下设置了限制,Kubernetes默认假定请求的值与限制的值相同。请求和限制适用于两种类型的资源——可压缩(如CPU)和不可压缩(如内存)。对于不可压缩的资源,有适当的约束是非常重要的。以下是请求和限制的概述:如果Pod中的服务使用的CPU资源超过指定的限制值,Pod将被节流,但不会终止。如果不设置限制值,Pod可以使用所有空闲的CPU资源。如果Pod使用的内存资源超过了指定的限制值,Pod中的容器进程就会因OOM而被终止。在这种情况下,Kubernetes更愿意在原来的节点上重启容器,或者干脆再创建一个Pod。0≤请求≤节点可分配;请求≤限制≤无限。场景分析理解了request和limit的概念后,回顾一下上面提到的三种情况:(1)Case1首先,你要知道CPU资源和内存资源是完全不同的。CPU资源是可压缩的,CPU分配和管理基于完全公平调度器(CFS)。简而言之,如果Pod中的服务使用的CPU资源超过指定的限制值,它将被Kubernetes限制。对于没有CPU限制的Pod,一旦闲置CPU资源耗尽,之前分配的CPU资源量会逐渐减少。在这两种情况下,Pod最终都将无法处理外部请求,从而导致更长的延迟和响应时间。(2)对比Case2,内存资源无法压缩,Pod无法共享内存资源。这意味着如果内存耗尽,分配新的内存资源肯定会失败。Pod中的某些进程在初始化时特别需要一定量的内存。例如,JVM在启动时会申请一定数量的内存。如果指定的内存请求小于JVM应用程序的内存,内存中的应用程序将失败(OOM终止)。因此,此pod将不断重启并失败。(3)Case3在创建Pod时,Kubernetes需要均衡综合地分配或配置不同的资源,包括CPU和内存。同时,Kubernetes的调度算法需要考虑各种因素,比如NodeResourcesLeastAllocated和Podaffinity等。内存资源经常分布不均的原因是内存被认为比应用程序的其他资源更稀缺。此外,Kubernetes调度程序根据集群的当前状态工作。也就是说,当一个新的Pod被创建时,调度器会根据集群当时的资源规格选择最好的节点让Pod运行。由于Kubernetes集群是高度动态的,因此这里可能会出现潜在问题。例如,为了维护一个节点,它可能需要被锁定,并且该节点上运行的所有pod将被调度到其他节点。而由此产生的问题是,维护之后,这些pod并没有自动调度回原节点。这是因为Kubernetes本身无法将正在运行的Pod重新绑定到另一个节点,因此无法将其重新调度到另一个节点。GoodPractice从上面的分析我们可以知道,集群的稳定性直接影响到应用的性能。临时资源短缺通常是集群不稳定的主要原因,而云平台的不稳定意味着应用程序故障甚至节点故障。这里有两种提高集群稳定性的方法:第一,通过编辑Kubelet配置文件预留一定的系统资源。在处理内存或磁盘空间等不可压缩的计算资源时,这一点尤为重要。其次,为Pod配置适当的服务质量(QoS)类。Kubernetes使用QoS类来确定Pod的调度和驱逐优先级。可以为不同的Pod分配不同的QoS等级,包括“Guaranteed”(最高优先级)、“Burstable”和“BestEffort”(最低优先级)。保证。Pod中的每个容器(包括init容器)都必须指定对CPU和内存的请求和限制,并且它们必须相等。可爆裂。Pod中至少有一个容器指定了对CPU或内存的请求。最大努力。Pod中的容器没有指定的CPU和内存请求和限制。注意:使用Kubelet的CPU管理策略,可以为特定的Pod设置CPU亲和力。当资源耗尽时,集群将首先终止具有BestEffort的QoS类的Pod,然后是Burstable。换句话说,优先级最低的Pod首先终止。如果有足够的资源可用,所有Pod都可以分配一个Guaranteed类。这可以看作是计算资源与性能和稳定性之间的权衡。您可能希望使用更多资源,但集群可以更高效地工作。同时,为了提高资源利用率,可以将运行业务服务的Pod分配为Guaranteed类。对于其他服务,根据优先级为它们分配Burstable或BestEffort类别。下面我们就以KubeSphere容器平台为例,来了解一下如何更好的为Pod配置资源。使用KubeSphere分配资源如上所述,请求和限制是集群稳定性的两个重要组成部分。作为Kubernetes的主要版本之一,KubeSphere具有简单、清晰、交互式的用户界面,大大降低了Kubernetes的学习难度。一、启动前要做的工作KubeSphere有一个强大的多租户系统,可以对不同的用户进行细粒度的访问控制。在KubeSphere3.0中,可以为命名空间(ResourceQuotas)和容器(LimitRanges)分别设置请求和限制。要执行这些操作,需要创建一个工作区、一个项目(即命名空间)和一个帐户(ws-admin)。2.设置资源配额进入您项目的概览页面,导航至项目设置中的基本信息,然后从管理项目下拉菜单中选择编辑配额。在出现的对话框中,为项目设置请求和限制。需要记住的一点:此页面上设置的请求或限制必须大于为项目中所有Pod指定的总请求或限制。在未指定请求或限制的情况下在项目中创建容器时,您将在创建时看到一条错误消息(记录在事件中)。配置项目配额后,您需要为项目中创建的所有容器指定请求和限制。项目配额为所有容器设置规则。注意:KubeSphere中的项目配额与Kubernetes中的ResourceQuotas相同。除了CPU和内存之外,还可以为Deployments和ConfigMaps等其他对象单独设置资源配额。3.设置默认的请求和限制如前所述,如果指定了项目配额,则需要相应地配置Pod的请求和限制。实际上,在测试甚至生产中,请求值和限制值对于大多数pod来说非常接近,甚至相等。为了简化创建工作负载的过程,KubeSphere允许用户预先设置容器的默认请求和限制。这样就无需在每次创建pod时都设置请求和限制。要设置默认请求和限制,您需要执行以下步骤:(1)同样在“基本信息”页面上,从“管理项目”下拉菜单中单击“编辑资源默认请求”。在出现的对话框中,为容器配置默认请求和限制。注意:KubeSphere中默认的容器请求和限制在Kubernetes中称为LimitRanges。(2)稍后创建工作负载时,会自动填充请求和限制。对于运行关键业务流程的容器,它们需要处理比其他容器更多的流量。确实没有一刀切的解决方案,您需要根据这些容器的要求和约束做出谨慎而全面的决定。因此,需要考虑以下问题:①容器是CPU密集型还是IO密集型?②高可用吗?③服务的上下游对象是什么?如果你长期观察一些容器的运行,你会发现它是周期性的。因此,历史监控数据可以作为配置请求和限制时的重要参考。对于平台集成的Prometheus,KubeSphere拥有强大而全面的可观察性系统,可以实现更细粒度的资源监控。纵向上,它涵盖了从集群到Pod的数据;在横向上,它跟踪有关CPU、内存、网络和存储的信息。通常,可以根据历史数据的平均值来指定请求数,限制需要高于平均值。也就是说,可能需要根据需要对最终决定进行一些调整。源代码分析既然您已经看到了配置请求和约束的一些良好实践,那么让我们更深入地了解一下源代码。(1)Request和plan下面的代码展示了Pod的request和Pod中容器的request的关系。从上面的代码可以看出,调度器会计算要调度的Pod所需的资源。具体来说,它会根据Pod的规格分别计算初始化容器的总请求数和worker容器的总请求数,取大的那个。需要注意的是,对于轻量级的虚拟机(比如kata容器),需要在缓存中包含自己的虚拟化资源消耗。在下一个过滤阶段,检查所有节点是否满足条件。注:调度过程需要不同的阶段,包括预过滤器、过滤器、后过滤器和评分。过滤后,如果只有一个节点适用,则Pod会被调度到该节点。如果有多个适用的Pod,调度器将选择加权分数总和最高的节点。评分插件的实现基于多种因素,调度插件实现一个或多个扩展点。需要注意的是request的值和limit的值直接影响插件NodeResourcesLeastAllocated的最终结果。源码如下:对于NodeResourcesLeastAllocated,如果一个节点对同一个Pod的资源越多,它的得分就会越高。也就是说,一个Pod会更有可能被调度到资源充足的节点上。在创建Pod时,Kubernetes需要分配不同的资源,包括CPU和内存。每个资源都有一个权重(源代码中的resToWeightMap结构)。总的来说,它们告诉Kubernetes调度程序最好的决策是实现资源平衡。在评分阶段,除了NodeResourcesLeastAllocated,调度器还使用其他插件进行评分,例如InterPodAffinity。(2)QoS与调度作为Kubernetes中的一种资源保护机制,QoS主要用于控制不可压缩的资源(如内存)。它还会影响不同Pod和容器的OOM分数。当节点内存不足时,内核(OOMKiller)会终止优先级较低的Pod(分数越高,优先级越低)。源代码如下:Epilogue作为一个可移植和可扩展的开源平台,Kubernetes诞生于管理容器化的工作负载和服务。它拥有一个全面、快速发展的生态系统,帮助它巩固了其作为容器编排事实上的标准的地位。用户学习Kubernetes并不是那么容易,这就是KubeSphere发挥作用的地方。KubeSphere使用户能够在其仪表板上执行几乎任何操作,同时还可以选择使用内置的WebKubectl工具来运行命令。本文重点介绍请求和限制,它们在Kubernetes中的基本逻辑,以及如何使用KubeSphere对其进行配置,以简化集群的运维。原标题:DiveDeepIntoResourceRequestsandLimitsinKubernetes,作者:SherlockXu
