掘金 后端 ( ) • 2024-05-07 18:11

本文译自

Kubernetes capacity planning: How to rightsize the requests of your cluster

原文链接:https://sysdig.com/blog/kubernetes-capacity-planning/

Kubernetes 容量规划是基础架构工程师面对的主要挑战之一,正确理解 Kubernetes 的资源要求和限制并非易事,这不仅需要对 Kubernetes 有深入的认识,同时要有足够的经验和丰富的技术积累。

通常情况下我们可能会预留更多的资源,以确保容器不会耗尽内存或受到 CPU 限制。那么这种情况带来的问题就是即使不使用这些资源,也需要为之付费,同时也增加了调度的难度。这也是为什么 Kubernetes 容量规划一直寻求的是集群稳定可靠性和资源使用之间的平衡。

在本文中,您将会了解如何识别未使用的资源以及如何合理设置群集的容量。

不要过于贪心


如果只是一个容器需要的资源超出了限制,可能不会有太大影响。但如果一个大规模集群中全部容器都有这种情况,那么额外的成本将不容小觑。

另外一种情况就是Pod占用资源过大,就需要花费更多的精力来应对调度问题。

这里有两个开源工具能够为 Kubernetes 容量规划提供帮助。

  • kube-state-metrics:用于收集和报告Kubernetes集群中对象的状态信息的监控工具。

  • cAdvisor:展示和分析容器运行状态的工具

通过在群集中运行这些工具能够帮助我们合理设置集群资源。

如何检测未充分利用的资源

CPU

计算能力是最难调整的参数之一,太小很容易就成为了节点性能的瓶颈,太大又会导致多数计算资源处于空闲状态。

检测空闲CPU资源

利用container_cpu_usage_seconds_totalkube_pod_container_resource_requests参数,可以检测到 CPU 利用情况。

sum((rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[30m]) - on (namespace,pod,container) group_left avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource="cpu"})) * -1 >0)

从上面的示例中可以看到有~7.10~7.85之间的核心没有被使用。

如何识别哪些命名空间浪费了 CPU

将上面的 PromQL 语句按命名空间过滤,可以得到更细粒度的数据。

sum by (namespace)((rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[30m]) - on (namespace,pod,container) group_left avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource="cpu"})) * -1 >0)

查找 CPU 占用前10的容器

可以使用该topk函数获取 上述 PromQL 查询的Top n 结果

topk(10,sum by (namespace,pod,container)((rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[30m]) - on (namespace,pod,container) group_left avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource="cpu"})) * -1 >0))

内存

正确的内存规划同样至关重要。如果内存不足,那么节点将在内存不足时开始驱逐 pod。但同样内存也是有限的,合理地设置能够使得节点的部署密度更高,资源的利用率也就越高。

检测未使用的内存

通过container_memory_usage_byteskube_pod_container_resource_requests可以得知有多少内存被浪费。

sum((container_memory_usage_bytes{container!="POD",container!=""} - on (namespace,pod,container) avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource="memory"})) * -1 >0 ) / (1024*1024*1024)

在该示例中,有0.8Gb内存没有被使用

如何识别哪些命名空间浪费了内存

和CPU类似,我们可以通过命名空间对查询结果进行分析。

sum by (namespace)((container_memory_usage_bytes{container!="POD",container!=""} - on (namespace,pod,container) avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource="memory"})) * -1 >0 ) / (1024*1024*1024)

查找内存过大的前10容器

同样的使用topk确定每个命名空间内浪费内存最多的前 10 个容器。

topk(10,sum by (namespace,pod,container)((container_memory_usage_bytes{container!="POD",container!=""} - on (namespace,pod,container) avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource="memory"})) * -1 >0 ) / (1024*1024*1024))

如何优化容器的资源使用

在 Kubernetes 容量规划中,为了预留足够的资源,需要对容器当前资源的使用情况进行合理分析。可以使用以下 PromQL 查询来计算属于同一工作负载的所有容器的平均 CPU 利用率。Deployment、 StatefulSet、DaemonSet都可以理解为工作负载。

avg 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"}))

在该例中,可以得到每个容器的平均 CPU 利用率。可以根据经验值将容器的Request设置为 CPU 、内存平均使用率的 85% 到 115%。

如何衡量优化的影响

在执行了一些 Kubernetes 容量规划操作之后,您需要检查更改对基础架构的影响。为此,您可以将未充分利用的 CPU 内核现在与一周前的值进行比较,以评估优化后的影响。

sum((rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[30m]) - on (namespace,pod,container) group_left avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource="cpu"})) * -1 >0) - sum((rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[30m] offset 1w) - on (namespace,pod,container) group_left avg by (namespace,pod,container)(kube_pod_container_resource_requests{resource="cpu"} offset 1w )) * -1 >0)

上图中可以看到优化后集群中未使用的CPU核数明显减少。

总结

本文介绍了超量使用资源带来的问题以及如何检测集群资源分配问题,并详细说明了如何调整容器的资源分配大小,并对优化效果进行简单的评估。

目前 Kubernetes 容量规划在依靠各类工具获取相关指标后,仍然需要有较多相关经验,同时一些参数的设置仍主要参考经验值和历史值,这也对未来相关工具和技术的发展提出了新的要求和挑战。