有效设置Kubernetes的request和limit对应用程序性能、稳定性和成本有重大影响。然而,在过去的一年里,与许多团队的合作向我们表明,很难确定这些参数的正确值。出于这个原因,我们创建了这个简短指南,以帮助团队更准确地设置Kubernetes的申请和限制。
基础知识
资源请求和限制是在容器级别指定的可选参数。Kubernetes将一个Pod的request和limit计算为其所有容器中request和limit的总和。然后,Kubernetes将这些参数用于调度和资源分配决策。
Request
Pods将获得他们request的内存。如果它们超过了它们的内存请求,如果另一个吊舱恰好需要这个内存,它们可能会被杀死。只有在关键系统或高优先级工作负载需要内存的情况下,当使用的内存少于request的内存时,才会终止Pod。
类似地, 如果有可用CPU,Pod中的每个容器都被分配CPU。如果其他正在运行的Pods/Job不需要可用资源,则可能会分配额外的CPU周期。
注意:如果Pod的总请求在单个节点上不可用,那么Pod将保持挂起状态(即不运行),直到这些资源可用。
Limit
资源limit有助于Kubernetes调度程序更好地处理资源争用。当Pod使用的内存超过其limit时,其进程将被内核终止,以保护集群中的其他应用程序。当Pod超过其CPU限制时,将对其进行CPU节流。
如果没有设置限制,那么吊舱可以在可用时使用多余的内存和CPU。
以下是如何设置容器规范的request和limit的快速示例:
apiVersion: v1
kind: Pod
metadata:
name: hello-app
spec:
containers:
- name: wp
image: wordpress
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
CPU requests以CPU单位设置,其中1000 millicpu(“m”)等于1 vCPU或1 Core。所以250m的CPU相当于1/4的CPU。可以使用Ti、Gi、Mi或Ki单位设置内存。有关这些参数的力学机制的更高级技术信息,我们建议阅读以下文章:
- https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/resource-qos.md
- Resource Management for Pods and Containers | Kubernetes
权衡
确定request和limit的正确级别是为了管理权衡,如下表所示。在设置request时,在运行应用程序的成本和该应用程序的性能/停机风险之间存在着内在的权衡。平衡这些风险取决于额外CPU/RAM的相对成本与应用程序节流或停机事件的预期成本。例如,如果再分配一个1 Gb的RAM(成本5美元)可以将应用程序中断事件的风险(成本10000美元)降低1%,那么这些计算资源的额外成本是值得的。
请求 | 太低了 | 太高了 |
---|---|---|
中央处理器 | 饥饿–可能无法获得所需的CPU周期 | 效率低下–需要额外的CPU来安排其他Pod |
存储器 | 杀伤风险–如果其他吊舱需要内存,可能会终止 | 效率低下-需要额外的RAM来安排其他吊舱 |
在设定limit时,权衡是相似的,但并不完全相同。这里的权衡是共享基础架构上各个应用程序的相对性能与运行这些应用程序的总成本。例如,将CPU limit 的数量设置为高于分配的CPU数量,会使应用程序面临潜在的限制风险。提供额外的CPU(即增加开支)是一个潜在的解决方案,而降低某些应用程序的CPU限制(即增加节流风险)则是另一个解决方案。
限制 | 太低了 | 太高了 |
---|---|---|
中央处理器 | CPU调节 | 耗尽其他吊舱或资源效率低下 |
存储器 | 被内核杀死 | 耗尽其他吊舱或资源效率低下 |
在下一节中,我们将介绍一个更有效地管理这些权衡的框架。
确定正确的值
设置request时,首先确定容器在特定时间窗口(例如24小时)内的使用超过其request的可接受概率。为了预测未来的情况,我们可以分析历史资源使用情况。例如,允许使用率超过request阈值的概率为0.01(即3个9),这意味着平均每天1.44分钟,它将面临更大的节流或死亡风险。
您可以将应用程序划分为不同的可用性层,并应用这些经验规则来确定适当的可用性级别:
层 | 请求 | 限制 |
---|---|---|
关键/高可用性 | 99.99%+100%净空 | 2倍 request 或更高request(如果资源可用) |
生产/非关键 | 99%+50%净空 | 2x request |
开发/实验 | 95%或考虑命名空间配额 | 1.5x request 或考虑命名空间配额 |
这种分析历史使用模式的方法通常既能很好地表示未来,又易于理解/反思。应用额外的净空允许历史采样可能错过的波动。我们建议至少测量一周以上的使用量,并根据Pod的具体可用性要求设置阈值。
*共享实验集群的开发人员可能需要更广泛的保护资源配额.Quotas在命名空间级别设置聚合上限,有助于保护诸如长时间运行的批处理或ML作业之类的任务,使其不会因为有人在另一命名空间中不正确地指定了资源而被终止。
解决方案
看到正确设置这些参数并随着时间的推移进行管理的困难,促使我们在Kubecost产品中创建一个解决方案,以直接为您的应用程序生成建议。我们的建议基于可配置的可用性层(如生产或开发),可通过Kubecost产品中的命名空间或其他概念轻松跟踪。
除了提供请求建议外,此解决方案还可以主动检测内存不足和CPU节流风险。完整的Kubecost产品可通过单个Helm命令获得(安装选项)并且可以在Namespace视图中轻松查看每个容器的这些建议。我们的商业产品对小型集群免费,对大型集群免费试用,并且基于Kubecost开源项目 .
此外,如果您想自己计算这些指标,这里还有一些Prometheus查询示例!
内存请求(生产层)
我们建议container_memory_working_set_bytes
因为这个指标不包括缓存的数据,并且是Kubernetes用于OOM/调度决策的指标。此中的更多信息文章 .
1.5 * avg(quantile_over_time(.99,container_memory_working_set_bytes{container_name!="POD",container_name!=""}[7d])) by (container_name,pod_name,namespace)
CPU请求(生产层)
首先,使用此表达式创建录制规则。注意,我们建议使用irate
捕捉短期峰值是资源需求。
avg( irate(container_cpu_usage_seconds_total{container_name!="POD", container_name!=""}[5m]) ) by (container_name,pod_name,namespace)
然后运行此查询:
1.5 * quantile_over_time(.99,container_cpu_usage_irate[7d])
垂直吊舱自动缩放
垂直吊舱自动缩放(VPA)的目标是不必担心为容器的CPU和内存request指定值。在某些情况下,它可能是一个很好的解决方案,通常使用无状态工作负载,但您应该注意到,截至2019年9月,此工具仍处于测试阶段。以下是需要注意的一些实际限制:
- 当VerticalPodAutoscaler需要更改Pod的资源request时,Pod被收回,需要重新启动。
- 如果配置不正确,VPA可能会导致性能风险和中断,并增加可观察性复杂性。
- 为了适当地处理扩展事件,建议还启用Cluster Autoscaler来处理工作负载的增加资源需求大小。
- VPA需要仔细调整,以实现具有不同参数的基于层的解决方案,用于高可用应用程序、开发、产品、登台等。
我们建议团队在将VPA用于关键生产工作负载时要谨慎。它给您的基础设施带来了复杂性,您应该充分确保您的部署和VPA本身配置正确。撇开风险不谈,如果应用得当,它可能是一个很好的解决方案。
有关VPA的更多信息,请访问:
- https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler网站
- https://github.com/kubernetes/community/blob/master/contributors/design-proposals/autoscaling/vertical-pod-autoscaler.md
结论
有效地设置请求和限制可以决定Kubernetes中应用程序的性能和可靠性。