博客
关于我
监控神器Prometheus用不对,也就是把新手村的剑
阅读量:796 次
发布时间:2023-03-22

本文共 6856 字,大约阅读时间需要 22 分钟。

监控系统的历史与 Prometheus 的实践

监控系统的历史悠久,是一个非常成熟的领域,而 Prometheus 作为新生代的开源监控系统,逐渐成为云原生生态系统的事实标准,展现出其广泛的受欢迎程度。本文将分享在 Prometheus 实践中遇到的问题和思考。

Prometheus 的几点原则

  • 监控是基础设施

    监控的目的是为了解决问题,不要仅仅追求大而全的方案,尤其是不必要的指标采集,否则会浪费人力和存储资源(To B 商业产品例外)。

  • 告警的处理流程

    只有处理告警的通知才会发出,发出后必须得到及时处理。

  • 简洁的架构更好

    业务系统都挂上监控,监控系统也不能挂。Google SRE 中提到避免使用“Magic”系统,如机器学习报警阈值或自动修复等,这一点见仁见智,许多公司都在尝试智能化运维。

  • Prometheus 的局限性

  • 基于 Metric 的监控

    Prometheus 不适用于日志(Logs)、事件(Event)或调用链(Tracing)。

  • 默认是 Pull 模型

    合理规划网络,尽量不要进行数据转发。

  • 集群化和水平扩展

    对于集群化和水平扩展,官方和社区没有一键解决方案,需要合理选择 Federate、Cortex、Thanos 等方案。

  • 可用性优先于一致性

    监控系统通常更注重可用性,容忍部分副本数据丢失,保证查询请求成功。后面会提到 Thanos 去重时的相关内容。

  • 数据准确性

    Prometheus 不一定保证数据的准确性。一是 rate、histogram_quantile 等函数会进行统计和推断,可能产生反直觉的结果;二是查询范围过长时会进行降采样,导致数据精度丢失,这与时序数据的特点有关,与日志系统不同。

  • K8S 集群中常用的 exporter

    Prometheus 属于 CNCF 项目,拥有丰富的 exporter 来满足各种需求。你可以在官方和非官方资源中找到 exporter。如果仍然无法满足需求,可以编写自定义 exporter,简单方便且自由开放,但这也带来了选型和试错的成本。

    K8S 生态中的组件都提供 /metric 接口以进行自监控。以下是一些我们正在使用的 exporter:

    • cadvisor:集成在 Kubelet 中。
    • kubelet:10255 为非认证端口,10250 为认证端口。
    • apiserver:6443 端口,关注请求数和延迟等。
    • scheduler:10251 端口。
    • controller-manager:10252 端口。
    • etcd:监控写入延迟、存储容量等。
    • docker:需要开启 experimental 特性,配置 metrics-addr。
    • kube-proxy:默认 127.0.0.1 暴露,10249 端口。
    • kube-state-metrics:官方项目,采集 pod、deployment 等资源的元信息。
    • node-exporter:采集机器指标如 CPU、内存、磁盘。
    • blackbox_exporter:网络探测,支持 DNS、Ping、HTTP 监控。
    • process-exporter:采集进程指标。
    • nvidia exporter:用于 GPU 数据监控。
    • node-problem-detector:监测节点状态,报告异常。
    • 应用层 exporter:如 MySQL、Nginx、消息队列等,根据业务需求添加。

    K8S 核心组件监控与 Grafana 面板

    在 K8S 集群运行中,需要关注核心组件的状态和性能,如 kubelet、apiserver 等。基于上述 exporter 的指标,可以在 Grafana 中绘制相关图表。

    Prometheus All IN One 实现

    Prometheus 的 exporter 是独立的,各司其职。但是 exporter 越多,运维压力越大,尤其是对 Agent 做资源控制和版本升级。我们尝试对一些 exporter 进行组合,方案有二:

  • 通过主进程启动多个 exporter 进程

    仍然可以跟随社区版本进行更新和 bug 修复。

  • 使用 Telegraf 支持多种类型的 Input

    将 Node-Exporter、Process-Exporter 等指标统一通过 Telegraf 进行采集。

  • 合理选择黄金指标

    采集的指标有很多,我们应该关注哪些?Google 的“SRE Handbook”中提出了“四个黄金信号”:延迟、流量、错误数、饱和度。实际操作中可以使用 Use 或 Red 方法作为指导,Use 用于资源,Red 用于服务。

    Prometheus 采集中常见的服务分为三种类型:

  • 在线服务:如 Web 服务、数据库等,关注请求速率、延迟和错误率。
  • 离线服务:如日志处理、消息队列等,关注队列数量、处理速度和错误。
  • 批处理任务:如持续集成任务,关注运行时间和错误数。
  • K8S 1.16 中 Cadvisor 的指标兼容性问题

    在 K8S 1.16 版本中,Cadvisor 的指标去掉了 pod_Name 和 container_name 的 label,替换为 pod 和 container。如之前依赖这两个 label 进行查询或 Grafana 绘图,需更改 Sql 配置。

    Prometheus 采集外部 K8S 集群

    如果 Prometheus 部署在集群外,需要采集多个 K8S 集群的数据。以 Pod 方式运行在集群内是不需要证书的(In-Cluster 模式),但集群外需要声明 token 证书,并替换 address。以 Cadvisor 为例,Job 配置可以参考以下示例:

    GPU 指标的获取

    Nvidia-smi 可以查看机器上的 GPU 资源,而 Cadvisor 实际上暴露了容器使用 GPU 情况的 Metric。如果需要更详细的 GPU 数据,可以安装 dcgm exporter(从 K8S 1.13 开始支持)。

    Prometheus 时区设置

    Prometheus 为避免时区混乱,专门使用 Unix Time 和 Utc 进行显示。不支持在配置文件中设置时区,也不能读取本机 /etc/timezone 时区。实际上这个限制不影响使用:

    • 可以通过 Grafana 进行时区转换。
    • 调接口时,可以处理时间戳。
    • 2.16 版本的新版 Web UI 已引入本地时区选项。

    如何采集 LB 后面的 RS 的 Metric

    假如你有一个负载均衡 LB,但网络上 Prometheus 只能访问到 LB 本身,无法访问后面的 RS,如何采集 RS 暴露的 Metric?可以采取以下措施:

  • RS 的服务加 Sidecar Proxy

    或者在本机增加 Proxy 组件,确保 Prometheus 能访问到。

  • LB 增加转发规则

    将 /backend1 和 /backend2 请求转发到两个单独的后端,再由 Prometheus 访问 LB 采集。

  • Prometheus 版本选择

    Prometheus 当前最新版本为 2.16,尽量使用最新版本,1.X 版本不再支持。

    Prometheus 内存问题

    随着规模的变大,Prometheus 需要的 CPU 和内存都会升高,内存通常会成为瓶颈。内存消耗主要是因为每隔 2 小时 Prometheus 会将已缓冲在内存中的数据压缩到磁盘上。以下是一些优化方案:

    • 减少存储规模:通过降低采集频率或减少指标数量。
    • 使用预测函数:如 deriv 和 predict_linear,基于当前数据预测未来值。
    • 避免大范围查询:确保 range duration 大于等于 step。
    • 优化查询逻辑:减少 join 和 group 操作,使用 relabel 配合。

    Prometheus 容量规划

    除了内存规划,还需要考虑磁盘存储。Prometheus 每 2 小时将已缓冲数据压缩到磁盘上,包括 Chunks、Indexes、Tombstones 和 Metadata。以下是一些规划建议:

    • 单机版 Prometheus:计算本地磁盘使用量。
    • Remote-Write:和已有的 TSDB 共用即可。
    • Thanos 方案:本地磁盘可以忽略(2 小时),计算对象存储的大小。

    对 Apiserver 的性能影响

    如果使用 kubernetes_sd_config 进行服务发现,请求会经过集群的 Apiserver。随着规模的变大,需要评估对 Apiserver 性能的影响,尤其是在 Proxy 失败时,可能导致 CPU 升高。建议直接拉取节点端口,减少对 Apiserver 的负载。

    Rate 的计算逻辑

    Prometheus 中的 rate 函数用于计算速率,主要用于 Counter 类型的指标。rate 会自动处理 Counter 重置的问题,避免了手动计算元数据。以下是一些关键点:

    • rate 的计算范围向量时间至少设为抓取间隔的四倍。
    • rate 会自动处理 Counter 重置,将其视为新的计数开始。

    反直觉的 P95 统计

    histogram_quantile 函数用于计算百分位数,P95 表示 95% 的请求时间小于该值。P95 的含义是 5% 的请求大于该值,95% 的请求小于该值。与平均值的关系不明确,可能会出现反直觉的结果。

    慢查询问题

    Prometheus 提供的 Promql 查询语句可能会导致慢查询。以下是一些常见原因和解决方案:

    • 不合理的查询条件,如大范围查询或复杂的 join。
    • rate 函数的 range duration 不大于 step,导致数据丢失。
    • 查询时缺乏对元数据的处理,如重置 Counter。

    高基数问题

    高基数是时序数据库的热点问题,尤其是在标签(labels)中。高基数会导致索引失效,影响查询性能。以下是一些建议:

    • 避免在 Label 中使用无限或高变化的字段,如客户端 IP。
    • 使用 Prometheus 的 Tsdb 工具查看当前 Label 的分布情况。
    • 使用 record rule 减少指标数量,优化查询性能。

    Prometheus 重启慢与热加载

    Prometheus 重启时需要加载 Wal 文件到内存中,保留时间越久,Wal 文件越大,重启时间越长。以下是一些优化建议:

    • 使用 Prometheus 的热加载功能,避免手动重启。
    • Prometheus 2.6 版本对 Wal 的加载速度进行了优化,重启时间不超过 1 分钟。

    你的应用需要暴露多少指标

    在开发服务时,需要决定暴露多少 Metric。Brian Brazil 的建议指出,简单服务如缓存等大约暴露 120 个指标,Prometheus 本身暴露了 700 多个指标。如果应用很大,也尽量不要超过 10000 个指标。

    node-exporter 的问题

  • 不支持进程监控

    Node-Exporter 不支持进程指标采集,可以使用 Process-Exporter 或 Telegraf。

  • 仅支持 Unix 系统

    对于 Windows 机器,使用 wmi_exporter。

  • 版本问题

    node-exporter 是较为老旧的组件,建议使用 0.16 或 0.17 版本。

  • relabel_configs 与 metric_relabel_configs

    relabel_config 发生在采集之前,metric_relabel_configs 发生在采集之后,合理搭配可以满足多种场景配置。

    Prometheus 的预测能力

    Prometheus 提供了 deriv 和 predict_linear 函数,基于当前数据预测未来值。以下是一些示例:

    • mem_free 的使用:基于当前的下降速度预测何时达到阈值。
    • Pod 内存使用率:预测何时达到 Limit 值。

    alertmanager 的上层封装

    Prometheus 部署后,报警配置是很频繁的操作。alertmanager 提供了丰富的报警能力,如分组、抑制等。但对业务部门用户来说,直接使用 alertmanager 的配置可能不够友好。建议进行封装,如通过表单化配置或 webhook 集成到现有的报警平台。

    错误的高可用设计

    有些人提出过将 Metric 推到消息队列,再通过 Exposer 中转再由 Prometheus 拉取的方案,但这种方案存在以下问题:

    • 增加了队列组件,增加了依赖。
    • 抓取时间可能不同步,导致数据陈旧。
    • 扩展性问题,Prometheus 更适合大量小目标,而不是一个大目标。

    Prometheus-operator 的场景

    Prometheus-operator 提供了 CRD 封装,便于扩展 Prometheus 实例,同时提供了丰富的 Grafana 模板。但也有一些局限:

    • 依赖 K8S 集群,无法在集群外部署。
    • 对于多集群场景,需要做一定的修改。
    • 屏蔽了太多细节,对用户来说可能导致排查困难。

    高可用方案

    Prometheus 高可用的方案包括:

  • 基础 HA:两套 Prometheus 实例采集完全一样的数据,外部挂负载均衡。
  • HA + 远程存储:通过 Remote Write 写入远程存储,解决存储持久化问题。
  • 联邦集群:按功能分区,不同 Shard 采集不同的数据,Global 节点统一存放。
  • Thanos 或 Victoriametrics:解决全局查询和多副本数据 Join 问题。
  • 容器日志与事件

    本文主要是 Prometheus 监控内容,以下是日志和事件处理的简单介绍:

    • 日志采集与推送:使用 Fluentd、Filebeat 等采集和推送到 ES、对象存储或 Kafka。
    • 日志解析转 Metric:提取特定字符串、解析 Nginx 日志等。
    • 事件处理:使用 kube-eventer 或 event_exporter 将 Events 转化为 Metric 或推送到 ES。

    参考资料

    • https://tech.meituan.com/2018/11/01/cat-in-depth-java-application-monitoring.html
    • https://dbaplus.cn/news-134-1462-1.html
    • https://www.infoq.cn/article/P3A5EuKl6jowO9v4_ty1
    • https://zhuanlan.zhihu.com/p/60791449
    • http://download.xuliangwei.com/jiankong.html#0-%E7%9B%91%E6%8E%A7%E7%9B%AE%E6%A0%87
    • https://aleiwu.com/post/prometheus-bp/
    • https://www.infoq.cn/article/1AofGj2SvqrjW3BKwXlN
    • http://bos.itdks.com/e8792eb0577b4105b4c9d19eb0dd1892.pdf
    • https://www.infoq.cn/article/ff46l7LxcWAX698zpzB2
    • https://www.robustperception.io/putting-queues-in-front-of-prometheus-for-reliability
    • https://www.slideshare.net/cadaam/devops-taiwan-monitor-tools-prometheus
    • https://www.robustperception.io/how-much-disk-space-do-prometheus-blocks-use
    • https://www.imooc.com/article/296613
    • https://dzone.com/articles/what-is-high-cardinality
    • https://www.robustperception.io/cardinality-is-key
    • https://www.robustperception.io/using-tsdb-analyze-to-investigate-churn-and-cardinality
    • https://blog.timescale.com/blog/prometheus-ha-postgresql-8de68d19b6f5/
    • https://asktug.com/t/topic/2618

    作者:徐亚松

    来源:http://www.xuyasong.com/?p=1921

    转载地址:http://pcqfk.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现检查一个数字是否可以被另一个数字整除算法(附完整源码)
    查看>>
    Objective-C实现检查一年是否是闰年算法 (附完整源码)
    查看>>
    Objective-C实现检查三个点在 3D 中是否共线算法(附完整源码)
    查看>>
    Objective-C实现检查字符串是否包含字母表中所有字母的算法(附完整源码)
    查看>>
    Objective-C实现检查字符是否为字母算法(附完整源码)
    查看>>
    Objective-C实现检查数字是否为偶数算法(附完整源码)
    查看>>
    Objective-C实现检查数字是否为奇数算法(附完整源码)
    查看>>
    Objective-C实现检查给定图中是否存在循环算法(附完整源码)
    查看>>
    Objective-C实现检查给定字符串是否在camelCase中算法(附完整源码)
    查看>>
    Objective-C实现检查给定的字符串是否在kebabcase中算法(附完整源码)
    查看>>
    Objective-C实现检检查回文字符串(区分大小写)算法(附完整源码)
    查看>>
    Objective-C实现检测耳机插拔功能(附完整源码)
    查看>>
    Objective-C实现模拟键盘鼠标(附完整源码)
    查看>>
    Objective-C实现欧几里得距离(附完整源码)
    查看>>
    Objective-C实现欧几里得距离(附完整源码)
    查看>>
    Objective-C实现欧拉路径和欧拉回路算法(附完整源码)
    查看>>
    Objective-C实现正向CMDShell(附完整源码)
    查看>>
    Objective-C实现正数num使用递归找到它的二进制算法(附完整源码)
    查看>>
    Objective-C实现水波纹显示效果(附完整源码)
    查看>>
    Objective-C实现求 1 到 20 的所有数整除的最小正数算法 (附完整源码)
    查看>>