监控 Kubernetes 节点上的 pod 资源使用情况
Monitoring pod resource usage on Kubernetes nodes
用例/问题
我负责维护一个有 40 个节点(分为 2 个区域)的 kubernetes 集群。我们在这个集群中有大约 100 个微服务和平台,比如 Kafka 代理 运行ning。所有微服务都定义了资源请求和限制。然而,它们中的大多数都是可突发的,并且没有保证的 RAM。在我们的集群中部署他们的服务的开发人员定义的限制远远大于请求(参见下面的示例),最终导致各种节点上的大量驱逐 pods。尽管如此,我们仍然希望在我们的服务中使用可突发资源,因为我们可以使用可突发资源来节省资金。因此我需要更好地监控每个节点上所有 pods 运行 的可能性,包含这些信息:
- 节点名称&CPU/内存容量
- 所有广告连播名称加上
- pod 的资源请求和限制
- pod 的当前 cpu & ram 使用情况
这样我就可以轻松识别出两种有问题的服务:
案例 A: 设置巨大资源限制的微服务,因为开发人员只是在测试东西或者懒得 bench/monitor 他的服务
resources:
requests:
cpu: 100m
ram: 500Mi
limits:
cpu: 6
ram: 20Gi
案例B:同一节点上设置了不准确资源限制的服务太多(例如500Mi,但服务不断使用1.5Gi RAM)。这种情况发生在我们身上,因为 Java 开发人员没有注意到 Java 垃圾收集器只会在 75% 的可用 RAM 已被使用时才开始清理。
我的问题:
我如何正确地监控它并因此识别错误配置的微服务以防止此类驱逐问题?在较小的比例下,我可以简单地 运行 kubectl describe nodes
和 kubectl top pods
手动计算出来,但在这个比例下,它不再起作用了。
注意:我找不到针对此问题的任何现有解决方案(包括使用 kube 指标和类似指标的 prometheus + grafana 板)。我认为这是可能的,但在 Grafana 中可视化这些东西真的很难。
如果可以,建议你使用LimitRange and ResourceQuota资源,例如:
apiVersion: v1
kind: ResourceQuota
metadata:
name: happy-developer-quota
spec:
hard:
requests.cpu: 400m
requests.memory: 200Mi
limits.cpu: 600m
limits.memory: 500Mi
对于限制范围:
apiVersion: v1
kind: LimitRange
metadata:
name: happy-developer-limit
spec:
limits:
- default:
cpu: 600m
memory: 100Mib
defaultRequest
cpu: 100m
memory: 200Mib
max:
cpu: 1000m
memory: 500Mib
type: Container
这可以防止人们在默认命名空间内创建超小或超大容器。
这是一个已知问题,因为仍有一个未解决的问题 github issue,并且社区要求开发人员创建一个新命令来显示 pod/container 总计 CPU 和内存使用情况。请检查此 link,因为社区提供了一些想法和解决方法,看起来它们可能对您的案例有用。
您是否使用了正确的指标,却没有看到所需的信息?
Here 是 pod 指标列表,我认为其中一些指标对您的用例很有用。
尽管由于社区和其他一些资源,这个问题还没有完全可用的解决方案,但有几种方法可以实现您的目标:
正如本 article:
中所建议的
kubectl get nodes --no-headers | awk '{print }' | xargs -I {} sh -c 'echo {}; kubectl describe node {} | grep Allocated -A 5 | grep -ve Event -ve Allocated -ve percent -ve -- ; echo'
另外本文作者推荐CoScale我没有用过,但如果其他方案都不行的话,看来值得一试。
我认为还有一点是,如果您的开发人员分配的资源远远超过需要,您可能永远无法控制。 Nicola Ben 推荐的解决方案将帮助您缓解此类问题。
我最终为此编写了一个自己的 prometheus exporter。虽然节点导出器提供使用统计信息,而 kube 状态指标公开有关您的 kubernetes 资源对象的指标,但组合和聚合这些指标并不容易,以便它们提供有价值的信息来解决所描述的用例。
使用 Kube Eagle (https://github.com/google-cloud-tools/kube-eagle/) you can easily create such a dashboard (https://grafana.com/dashboards/9871):
我还写了一篇关于这如何帮助我节省大量硬件资源的中型文章:https://medium.com/@martin.schneppenheim/utilizing-and-monitoring-kubernetes-cluster-resources-more-effectively-using-this-tool-df4c68ec2053
以下 PromQL 查询可能有助于监控 per-node 资源使用情况:
与 requests.memory
相比,具有内存 over-utilization 的容器
max_over_time(container_memory_usage_bytes{container!=""}[1h])
> on(namespace,pod,container) group_left()
kube_pod_container_resource_requests{resource="memory"}
此类容器的行动要点:将其requests.memory
增加到实际内存使用量。这样应该可以降低pod重调度事件的概率和OOM事件的概率。
与 requests.cpu
相比 CPU over-utilization 的容器
rate(container_cpu_usage_seconds_total{container!=""}[5m])
> on(namespace,pod,container) group_left()
kube_pod_container_resource_requests{resource="cpu"}
此类容器的行动要点:将其 requests.cpu
增加到实际 CPU 使用。这应该会降低 pod 重新安排事件的概率和 CPU 饥饿的概率。
内存超过 50% 的容器under-utilization
max_over_time(container_memory_usage_bytes{container!=""}[1h])
< on(namespace,pod,container) group_left()
(kube_pod_container_resource_requests{resource="memory"} * 0.5)
此类容器的行动要点:将它们的 resquests.memory
减少到实际内存使用量。这应该为具有更高内存要求的 pods 释放可分配内存。
超过 50% 的容器 CPU under-utilization
rate(container_cpu_usage_seconds_total{container!=""}[5m])
< on(namespace,pod,container) group_left()
(kube_pod_container_resource_requests{resource="cpu"} * 0.5)
此类容器的行动要点:将它们的 requests.cpu
减少到实际 CPU 使用。这应该为具有更高 CPU 要求的 pods 释放可分配的 CPU。
内存超过 50% 的节点 under-utilization
sum(max_over_time(container_memory_usage_bytes{container!=""}[1h])) by (node)
< on(node)
(kube_node_status_capacity{resource="memory"} * 0.5)
此类节点的操作要点:要么减少这些节点上的可用内存,要么从 Kubernetes 集群中移除此类节点,以提高其余节点的内存利用率。这将节省 Kubernetes 集群的成本。
超过 50% 的节点 CPU under-utilization
sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) by (node)
< on (node)
(kube_node_status_capacity{resource="cpu"} * 0.5)
此类节点的行动要点:要么减少这些节点上的可用 CPU 核心,要么从 Kubernetes 集群中删除此类节点以增加 CPU 在剩余节点上的利用率。这将节省 Kubernetes 集群的成本。
用例/问题
我负责维护一个有 40 个节点(分为 2 个区域)的 kubernetes 集群。我们在这个集群中有大约 100 个微服务和平台,比如 Kafka 代理 运行ning。所有微服务都定义了资源请求和限制。然而,它们中的大多数都是可突发的,并且没有保证的 RAM。在我们的集群中部署他们的服务的开发人员定义的限制远远大于请求(参见下面的示例),最终导致各种节点上的大量驱逐 pods。尽管如此,我们仍然希望在我们的服务中使用可突发资源,因为我们可以使用可突发资源来节省资金。因此我需要更好地监控每个节点上所有 pods 运行 的可能性,包含这些信息:
- 节点名称&CPU/内存容量
- 所有广告连播名称加上
- pod 的资源请求和限制
- pod 的当前 cpu & ram 使用情况
这样我就可以轻松识别出两种有问题的服务:
案例 A: 设置巨大资源限制的微服务,因为开发人员只是在测试东西或者懒得 bench/monitor 他的服务
resources:
requests:
cpu: 100m
ram: 500Mi
limits:
cpu: 6
ram: 20Gi
案例B:同一节点上设置了不准确资源限制的服务太多(例如500Mi,但服务不断使用1.5Gi RAM)。这种情况发生在我们身上,因为 Java 开发人员没有注意到 Java 垃圾收集器只会在 75% 的可用 RAM 已被使用时才开始清理。
我的问题:
我如何正确地监控它并因此识别错误配置的微服务以防止此类驱逐问题?在较小的比例下,我可以简单地 运行 kubectl describe nodes
和 kubectl top pods
手动计算出来,但在这个比例下,它不再起作用了。
注意:我找不到针对此问题的任何现有解决方案(包括使用 kube 指标和类似指标的 prometheus + grafana 板)。我认为这是可能的,但在 Grafana 中可视化这些东西真的很难。
如果可以,建议你使用LimitRange and ResourceQuota资源,例如:
apiVersion: v1
kind: ResourceQuota
metadata:
name: happy-developer-quota
spec:
hard:
requests.cpu: 400m
requests.memory: 200Mi
limits.cpu: 600m
limits.memory: 500Mi
对于限制范围:
apiVersion: v1
kind: LimitRange
metadata:
name: happy-developer-limit
spec:
limits:
- default:
cpu: 600m
memory: 100Mib
defaultRequest
cpu: 100m
memory: 200Mib
max:
cpu: 1000m
memory: 500Mib
type: Container
这可以防止人们在默认命名空间内创建超小或超大容器。
这是一个已知问题,因为仍有一个未解决的问题 github issue,并且社区要求开发人员创建一个新命令来显示 pod/container 总计 CPU 和内存使用情况。请检查此 link,因为社区提供了一些想法和解决方法,看起来它们可能对您的案例有用。
您是否使用了正确的指标,却没有看到所需的信息? Here 是 pod 指标列表,我认为其中一些指标对您的用例很有用。
尽管由于社区和其他一些资源,这个问题还没有完全可用的解决方案,但有几种方法可以实现您的目标: 正如本 article:
中所建议的kubectl get nodes --no-headers | awk '{print }' | xargs -I {} sh -c 'echo {}; kubectl describe node {} | grep Allocated -A 5 | grep -ve Event -ve Allocated -ve percent -ve -- ; echo'
另外本文作者推荐CoScale我没有用过,但如果其他方案都不行的话,看来值得一试。
我认为还有一点是,如果您的开发人员分配的资源远远超过需要,您可能永远无法控制。 Nicola Ben 推荐的解决方案将帮助您缓解此类问题。
我最终为此编写了一个自己的 prometheus exporter。虽然节点导出器提供使用统计信息,而 kube 状态指标公开有关您的 kubernetes 资源对象的指标,但组合和聚合这些指标并不容易,以便它们提供有价值的信息来解决所描述的用例。
使用 Kube Eagle (https://github.com/google-cloud-tools/kube-eagle/) you can easily create such a dashboard (https://grafana.com/dashboards/9871):
我还写了一篇关于这如何帮助我节省大量硬件资源的中型文章:https://medium.com/@martin.schneppenheim/utilizing-and-monitoring-kubernetes-cluster-resources-more-effectively-using-this-tool-df4c68ec2053
以下 PromQL 查询可能有助于监控 per-node 资源使用情况:
与 requests.memory
相比,具有内存 over-utilization 的容器
max_over_time(container_memory_usage_bytes{container!=""}[1h])
> on(namespace,pod,container) group_left()
kube_pod_container_resource_requests{resource="memory"}
此类容器的行动要点:将其requests.memory
增加到实际内存使用量。这样应该可以降低pod重调度事件的概率和OOM事件的概率。
与 requests.cpu
相比 CPU over-utilization 的容器
rate(container_cpu_usage_seconds_total{container!=""}[5m])
> on(namespace,pod,container) group_left()
kube_pod_container_resource_requests{resource="cpu"}
此类容器的行动要点:将其 requests.cpu
增加到实际 CPU 使用。这应该会降低 pod 重新安排事件的概率和 CPU 饥饿的概率。
内存超过 50% 的容器under-utilization
max_over_time(container_memory_usage_bytes{container!=""}[1h])
< on(namespace,pod,container) group_left()
(kube_pod_container_resource_requests{resource="memory"} * 0.5)
此类容器的行动要点:将它们的 resquests.memory
减少到实际内存使用量。这应该为具有更高内存要求的 pods 释放可分配内存。
超过 50% 的容器 CPU under-utilization
rate(container_cpu_usage_seconds_total{container!=""}[5m])
< on(namespace,pod,container) group_left()
(kube_pod_container_resource_requests{resource="cpu"} * 0.5)
此类容器的行动要点:将它们的 requests.cpu
减少到实际 CPU 使用。这应该为具有更高 CPU 要求的 pods 释放可分配的 CPU。
内存超过 50% 的节点 under-utilization
sum(max_over_time(container_memory_usage_bytes{container!=""}[1h])) by (node)
< on(node)
(kube_node_status_capacity{resource="memory"} * 0.5)
此类节点的操作要点:要么减少这些节点上的可用内存,要么从 Kubernetes 集群中移除此类节点,以提高其余节点的内存利用率。这将节省 Kubernetes 集群的成本。
超过 50% 的节点 CPU under-utilization
sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) by (node)
< on (node)
(kube_node_status_capacity{resource="cpu"} * 0.5)
此类节点的行动要点:要么减少这些节点上的可用 CPU 核心,要么从 Kubernetes 集群中删除此类节点以增加 CPU 在剩余节点上的利用率。这将节省 Kubernetes 集群的成本。