container_memory_usage_bytes 按部署名称

container_memory_usage_bytes by deployment name

给定一个 kubernetes 集群:

  1. prometheus
  2. node-exporter
  3. kube-state-metrics

我喜欢使用指标 container_memory_usage_bytes 但 select 是 deployment_name 而不是 pod

选择器如 container_memory_usage_bytes{pod_name=~"foo-.+"} 如果 deployment_name=foo 很好,只要没有 deployment_name=foo-bar 的部署。

我想用指标 kube_pod_container_resource_limits_memory_bytes 实现同样的效果。

有办法实现吗?

TL;DR

没有直接的方法通过deployment-name查询prometheus。

您可以使用部署标签查询特定部署的内存使用情况。

使用的查询:

sum(
  kube_pod_labels{label_app=~"ubuntu.*"} * on (pod) group_right(label_app) container_memory_usage_bytes{namespace="memory-testing", container=""}
  ) 
  by (label_app)

有一篇很棒的文章解释了这个查询背后的概念。我鼓励您阅读它:

我在下面的示例中包含了解释。


题中提到的选择器: container_memory_usage_bytes{pod_name=~"foo-.+"}

.+ - match any string but not an empty string

与 pods 喜欢:

  • foo-12345678-abcde - 将匹配(部署foo
  • foo-deployment-98765432-zyxzy - 将匹配(部署foo-deployment

如上所示,它将匹配 pods 和两个部署。

更多参考:


如前所述,您可以使用部署中的标签来查明特定部署使用的资源。

假设:

  • memory-testing 命名空间中有 2 个部署:
    • ubuntu 有 3 个副本
    • ubuntu-additional 有 3 个副本
  • 以上部署的标签与其名称相同(可以不同):
    • app: ubuntu
    • app: ubuntu-additional
  • Kubernetes集群版本1.18.X

Why do I specify Kubernetes version?

Kubernetes 1.16 will remove the duplicate pod_name and container_name metric labels from cAdvisor metrics. For the 1.14 and 1.15 release all pod, pod_name, container and container_name were available as a grace period.

这意味着您需要替换如下参数:

  • podpod_name
  • containercontainer_name

部署Prometheus等工具监控我使用的集群:Github.com: Coreos: Kube-prometheus

ubuntu 部署中的 pods 配置为生成人工负载 (stress-ng)。这样做是为了展示如何避免使用资源翻倍的情况。

pods在memory-testing命名空间中使用的资源:

$ kubectl top pod --namespace=memory-testing
NAME                                 CPU(cores)   MEMORY(bytes)   
ubuntu-5b5d6c56f6-cfr9g              816m         280Mi           
ubuntu-5b5d6c56f6-g6vh9              834m         278Mi            
ubuntu-5b5d6c56f6-sxldj              918m         288Mi           
ubuntu-additional-84bdf9b7fb-b9pxm   0m           0Mi             
ubuntu-additional-84bdf9b7fb-dzt72   0m           0Mi             
ubuntu-additional-84bdf9b7fb-k5z6w   0m           0Mi     

如果您要使用以下查询查询 Prometheus:

container_memory_usage_bytes{namespace="memory-testing", pod=~"ubuntu.*"}

你会得到类似于下面的输出(出于示例目的,它被剪切成只显示一个 pod,默认情况下它会显示名称为 ubuntu 和 [=28= 的所有 pods ] 命名空间):

container_memory_usage_bytes{endpoint="https-metrics",id="/kubepods/besteffort/podb96dea39-b388-471e-a789-8c74b1670c74",instance="192.168.0.117:10250",job="kubelet",metrics_path="/metrics/cadvisor",namespace="memory-testing",node="node1",pod="ubuntu-5b5d6c56f6-cfr9g",service="kubelet"} 308559872
container_memory_usage_bytes{container="POD",endpoint="https-metrics",id="/kubepods/besteffort/podb96dea39-b388-471e-a789-8c74b1670c74/312980f90e6104d021c12c376e83fe2bfc524faa4d4cee6553182d0fa2e007a1",image="k8s.gcr.io/pause:3.2",instance="192.168.0.117:10250",job="kubelet",metrics_path="/metrics/cadvisor",name="k8s_POD_ubuntu-5b5d6c56f6-cfr9g_memory-testing_b96dea39-b388-471e-a789-8c74b1670c74_0",namespace="memory-testing",node="node1",pod="ubuntu-5b5d6c56f6-cfr9g",service="kubelet"} 782336
container_memory_usage_bytes{container="ubuntu",endpoint="https-metrics",id="/kubepods/besteffort/podb96dea39-b388-471e-a789-8c74b1670c74/1b93889a3e7415ad3fa040daf89f3f6bc77e569d85069de518267666ede8e21c",image="ubuntu@sha256:55cd38b70425947db71112eb5dddfa3aa3e3ce307754a3df2269069d2278ce47",instance="192.168.0.117:10250",job="kubelet",metrics_path="/metrics/cadvisor",name="k8s_ubuntu_ubuntu-5b5d6c56f6-cfr9g_memory-testing_b96dea39-b388-471e-a789-8c74b1670c74_0",namespace="memory-testing",node="node1",pod="ubuntu-5b5d6c56f6-cfr9g",service="kubelet"} 307777536

此时您需要选择要使用的指标。在这个例子中,我使用了第一个。如需更深入的了解,请查看这篇文章:

如果我们将这些指标与 sum (QUERY) by (pod) 相加,实际上我们报告的已用资源会增加一倍。

剖析主要查询:

container_memory_usage_bytes{namespace="memory-testing", container=""}

以上查询将输出每个 pod 的已用内存指标记录。 container=""参数用于只获取一条没有container参数的记录(前面提到)。

kube_pod_labels{label_app=~"ubuntu.*"}

上面的查询将输出带有 pods 的记录及其正则表达式 ubuntu.*

的标签
kube_pod_labels{label_app=~"ubuntu.*"} * on (pod) group_right(label_app) container_memory_usage_bytes{namespace="memory-testing", container=""}

以上查询会将 kube_pod_labels 中的 podcontainer_memory_usage_bytes 中的 pod 相匹配,并将 label_app 添加到每个记录中。

sum (kube_pod_labels{label_app=~"ubuntu.*"} * on (pod) group_right(label_app) container_memory_usage_bytes{namespace="memory-testing", container=""}) by (label_app)

以上查询将按 label_app.

对记录求和

在那之后,您应该能够获得将通过标签(实际上是 Deployment)对已用内存求和的查询。


至于:

The same I'd like to achieve with the metric kube_pod_container_resource_limits_memory_bytes.

您可以使用下面的查询来获取标记有标签的部署的内存限制,如前例所示,假设部署中的每个 pod 都具有相同的限制:

kube_pod_labels{label_app="ubuntu-with-limits"} * on (pod) group_right(label_app) kube_pod_container_resource_limits_memory_bytes{namespace="memory-testing", pod=~".*"}

您可以在此查询中应用 avg()mean()max() 等函数来获取将成为您的内存限制的单个数字:

avg(kube_pod_labels{label_app="ubuntu-with-limits"} * on (pod) group_right(label_app) kube_pod_container_resource_limits_memory_bytes{namespace="memory-testing", pod=~".*"}) by (label_app)

如果您使用 VPA,您的内存限制可能会有所不同。在那种情况下,您可以同时显示所有这些或使用 avg() 获取所有“部署”的平均值。


作为上述解决方案的解决方法,您可以尝试使用如下正则表达式:

container_memory_usage_bytes{pod=~"^ubuntu-.{6,10}-.{5}"}

以下 PromQL 查询应该 return per-deployment Kubernetes 中的内存使用情况:

sum(
  label_replace(
    container_memory_usage_bytes{pod!=""},
    "deployment", "", "pod", "(.+)-[^-]+-[^-]+"
  )
) by (namespace,deployment)

查询的工作方式如下:

  1. container_memory_usage_bytes{pod!=""}time series selector selects all the time series with the name container_memory_usage_bytes and with non-empty pod label. We need to filter out time series without pod label, since such time series account for cgroups hierarchy, which isn't needed in this query. See this answer了解更多详情。

  2. 内部label_replace()pod标签中提取部署名称并将其放入deployment标签。它期望 pod 名称使用以下模式构造:<deployment>-<some_suffix_1>-<some_suffix_2>.

  3. 外部 sum() 总结了每个具有相同 namespacedeployment 标签的组的 pod 内存使用量。