Kubernetes 资源限制往往是一个难以调整的配置,因为你必须在太严格或者太宽松的限制之间找到最佳的平衡点。
通过本文,你可以学习到如何设置正确的 Kubernetes 资源限制:从检测到无限制的容器,到找出你应该在集群中正确配置的 Kubernetes 资源限制。我们假设你使用 Prometheus 来监控你的 Kubernetes 集群。这就是为什么本文中的每个步骤都使用 PromQL 查询进行示例说明的原因。
检测没有 Kubernetes 资源限制的容器
设置正确的 Kubernetes 资源限制的第一步是检测没有任何限制的容器。没有 Kubernetes 资源限制的容器可能会在你的节点中造成非常严重的后果。在最好的情况下,节点将开始按顺序或评分驱逐 pod。由于 CPU 节流,它们也会出现性能问题。在最坏的情况下,节点将由于内存不足而被终止。
查找没有 Kubernetes 资源限制的容器
- 根据命名空间查找没有限制 CPU 的容器
sum by (namespace)(count by (namespace,pod,container)(kube_pod_container_info{container!=""}) unless sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="cpu"}))
- 根据命名空间查找没有限制内存的容器
sum by (namespace)(count by (namespace,pod,container)(kube_pod_container_info{container!=""}) unless sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="memory"}))
发现太多容器没有 Kubernetes 资源限制?
也许你发现了很多没有Kubernetes资源限制的容器。现在让我们关注最危险的。如何查看?很简单,只需找到使用最多资源且没有Kubernetes资源限制的前10个容器。
- 使用最多CPU且没有CPU限制的前10个容器
topk(10,sum by (namespace,pod,container)(rate(container_cpu_usage_seconds_total{container!=""}[5m])) unless sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="cpu"}))
- 使用最多内存且没有内存限制的前10个容器
topk(10,sum by (namespace,pod,container)(container_memory_usage_bytes{container!=""}) unless sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="memory"}))
检测 Kubernetes 资源限制过于严格的容器
检测 CPU 限制过于严格的容器
如果容器非常接近其 CPU 限制,在需要执行比平时更多的 CPU 操作时,由于 CPU 节流,它的性能会下降。
- 使用此查询查找 CPU 使用率接近其限制的容器:
(sum by (namespace,pod,container)(rate(container_cpu_usage_seconds_total{container!=""}[5m])) / sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="cpu"})) > 0.8
检测内存限制过于严格的容器
如果容器接近其内存限制并超过了它,它将被终止。
这张图表显示了一个容器如何增加它的内存使用量,直到它达到限制并被终止。
- 使用此查询查找内存使用量接近其限制的容器:
(sum by (namespace,pod,container)(container_memory_usage_bytes{container!=""}) / sum by (namespace,pod,container)(kube_pod_container_resource_limits{resource="memory"})) > 0.8
如何设置正确的 Kubernetes 资源限制?
一种办法是观察一段时间我们想要限制的容器的资源使用情况。为此,我们需要把注意力集中在相同类型和工作负载的容器上(deployment, daemonset, statefulset等)。在这里,我们有两种策略:
保守策略
我们将选择每个时间段消耗最多的容器的值。如果我们将限制设置为该值,容器将不会耗尽资源。
- 使用保守策略找到正确的 CPU 限制
max by (namespace,owner_name,container)((rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[5m])) * on(namespace,pod) group_left(owner_name) avg by (namespace,pod,owner_name)(kube_pod_owner{owner_kind=~"DaemonSet|StatefulSet|Deployment"}))
使用保守策略找到正确的内存限制
max by (namespace,owner_name,container)((container_memory_usage_bytes{container!="POD",container!=""}) * on(namespace,pod) group_left(owner_name) avg by (namespace,pod,owner_name)(kube_pod_owner{owner_kind=~"DaemonSet|StatefulSet|Deployment"}))
激进策略
我们将选择99分位数作为限制。这将排除掉那1%超出限制的值。如果存在你不想要的偶发异常或峰值,这是一个很好的策略。
- 使用激进的策略找到正确的 CPU 限制
quantile by (namespace,owner_name,container)(0.99,(rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[5m])) * on(namespace,pod) group_left(owner_name) avg by (namespace,pod,owner_name)(kube_pod_owner{owner_kind=~"DaemonSet|StatefulSet|Deployment"}))
使用激进的策略找到正确的内存限制
quantile by (namespace,owner_name,container)(0.99,(container_memory_usage_bytes{container!="POD",container!=""}) * on(namespace,pod) group_left(owner_name) avg by (namespace,pod,owner_name)(kube_pod_owner{owner_kind=~"DaemonSet|StatefulSet|Deployment"}))
集群有足够的容量吗?
在 Kubernetes 中,节点根据每个 pod 的容器请求来确保其中调度的 pod 有足够的资源。这也意味着节点承诺为每个容器提供在其限制范围内设置的 CPU 和内存量。
讨论限制非常宽松的容器与讨论限制过量使用是一样的。当所有 Kubernetes 资源限制的总和大于该资源的容量时,就会发生这种情况。
当您在集群中过量使用资源时,一切都可能在正常情况下完美运行,但在高负载情况下,容器可能会开始消耗 CPU 和内存并达到其限制值。这将导致节点开始执行 pod eviction,并且在非常紧急的情况下,由于集群中可用资源的匮乏,节点将被终止。
查找集群的过量使用情况
我们可以通过以下方式检查集群在内存和 CPU 上的过量使用百分比:
- 集群内存过量使用百分比
100 * sum(kube_pod_container_resource_limits{container!="",resource="memory"} ) / sum(kube_node_status_capacity_memory_bytes)
- 集群 CPU 过量使用百分比
100 * sum(kube_pod_container_resource_limits{container!="",resource="cpu"} ) / sum(kube_node_status_capacity_cpu_cores)
通常,并非所有容器都会同时消耗所有资源,因此从资源的角度来看,100% 的过量使用是理想的。另一方面,这将会为那些永远不会使用到的基础设施付出额外的成本。
为了更好地调整集群的容量,你可以选择保守策略,确保过量使用低于 125%,或者如果让过量使用达到集群容量的 150%,则选择激进策略。
查找节点的过量使用情况
检查每个节点的过量使用也很重要。节点过度使用的一个示例是一个pod请求为2个CPU,但是限制却为8个CPU。该 pod 可以在具有 4 个核心的节点中调度,但由于 pod 有 8 个核心作为限制,该节点中的过度使用将为 8 – 4 = 4 个核心。
- 节点内存过量使用百分比
sum by (node)(kube_pod_container_resource_limits{container!=””,resource=”memory”} ) / sum by (node)(kube_node_status_capacity_memory_bytes)
- 节点 CPU 过量使用百分比
sum by (node)(kube_pod_container_resource_limits{container!=””,resource=”memory”} ) / sum by (node)(kube_node_status_capacity_memory_bytes)
正确调整资源限制后的最终效果
*原文:https://sysdig.com/blog/kubernetes-resource-limits/*本文部分图片来源于网络,如有侵权请联系删除