HOOOS

Prometheus 监控指标优化之道:Kubernetes 环境下的实践指南

0 87 云原生老司机 KubernetesPrometheus监控
Apple

Prometheus 监控指标优化之道:Kubernetes 环境下的实践指南

“喂,小王啊,最近咱们 Kubernetes 集群的 Prometheus 报警有点多,你看看是不是指标太多了,CPU 负载也挺高的。”

“啊?张哥,我这就去查查!Prometheus 指标优化确实是个大问题,搞不好就影响性能,还容易误报。”

相信不少用 Prometheus 监控 Kubernetes 的同学都遇到过类似的问题。Prometheus 作为云原生监控的“扛把子”,确实好用,但在 Kubernetes 这种动态环境下,指标数量很容易爆炸式增长,给系统带来压力。今天咱们就来聊聊,在 Kubernetes 环境下,如何优化 Prometheus 监控指标,让监控更精准、更高效。

为什么要优化 Prometheus 指标?

在 Kubernetes 中,Pod 的生命周期是短暂的,服务也是动态伸缩的。这种动态性导致 Prometheus 需要抓取的指标数量非常庞大。过多的指标会带来以下问题:

  1. 存储压力大: Prometheus 默认将指标数据存储在本地磁盘,指标过多会占用大量磁盘空间。
  2. 查询性能下降: 指标过多会导致查询速度变慢,影响 Grafana 等可视化工具的展示效果。
  3. CPU 和内存消耗增加: Prometheus 需要消耗 CPU 和内存来抓取、处理和存储指标,指标过多会增加 Prometheus Server 的负担。
  4. 误报增多: 指标过多容易导致误报,增加运维人员的排查成本。

所以,优化 Prometheus 指标是提高监控效率、降低系统负担的必经之路。

指标优化策略

1. 指标选择:只抓取需要的指标

“不是所有的指标都需要,就像不是所有的牛奶都叫特仑苏。”

Prometheus 默认会抓取大量的指标,但很多指标其实我们并不关心。因此,第一步就是要筛选出真正需要的指标。我们可以通过以下几种方式来选择指标:

  • 了解指标含义: 仔细阅读 Prometheus 官方文档和相关 exporter 的文档,了解每个指标的含义和用途,选择对我们有价值的指标。
  • 参考最佳实践: 业界有很多关于 Prometheus 监控的最佳实践,比如 Google 的 SRE 黄金指标(RED:请求速率、错误率、延迟)和 USE 方法(Utilization、Saturation、Errors),可以参考这些最佳实践来选择指标。
  • 根据业务需求: 不同的业务场景需要关注的指标不同,例如,电商业务可能更关注订单量、支付成功率等指标,而游戏业务可能更关注在线人数、延迟等指标。

在 Kubernetes 中,我们可以通过 kube-state-metrics 获取到很多关于 Kubernetes 资源对象的指标,比如 Pod 的 CPU、内存使用情况,Deployment 的副本数等。我们可以根据需要选择这些指标。

举个栗子:

假设我们只想监控 Pod 的 CPU 和内存使用情况,以及容器的重启次数,可以在 Prometheus 的配置文件中添加以下配置:

scrape_configs:
  - job_name: 'kubernetes-pods'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        action: keep
        regex: my-app # 只抓取标签为 app=my-app 的 Pod 的指标
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name
    metric_relabel_configs:
      - source_labels: [__name__]
        action: keep
        regex: (container_cpu_usage_seconds_total|container_memory_working_set_bytes|kube_pod_container_status_restarts_total)

这个配置只抓取了 container_cpu_usage_seconds_totalcontainer_memory_working_set_byteskube_pod_container_status_restarts_total 这三个指标,并且只抓取标签为 app=my-app 的 Pod 的指标。这样可以大大减少 Prometheus 需要抓取的指标数量。

2. 指标聚合:降低指标维度

“指标太多看不清?聚合一下就清晰了!”

Prometheus 的指标通常包含多个维度(label),例如,http_requests_total{method="GET", status="200", path="/api/v1/users"} 这个指标就包含了 methodstatuspath 三个维度。维度越多,指标数量就越多。我们可以通过聚合来降低指标的维度,从而减少指标数量。

Prometheus 提供了多种聚合函数,例如:

  • sum():求和
  • avg():求平均值
  • max():求最大值
  • min():求最小值
  • rate():计算速率
  • irate():计算瞬时速率

我们可以根据需要选择合适的聚合函数来降低指标的维度。

举个栗子:

假设我们想统计所有 HTTP 请求的总数,而不需要区分请求方法、状态码和路径,可以使用以下 PromQL 语句:

sum(http_requests_total)

这个语句会将所有 http_requests_total 指标按照时间进行求和,得到一个不包含任何维度的指标,表示所有 HTTP 请求的总数。

3. 自定义指标:按需定制

“Prometheus 提供的指标不够用?自己动手,丰衣足食!”

有时候,Prometheus 提供的指标并不能满足我们的需求,或者我们需要对指标进行一些特殊的处理。这时候,我们可以自定义指标。

Prometheus 提供了多种方式来自定义指标,例如:

  • 使用 exporter: exporter 是一个独立的程序,负责将各种系统的监控数据转换成 Prometheus 可以识别的格式。我们可以编写自己的 exporter 来暴露自定义的指标。
  • 使用 client library: Prometheus 提供了多种语言的 client library,例如 Go、Java、Python 等。我们可以使用这些 client library 在我们的应用程序中嵌入代码,直接暴露自定义的指标。
  • 使用 textfile collector: textfile collector 是 Prometheus 的一个内置功能,可以从文本文件中读取指标。我们可以将自定义的指标写入文本文件,然后让 Prometheus 定期读取这些文件。

举个栗子:

假设我们想监控某个业务逻辑的处理时间,可以使用 client library 在我们的应用程序中嵌入代码:

package main

import (
    "fmt"
    "net/http"
    "time"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
    myBusinessLogicDuration = prometheus.NewHistogram(prometheus.HistogramOpts{
        Name: "my_business_logic_duration_seconds",
        Help: "Duration of my business logic in seconds.",
        Buckets: prometheus.LinearBuckets(0.01, 0.01, 10),
    })
)

func init() {
    prometheus.MustRegister(myBusinessLogicDuration)
}

func myBusinessLogic() {
    start := time.Now()
    // ... 执行业务逻辑 ...
    duration := time.Since(start).Seconds()
    myBusinessLogicDuration.Observe(duration)
}

func main() {
    http.HandleFunc("/metrics", promhttp.Handler().ServeHTTP)
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        myBusinessLogic()
        fmt.Fprintln(w, "Hello, world!")
    })
    fmt.Println("Server listening on port 8080")
    http.ListenAndServe(":8080", nil)
}

这个程序定义了一个名为 my_business_logic_duration_seconds 的 Histogram 指标,用于记录业务逻辑的处理时间。每次执行业务逻辑时,都会调用 Observe() 方法将处理时间添加到指标中。然后,我们可以通过访问 /metrics 路径来获取 Prometheus 格式的指标数据。

4. Recording Rules:预计算

“复杂查询太耗时?预计算来帮你提速!”

对于一些复杂的 PromQL 查询,例如,计算某个指标的 99 分位值,每次查询都需要扫描大量的数据,非常耗时。Prometheus 提供了 Recording Rules 功能,可以预先计算这些复杂的查询,并将结果保存为新的指标。这样,我们就可以直接查询预计算后的指标,大大提高查询速度。

Recording Rules 的配置方式如下:

rule_files:
  - "/etc/prometheus/rules/*.rules"

groups:
- name: example
  rules:
  - record: job:http_requests_total:sum
    expr: sum(http_requests_total) by (job)
  - record: job:request_latency_seconds:99quantile
    expr: histogram_quantile(0.99, sum(rate(request_latency_seconds_bucket[5m])) by (le, job))

这个配置定义了两个 Recording Rules:

  • job:http_requests_total:sum:计算每个 job 的 HTTP 请求总数。
  • job:request_latency_seconds:99quantile:计算每个 job 的请求延迟的 99 分位值。

配置完成后,Prometheus 会定期执行这些 Recording Rules,并将结果保存为新的指标。我们可以直接查询这些新的指标,例如:

job:http_requests_total:sum{job="my-job"}

job:request_latency_seconds:99quantile{job="my-job"}

5. Alerting Rules:合理配置报警规则

“报警太多太烦人?合理配置才能更安心!”

Prometheus 的报警功能可以让我们及时发现问题,但过多的报警会让我们疲于应对,甚至忽略真正重要的报警。因此,我们需要合理配置报警规则,避免误报和漏报。

配置报警规则时,需要注意以下几点:

  • 设置合理的阈值: 阈值设置过低会导致误报,设置过高会导致漏报。我们需要根据实际情况设置合理的阈值。
  • 设置合理的报警持续时间: 有些指标可能会出现短暂的波动,如果报警持续时间设置过短,会导致误报。我们可以设置一个合理的报警持续时间,例如,只有当指标超过阈值持续 5 分钟才触发报警。
  • 设置合理的报警级别: 不同的报警级别对应不同的处理方式。我们需要根据报警的重要程度设置合理的报警级别。
  • 使用抑制规则: 当某个报警已经触发时,我们可以使用抑制规则来阻止其他相关的报警触发,避免报警风暴。
  • 使用静默规则: 当我们正在处理某个问题时,可以使用静默规则来暂时关闭相关的报警,避免被打扰。

举个栗子:

groups:
- name: example
  rules:
  - alert: HighRequestLatency
    expr: job:request_latency_seconds:99quantile{job="my-job"} > 0.1
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: High request latency for job {{ $labels.job }}
      description: Request latency for job {{ $labels.job }} has been above 0.1 seconds for 5 minutes.

这个配置定义了一个名为 HighRequestLatency 的报警规则,当 my-job 的请求延迟的 99 分位值超过 0.1 秒,并且持续 5 分钟时,触发一个级别为 critical 的报警。

总结

Prometheus 指标优化是一个持续的过程,需要我们不断地根据实际情况进行调整。通过合理的指标选择、聚合、自定义、预计算和报警规则配置,我们可以让 Prometheus 监控更精准、更高效,为我们的 Kubernetes 集群保驾护航。

“Prometheus 监控就像养花,需要精心呵护,才能开出美丽的花朵。”希望今天的分享能帮助你更好地管理 Prometheus 监控指标,让你的 Kubernetes 集群更加稳定、可靠。

如果你还有其他关于 Prometheus 监控的问题,欢迎在评论区留言,我会尽力解答。

点评评价

captcha
健康