Prometheus监控概述


一、监控系统概论

监控系统在这里特指对数据中心的监控,主要针对数据中心内的硬件和软件进行监控和告警。企业的 IT 架构逐步从传统的物理服务器,迁移到以虚拟机为主导的 IaaS 云。无论基础架构如何调整,都离不开监控系统的支持。

不仅如此。越来越复杂的数据中心环境对监控系统提出了更越来越高的要求:需要监控不同的对象,例如容器,分布式存储,SDN网络,分布式系统。各种应用程序等,种类繁多,还需要采集和存储大量的监控数据,例如每天数TB数据的采集汇总。以及基于这些监控数据的智能分析,告警及预警等。

在每个企业的数据中心内,或多或少都会使用一些开源或者商业的监控系统。从监控对象的角度来看,可以将监控分为网络监控,存储监控,服务器监控和应用监控等,因为需要监控数据中心的各个方面。所以监控系统需要做到面面俱到,在数据中心中充当“天眼“角色。

image-20200411183215918

image-20200411183117435

时间序列数据库当中(TSDB):属于同一指标名称,同一标签集合的、有时间戳标记的数据流。除了存储的时间序列,Prometheus 还可以根据查询请求产生临时的、衍生的时间序列作为返回结果。

OpenTSDB 中使用的标记法相同。

scrape configuration documentation

对每一个实例而言,Prometheus 按照以下时序来存储所采集的数据样本:

  • up{job="", instance=""}: 1 表示该实例正常工作

  • up{job="", instance=""}: 0 表示该实例故障

  • scrape_duration_seconds{job="", instance=""} 表示拉取数据的时间间隔

  • scrape_samples_post_metric_relabeling{job="", instance=""} 表示采用重定义标签(relabeling)操作后仍然剩余的样本数

  • scrape_samples_scraped{job="", instance=""} 表示从该数据源获取的样本数

其中 up 时序可以有效应用于监控该实例是否正常工作。

Graphite 功能较少,它专注于两件事,存储时序数据, 可视化数据,其他功能需要安装相关插件,而 Prometheus 属于一站式,提供告警和趋势分析的常见功能,它提供更强的数据存储和查询能力。
  • 在水平扩展方案以及数据存储周期上,Graphite 做的更好。
  • InfluxDB 是一个开源的时序数据库,主要用于存储数据,如果想搭建监控告警系统, 需要依赖其他系统。
  • InfluxDB 在存储水平扩展以及高可用方面做的更好, 毕竟核心是数据库。
  • OpenTSDB 是一个分布式时序数据库,它依赖 Hadoop 和 HBase,能存储更长久数据, 如果你系统已经运行了 Hadoop 和 HBase, 它是个不错的选择。
  • 如果想搭建监控告警系统,OpenTSDB 需要依赖其他系统。
  • Nagios 数据不支持自定义 Labels, 不支持查询,告警也不支持去噪,分组, 没有数据存储,如果想查询历史状态,需要安装插件。
  • Nagios 是上世纪 90 年代的监控系统,比较适合小集群或静态系统的监控,显然 Nagios 太古老了,很多特性都没有,相比之下Prometheus 要优秀很多。
  • Sensu 广义上讲是 Nagios 的升级版本,它解决了很多 Nagios 的问题,如果你对 Nagios 很熟悉,使用 Sensu 是个不错的选择。
  • Sensu 依赖 RabbitMQ 和 Redis,数据存储上扩展性更好。
  • 总结

    • Prometheus 属于一站式监控告警平台,依赖少,功能齐全。
    • Prometheus 支持对云或容器的监控,其他系统主要对主机监控。
    • Prometheus 数据查询语句表现力更强大,内置更强大的统计函数。
    • Prometheus 在数据存储扩展性以及持久性上没有 InfluxDB,OpenTSDB,Sensu 好。

    六、Export

    6.1、文本格式

    在讨论 Exporter 之前,有必要先介绍一下 Prometheus 文本数据格式,因为一个 Exporter 本质上就是将收集的数据,转化为对应的文本格式,并提供 http 请求。

    Exporter 收集的数据转化的文本内容以行 (\n) 为单位,空行将被忽略, 文本内容最后一行为空行

    注释

    文本内容,如果以 # 开头通常表示注释。

    • 以 # HELP 开头表示 metric 帮助说明。
    • 以 # TYPE 开头表示定义 metric 类型,包含 countergaugehistogramsummary, 和 untyped 类型。
    • 其他表示一般注释,供阅读使用,将被 Prometheus 忽略。

    采样数据

    内容如果不以 # 开头,表示采样数据。它通常紧挨着类型定义行,满足以下格式:

    metric_name [
      "{" label_name "=" `"` label_value `"` { "," label_name "=" `"` label_value `"` } [ "," ] "}"
    ] value [ timestamp ]
    
    • 1.
    • 2.
    • 3.
       

    下面是一个完整的例子:

    # HELP http_requests_total The total number of HTTP requests.
    # TYPE http_requests_total counter
    http_requests_total{method="post",code="200"} 1027 1395066363000
    http_requests_total{method="post",code="400"}    3 1395066363000
    
    # Escaping in label values:
    msdos_file_access_time_seconds{path="C:\\DIR\\FILE.TXT",error="Cannot find file:\n\"FILE.TXT\""} 1.458255915e9
    
    # Minimalistic line:
    metric_without_timestamp_and_labels 12.47
    
    # A weird metric from before the epoch:
    something_weird{problem="division by zero"} +Inf -3982045
    
    # A histogram, which has a pretty complex representation in the text format:
    # HELP http_request_duration_seconds A histogram of the request duration.
    # TYPE http_request_duration_seconds histogram
    http_request_duration_seconds_bucket{le="0.05"} 24054
    http_request_duration_seconds_bucket{le="0.1"} 33444
    http_request_duration_seconds_bucket{le="0.2"} 100392
    http_request_duration_seconds_bucket{le="0.5"} 129389
    http_request_duration_seconds_bucket{le="1"} 133988
    http_request_duration_seconds_bucket{le="+Inf"} 144320
    http_request_duration_seconds_sum 53423
    http_request_duration_seconds_count 144320
    
    # Finally a summary, which has a complex representation, too:
    # HELP rpc_duration_seconds A summary of the RPC duration in seconds.
    # TYPE rpc_duration_seconds summary
    rpc_duration_seconds{quantile="0.01"} 3102
    rpc_duration_seconds{quantile="0.05"} 3272
    rpc_duration_seconds{quantile="0.5"} 4773
    rpc_duration_seconds{quantile="0.9"} 9001
    rpc_duration_seconds{quantile="0.99"} 76656
    rpc_duration_seconds_sum 1.7560473e+07
    rpc_duration_seconds_count 2693
    
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.
    • 6.
    • 7.
    • 8.
    • 9.
    • 10.
    • 11.
    • 12.
    • 13.
    • 14.
    • 15.
    • 16.
    • 17.
    • 18.
    • 19.
    • 20.
    • 21.
    • 22.
    • 23.
    • 24.
    • 25.
    • 26.
    • 27.
    • 28.
    • 29.
    • 30.
    • 31.
    • 32.
    • 33.
    • 34.
    • 35.
    • 36.
       

    需要特别注意的是,假设采样数据 metric 叫做 x, 如果 x 是 histogram 或 summary 类型必需满足以下条件:

    • 采样数据的总和应表示为 x_sum
    • 采样数据的总量应表示为 x_count
    • summary 类型的采样数据的 quantile 应表示为 x{quantile="y"}
    • histogram 类型的采样分区统计数据将表示为 x_bucket{le="y"}
    • histogram 类型的采样必须包含 x_bucket{le="+Inf"}, 它的值等于 x_count 的值。
    • summary 和 historam 中 quantile 和 le 必需按从小到大顺序排列。

    6.2、常用查询

    收集到 node_exporter 的数据后,我们可以使用 PromQL 进行一些业务查询和监控,下面是一些比较常见的查询。

    注意:以下查询均以单个节点作为例子,如果大家想查看所有节点,将 instance="xxx" 去掉即可。

    CPU 使用率

    100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
    
    • 1.
       

    CPU 各 mode 占比率

    avg by (instance, mode) (irate(node_cpu_seconds_total[5m])) * 100
    
    • 1.
       

    机器平均负载

    node_load1{instance="xxx"} // 1分钟负载
    node_load5{instance="xxx"} // 5分钟负载
    node_load15{instance="xxx"} // 15分钟负载
    
    • 1.
    • 2.
    • 3.
       

    内存使用率

    100 - ((node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes)/node_memory_MemTotal_bytes) * 100
    
    • 1.
       

    磁盘使用率

    100 - node_filesystem_free{instance="xxx",fstype!~"rootfs|selinuxfs|autofs|rpc_pipefs|tmpfs|udev|none|devpts|sysfs|debugfs|fuse.*"} / node_filesystem_size{instance="xxx",fstype!~"rootfs|selinuxfs|autofs|rpc_pipefs|tmpfs|udev|none|devpts|sysfs|debugfs|fuse.*"} * 100
    
    • 1.
       

    或者你也可以直接使用 {fstype=“xxx”} 来指定想查看的磁盘信息

    网络 IO

    // 上行带宽
    sum by (instance) (irate(node_network_receive_bytes{instance="xxx",device!~"bond.*?|lo"}[5m])/128)
    
    // 下行带宽
    sum by (instance) (irate(node_network_transmit_bytes{instance="xxx",device!~"bond.*?|lo"}[5m])/128)
    
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.
       

    网卡出/入包

    // 入包量
    sum by (instance) (rate(node_network_receive_bytes{instance="xxx",device!="lo"}[5m]))
    
    // 出包量
    sum by (instance) (rate(node_network_transmit_bytes{instance="xxx",device!="lo"}[5m]))