关于本文档 · 贡献者 · 文档协议 · 致谢
关于本文档
文档名称:《云原生监控系统 Prometheus》
使用协议:《知识共享公共许可协议(CCPL)》
贡献者
| 贡献者名称 | 贡献 度 |
文档变更记录 | 个人主页 |
|---|---|---|---|
| 马哥(马永亮) | 主编 | http://github.com/iKubernet es/ |
|
| 王晓春 | 作者 | 220页,版本迭代升级,修订和内容丰富 | http://www.wangxiaochun.c om |
文档协议
署名要求 :使用本系列文档,您必须保留本页中的文档来源信息,具体请参考《知识共享 (Creative Commons) 署名4.0公共许可协议国际版》。
非商业化使用 :遵循《知识共享公共许可协议(CCPL)》,并且您不能将本文档用于马哥教育相关业务之外的其他任何商业用途。
您的权利 :遵循本协议后,在马哥教育相关业务之外的领域,您将有以下使用权限:
共享 — 允许以非商业性质复制本作品。
改编 — 在原基础上修改、转换或以本作品为基础进行重新编辑并用于个人非商业使用。
致谢
本文档中部分素材参考了相关项目的文档,以及通过搜索引擎获得的内容,这里先一并向相关的贡献者表示感谢。
内容概述
-
Prometheus 介绍
-
Prometheus 部署
-
Node Exporter 采集数据
-
Pushgateway 采集数据
-
Prometheus 配置和标签管理
-
PromQL 查询语言
-
Grafana 图形化展示
-
Prometheus 告警机制
-
Prometheus 服务发现
-
各种 Exporter 高级功能
1 Prometheus 介绍
1.1 监控系统组成
一个完整的监控系统需要包括如下功能:数据产生、数据采集、数据存储、数据处理、数据展示分析、 告警

1.1.1 数据来源
我们如果要监控数据,首先得有数据,也就是说,这些数据应该可以被记录下来,或者被暴露出来,数据常见的产生、直接或间接暴露方式的方式如下
硬件本身的记录信息 - 以文件或者以内存属性的方式存在
应用业务的接口 - 主动暴露软件本身的运行状态,比如 redis info、各种status等
相关的信息采集工具 - 方便收集数据或者采集数据的系统级别的命令等
注意:这些数据在长时间的运行过程中,都是以固定的"属性指标"来描述他们,我们把这些称为 metric。监控系统就需要对每个环境的每一个指标都要进行数据的获取,并且按照用户需要的方式提供给用户来使用。
1.1.2 数据采集和传输
对于上面所说的Metric指标数据,我们不是说只要获取一次就可以了,而是需要持续性、周期性的方式来采集。根据数据采集方式的不同划分为了两个分类:
软件层面:
agent: 专用的软件的一种应用机制。
ssh: 系统常见的一种应用通信机制,但是并非所有系统都支持。
SNMP: 简单网络管理协议(Simple Network Management Protocol),是工作在各种网络设备中的一种机制。
硬件层面:
IPMI: 智慧平台管理接口(Intelligent Platform Management Interface)是一种工业标准用于采集硬件设备的各种物理健康状态数据,如温度、电压、风扇工作状态、电源状态等。
注意:由于每个业务场景,我们需要采集的指标量不好评估,甚至一个业务场景,就需要采集数百个指标,如果按照上述所说的周期性采集的方式来说,数据的采集量是相当大的
1.1.3 数据存储
由于我们采集到的"样本数据",不是一次性使用的,尤其是单个数据是没有意义的,我们需要将这些数据存储下来,在后续的工作场景中进行聚合操作,从而来满足我们的需求。所以这些数据的存储也是一个非常重要的点。同时,我们在后续使用这些数据的时候,不仅仅要知道这些数据,还要知道这些数据的时间属性--什么时候的数据。所以这些数据在存储的时候,必须有一个重要的时间维度。 所以我们一般将这种用于监控场景的数据,称为时间序列数据 - TS(Time series data),专门用于存储这些数据的数据库,称其为时序数据库(TSDB Time series database)
时序列数据库是用来存储时序列(time-series)数据并以时间(点或区间)建立索引的软件
一般时序列数据都具备以下特点
-
数据结构简单:某一度量指标在某一时间点只会有一个值,没有复杂的结构(嵌套、层次等)和关系(关联、主外键等)
-
数据量大:由于时序列数据由所监控的大量数据源来产生、收集和发送,比如主机、IoT设备、终端或App等
1.1.4 数据处理
如果仅仅采集到的是单条数据,本身没有太大的意义,我们需要对数据进行各种聚合和处理操作才可以正常的用于工作分析场景。所以对于各种聚合操作之后的数据,我们也需要进行分析和展示
1.1.5 数据分析展示
无论是采集到的时序数据,还是经过聚合分析之后的统计数据,由于数据量巨大,用肉眼观察很难能够看得情楚,尤其是通过表格来查看成千上万条数据,来分析其内在的逻辑趋势关系更是如此。所以,对于监控系统来说,其本身的数据可视化功能是非常重要的,以各种图形演示的方式展示我们数据的发展趋势,方便我们进行分析。
1.1.6 告警
作为人是有休息的时候,有打盹的时候,不可能时时刻刻处于精神紧张的状态,所以我们需要在某些特殊情况下,提醒我们去看相关的数据,所以我们就需要根据日常工作中采集到的数据,来分析出正常的状态值,然后将其作为一个阈值指标。接下来在后续数据采集的时候,让实时的数据,与阈值进行比较,一旦超出我们的阈值判断机制,就通过告警机制通知给我们。提高我们的工作效率。
采集到的数据达到一定的条件,比如磁盘空间满等,应该自动触发告警提示,比如:微信,邮件,短信等,方便及时发现问题并解决
1.2 监控内容
1.2.1 资源数据
硬件设备:服务器、路由器、交换机、IO系统等
系统资源:OS、网络、容器、VM实例
应用软件:Nginx、MySQL、Java应用等
1.2.2 业务服务
业务状态:服务通信、服务运行、服务下线、性能指标、QPS、DAU(Daily Active User )日活、转化率、业务接口(登陆,注册,聊天,留⾔)、产品转化率、充值额度、⽤户投诉等
一般故障:访问缓慢、存储空间不足,数据同步延迟,主机宕机、主机不可达
严重故障:服务不可用、集群故障
1.2.3 趋势分析
数据统计:时间序列数据展示历史数据等
数据预测:事件什么时候发生、持续时间、发生概率是多大等,比如:电商大促时间
1.3 监控设施实现方式
对于Linux系统来说,它的系统监控的实现方式很多,主要有系统命令、开源软件、监控平台等
1.3.1 系统命令

1.3.2 开源软件

对于传统的业务数据监控来说,Zabbix 是优秀的,由于 Zabbix 诞生的时代业务数据量相对不是太多, 所以它默认采取的是关系型数据库作为后端存储。
所以随着业务场景的发展,尤其是微服务、云原生场景的发展,大量数据的存储就成为了 Zabbix 本身的限制。所以就出现了另外一种监控软件 Prometheus。
1.3.3 监控平台
一些云服务商提供了监控平台可以实现监控功能

1.4 时序数据库
1.4.1 什么是序列数据
参考资料:https://db-engines.com/en/ranking/time+series+dbms

时间序列数据(TimeSeries Data) : 按照时间顺序记录系统、设备状态变化的数据被称为时序数据。
时序数据库记录的数据以时间为横座标,纵坐标为其它数据
时间序列数据库 (Time Series Database , 简称 TSDB) 是一种高性能、低成本、稳定可靠的在线时间序列数据库服务,提供高效读写、高压缩比存储、时序数据插值及聚合计算等服务,广泛应用于物联网 (IoT)设备监控系统、企业能源管理系统(EMS)、生产安全监控系统和电力检测系统等行业场景;除此以外,还提供时空场景的查询和分析的能力。
TSDB 具备秒级写入百万级时序数据的性能,提供高压缩比低成本存储、预降采样、插值、多维聚合计算、可视化查询结果等功能,解决由设备采集点数量巨大、数据采集频率高造成的存储成本高、写入和查询分析效率低的问题。
TSDB是一个分布式时间序列数据库,具备多副本高可用能力。同时在高负载大规模数据量的情况下可以方便地进行弹性扩容,方便用户结合业务流量特点进行动态规划与调整。
应用的场景很多:
-
物联网设备无时无刻不在产生海量的设备状态数据和业务消息数据,这些数据有助于进行设备监控、业务分析预测和故障诊断。
-
传统电力化工以及工业制造行业需要通过实时的监控系统进行设备状态检测,故障发现以及业务趋势分析。
-
系统运维和业务实时监控,通过对大规模应用集群和机房设备的监控,实时关注设备运行状态、资源利用率和业务趋势,实现数据化运营和自动化开发运维。
1.4.2 时间序列数据特点
-
大部分时间都是顺序写入操作,很少涉及修改数据
-
删除操作都是删除一段时间的数据,而不涉及到删除无规律数据
-
读操作一般都是升序或者降序
-
高效的压缩算法,节省存储空间,有效降低 IO,存储成本低
-
TSDB 使用高效的数据压缩技术,将单个数据点的平均使用存储空间降为1~2个字节,可以降低 90%存储使用空间,同时加快数据写入的速度。
-
高性能读写, 每秒百万级数据点写入,亿级数据点聚合结果秒级返回
1.5 Prometheus 简介
1.5.1 Prometheus 简介

Prometheus 是一个开源的系统监控和报警系统,它启发于 Google 的 borgmon 监控系统,在一定程度上可以理解为,Google BorgMon监控系统的开源版本。 该软件由工作在 SoundCloud 的 google 前员工在 2012 年创建,作为社区开源项目进行开发,并于 2015 年正式发布。2016 年,Prometheus 正式加入 CNCF(Cloud Native Computing Foundation),成为继 Kubernetes之后第二个在CNCF托管的项目, 现已广泛用于在容器和微服务领域中得到了广泛的应用,当然不仅限于此
云原生: https://landscape.cncf.io/

Prometheus 本身基于Go语言开发的一套开源的系统监控报警框架和时序列数据库(TSDB)。
Prometheus 的监控功能很完善和全面,性能也足够支撑上万台规模的集群。
网站:https://prometheus.io/
github:https://github.com/prometheus
其特点主要如下:
-
支持多维数据模型:由度量名和键值对组成的时间序列数据
-
内置时间序列数据库TSDB(Time Series Database )
-
支持PromQL(Prometheus Query Language)查询语言,可以完成非常复杂的查询和分析,对图表展示和告警非常有意义
-
支持 HTTP 的 Pull 方式采集时间序列数据
-
支持 PushGateway 采集瞬时任务的数据
-
支持静态配置和服务发现两种方式发现目标
多种可视化和仪表盘,支持第三方 Dashboard,比如:Grafana

数据特点
-
监控指标,采用独创的指标格式,我们称之为Prometheus格式,这个格式在监控场景中很常见。 数据标签,支持多维度标签,每个独立的标签组合都代表一个独立的时间序列
-
数据处理,Prometheus内部支持多种数据的聚合、切割、切片等功能。
-
数据存储,Prometheus支持双精度浮点型数据存储和字符串
适用场景
Prometheus 非常适合记录任何纯数字时间序列。它既适合以机器为中心的监控场景,也适合于高度动态的面向服务的体系结构的监控场景。尤其是在微服务世界中,它对多维数据收集和查询的支持是一种特别的优势。
Prometheus的设计旨在提高可靠性,使其成为中断期间要使用的系统,以使您能够快速诊断问题。每个Prometheus服务器都是独立的,而不依赖于网络存储或其他远程服务。当基础结构的其他部分故障时,您可以依靠它,并且无需设置广泛的基础结构即可使用它。
由于Prometheus重视可靠性。在故障情况下,我们可以查看有关系统的可用统计信息。但是如果您需要100%的准确性,则Prometheus并不是一个不错的选择,因为所收集的数据可能不会足够详细和完整。在这种情况下,最好使用其他系统来收集和分析数据以进行计费,并使用Prometheus进行其余的监视。
Prometheus 不足
-
不支持集群化
-
被监控集群规模过大后本身性能有一定瓶颈
-
中文支持不好中文资料也很少
1.5.2 Prometheus 架构
官方文档:
https://prometheus.io/docs/
https://prometheus.io/docs/introduction/overview/
1.5.2.1 数据获取逻辑
Prometheus 同其它TSDB相比有一个非常典型的特性:它主动从各Target上“拉取(pull)”数据,相当于 Zabbix里的被动模式,而非等待被监控端的“推送(push)”;
两个方式各有优劣,其中,Pull模型的优势在于:集中控制:有利于将配置集在 Prometheus Server上完成,包括指标及采取速率等,Prometheus的根本目标在于收集在Target上预先完成聚合的聚合型数据,而非一款由事件驱动的存储系统

1.5.2.2 Prometheus 架构

Prometheus 的主要模块包括:
prometheus :
时序数据存储、监控指标管理
可视化:
Prometheus web UI : 集群状态管理、promQL
Grafana:非常全面的可视化套件
数据采集
Exporter: 为当前的客户端暴露出符合 Prometheus 规格的数据指标,Exporter 以守护进程的模式运行井开始采集数据,Exporter 本身也是一个http_server 可以对http请求作出响应返回数据 (K/V形式的metrics)
Pushgateway : 拉模式下数据的采集工具
监控目标
服务发现 :文件方式、dns方式、console方式、k8s方式
告警:
alertmanager
Prometheus 由几个主要的软件组件组成,其职责概述如下。
| 组件 | 解析 |
|---|---|
| Prometheus Server |
彼此独立运行,仅依靠其本地存储来实现其核心功能:抓取时序数据,规则处理和警报等。 |
| Client Library | 客户端库,为需要监控的服务生成相应的metrics并暴露给Prometheus server。当Prometheus server来pull时,直接返回实时状态的metrics。 |
| Push Gateway |
exporter采集类型已经很丰富,但是依然需要很多自定义的监控数据,用 pushgateway可以实现自定义的监控数据,任意灵活想做什么都可以做到 exporter的开发需要使用真正的编程语言,不支持shell这种快速脚本,而 pushgateway开发去容易的多 pushgateway主要用于短期的jobs。由于这类jobs存在时间较短,可能在 Prometheus来pull之前就消失了。为此,这次jobs可以直接向Prometheus server端推送它们的metrics。这种方式主要用于服务层面的metrics,对于机器层面的metrices,需要使用node exporter |
| Exporters | 部署到第三方软件主机上,用于暴露已有的第三方服务的metrics给 Prometheus。 |
| Alertmanager | 从Prometheus server端接收到alerts后,会进行去除重复数据,分组,并路由到对应的接受方式,以高效向用户完成告警信息发送。常见的接收方式有:电子邮件,pagerduty,OpsGenie, webhook等,一些其他的工具。 |
| Data Visualization |
Prometheus Web UI(Prometheus Server内建),及Grafana等 |
| Service Discovery |
动态发现待监控的Target,从而完成监控配置的重要组件,在容器化环境中尤为有用;该组件目前由Prometheus Server内建支持; |
在上诉的组件中,大多数都是用Go编写的,因此易于构建和部署为静态二进制文件。
1.5.2.3 工作流程
-
Prometheus server 定期从配置好的 jobs 或者 exporters 中拉 metrics,或者接收来自 Pushgateway 发过来的 metrics,或者从其他的 Prometheus server 中拉 metrics。
-
Prometheus server 在本地存储收集到的 metrics,并运行已定义好的 alert.rules,记录新的时间序列或者向 Alertmanager 推送警报,实现一定程度上的完全冗余功能。
-
Alertmanager 根据配置文件,对接收到的警报进行去重分组,根据路由配置,向对应主机发出告警。
集成Grafana或其他API作为图形界面,用于可视化收集的数据。
1.5.2.4 生态组件
Prometheus 只负责时序型指标数据的采集及存储
其它的功能,如: 数据的分析、聚合及直观展示以及告警等功能并非由Prometheus Server所负责,需要配合其它组件实现
支持丰富的 Exporter 实现各种应用的监控
https://prometheus.io/docs/instrumenting/exporters/



1.5.3 Prometheus 数据模型
Prometheus中存储的数据为时间序列,即基于同一度量标准或者同一时间维度的数据流。除了时间序列数据的正常存储之外,Prometheus还会基于原始数据临时生成新的时间序列数据,用于后续查询的依据或结果。
每个时间序列都由metric名称(表示某项指标)和标签(键值对形式,表示属性,其为可选项)组合成唯一标识。
1.5.3.1 Metric 名字
-
该名字必须有意义,用于表示 metric 的一般性功能,例如:http_requests_total 表示 http 请求的总数。
-
metric 名字由 ASCII 字符,数字,下划线,以及冒号组成,且必须满足正则表达式
[a-zA-Z_:][a-zA-Z0-9_:]*的 查询需求。
注意:冒号是为用户定义的记录规则保留的。

1.5.3.2 标签
-
标签是以键值对的样式而存在,不同的标签用于表示时间序列的不同维度标识
-
基本格式:
<metric name>{<label name>=<label value>, …}
#示例样式:
http_requests_total{method="POST",endpoint="/api/tracks"}
解析: http_requests_total{method="POST"} 表示所有 http 请求中的 POST 请求,
endpoint="/api/tracks"表示请求的url地址是/api/tracks。当method="GET"时,则为新的
一个 metric
- 标签中的键名由 ASCII 字符,数字,以及下划线组成,且必须满足正则表达式 [a-zA-Z_:][a-zA-Z09_:]*。以__开头的标签名称保留供内部使用
标签值可以包含任何Unicode字符,标签值为空的标签被认为等同于不存在的标签
查询语言允许基于这些维度进行过滤和聚合。更改任何标签值,包括添加或删除标签,都会创建一个新的时间序列。

1.5.3.3 指标类型
Prometheus客户端库提供了四种核心度量标准类型。
官方说明
https://prometheus.io/docs/concepts/metric_types/
说明
| 类型 | 解析 |
|---|---|
| Counter - 累计 |
counter是一个累加的计数器,代表一个从0开始累积单调递增的计数器,其值只能在重新启动时增加或重置为零。典型的应用如:用户的访问量,请求的总个数,任务的完成数量或错误的数量等。不能使用Counter来表示递减值。 |
| Gauge是一种度量标准,只有一个简单的返回值,或者叫瞬时状态,可以代表可以 | |
| Gauge -量规 | 任意metric的上下波动的数值。通常用于测量值,例如,硬盘剩余空间,当前的内存使用量,一个待处理队列中任务的个数等,还用于可能上升和下降的“计数”,例如并发请求数。 |
| Histogram -直方图 |
Histogram统计数据的分布情况。比如最小值,最大值,中间值,还有中位数,75 百分位,90百分位, 95百分位.98百分位,99百分位,和9.9百分位的值(percenties ,代表着近似的百分比估算数值比如:每天1000万请中,统计http_response_time不同响应时间的分布情况,响应时间在0-0.05s有多少,0.05s到2s有多少,10s以上有多少每个存储桶都以"_BucketFuncName{...}"样式来命名.例如hist_sum、hist_count 等可以基于histogram_quantile()函数对直方图甚至是直方图的聚合来进行各种分析计算。 |
| 用于表示一段时间内的数据采样结果,典型的应用如:请求持续时间,响应大小。但它直接存储了分位数(将一个随机变量的概率分布范围分为几个等份的数值点,常用 | |
| Summary -摘要 |
的有中位数即二分位数、四分位数、百分位数等),而不是通过区间来计算。类似于直方图,摘要会基于阶段性的采样观察结果进行信息描述。它还提供了观测值的累计计算、百分位计算等功能,每个摘要的命名与Histogram类似,例如: summary_sum、summary_count等 |

1.5.3.4 数据格式
Prometheus 数据格式,本质上就是将收集的数据转化为对应的文本格式,并提供 http 请求。 Exporter 收集的数据转化的文本内容以行 (\n) 为单位,空行将被忽略, 文本内容最后一行为空行文本内容,如果以 # 开头通常表示注释。
以 # HELP 开头表示 metric 帮助说明。
以 # TYPE 开头表示定义 metric 类型,包含 counter, gauge, histogram, summary, 和 untyped 类型。 其他表示一般注释,供阅读使用,将被 Prometheus 忽略。
1.5.3.5 任务和实例
用Prometheus术语来说,一个单独 scrape(

例如,一个 API 服务 job 包含四个 instances:
job: api-server
instance 1: 1.2.3.4:5670
instance 2: 1.2.3.4:5671
instance 3: 5.6.7.8:5670
instance 4: 5.6.7.8:5671
对于任务实例来说,他们还可以借助于特殊的字符串来表示通用的功能,常见的使用样式如下:
#判断任务是否健康,1代表正常,0代表不正常
up{job="<job-name>", instance="<instance-id>"}
#获取任务的持续时间
scrape_duration_seconds{job="<job-name>", instance="<instance-id>"}
# 任务执行后剩余的样本数
scrape_samples_post_metric_relabeling{job="<job-name>", instance="<instance-
id>"}
# 暴露的样本数量
scrape_samples_scraped{job="<job-name>", instance="<instance-id>"}
# 样本的大概数量
scrape_series_added{job="<job-name>", instance="<instance-id>"}
总结
数据模型:metric名称+标签
数据类型:Counter+Gauge+Histogram+Summary
- 任务:多个instances组成一个jobs
1.5.4 Prometheus 数据处理
1.5.4.1 数据获取
这些metric数据,是基于HTTP call方式来进行获取的,从对方的配置文件中指定的网络端点(endpoint, 即IP:Port,表示一个应用)上周期性获取指标数据。每一个端点上几乎不可能只有一个数据指标。

根据上面的了解,这些指标都必须以http的方式暴露出来,而这也是,prometheus无法直接获取内核等相关数据的原因,只能借助于其他的机制才可以。prometheus默认支持通过三种类型的途径从目标上“抓取(Scrape)”指标数据;
| 方式 | 解析 |
|---|---|
| Exporters | 部署到对应节点上,负责从目标应用程序上采集和聚合原始格式的数据,并转换或聚合为Prometheus格式的指标,以http方式向外暴露本地节点数据后 |
| Instrumentation | 指附加到应用程序中形成内建的检测系统,采集数据并暴露出来的客户端库,当然了,暴露的方式也是http方式 |
| Pushgateway | 接收节点上的任务机制获取数据并转换成Prometheus格式数据,然后推送给prometheus |

1.5.4.2 数据存储
Prometheus 采用的是time-series(时间序列)的方式以一种自定义的格式存储在本地硬盘上
Prometheus的本地T-S(time-series)数据库以每两小时为间隔分成block为单位存储,每一个Block中又分为多个Chunk文件
Chunk是作为存储的基本单位,用来存放采集过来的数据的T-S数据,包括metadata和索引文件(index)。 Index文件是对metrics(对应一次KV采集数据)和 labels(标签)进行索引之后存储在chunk文件中
Prometheus平时是将采集过来的数据先都存放在内存之中, 以类似缓存的方式用于加快搜索和访问。
Prometheus提供一种保护机制叫做WAL( Write-Ahead Logging )可以将数据存入硬盘中的chunk文件, 当出现宕机时,重新启动时利用此日志系统来恢复加载至内存
[root@prometheus ~]#tree /usr/local/prometheus/data
/usr/local/prometheus/data
├── 01G9RSD61ZEF16T5YGE91K49MZ
│ ├── chunks
│ │ └── 000001
│ ├── index
│ ├── meta.json
│ └── tombstones
├── 01G9RZ8VXF2FHHB18CW0594P8T
│ ├── chunks
│ │ └── 000001
│ ├── index
│ ├── meta.json
│ └── tombstones
├── chunks_head
│ ├── 000002
│ └── 000003
├── lock
├── queries.active
└── wal
├── 00000000
├── 00000001
└── 00000002
6 directories, 15 files
1.5.4.3 数据分析
Prometheus提供了内置的数据查询语言PromQL(全称为Prometheus Query Language),支持用户进行实时的数据查询及聚合操作;
PromQL支持处理两种向量,并内置提供了一组用于数据处理的函数
即时向量:在最近一次的单个时间戳上采集和跟踪的数据指标,即时间点数据时间范围向量:指定时间范围内的所有时间戳上的数据指标,即时间段数据

1.5.4.4 数据告警
抓取到异常值后,Prometheus支持通过告警(Alert)机制向用户发送反馈或警示,以触发用户能够及时采取应对措施;但是Prometheus Server仅负责生成告警指示,具体的告警行为由另一个独立的应用程序 AlertManager负责
-
告警指示由Prometheus Server基于用户提供的告警规则周期性计算生成
-
Alertmanager接收到Prometheus Server 发来的告警指示后,基于用户定义的告警路由(route)向告警接收人发送告警信息;

2 Prometheus 部署和监控
Prometheus部署相关软件版本
为了更好的更全面的演示 Prometheus 功能,我们将相关的组件也安装起来,以实现业务环境的全监控,相关软件版本信息如下
| 软件 | 地址 |
|---|---|
| prometheus | https://github.com/prometheus/prometheus/releases/download/v2.30. 3/prometheus-2.30.3.linux-amd64.tar.gz |
| alertmanager | https://github.com/prometheus/alertmanager/releases/download/v0.2 3.0/alertmanager-0.23.0.linux-amd64.tar.gz |
| node_exporter | https://github.com/prometheus/node_exporter/releases/download/v1. 2.2/node_exporter-1.2.2.linux-amd64.tar.gz |
| mysqld_exporter | https://github.com/prometheus/mysqld_exporter/releases/download/v 0.13.0/mysqld_exporter-0.13.0.linux-amd64.tar.gz |
| grafana | https://dl.grafana.com/enterprise/release/grafana-enterprise_8.2.1_am d64.deb |
2.1 部署 Prometheus
2.1.1 常见部署方式
包安装
RHEL系统: https://packagecloud.io/app/prometheus-rpm/release/search
Ubuntu和Debian可直接使用apt命令安装
二进制安装
https://prometheus.io/download/
基于 Docker 运行
https://prometheus.io/docs/prometheus/latest/installation/
基于 Kubernetes Operator 安装
https://github.com/coreos/kube-prometheus
2.1.2 Docker 镜像直接启动
[root@prometheus ~]#docker run -d --name prometheus -p 9090:9090
prom/prometheus
#浏览器访问:http://prometheus服务器:9090/



2.1.3 二进制安装 Prometheus
2.1.3.1 下载二进制包并解压
官方下载: https://prometheus.io/download/
[root@prometheus local]#pwd
/usr/local/
[root@prometheus local]#wget
https://github.com/prometheus/prometheus/releases/download/v2.19.2/prometheus-
2.19.2.linux-amd64.tar.gz
[root@prometheus local]#ls -l prometheus-2.19.2.linux-amd64.tar.gz
-rw-r--r--1 root root 64152439 Jul 521:13 prometheus-2.19.2.linux-
amd64.tar.gz
[root@prometheus local]#tar xvf prometheus-2.19.2.linux-amd64.tar.gz
[root@prometheus local]#ln -s prometheus-2.19.2.linux-amd64 prometheus
[root@prometheus local]#cd prometheus/
[root@prometheus prometheus]#mkdir bin conf data
[root@prometheus prometheus]#mv prometheus promtool bin/
[root@prometheus prometheus]#mv prometheus.yml conf/
[root@prometheus prometheus]#useradd -r -s /sbin/nologin prometheus
[root@prometheus prometheus]#chown -R prometheus.prometheus
/usr/local/prometheus/
[root@prometheus ~]#cat /etc/profile.d/prometheus.sh
exportPROMETHEUS_HOME=/usr/local/prometheus
exportPATH=${PROMETHEUS_HOME}/bin:$PATH
[root@prometheus ~]#source /etc/profile.d/prometheus.sh
#查看配置文件,默认可不修改
[root@prometheus ~]#grep -Ev "^ *#|^$" /usr/local/prometheus/conf/prometheus.yml
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is
every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is
every 1 minute.
alerting:
alertmanagers:
- static_configs:
- targets:
rule_files:
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
#属性解析:主要是global和 scrape_configs 两部分的配置,在这里目前我们保持默认即可
#检查配置文件是否正确
[root@prometheus ~]#promtool check config
/usr/local/prometheus/conf/prometheus.yml
Checking /usr/local/prometheus/conf/prometheus.yml
SUCCESS: 0 rule files found
2.1.3.2 创建 service 文件
[root@prometheus ~]#vim /lib/systemd/system/prometheus.service
[root@prometheus ~]#cat /lib/systemd/system/prometheus.service
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
After=network.target
[Service]
Restart=on-failure
User=prometheus
Group=prometheus
WorkingDirectory=/usr/local/prometheus/
ExecStart=/usr/local/prometheus/bin/prometheus --
config.file=/usr/local/prometheus/conf/prometheus.yml
ExecReload=/bin/kill -HUP$MAINPID
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
#配置解析:
#我们需要将定制的prometheus的配置文件和数据目录作为启动参数配置好
#其它的参数,可以基于prometheus --help 查看更多
[root@prometheus ~]#systemctl daemon-reload
[root@prometheus ~]#systemctl enable --now prometheus.service
[root@prometheus ~]#ss -tnlp |grep prometheus
LISTEN 0128 *:9090 *:*
users:(("prometheus",pid=84755,fd=10))
#结果显示:可以看到当前主机上可以看到一个端口9090,可通过下面地址看到prometheus的服务页面
范例: 查看prometheus命令选项
[root@prometheus ~]#/usr/local/prometheus/bin/prometheus --help
usage: prometheus [<flags>]
The Prometheus monitoring server
Flags:
-h, --help Show context-sensitive help (also try --help-
long and --help-man).
--version Show application version.
--config.file="prometheus.yml"
Prometheus configuration file path.
--web.listen-address="0.0.0.0:9090"
Address to listen on for UI, API, and
telemetry.
--web.config.file="" [EXPERIMENTAL] Path to configuration file that
can enable TLS or authentication.
--web.read-timeout=5m Maximum duration before timing out read of the
request, and closing idle connections.
--web.max-connections=512 Maximum number of simultaneous connections.
--web.external-url=<URL> The URL under which Prometheus is externally
reachable (for example, if Prometheus is served via a
reverse proxy). Used for generating relative
and absolute links back to Prometheus itself. If the
URL has a path portion, it will be used to
prefix all HTTP endpoints served by Prometheus. If
omitted, relevant URL components will be derived
automatically.
--web.route-prefix=<path> Prefix for the internal routes of web
endpoints. Defaults to path of --web.external-url.
--web.user-assets=<path> Path to static asset directory, available at
/user.
--web.enable-lifecycle Enable shutdown and reload via HTTP request.
--web.enable-admin-api Enable API endpoints for admin control actions.
--web.enable-remote-write-receiver
Enable API endpoint accepting remote write
requests.
--web.console.templates="consoles"
Path to the console template directory,
available at /consoles.
--web.console.libraries="console_libraries"
Path to the console library directory.
--web.page-title="Prometheus Time Series Collection and Processing Server"
Document title of Prometheus instance.
--web.cors.origin=".*" Regex for CORS origin. It is fully anchored.
Example: 'https?://(domain1|domain2)\.com'
--storage.tsdb.path="data/"
Base path for metrics storage. Use with server
mode only.
--storage.tsdb.retention=STORAGE.TSDB.RETENTION
[DEPRECATED] How long to retain samples in
storage. This flag has been deprecated, use
"storage.tsdb.retention.time" instead. Use with
server mode only.
--storage.tsdb.retention.time=STORAGE.TSDB.RETENTION.TIME
How long to retain samples in storage. When
this flag is set it overrides "storage.tsdb.retention".
If neither this flag nor
"storage.tsdb.retention" nor "storage.tsdb.retention.size" is set, the
retention time defaults to 15d. Units Supported:
y, w, d, h, m, s, ms. Use with server mode only.
--storage.tsdb.retention.size=STORAGE.TSDB.RETENTION.SIZE
Maximum number of bytes that can be stored for
blocks. A unit is required, supported units: B, KB,
MB, GB, TB, PB, EB. Ex: "512MB". Based on
powers-of-2, so 1KB is 1024B. Use with server mode only.
--storage.tsdb.no-lockfile
Do not create lockfile in data directory. Use
with server mode only.
--storage.tsdb.allow-overlapping-blocks
Allow overlapping blocks, which in turn enables
vertical compaction and vertical query merge. Use
with server mode only.
--storage.tsdb.head-chunks-write-queue-size=0
Size of the queue through which head chunks are
written to the disk to be m-mapped, 0 disables the
queue completely. Experimental. Use with server
mode only.
--storage.agent.path="data-agent/"
Base path for metrics storage. Use with agent
mode only.
--storage.agent.wal-compression
Compress the agent WAL. Use with agent mode
only.
--storage.agent.retention.min-time=STORAGE.AGENT.RETENTION.MIN-TIME
Minimum age samples may be before being
considered for deletion when the WAL is truncated Use with
agent mode only.
--storage.agent.retention.max-time=STORAGE.AGENT.RETENTION.MAX-TIME
Maximum age samples may be before being forcibly
deleted when the WAL is truncated Use with agent
mode only.
--storage.agent.no-lockfile
Do not create lockfile in data directory. Use
with agent mode only.
--storage.remote.flush-deadline=<duration>
How long to wait flushing sample on shutdown or
config reload.
--storage.remote.read-sample-limit=5e7
Maximum overall number of samples to return via
the remote read interface, in a single query. 0
means no limit. This limit is ignored for
streamed response types. Use with server mode only.
--storage.remote.read-concurrent-limit=10
Maximum number of concurrent remote read calls.
0 means no limit. Use with server mode only.
--storage.remote.read-max-bytes-in-frame=1048576
Maximum number of bytes in a single frame for
streaming remote read response types before
marshalling. Note that client might have limit
on frame size as well. 1MB as recommended by
protobuf by default. Use with server mode only.
--rules.alert.for-outage-tolerance=1h
Max time to tolerate prometheus outage for
restoring "for" state of alert. Use with server mode
only.
--rules.alert.for-grace-period=10m
Minimum duration between alert and restored
"for" state. This is maintained only for alerts with
configured "for" time greater than grace period.
Use with server mode only.
--rules.alert.resend-delay=1m
Minimum amount of time to wait before resending
an alert to Alertmanager. Use with server mode
only.
--alertmanager.notification-queue-capacity=10000
The capacity of the queue for pending
Alertmanager notifications. Use with server mode only.
--query.lookback-delta=5m The maximum lookback duration for retrieving
metrics during expression evaluations and federation.
Use with server mode only.
--query.timeout=2m Maximum time a query may take before being
aborted. Use with server mode only.
--query.max-concurrency=20
Maximum number of queries executed concurrently.
Use with server mode only.
--query.max-samples=50000000
Maximum number of samples a single query can
load into memory. Note that queries will fail if they
try to load more samples than this into memory,
so this also limits the number of samples a query
can return. Use with server mode only.
--enable-feature= ... Comma separated feature names to enable. Valid
options: agent, exemplar-storage,
expand-external-labels, memory-snapshot-on-
shutdown, promql-at-modifier, promql-negative-offset,
promql-per-step-stats, remote-write-receiver
(DEPRECATED), extra-scrape-metrics,
new-service-discovery-manager, auto-gomaxprocs.
See
https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details.
--log.level=info Only log messages with the given severity or
above. One of: [debug, info, warn, error]
--log.format=logfmt Output format of log messages. One of: [logfmt,
json]
2.1.3.3 测试访问
#浏览器访问:
http:/prometheus.wang.org:9090/


#浏览器访问:
http://prometheus.wang.org:9090/metrics

[root@prometheus ~]#curl http://localhost:9090/metrics
# HELP go_gc_duration_seconds A summary of the pause duration of garbage
collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 3.3093e-05
go_gc_duration_seconds{quantile="0.25"} 6.2107e-05
go_gc_duration_seconds{quantile="0.5"} 9.2564e-05
go_gc_duration_seconds{quantile="0.75"} 0.000143356
go_gc_duration_seconds{quantile="1"} 0.002131003
go_gc_duration_seconds_sum 0.032219258
go_gc_duration_seconds_count 248
# HELP go_goroutines Number of goroutines that currently exist.
......
2.1.3.4 Dashboard 菜单说明
#一级目录解析
Alerts #Prometheus的告警信息菜单
Graph #Prometheus的图形展示界面,这是prometheus默认访问的界面
Status #Prometheus的状态数据界面
Help #Prometheus的帮助信息界面
#Status子菜单,在Status菜单下存在很多的子选项,其名称和功能效果如下:
Runtime & Build Information 服务主机的运行状态信息及内部的监控项基本信息
Command-Line Flags 启动时候从配置文件中加载的属性信息
Configuration 配置文件的具体内容(yaml格式)
Rules 查询、告警、可视化等数据分析动作的规则记录
Targets 监控的目标对象,包括主机、服务等以endpoint形式存在
Service Discovery 自动发现的各种Targets对象列表
点击一级菜单Graph,该界面的基本功能分区样式如下

注意:
我们选择监控项的作用就是生成规则表达式,当然,规则表达式的功能远远超过选择监控项的功能。 但是这些定制采集数据的表达式,在刷新的时候,就没有了,这也是我们需要可视化插件的原因。 我们选择一个监控项"scrape_duration_seconds",然后点击"Execute",查看效果

2.1.3.5 优化配置
[root@prometheus ~]#/usr/local/prometheus/bin/prometheus --help
--web.read-timeout=5m #Maximum duration before timing out read of the request, and closing idle connections. 请求连接的最 ⼤ 等待时间 , 可以防 ⽌ 太多的空闲连接占 ⽤ 资源 --web.max-connections=512 #Maximum number of simultaneous connections. 最 ⼤ 链接数 --storage.tsdb.retention=15d #How long to retain samples in the
storage.prometheus开始采集监控数据后会存在内存中和硬盘中对于保留期限的设置,太长硬盘和内存都
吃不消,太短要查历史数据就没有了,企业中设置15天为宜,默认值为0
--storage.tsdb.path="data/" #Base path for metrics storage. 存储数据路径 , 建议独立分区 , 防止把根 ⽬ 录塞满 , 默认 data/ 目录
--query.timeout=2m #Maximum time a query may take before being aborted.此为默认值
2m
--query.max-concurrency=20#Maximum number of queries executed concurrently.此为默
认值20
查看配置

2.2 安装 Node Exporter
安装 Node Exporter 用于收集各 node 主机节点上的监控指标数据,监听端口为9100
官方下载: https://prometheus.io/download/
2.2.1 下载并解压
在需要监控的所有节点主机上进行安装
[root@node1 ~]#wget -P /usr/local/
https://github.com/prometheus/node_exporter/releases/download/v1.2.2/node_export
er-1.2.2.linux-amd64.tar.gz
[root@node1 ~]#cd /usr/local
[root@node1 local]#tar xvf node_exporter-1.2.2.linux-amd64.tar.gz
[root@node1 local]#ln -s node_exporter-1.2.2.linux-amd64 node_exporter
[root@node1 local]#cd node_exporter
[root@node1 node_exporter]#mkdir bin
[root@node1 node_exporter]#mv node_exporter bin/
2.2.2 准备 service 文件
[root@node1 ~]#vim /lib/systemd/system/node_exporter.service
[root@node1 ~]#cat /lib/systemd/system/node_exporter.service
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/node_exporter/bin/node_exporter
ExecReload=/bin/kill -HUP$MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
范例: 查看node_exporter命令选项
[root@ubuntu2004 ~]#node_exporter --help
usage: node_exporter [<flags>]
Flags:
-h, --help Show context-sensitive help (also try --help-
long and --help-man).
--collector.bcache.priorityStats
Expose expensive priority stats.
--collector.cpu.guest Enables metric node_cpu_guest_seconds_total
--collector.cpu.info Enables metric cpu_info
--collector.cpu.info.flags-include=COLLECTOR.CPU.INFO.FLAGS-INCLUDE
Filter the `flags` field in cpuInfo with a
value that must be a regular expression
--collector.cpu.info.bugs-include=COLLECTOR.CPU.INFO.BUGS-INCLUDE
Filter the `bugs` field in cpuInfo with a value
that must be a regular expression
--collector.diskstats.ignored-devices="^(ram|loop|fd|(h|s|v|xv)d[a-
z]|nvme\\d+n\\d+p)\\d+$"
Regexp of devices to ignore for diskstats.
--collector.ethtool.device-include=COLLECTOR.ETHTOOL.DEVICE-INCLUDE
Regexp of ethtool devices to include (mutually
exclusive to device-exclude).
--collector.ethtool.device-exclude=COLLECTOR.ETHTOOL.DEVICE-EXCLUDE
Regexp of ethtool devices to exclude (mutually
exclusive to device-include).
--collector.ethtool.metrics-include=".*"
Regexp of ethtool stats to include.
--collector.filesystem.mount-points-
exclude="^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)"
Regexp of mount points to exclude for
filesystem collector.
--collector.filesystem.fs-types-exclude="^(autofs|binfmt_misc|bpf|cgroup2?
|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|
proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$"
Regexp of filesystem types to exclude for
filesystem collector.
--collector.ipvs.backend-
labels="local_address,local_port,remote_address,remote_port,proto,local_mark"
Comma separated list for IPVS backend stats
labels.
--collector.netclass.ignored-devices="^$"
Regexp of net devices to ignore for netclass
collector.
--collector.netclass.ignore-invalid-speed
Ignore devices where the speed is invalid. This
will be the default behavior in2.x.
--collector.netdev.device-include=COLLECTOR.NETDEV.DEVICE-INCLUDE
Regexp of net devices to include (mutually
exclusive to device-exclude).
--collector.netdev.device-exclude=COLLECTOR.NETDEV.DEVICE-EXCLUDE
Regexp of net devices to exclude (mutually
exclusive to device-include).
--collector.netdev.address-info
Collect address-info for every device
--
collector.netstat.fields="^(.*_(InErrors|InErrs)|Ip_Forwarding|Ip(6|Ext)_(InOcte
ts|OutOctets)|Icmp6?
_(InMsgs|OutMsgs)|TcpExt_(Listen.*|Syncookies.*|TCPSynRetrans|TCPTimeouts)|Tcp_(
ActiveOpens|InSegs|OutSegs|OutRsts|PassiveOpens|RetransSegs|CurrEstab)|Udp6?
_(InDatagrams|OutDatagrams|NoPorts|RcvbufErrors|SndbufErrors))$"
Regexp of fields to return for netstat
collector.
--collector.ntp.server="127.0.0.1"
NTP server to use for ntp collector
--collector.ntp.protocol-version=4
NTP protocol version
--collector.ntp.server-is-local
Certify that collector.ntp.server address is not
a public ntp server
--collector.ntp.ip-ttl=1 IP TTL to use while sending NTP query
--collector.ntp.max-distance=3.46608s
Max accumulated distance to the root
--collector.ntp.local-offset-tolerance=1ms
Offset between local clock and local ntpd time
to tolerate
--path.procfs="/proc" procfs mountpoint.
--path.sysfs="/sys" sysfs mountpoint.
--path.rootfs="/" rootfs mountpoint.
--collector.perf.cpus="" List of CPUs from which perf metrics should be
collected
--collector.perf.tracepoint=COLLECTOR.PERF.TRACEPOINT ...
perf tracepoint that should be collected
--collector.powersupply.ignored-supplies="^$"
Regexp of power supplies to ignore for
powersupplyclass collector.
--collector.qdisc.fixtures=""
test fixtures to use for qdisc collector end-
to-end testing
--collector.runit.servicedir="/etc/service"
Path to runit service directory.
--collector.supervisord.url="http://localhost:9001/RPC2"
XML RPC endpoint.
--collector.systemd.unit-include=".+"
Regexp of systemd units to include. Units must
both match include and not match exclude to be
included.
--collector.systemd.unit-exclude=".+\\.
(automount|device|mount|scope|slice)"
Regexp of systemd units to exclude. Units must
both match include and not match exclude to be
included.
--collector.systemd.enable-task-metrics
Enables service unit tasks metrics
unit_tasks_current and unit_tasks_max
--collector.systemd.enable-restarts-metrics
Enables service unit metric
service_restart_total
--collector.systemd.enable-start-time-metrics
Enables service unit metric
unit_start_time_seconds
--collector.tapestats.ignored-devices="^$"
Regexp of devices to ignore for tapestats.
--collector.textfile.directory=""
Directory to read text files with metrics from.
--collector.vmstat.fields="^(oom_kill|pgpg|pswp|pg.*fault).*"
Regexp of fields to return for vmstat
collector.
--collector.wifi.fixtures=""
test fixtures to use for wifi collector metrics
--collector.arp Enable the arp collector (default: enabled).
--collector.bcache Enable the bcache collector (default: enabled).
--collector.bonding Enable the bonding collector (default:
enabled).
--collector.btrfs Enable the btrfs collector (default: enabled).
--collector.buddyinfo Enable the buddyinfo collector (default:
disabled).
--collector.conntrack Enable the conntrack collector (default:
enabled).
--collector.cpu Enable the cpu collector (default: enabled).
--collector.cpufreq Enable the cpufreq collector (default:
enabled).
--collector.diskstats Enable the diskstats collector (default:
enabled).
--collector.dmi Enable the dmi collector (default: enabled).
--collector.drbd Enable the drbd collector (default: disabled).
--collector.drm Enable the drm collector (default: disabled).
--collector.edac Enable the edac collector (default: enabled).
--collector.entropy Enable the entropy collector (default:
enabled).
--collector.ethtool Enable the ethtool collector (default:
disabled).
--collector.fibrechannel Enable the fibrechannel collector (default:
enabled).
--collector.filefd Enable the filefd collector (default: enabled).
--collector.filesystem Enable the filesystem collector (default:
enabled).
--collector.hwmon Enable the hwmon collector (default: enabled).
--collector.infiniband Enable the infiniband collector (default:
enabled).
--collector.interrupts Enable the interrupts collector (default:
disabled).
--collector.ipvs Enable the ipvs collector (default: enabled).
--collector.ksmd Enable the ksmd collector (default: disabled).
--collector.lnstat Enable the lnstat collector (default:
disabled).
--collector.loadavg Enable the loadavg collector (default:
enabled).
--collector.logind Enable the logind collector (default:
disabled).
--collector.mdadm Enable the mdadm collector (default: enabled).
--collector.meminfo Enable the meminfo collector (default:
enabled).
--collector.meminfo_numa Enable the meminfo_numa collector (default:
disabled).
--collector.mountstats Enable the mountstats collector (default:
disabled).
--collector.netclass Enable the netclass collector (default:
enabled).
--collector.netdev Enable the netdev collector (default: enabled).
--collector.netstat Enable the netstat collector (default:
enabled).
--collector.network_route Enable the network_route collector (default:
disabled).
--collector.nfs Enable the nfs collector (default: enabled).
--collector.nfsd Enable the nfsd collector (default: enabled).
--collector.ntp Enable the ntp collector (default: disabled).
--collector.nvme Enable the nvme collector (default: enabled).
--collector.os Enable the os collector (default: enabled).
--collector.perf Enable the perf collector (default: disabled).
--collector.powersupplyclass
Enable the powersupplyclass collector (default:
enabled).
--collector.pressure Enable the pressure collector (default:
enabled).
--collector.processes Enable the processes collector (default:
disabled).
--collector.qdisc Enable the qdisc collector (default: disabled).
--collector.rapl Enable the rapl collector (default: enabled).
--collector.runit Enable the runit collector (default: disabled).
--collector.schedstat Enable the schedstat collector (default:
enabled).
--collector.sockstat Enable the sockstat collector (default:
enabled).
--collector.softnet Enable the softnet collector (default:
enabled).
--collector.stat Enable the stat collector (default: enabled).
--collector.supervisord Enable the supervisord collector (default:
disabled).
--collector.systemd Enable the systemd collector (default:
disabled).
--collector.tapestats Enable the tapestats collector (default:
enabled).
--collector.tcpstat Enable the tcpstat collector (default:
disabled).
--collector.textfile Enable the textfile collector (default:
enabled).
--collector.thermal_zone Enable the thermal_zone collector (default:
enabled).
--collector.time Enable the time collector (default: enabled).
--collector.timex Enable the timex collector (default: enabled).
--collector.udp_queues Enable the udp_queues collector (default:
enabled).
--collector.uname Enable the uname collector (default: enabled).
--collector.vmstat Enable the vmstat collector (default: enabled).
--collector.wifi Enable the wifi collector (default: disabled).
--collector.xfs Enable the xfs collector (default: enabled).
--collector.zfs Enable the zfs collector (default: enabled).
--collector.zoneinfo Enable the zoneinfo collector (default:
disabled).
--web.listen-address=":9100"
Address on which to expose metrics and web
interface.
--web.telemetry-path="/metrics"
Path under which to expose metrics.
--web.disable-exporter-metrics
Exclude metrics about the exporter itself
(promhttp_*, process_*, go_*).
--web.max-requests=40 Maximum number of parallel scrape requests. Use
0 to disable.
--collector.disable-defaults
Set all collectors to disabled by default.
--web.config="" [EXPERIMENTAL] Path to config yaml file that
can enable TLS or authentication.
--log.level=info Only log messages with the given severity or
above. One of: [debug, info, warn, error]
--log.format=logfmt Output format of log messages. One of: [logfmt,
json]
--version Show application version.
2.2.3 启动 Node Exporter 服务
[root@node1 ~]#systemctl daemon-reload
[root@node1 ~]#systemctl enable --now node_exporter.service
[root@node1 ~]#systemctl is-active node_exporter
active
[root@node1 ~]#ss -ntlp|grep node_exporter
LISTEN 0128 *:9100 *:*
users:(("node_exporter",pid=33761,fd=3))
#结果显示:可以看到当前主机上可以看到一个端口9100
2.2.4 访问 Node Exporter Web 界面
浏览器访问
http://node1.wang.org:9100/


2.3 Prometheus 采集 Node 数据
配置 prometheus 通过 node exporter 组件采集node节点的监控指标数据
2.3.1 修改 Prometheus 配置文件
[root@prometheus ~]#vim /usr/local/prometheus/conf/prometheus.yml
[root@prometheus ~]#grep -Ev '^ *#|^$' /usr/local/prometheus/conf/prometheus.yml
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is
every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is
every 1 minute.
alerting:
alertmanagers:
- static_configs:
- targets:
rule_files:
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: 'node_exporter'#添加以下行,指定监控的node exporter节点
static_configs:
- targets: ['10.0.0.104:9100','10.0.0.105:9100','10.0.0.106:9100']
#- targets: ['10.0.0.107:9100'] 或者以这种格式也也可以支持
#- targets: ['10.0.0.108:9100']
#属性解析:
#新增一个job_name 和 static_configs的属性
#targets 就是前面基本概念中提到的instance,格式就是"ip:port"
#检查语法
[root@prometheus ~]#promtool check config
/usr/local/prometheus/conf/prometheus.yml
#重启prometheus服务:
[root@prometheus ~]#systemctl restart prometheus
2.3.2 Prometheus 验证 Node 节点状态
浏览器访问如下地址
http://master1.wang.org:9090/targets
#结果显示:当我们把鼠标放到Labels部位的时候,就会将改target的属性信息标识出来,其中"__*"开头
的就是该对象的私有属性,当我们点击Endpoint的时候,就可以看到该node节点上的所有定制好的监控项。

2.3.3 Prometheus 验证 Node 节点监控数据
点上面页面的主机链接,可以直接跳转至对应节点的页面



2.4 Grafana 展示 Prometheus 数据
2.4.1 Grafana 简介
Grafana是一个开源的度量分析与可视化套件,它基于go语言开发。经常被用作基础设施的时间序列数据和应用程序分析的可视化,应用场景非常多。
Grafana不仅仅支持很多类型的时序数据库数据源,比如Graphite、InfluxDB、Prometheus、 Elasticsearch等,虽然每种数据源都有独立的查询语言和能力,但是Grafana的查询编辑器支持所有的数据源,而且能很好的支持每种数据源的特性。通过该查询编辑器可以对所有数据进行整合,而且还可以在同一个dashboard上进行综合展示。
尤其是Grafana最具特色的就是各种各样漂亮的可视化界面,在Grafana提供了各种定制好的,可以直接给各种软件直接使用的展示界面模板,
默认监听于TCP协议的3000端口,支持集成其他认证服务,且能够通过/metrics输出内建指标;
可以在 https://grafana.com/dashboards/ 页面查询到我们想要的各种dashboard模板。
2.4.2 Grafana 部署
Grafana官方下载链接
https://grafana.com/grafana/download
在prometheus服务器同时也安装grafana
#安装软件
[root@grafana ~]#wget https://dl.grafana.com/enterprise/release/grafana-
enterprise_8.2.1_amd64.deb
#从国内镜站下载
[root@grafana ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/grafana/apt/pool/main/g/grafana/grafana_9.0
.6_amd64.deb
[root@grafana ~]#apt update
[root@grafana ~]#apt -y install ./grafana-enterprise_8.2.1_amd64.deb
#注意:这里安装的是本地文件,所以要加文件路径
#如果安装失败,解决依赖关系
[root@grafana ~]#apt -y --fix-broken install
#查看插件列表(此步可选)
[root@grafana ~]#grafana-cli plugins list-remote
#安装插件,如果安装失败,多试几次(此步可选)
[root@grafana ~]#grafana-cli plugins install grafana-piechart-panel
[root@grafana ~]#grafana-cli plugins ls
#启动服务
[root@grafana ~]#systemctl daemon-reload
[root@grafana ~]#systemctl enable --now grafana-server.service
#检查效果
[root@grafana ~]#systemctl status grafana-server.service
[root@grafana ~]#ss -ntulp|grep grafana
tcp LISTEN 04096 *:3000 *:*
users:(("grafana-server",pid=35383,fd=8))
#结果显示:当前主机上出现了一个端口3000
2.4.3 配置 Prometheus 数据源
2.4.3.1 登录 Grafana Web
#浏览器访问 http://master1.wang.org:3000/,查看效果
#输入用户名和密码:admin/admin,就会进入到更改密码的页面,查看效果


输入更改后的密码后,此处为了方便还用原来的密码admin, 点击"Submit"后,就会进入到首页,查看效果
2.4.3.2 添加 Prometheus 的数据源
添加数据源: 点击 "Add your first data source"

选择 "Prometheus" 出现添加界面

按照如下配置信息,在Settings界面对Prometheus进行配置 ,效果如下


#注意:这里默认地址无法使用,将Prometheus的地址(10.0.0.101:9090或者localhost:9090)输入进
去,其它没有做任何变动。
其它信息不用设置,点击最下面的"Save & Test" 查看效果

2.4.3.3 使用数据源插件中内置的Dashboard
点Dashboards页签内的import,导入内置的三个模板


查看默认的三个模板



出现这种效果,就表明配置完毕了
2.4.4 导入指定模板展示 Node Exporter 数据
上面内置的模板不太理想,导入指定的网络上比较合适的 Dashboard 模板
2.4.4.1 登录 Grafana 官网查找模板
https://grafana.com/grafana/dashboards/


2.4.4.2 导入指定模板
导入8919和1860模板

点击"import",将"https://grafana.com/dashboards/8919或1860"添加到如下位置,点 Load 后效
果如下

#注意:选择dashboard的时候,一定要选择合适版本,否则会导致无法正常使用
然后就会自动将改dashboard资源显示出来,效果如下

#注意:一定要选择需要可视化的数据源。
在Prometheus Data Source右侧选择刚才配置的Prometheus数据源即可,然后点击"Import",查看效果

结果显示:一旦我们的node_exporter部署完毕后,节点的信息立刻就展示出来了。
如果看不到数据的话
- 没有安装节点监控 NodePort软件
浏览器的时间与服务器的时间误差超过3s以上
再次导入1860 模板

2.5 监控 Zookeeper
监控的指标可以通过下面方式提供
Prometheus 内置
应用内置的功能模块,比如: Zookeeper 额外的exporter,使用第三方开发的功能程序语言内置的功能代码,需要开发能力
2.5.1 安装和配置 Zookeeper
#安装zookeeper
略
#修改配置支持prometheus
[root@node3 ~]#vim /usr/local/zookeeper/conf/zoo.cfg
#在最后面加下面三行,默认带有下面三行只需要取消注释即可
metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetr
icsProvider
metricsProvider.httpPort=7000
metricsProvider.exportJvmInfo=true
[root@node3 ~]#systemctl restart zookeeper.service
#浏览器访问:http://node1.wang.org:7000/metrics

2.5.2 修改 Prometheus 配置
[root@prometheus ~]#vim /usr/local/prometheus/conf/prometheus.yml
#在最后面加下面三行
- job_name: 'zookeeper'
static_configs:
- targets: ['10.0.0.101:7000']
[root@prometheus ~]#systemctl restart prometheus.service
2.5.3 查看 Prometheus 的监控数据
浏览器访问:http://prometheus.wang.org:9090/targets

2.5.4 查看 Grafana 监控数据
访问下面地址,搜索zookeeper
https://grafana.com/grafana/dashboards/


访问grafana管理页面
http://prometheus.wang.org:3000/

导入dashboard的ID: 10465

点击 Load

点击 import

选择监控的源为zookeeper,就可以看到下面界面


2.6 Pushgateway 采集自定义数据
2.6.1 Pushgateway 介绍
官方连接
https://prometheus.io/docs/practices/pushing/
虽然有很多的Exporter提供了丰富的数据,但生产环境中仍需要采集用户自定义的数据,可以利用 Pushgateway实现
Pushgateway 是另⼀种采⽤客户端主动推送数据的⽅式,也可以获取监控数据的prometheus 插件
与exporter 不同, Exporter 是被动采集数据
它是可以单独运⾏在任何节点上的插件(并不⼀定要在被监控客户端)
⽤户⾃定义的脚本或程序将需要监控的数据推送给 Pushgateway ,然后prometheus server再向 pushgateway拉取数据
Pushgateway 缺点
-
Pushgateway 会形成⼀个单点瓶颈,假如好多个应用同时发送给⼀个pushgateway的进程,如果这个进程没了,那么监控数据也就无法获取了
-
Pushgateway 并不能对发送过来的数据进⾏更智能的判断,假如脚本中间采集出问题,那么有问题的数据 pushgateway⼀样照单全收发送给prometheus
2.6.2 安装 Pushgateway
[root@prometheus ~]#wget
https://github.com/prometheus/pushgateway/releases/download/v1.4.3/pushgateway-
1.4.3.linux-amd64.tar.gz
[root@prometheus ~]#tar xf pushgateway-1.4.3.linux-amd64.tar.gz -C /usr/local/
[root@prometheus ~]#ln -s pushgateway-1.4.3.linux-amd64/ pushgateway
[root@prometheus ~]#ls /usr/local/pushgateway
LICENSE NOTICE pushgateway
[root@prometheus ~]#mkdir /usr/local/pushgateway/bin
[root@prometheus ~]#mv /usr/local/pushgateway/pushgateway
/usr/local/pushgateway/bin
[root@prometheus ~]#ldd /usr/local/pushgateway/bin/pushgateway
不是动态可执行文件
[root@prometheus ~]#ln -s /usr/local/pushgateway/bin/pushgateway /usr/local/bin/
[root@prometheus ~]#pushgateway --help
usage: pushgateway [<flags>]
The Pushgateway
Flags:
-h, --help Show context-sensitive help (also try --help-
long and --help-man).
--web.config.file="" [EXPERIMENTAL] Path to configuration file that
can enable TLS or authentication.
--web.listen-address=":9091"
Address to listen on for the web interface,
API, and telemetry.
--web.telemetry-path="/metrics"
Path under which to expose metrics.
--web.external-url= The URL under which the Pushgateway is
externally reachable.
--web.route-prefix="" Prefix for the internal routes of web
endpoints. Defaults to the path of --web.external-url.
--web.enable-lifecycle Enable shutdown via HTTP request.
--web.enable-admin-api Enable API endpoints for admin control actions.
--persistence.file="" File to persist metrics. If empty, metrics are
only kept in memory.
--persistence.interval=5m The minimum interval at which to write out the
persistence file.
--push.disable-consistency-check
Do not check consistency of pushed metrics.
DANGEROUS.
--log.level=info Only log messages with the given severity or
above. One of: [debug, info, warn, error]
--log.format=logfmt Output format of log messages. One of: [logfmt,
json]
--version Show application version.
[root@prometheus ~]#pushgateway
ts=2022-08-06T14:55:02.911Z caller=main.go:85 level=info msg="starting
pushgateway"version="(version=1.4.3, branch=HEAD,
revision=f9dc1c8664050edbc75916c3664be1df595a1958)"
ts=2022-08-06T14:55:02.911Z caller=main.go:86 level=info build_context="
(go=go1.18.2, user=root@75e397dd33fe, date=20220530-19:02:00)"
ts=2022-08-06T14:55:02.913Z caller=main.go:139 level=info listen_address=:9091
ts=2022-08-06T14:55:02.914Z caller=tls_config.go:195 level=info msg="TLS is
disabled."http2=false
#准备service文件
[root@prometheus ~]#cat > /lib/systemd/system/pushgateway.service <<EOF
[Unit]
Description=Prometheus Pushgateway
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/pushgateway/bin/pushgateway
ExecReload=/bin/kill -HUP$MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
#启动服务
[root@prometheus ~]#systemctl daemon-reload
[root@prometheus ~]#systemctl enable --now pushgateway.service
2.6.3 配置 Prometheus 收集 Pushgateway 数据
[root@prometheus ~]#vim /usr/local/prometheus/conf/prometheus.yml
- job_name: "pushgateway"
static_configs:
- targets:
-"10.0.0.100:9091"
#支持文件形式的自动发现格式
- job_name: pushgateway
honor_labels: true
file_sd_configs:
- files:
- targets/pushgateway/*.json
refresh_interval: 5m
#pushgateway目标:
[{"targets": ["pushgateway1.wang.org"]}]
#如果honor_labels设置为true,那么Prometheus将使用Pushgateway上的job和instance标签。如果
设置为false那么它将重命名这些值,在它们前面加上exported_前缀,并在服务器上为这些标签附加新值。
2.6.4 配置客户端发送数据给 Pushgateway
要推送一个度量,您需要使用以下URL路径定义向Pushgateway端点发送一个HTTP POST请求。 推送 Metric 格式
http://<pushgateway_address>:
<push_port>/metrics/job/<job_name>/[<label_name1>/<label_value1>]/[<label_nameN>
/<label_valueN>]
<job_name>将成为被推送的指标的标签作业的值,而<label_name>/<label_value〉对将成内额外的标签/值对。
删除 Metric 格式
#删除指定job_name中的所有metric
curl-X DELETE http://<pushgateway_address>:<push_port/metrics/job/<job_name>
#删除指定实例的metric
curl-x DELETE http://<pushgateway_address>:
<push_port/metrics/job/<job_name>/instance/<instance_name>
范例: 命令
#下面为发送一次数据,如果想周期性发送,可以通过cron或脚本循环实现
[root@ubuntu2004 ~]#echo "age 8" | curl --data-binary @-
http://pushgateway.wang.org:9091/metrics/job/pushgateway/instance/`hostname -I`
#说明
pushgateway.wang.org:9091 #安装为Pushgateway主机的IP和端口
pushgateway #Prometheus的job名称
`hostname -I`#取当前主机的IP为instance名称
范例: 通用脚本
#编定自定义的metric的脚本
[root@ubuntu2004 ~]#vim pushgateway_metric.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2022-08-08
#FileName: pushgateway_metric.sh
#URL: http://www.wangxiaochun.com
#Description: The test script
#Copyright (C): 2022 All rights reserved
#********************************************************************
METRIC_NAME=login_number
METRIC_VALUE="who | wc -l"
PUSHGATEWAY_HOST=pushgateway.wang.org:9091
EXPORTED_JOB=pushgateway_job
SLEEP_TIME=1
CURL_URL="curl --data-binary @-
http://${PUSHGATEWAY_HOST}/metrics/job/${EXPORTED_JOB}/instance/`hostname -I`"
action() {
whiletrue ;do
VALUE=`eval "$METRIC_VALUE"`
echo"${METRIC_NAME}${VALUE}" | $CURL_URL
sleep$SLEEP_TIME
done
}
action
[root@ubuntu2004 ~]#bash pushgateway_metric.sh
2.6.5 验证数据





3 Prometheus 配置和标签管理
3.1 配置文件说明
Prometheus可以通过命令行或者配置文件的方式对服务进行配置。
-
命令行方式一般用于不可变的系统参数配置,例如存储位置、要保留在磁盘和内存中的数据量等; 配置文件用于定义与数据动态获取相关的配置选项和文件等内容。
-
命令行方式的配置属性可以通过 prometheus -h 的方式来获取,这些配置属性主要在服务启动时候设置.
-
配置文件方式,需要在prometheus.yml 文件中修改配置属性,该配置文件的内容是以YAML格式编写的。
官方文档:
https://prometheus.io/docs/prometheus/latest/configuration/configuration/
默认情况下,Prometheus 的配置文件有四部分组成,效果如下:
]# egrep -v '^#| #|^$' prometheus.yml
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default
is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is
every 1 minute.
# scrape_timeout is set to the global default (10s).
alerting:
alertmanagers:
- static_configs:
- targets:
rule_files:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
配置解析:
#核心配置:
global #全局配置内容
alerting #触发告警相关的配置,主要是与Alertmanager相关的设置。
rule_files #各种各样的外置规则文件配置,包含了各种告警表达式、数据查询表达式等
scrape_configs #监控项的配置列表,这是最核心的配置
#除了默认的四项配置之外,prometheus还有另外可选的其它配置如下
#扩展配置(8项)
tls_config、static_config、relabel_config、metric_relabel_configs、
alert_relabel_configs、alertmanager_config、remote_write、remote_read
#平台集成配置(12项)
azure_sd_config、consul_sd_config、dns_sd_config、ec2_sd_config、
openstack_sd_config、file_sd_config、gce_sd_config、kubernetes_sd_config、
marathon_sd_config、nerve_sd_config、serverset_sd_config、triton_sd_config
scrape_configs 管理
scrape_configs 是操作最多的一个配置段,它指定了一组监控目标及其细节配置参数,这些目标和参数描述了如何获取指定主机上的时序数据。配置样例如下:
scrape_configs:
- job_name: '<job_name>'
static_configs:
- targets: [ '<host_ip:host_port>', ... ]
labels: { <labelname>: <labelvalue> ... }
#配置解析:
#在一般情况下,一个scrape_configs配置需要指定一个或者多个job,根据我们之前对基本概念的了解,
每一个job都是一系列的instance集合,借助job我们可以将目标主机进行分组管理。
#对于job内部的每一个instance的配置,都需要借助于static_configs参数获取目标列表,只要在该列表
位置的目标,都可以被Prometheus动态服务自动发现。
#static_configs可以借助于 targets 以ip+port 方式发现目标,也可以使用labels以标签方式发现
目标。
语法检查
[root@prometheus ~]#promtool check config
/usr/local/prometheus/conf/prometheus.yml
3.2 标签简介

标签功能: 用于对数据分组和分类,利用标签可以将数据进行过滤筛选
标签的常见场景:
删除不必要的指标从指标中删除敏感或不需要的标签添加、编辑或修改指标的标签值或标签格式
标签分类:
默认标签: Prometheus 自身内置形式: __keyname__ 应用标签: 应用本身内置形式: keyname 自定义标签: 用户定义形式: keyname
范例: 添加主机节点
#编辑prometheus.yml配置文件
scrape_configs:
...
- job_name: "prometheus"
static_configs:
- targets: ['10.0.0.101:9100']
- job_name: 'node_exporter'
static_configs:
- targets: ['10.0.0.104:9100','10.0.0.105:9100','10.0.0.106:9100']
#- '10.0.0.104:9100' #或者下面格式
#- '10.0.0.105:9100'
#- '10.0.0.106:9100'
#配置解析:static_configs 用于手工定制要监控的target
#重启服务
systemctl restart prometheus.service
#查看效果,可以看到如下的内置的标签

应用默认的标签如下形式

范例: 添加主机标签
#编辑prometheus.yml配置文件
[root@prometheus ~]#vim /usr/local/prometheus/conf/prometheus.yml
- job_name: 'node_exporter'
static_configs:
- targets: ['10.0.0.104:9100','10.0.0.105:9100','10.0.0.106:9100']
labels:
node: "worker node"
type: "test"
- job_name: 'zookeeper'
static_configs:
- targets: ['10.0.0.105:7000','10.0.0.106:7000']
labels: {app: 'zookeeper', type: 'dev'}
#app: 'zookeeper' #或者这种格式也支持
#type: 'dev'
#配置解析:labels: 的编写方法,在此处遵循 yaml的字典格式
#重启服务
[root@prometheus ~]#systemctl restart prometheus.service
#浏览器访问确认

3.3 标签管理
官方文档
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabe
l_config
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric
_relabel_configs
Prometheus对数据的处理流程是:
先从各目标节点上获取数据,然后对数据进行本地化处理,然后进行各种数据分析。这个流程中最核心的就是监控数据的本地化处理
在prometheus的配置选项中,有两个与监控指标密切相关的配置,relabel_config、 metric_relabel_configs,他们的作用就是监控目标上面的监控项进行标签管理和设置,便于在 prometheus上设置更灵活的时序数据。
标签主要有两种表现形式:
私有标签
私有标签以"__*"样式存在,用于获取监控目标的默认元数据属性,比如__address__用于获取目标的
地址,__scheme__用户获取目标的请求协议方法,__metrics_path__获取请求的url地址等
普通标签
对个监控主机节点上的监控指标进行各种灵活的管理操作,常见的操作有,删除不必要|敏感指标,添
加、编辑或者修改指标的标签值或者标签格式。
对于一些全局性的标签,可以在global部分通过属性来设置,效果如下:
global:
...
# 与外部系统通信时添加到任何时间序列或警报的标签
external_labels:
[ <labelname>: <labelvalue> ... ]
relabel_config、metric_relabel_configs 的使用格式基本上一致,虽然他们有很多配置,但是我们使用的最多的也就那么三四个。
#配置示例如下:
scrape_configs:
- job_name: 'prometheus'
metric_relabel_configs:
- source_labels: [<labelname> [, ...]]
regex: '<regex> | default = (.*)'
replacement: '<string> | default = $1'
target_label: '<labelname>'
action: '<relabel_action> | default = replace'
#属性解析:
source_labels #指定正则表达式匹配成功的Label进行标签管理
regex #source_labels对应Label的匹配正则表达式的指定值
target_label #在进行标签替换的时候,可以将原来的source_labels替换为指定修改后的
label
replacement #替换标签时,指定label对应的值进行修改后的值
action #对标签进行管理,常见的动作有replace|keep|drop|labelmap|labeldrop
等
#动作解析:
labeldrop #删除regex匹配的标签label
labelkeep #删除regex不匹配的标签label
labelmap #将regex对所有的标签名进行匹配,而后将匹配到的标签的值赋给replacement字段指定的
标签名的值;通常用于取出匹配的标签名的一部分生成新标签,旧的标签仍会存在
replace #此为默认值,通过regex匹配source_label的值,使用replacement来进行替换
keep #从获取的监控数据中删除与regex不匹配的目标 source_labels
drop #从获取的监控数据中删除与regex匹配的目标 source_labels
范例:
#删除示例
metric_relabel_configs:
- source_labels: [__name__]
regex: 'node_network_receive.*'
action: drop
#替换示例
metric_relabel_configs:
- source_labels: [id]
regex: '/.*'
replacement: '123456'
target_label: replace_id
配置区别
relabel_config、metric_relabel_configs这两个配置虽然在作用上类似,但是他们还是有本质上的区别的,这些区别体现在两个方面:执行顺序和数据处理上。
区
别
解析
执 relabel_configs用与发现目标前的标签设置,也就是说在scrape_configs前生效,针对的行 target对象顺 metric_relabel_configs 作用于scrape_configs生效后,即针对target对象上的监控数据序
数据 metric_relabel_configs 是 prometheus 在保存数据前的最后一步标签重新编辑,默认情况处下,它将监控不需要的数据,直接丢掉,不在prometheus 中保存理
3.4 案例
范例: 将默认标签修改为定制新标签
#编辑prometheus.yml配置文件
[root@prometheus ~]#vim /usr/local/prometheus/conf/prometheus.yml
scrape_configs:
...
- job_name: 'k8s-node'
static_configs:
- targets: ['10.0.0.104:9100','10.0.0.105:9100','10.0.0.106:9100']
relabel_configs:
- source_labels:
- __scheme__
- __address__
- __metrics_path__
regex: "(http|https)(.*)"
separator: ""
target_label: "endpoint"
replacement: "${1}://${2}"
action: replace
#配置解析:separator 是设定拼接的时候用到的分隔符,我们这里不用设置任何符号
#重启服务
[root@prometheus ~]#systemctl restart prometheus.service
#浏览器查看效果
#结果显示:基于默认的属性重写了一个新的标签。

范例: 基于已存在的标签匹配,然后进行删除
#编辑prometheus.yml配置文件
[root@prometheus ~]#vim /usr/local/prometheus/conf/prometheus.yml
scrape_configs:
...
static_configs:
- targets: ["localhost:9090"]
- job_name: 'k8s-node'
static_configs:
- targets: ['10.0.0.104:9100','10.0.0.105:9100','10.0.0.106:9100']
labels: {app: 'k8s-node'}
relabel_configs:
- source_labels:
- __scheme__
- __address__
- __metrics_path__
regex: "(http|https)(.*)"
separator: ""
target_label: "endpoint"
replacement: "${1}://${2}"
action: replace
- regex: "(job|app)"#加下面三行,所有名为job或app的标签修改标签名称,但旧的
标签还会存在
replacement: ${1}_name
action: labelmap
- regex: "(job|app)"#加下面两行,则删除旧的标签,注意上面修改和此删除的前后顺
序
action: labeldrop
#配置解析:第一条规则基于现有的匹配内容重写标签名称,第二条规则,删除旧标签的名称
#重启服务
[root@prometheus ~]#systemctl restart prometheus.service
#查看效果
#如下结果显示:第二条规则中,匹配到的标签就移除掉了

4 PromQL
4.1 指标数据
4.1.1 数据基础
时间序列数据:
-
按照时间顺序记录系统、设备状态变化的数据,每个数据称为一个样本
-
数据采集以特定的时间周期进行,随着时间将这些样本数据记录下来,将生成一个离散的样本数据序列,该序列也称为向量(Vector)
-
将多个序列放在同一个坐标系内(以时间为横轴,以序列为纵轴),将形成一个由数据点组成的矩阵

Prometheus基于指标名称(metrics name)以及附属的标签集(labelset)唯一定义一条时间序列
-
指标名称代表着监控目标上某类可测量属性的基本特征标识
-
标签则是这个基本特征上再次细分的多个可测量维度
4.1.2 数据模型
Prometheus中,每个时间序列都由指标名称(Metric Name)和标签(Label)来唯一标识,格式为
<metric name>{<label name>=<label value>, …}”;
-
指标名称:通常用于描述系统上要测定的某个特征
-
支持使用字母、数字、下划线和冒号,且必须能匹配RE2规范的正则表达式
-
例如,http_requests_total表示接收到的HTTP请求总数
-
标签:键值型数据,附加在指标名称之上,从而让指标能够支持多纬度特征;此为可选项
-
标签名称可使用字母、数字和下划线,且必须能匹配RE2规范的正则表达式
-
以“__”为前缀的名称为Prometheus系统预留使用
例如: 下面代表着两个不同的时间序列
http_requests_total{method=GET}
http_requests_total{method=POST}
Metric Name的表示方式有两种,其中后一种通常用于Prometheus内部,效果如下

样本数据
Prometheus的每个数据样本由两部分组成
float64格式的数据
毫秒精度的时间戳

注意事项
指标名称和标签的特定组合代表着一个时间序列
- 指标名称相同,但标签不同的组合分别代表着不同的时间序列不同的指标名称自然更是代表着不同的时间序列
PromQL支持基于定义的指标维度进行过滤和聚合
-
更改任何标签值,包括添加或删除标签,都会创建一个新的时间序列
-
应该尽可能地保持标签的稳定性,否则,则很可能创建新的时间序列,更甚者会生成一个动态的数据环境,并使得监控的数据源难以跟踪,从而导致建立在该指标之上的图形、告警及记录规则变得无效
4.2 查询基础
4.2.1 PromQL简介
Prometheus 提供一个内置的函数式的表达式语言PromQL(Prometheus Query Language),可以使用户实时地查找和聚合时间序列数据。表达式计算结果可以在图表中展示,也可以在Prometheus表达式浏览器中以表格形式展示,或者作为数据源, 以HTTP API的方式提供给外部系统使用。
注意:默认情况下,是以当前时间为基准点,来进行数据的获取操作
4.2.2 表达式形式
官方文档
https://prometheus.io/docs/prometheus/latest/querying/basics/
表达式: 每一个PromQL其实都是一个表达式,这些语句主要有四种存在样式:
-
数据类型
- instant vector 瞬时数据
在某一时刻,抓取的所有监控项数据。这些度量指标数据放在同一个key中。
-
range vector 范围数据
-
在某一个时间段内,抓取的所有监控项数据。
-
数据格式
-
scalar 标量
-
一个简单的浮点类型数值
-
string 字符串
-
一个之前没有被使用的简单字符串
-
日常图形展示中用到的数据就是基于上面四种样式组合而成的综合表达式,效果如下

PromQL的查询操需要针对有限个时间序列上的样本数据进行,挑选出目标时间序列是构建表达式时最为关键的一步,然后根据挑选出给定指标名称下的所有时间序列或部分时间序列的即时(当前)样本值或至过去某个时间范围内的样本值。
基本语法
对于PromQL来说,以下的几个基础知识是我们必须掌握和熟练应用的
数值
对于数值来说,主要记住两种类型的数值:字符串和数字。
字符串
字符串可以用单引号,双引号或反引号指定为文字,如果字符串内的特殊符号想要生效,我们可以使用反引
号。
"this is a string"
'these are unescaped: n t'
`these are not unescaped: n ' " t`
数字
#对于数据值的表示,可以使用我们平常时候的书写方法 "[-](digits)[.(digits)]"
2、2.43、-2.43等
4.2.3 数据选择器
所谓的数据选择器,其实指的是获取实时数据或者历史数据的一种方法
样式:
metrics_name{筛选label=值,...}[<时间范围>] offset <偏移>
它主要以下几种分类:
实时选择器 :
获取及时的一组时间序列和单个样本值,根据数据的精确度,可以有以下几种使用方法:
根据监控项名称获取最新值
node_filefd_allocated
prometheus_http_requests_total
- 通过{key=value,}样式获取符合条件的数据值
prometheus_http_requests_total{instance="localhost:9090", job="prometheus"}
prometheus_http_requests_total{handler=~".*meta.*"}
#属性解析:
多个条件间可以使用逗号","隔开,每个条件内部可以通过多种符号,表示不同含义
=(精确匹配)、!=(不匹配)、=~(正则匹配)、!~(正则不匹配)
如果条件中存在多值,可以使用"|"表示或的意思,env=~"staging|testing|development"
条件中必须包含一个与空标签值不匹配的选择器,不能写成{job=~".*"}
node_memory_MemFree_bytes{instance=~"10.0.0.(101|102):9100"}
#注意:指标 prometheus_http_requests_total 默认情况下,针对的是 localhost:9090 的
target,其他无效
通过 __name__ 匹配多个监控项的名称
{__name__="prometheus_http_requests_total"}
{__name__=~"^prometheus.*"}
范围选择器
工作方式与瞬时向量选择器一样,区别在于时间范围长一些,主要是在瞬时选择器多了一个[]格式的时间范围后缀,在[]内部可以采用多个单位表示不同的时间范围,比如s(秒)、m(分)、h(时)、d(日)、 w(周)、y(年)。
prometheus_http_requests_total{job="prometheus"}[5m]
#属性解析:这表示过去5分钟内的监控数据值,这些数据一般以表格方式展示,而不是列表方式展示
注意:范围向量选择器返回的是一定时间范围内的数据样本,虽然不同时间序列的数据抓取时间点相同,但它们的时间戳并不会严格对齐
多个Target上的数据抓取需要分散在抓取时间点前后一定的时间范围内,以均衡Prometheus Server的负载
因而,Prometheus在趋势上准确,但并非绝对精准

偏移修饰符
范围选择器可以获取最近时间段的数据,而对于某个历史时间段中的数据,就需要通过offset时间偏移的方式来进行获取了。
prometheus_http_requests_total offset 5m
prometheus_http_requests_total{code="200"} offset 5m
prometheus_http_requests_total{handler="/metrics"}[5m] offset 3m
#注意:offset与数据选择器是一个整体,不能分割,offset 偏移的是时间点
如果既有偏移又有范围,先偏移后再取范围,如[5m] offset 3m 表示取当前时间的3分钟前的5m范围的值
4.3 查询语法格式
对于PromQL来说,它的操作符号主要有以下两类:
二元运算符
聚合运算
4.3.1 二元运算符
对于二元运算符来说,它主要包含三类:算术、比较、逻辑,作用效果与我们平常使用的效果一致。
#算术运算符:+、-、*、/、%、^
#比较运算符:==、!=、=~、!~>、<、>=、<=
#逻辑运算符:and、or、unless 目前该运算符仅允许在两个即时向量之间进行操作,不支持标量(标量只有
一个数字,没有时序)参与运算
#运算符优先级:
1 ^
2 *, /, %
3+, -
4==, !=, <=, <, >=, >
5 and, unless
6 or
#注意:二元运算符是prometheus进行数据可视化或者数据分析操作的时候,应用非常多的一种功能。
简单示例:
#单位换算
node_memory_MemFree_bytes / (1024 * 1024)
#可用内存占用率
node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes * 100
#内存使用率
(node_memory_MemTotal_bytes - node_memory_MemFree_bytes) /
node_memory_MemTotal_bytes * 100
#磁盘使用率
(node_filesystem_size_bytes{mountpoint="/"} -
node_filesystem_free_bytes{mountpoint="/"})
/node_filesystem_size_bytes{mountpoint="/"} * 100
#阈值判断
(node_memory_MemTotal_bytes - node_memory_MemFree_bytes) /
node_memory_MemTotal_bytes > 0.95
#内存利用率是否超过80
( 1- node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes ) * 100 > bool
80
prometheus_http_requests_total > bool 1000#布尔值,当超过1000为1,否则为0
#注意:
对于比较运算符来说,条件成立有结果输出,否则没有结果输出
使用bool修改符后,布尔运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比
较结果0或者1。从而形成一条新的时间序列。
集合处理
# 并集
node_memory_MemTotal_bytes{instance="10.0.0.104:9100"} or
node_memory_MemFree_bytes{instance="10.0.0.105:9100" }
node_memory_MemTotal_bytes{instance=~"10.0.0.(103|104):9100"}
#交集
node_memory_MemTotal_bytes{instance="10.0.0.101:9100"} and
node_memory_MemFree_bytes{instance="10.0.0.104:9100" }
#补集
node_memory_MemTotal_bytes{job_name="k8s-node"} unless
node_memory_MemTotal_bytes{instance="10.0.0.104:9100"}
#注意:
and、or、unless 主要是针对获取的数据值进行条件选集合用的
and、or、unless 针对的对象是一个完整的表达式
4.3.2 聚合操作
官方文档
https://prometheus.io/docs/prometheus/latest/querying/operators/
聚合操作符aggregation operators虽然是一个个的功能,但是并不属于功能函数,仅仅代表对数据进行简单的功能处理。
常见的方法有:
sum、min、max、avg、count、count_values(值计数)
stddev(标准差)、stdvar(标准差异)、bottomk(最小取样)、topk(最大取样)、quantile(分布统计)
格式:
聚合操作符(metric表达式) sum、min、max、avg、count等
聚合操作符(描述信息,metric) count_values、bottomk、topk等
可以借助于without和by功能获取数据集中的一部分进行分组统计,格式如下
sum(数据选择表达式) without|by (<label list>)
#without 表示显示信息的时候,不包括指定的标签列表的分组统计
#by表示显示信息的时候,仅显示指定的标签的分组统计
示例
#内存总量
sum(node_memory_MemTotal_bytes)
#确认CPU的总个数
count(node_cpu_seconds_total{mode='system'})
#获取最大的值
max(prometheus_http_requests_total)
#分组统计计数
count_values("counts",node_filesystem_size_bytes)
#获取前5个最大值
topk(5, prometheus_http_requests_total)
#分组求和,除了job
sum(prometheus_http_requests_total) without (job)
#分组求和,仅仅是mode
sum(node_cpu_seconds_total) by (mode)
4.3.3 功能函数
官方文档
https://prometheus.io/docs/prometheus/latest/querying/functions/
默认情况下,prometheus官方默认的功能函数有40个,主要有以下几类
计算相关
绝对值abs()、导数deriv()、指数exp()、对数ln()、二进制对数log2()、10进制对数log10()、平方根
sqrt()
向上取整ceil()、向下取整floor()、四舍五入round()
样本差idelta()、差值delta()、递增值increase()、重置次数resets()
递增率irate()、变化率rate()、平滑值holt_winters()、直方百分位histogram_quantile()
预测值predict_linear()、参数vector()
范围最小值min_over_time()、范围最大值max_over_time()、范围平均值avg_over_time()、范围求
和值sum_over_time()、范围计数值count_over_time()、范围分位数quantile_over_time()、范围
标准差stddev_over_time()、范围标准方差stdvar_over_time()
取样相关
获取样本absent()、升序sort()、降序sort_desc()、变化数changes()
判断值scalar()、判断大clamp_max()、判断小clamp_min()
范围采样值absent_over_time(),
时间相关
day_of_month()、day_of_week()、days_in_month()、hour()、minute()、month()、time()、
timestamp()、year()
标签相关
标签合并label_join()、标签替换labelreplace()
示例:
ceil():向上取整
floor():向下取整
round():四舍五入
#示例
ceil(node_load15 * 10)
floor(node_load15 * 10)
round(node_load15 * 10)
increase(): 增长量,即last值-last前一个值
#示例:最近1分钟内CPU处于空闲状态时间
increase(node_cpu_seconds_total{cpu="0",mode="idle"}[1m])
#CPU 利用率
(1 - sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance) /
sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100
irate():查看瞬时变化率,即:(last值-last前一个值)/时间戳差值
#示例:查看CPU最近5m内最多的增长率
irate(node_cpu_seconds_total{instance="10.0.0.101:9100",mode="idle"}[5m])
rate():平均变化率,计算在指定时间范围内计数器每秒增加量的平均值,即(last值-first值)/时间差的秒
数
#示例:
#过去一分钟磁盘读的变化率
rate(node_disk_read_bytes_total[1m])
#一分钟内网卡传输的字节数(MB)
rate(node_network_transmit_bytes_total{device="eth0"}[1m]) /1024 /1024
time(): 获取当前时间值
#示例:
#计算当前每个主机的运行时间
(time() - node_boot_time_seconds) / 3600
#计算所有主机的总运行时间
sum(time() - node_boot_time_seconds) / 3600
histogram_quantile(): 百分取样值
#示例:
#计算过去10m内请求持续时间的第90个百分位数
histogram_quantile(0.9,
rate(prometheus_http_request_duration_seconds_bucket[10m]))
4.4 定制 Exporter
4.4.1 定制 Exporter 说明
Prometheus对于监控功能的核心要素就是metric的监控项是否正常工作,metric是对应的服务启动后,自动携带的一个url地址,通过该地址可以获取我们想要的监控项。
实际生产环境中,想要监控好多指标,但是prometheus 内置的环境中可能没有对应的metric监控项条目,比如监控docker应用、监控系统服务、网页的转化率等,所以就需要实现自定义的metric条目。
开发应用服务的时候,就需要根据metric的数据格式,定制标准的/metric接口。
各种语言帮助手册:
https://github.com/prometheus/client_golang
https://github.com/prometheus/client_python
https://github.com/prometheus/client_java
https://github.com/prometheus/client_rust
以python项目,可以借助于prometheus_client模块在python类型的web项目中定制metric接口。
ThreeStepDemo
One: Installtheclient:
pipinstallprometheus-client
Two: PastethefollowingintoaPythoninterpreter:
fromprometheus_clientimportstart_http_server, Summary
importrandom
importtime
# Create a metric to track time spent and requests made.
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing
request')
# Decorate function with metric.
@REQUEST_TIME.time()
defprocess_request(t):
"""A dummy function that takes some time."""
time.sleep(t)
if__name__ == '__main__':
# Start up the server to expose the metrics.
start_http_server(8000)
# Generate some requests.
whileTrue:
process_request(random.random())
Three: Visithttp://localhost:8000/toviewthemetrics.
4.4.2 定制 Exporter 实战案例: Python 实现
4.4.2.1 准备 Python 开发 Web 环境
#apt安装python3.9
~# apt update
~# apt install -y python3.9 (可选)
~# apt install -y python3-pip
#############################如何不安装虚拟环境下面不需要执行
#################################
#安装虚拟环境软件
~# pip3 install pbr virtualenv
~# pip3 install --no-deps stevedore virtualenvwrapper
#创建用户
~# useradd -m -s /bin/bash python
#准备目录
~# mkdir -p /data/venv
~# chown python.python /data/venv
#修改配置文件(可选)
~# su - python
~# vim .bashrc
force_color_prompt=yes#取消此行注释,清加颜色显示
#配置加速
~# mkdir ~/.pip
~# vim .pip/pip.conf
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host=pypi.douban.com
#配置虚拟软件
echo'export WORKON_HOME=/data/venv' >> .bashrc
echo'export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3' >> .bashrc
echo'export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv' >> .bashrc
echo'source /usr/local/bin/virtualenvwrapper.sh' >> .bashrc
source .bashrc
#注意:virtualenv 和 virtualenvwrapper.sh 的路径位置
#创建新的虚拟环境并自动进入
~# mkvirtualenv -p python3 flask_env
#进入已创建的虚拟环境
~# su - python
~# workon flask_env
#虚拟环境中安装相关模块库
~# pip install flask prometheus_client
~# pip list
#################################如何不安装虚拟环境上面不需要执行
##########################
#实际环境中安装相关模块库
~# pip3 install flask prometheus_client
~# pip3 list
#创建代码目录
~# mkdir code
4.4.2.2 项目代码
代码说明
from prometheus_client import Counter, Gauge, Summary
from prometheus_client.core import CollectorRegistry
class Monitor:
def __init__(self):
# 注册收集器
self.collector_registry = CollectorRegistry(auto_describe=False)
# summary类型监控项设计
self.summary_metric_name = Summary(name="summary_metric_name",
documentation="summary_metric_desc",
labelnames=("label1", "label2", "label3"),
registry=self.collector_registry)
# gauge类型监控项设计
self.gauge_metric_name = Gauge(name="gauge_metric_name",
documentation="summary_gauge_desc",
labelnames=("method", "code", "uri"),
registry=self.collector_registry)
# counter类型监控项设计
self.counter_metric_name = Counter(name="counter_metric_name",
documentation="summary_counter_desc",
labelnames=("method", "code", "uri"),
registry=self.collector_registry)
#属性解析:上面是几个常用的标准metric数据格式设计,
范例: 定制 flask web 项目
]# su - python
]# workon flask_env
]# cat ~/code/flask_metric.py
fromprometheus_clientimportstart_http_server,Counter, Summary
fromflaskimportFlask, jsonify
fromwsgiref.simple_serverimportmake_server
importtime
app = Flask(__name__)
# Create a metric to track time spent and requests made
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing
request')
COUNTER_TIME = Counter("request_count", "Total request count of the host")
@app.route("/metrics")
@REQUEST_TIME.time()
defrequests_count():
COUNTER_TIME.inc()
returnjsonify({"return": "success OK!"})
if__name__ == "__main__":
start_http_server(8000)
httpd = make_server( '0.0.0.0', 8001, app )
httpd.serve_forever()
#代码解析:
.inc() 表示递增值为1
start_http_server(8000) #收集数据的端口可以通过8000/metrics收集日志
make_sever( '0.0.0.0', 8001, app ) #表示另开启一个web服务的/metrics 链接专门用于接收请
求。
#启动项目:
]# python flask_meric.py
#浏览器访问 10.0.0.101:8000/metrics 可以看到大量的监控项,下面的几项就是我们自己定制的
...
# HELP request_processing_seconds Time spent processing request
# TYPE request_processing_seconds summary
request_processing_seconds_count0.0
request_processing_seconds_sum0.0
# TYPE request_processing_seconds_created gauge
request_processing_seconds_created1.5851566329768722e+09
# HELP request_count_total Total request count of the host
# TYPE request_count_total counter
request_count_total0.0
# TYPE request_count_created gauge
request_count_created1.5851566329769313e+09
当访问 10.0.0.101:8001/metrics 时,每刷新一次 10.0.0.101:8000/metrics的request_cont_toal值就会增加1
#如果希望持续性的进行接口访问的话,我们可以编写一个脚本来实现:
# cat curl_metrics.sh
#!/bin/bash
# 获取随机数
whiletrue;do
sleep_num=$(($RANDOM%3+1))
curl_num=$(($RANDOM%50+1))
for c_num in`seq $curl_num`
do
curl-s http://10.0.0.101:8001/metrics >>/dev/null 2>&1
done
sleep$sleep_num
done
4.4.2.3 Prometheus 集成
修改prometheus配置, 增加job任务
]# vim /usr/local/prometheus/conf/prometheus.yml
...
- job_name: 'my_metric'
static_configs:
- targets:
-"10.0.0.101:8000"
-"10.0.0.102:8000"
labels: {app: "flask_web"}
#属性解析:我们增加了一个自定义的metric的job目标
#检查语法
]#promtool check config /usr/local/prometheus/conf/prometheus.yml
#重启prometheus服务
]# systemctl restart prometheus.service
浏览器访问prometheus的target界面

进入到graph界面查看数据效果
request_count_total


结果显示:在prometheus上面可以看到正常的数据收集
4.4.3 定制 Exporter 实战案例: Golang 实现
基于Golang实现
#先安装go环境
略
#利用SDK实现
#cat main.go
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// Serve the default Prometheus metrics registry over HTTP on /metrics.
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":9527", nil)
}
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go mod init
go run main.go
go build -o exporter_demo
./exporter_demo
curl http://127.0.0.1:9527/metrics
# HELP go_gc_cycles_automatic_gc_cycles_total Count of completed GC cycles
generated by the Go runtime.
# TYPE go_gc_cycles_automatic_gc_cycles_total counter
go_gc_cycles_automatic_gc_cycles_total 0
# HELP go_gc_cycles_forced_gc_cycles_total Count of completed GC cycles forced by
the application.
# TYPE go_gc_cycles_forced_gc_cycles_total counter
go_gc_cycles_forced_gc_cycles_total 0
# HELP go_gc_cycles_total_gc_cycles_total Count of all completed GC cycles.
# TYPE go_gc_cycles_total_gc_cycles_total counter
go_gc_cycles_total_gc_cycles_total 0
# HELP go_gc_duration_seconds A summary of the pause duration of garbage
collection cycles.
5 Grafana 展示
5.1 Grafana 基础
功能简介
Grafana是一个可视化的集成套件,可以借助于现成的dashboard模板进行通用的界面展示,但是对于一些特殊的监控项的展示来说,我们还是需要实现独有的界面展示,而这就需要借助于Grafana的图形类型来实现特定的展示效果,对于绘图时候用到的可视化功能主要有两种方式:默认可视化方式和可视化插件
默认可视化方式
默认的可视化方式,我们可以点击左侧边栏的"+",然后选择"Dashboard",再选择"Choose virtualization"就可以看到默认的可视化样式,效果如下:

可视化插件
对于可视化插件来说,我们就需要借助于grafana-cli plugins命令从https://grafana.com/plugins/页面下载我们想要的可视化插件,每种插件中都集成了一些特定的可视化样式,我们可以点击左侧变量的"齿轮",点击"Plugins",就可以看到我们所安装的插件样式集,效果如下

注意:通过插件来操作graph的方式本质上就是通过可视化样式来进行操作。
图形展示
接下来我们通过现有的模板页面来学习一下Grafana中图形的展示方式以及制作流程。点击我们之前加载好的prometheus的模板页面,效果如下

可以看到,这张图里面有各种信息展示的界面,在概览信息展示区,除了一些基本信息的展示外,在首行的右
上角区域还有图形展示数据的时间选择区域范围,因为我们曾经说过prometheus是基于时间序列的数据就那
些监控的,所以时间维度的选择,对图形的展示限制非常大。
以折线图为例,当把鼠标放在图形的标题位置,就会出现一个"△",然后点击该三角就会出现图形的操作信息,效果如下

操作属性:
View #当前Graph的综合展示
Edit #Graph的属性编辑
Share #表示当前Graph对外分享时候的一些配置属性
explore #类似于view,综合展示更详细的信息
More #这部分包含了对当前图形的一些扩展信息,比如切割、复制、json数据展示、数据导出、触发器
点击View或者键盘输入缩写"x",进入到图形综合展示界面,效果如下

点击Explore或者键盘输入缩写"v",进入到图形详情展示界面

点击Edit或者键盘输入缩写"e",进入到图形编辑界面

配置解析
在Edit的界面最下面有该图形的配置方式,左侧有四个图标,分别表示:
Query #图形中展示的具体数据的查询表达式,每类数据一个查询语句
Virtualization #图形的可视化样式配置
General #可选配置
Alert #触发器、告警配置
数据查询语句界面

图形可视化配置属性

图形可选信息配置

关于Alert的告警和触发器配置,我们后续讲到告警配置的时候再说
实践流程
如果要制作一个Graph,需要按照如下步骤进行操作:
-
了解业务,分析指标
-
创建 Dashboard
-
创建 Graph
-
完善 Graph
-
其他信息,比如告警等
5.2 绘图案例
5.2.1 案例说明
在上一节,我们通过自定义的metric的方式,做好了一个监控项,那么接下来我们就需要完成以下绘图要求
-
绘制每分钟请求数量的曲线 QPS
-
绘制每分钟请求量变化率曲线
-
绘制每分钟请求处理平均耗时
需求分析如下
#上面的三个需求基本上都是曲线图,所以我们在Graph中选择折线图就可以了,而在绘图的时候,第一步需要
做的就是获取数据,所以我们现在需要做的就是在prometheus上,将这三个需求的PromQL写出来,效果如下
#绘制每分钟请求数量的曲线 QPS
increase(request_count_total{job="my_metric"}[1m])
increase(request_count_total{instance="10.0.0.101:8000",job="my_metric"}[1m])
#绘制每分钟请求量变化率曲线
irate(request_count_total{job="my_metric"}[1m])
irate(request_count_total{instance="10.0.0.101:8000",job="my_metric"}[1m])
#绘制每分钟请求处理平均耗时
request_processing_seconds_sum{job="my_metric"} /
request_processing_seconds_count{job="my_metric"}
request_processing_seconds_sum{instance="10.0.0.101:8000",job="my_metric"} /
request_processing_seconds_count{instance="10.0.0.101:8000",job="my_metric"}
在10.0.0.106上也运行python程序,实现自定义的metrics功能
5.2.2 绘图实现
创建图形
点击graph右侧的"+",点击"Dashboard",选择"Query",就可以进入到图形制作的界面,效果如下

设置语句 : 首选选择数据源,选择我们之前定制的"prometheus",效果如下

接下来开始配置查询语句,按照我们之前定制好的PromQL,然后复制到Metrics右侧的输入框中,配置好图例名称,然后点击右侧的"小眼睛",就可以看具体的效果,我们以"绘制每分钟请求数量的曲线 QPS"为例,效果如下,

#注意:
如果不写Legend的话,图例的名称是metrics的语句,我们这里的图例名称是"
{{instance}}_request_count"
如果想要instance变量生效的话,需要点击右侧的 Instant ,让该变量生效
设置图形
点击左侧的"virtualization",进入到图形化配置界面,在第一部分是对图的总体配置

结果显示:默认情况下,图形是折线图
第二部分是对坐标进行控制,这部分没有什么太重要的配置,无非就是显示不显示,样式等

#注意:X-Axis的Mode部分可以根据下拉项对x轴的图形样式进行配置,默认是基于时间进行排序
第三部分是对图形的图例进行设置

可选项配置
点击左侧的"General",进入到可选性配置界面

这个时候就完成了第一个图形的设置,点击右上角的"保存",然后进行一些配置,效果如下

点击"Save",查看最终效果

点击当前dashboard的顶格中间"add panel",就会在当前dashboard上增加可视化图形,接下来我们按照同样的方法,将其它两个图形也做出来,最终效果如下:

当将鼠标放到图形的位置时候,右下角会出现小三角,拖动它可以调整图形的大小,鼠标点击标题位置,就可以拖动图形的位置。
第一张图配置


第二张图配置

第三张图配置

第四张图配置
.jpg)
最终结果如下


6 告警通知
6.1 记录规则
6.1.1 规则简介
Prometheus 支持两种类型的规则:
记录规则警报规则
它们可以进行配置,然后定期进行评估。 要将规则包含在Prometheus中,需要先创建一个包含必要规则语句的文件,并让Prometheus通过Prometheus配置中的rule_fies字段加载该文件。 默认情况下, prometheus的规则文件使用YAML格式
规则的使用流程是:首先创建一个满足规则标准的规则语句,然后发送SIGHUP给Prometheus进程,这时候,prometheus在运行时重新加载规则文件,从而让规则在prometheus运行环境中生效。
可以借助于安装prometheus软件时候的promtool命令文件来进行规则语句的检测,检测方式如下:
#promtool check rules prometheus_rues_fie.yml
#说明:
当该文件在语法上有效时,检查器将已解析规则的文本表示形式打印到标准输出,然后以0返回状态退出。
如果有任何语法错误或无效的输入参数,它将打印一条错误消息为标准错误,并以1返回状态退出。
可以在prometheus.yaml配置文件中通过rule_fies属性进行导入即可,格式如下
rule_files:
-
"first_rules.yml" - "second_rules.yml" -
“../rules/*.yml” -
# 相对路径是相对于 prometheus.yml 配置文件的路径
6.1.2 记录规则说明
记录规则的作用其实将之前的监控命令采用配置文件的方式进行编写,从而大大减轻工作量。
最常用的场景是,我们将预先计算经常需要或计算量大的复杂的PromQL语句指定为一个独立的metric 监控项,这样我们在查询的时候就非常方便,而且查询预计算结果通常比每次需要原始表达式都要快得多,尤其是对于仪表板特别有用,仪表板每次刷新时都需要重复查询相同的表达式。总体来说,记录规则效果与shell中的别名相似
#规则文件的语法为:
groups:
[ - <rule_group> ]
一个简单的规则文件样式如下:
groups:
- name: example
interval: 10s
rules:
- record: job:http_inprogress_requests:sum
expr: sum(http_inprogress_requests) by (job)
labels:
[ <labelname>: <labelvalue> ]
属性解析:
name #规则组名,必须是唯一的
interval #定制规则执行的间隔时间
rules #设定规则具体信息
record #定制指标的名称
expr #执行成功的PromQL
labels #为该规则设定标签
6.1.3 记录规则案例
6.1.3.1 案例说明
在Prometheus查询部分指标时需要通过将现有的规则组合成一个复杂的表达式,才能查询到对应的指标结
果,比如在查询"自定义的指标请求处理时间",参考如下
request_processing_seconds_sum{instance="10.0.0.101:8000",job="my_metric"} /
request_processing_seconds_count{instance="10.0.0.101:8000",job="my_metric"}
这个查询语句写起来非常长,在我们graph绘图的时候,每次输入命令都是非常繁琐的,很容易出现问题。
6.1.3 2 记录规则实现
#创建规则记录文件
mkdir /usr/local/prometheus/rules
vim /usr/local/prometheus/rules/prometheus_record_rules.yml
groups:
- name: myrules
rules:
- record: "request_process_per_time"
expr: request_processing_seconds_sum{job="my_metric"} /
request_processing_seconds_count{job="my_metric"}
labels:
app: "flask"
role: "web"
- record: "request_count_per_minute"
expr: increase(request_count_total{job="my_metric"}[1m])
labels:
app: "flask"
role: "web"
#检查规则文件有效性
promtool check rules /usr/local/prometheus/rules/prometheus_record_rules.yml
Checking /usr/local/prometheus/rules/prometheus_record_rules.yml
SUCCESS: 2 rules found
#加载规则文件
#编辑配置文件
vim /usr/local/prometheus/conf/prometheus.yml
...
rule_files:
-"../rules/*.yml"#加此一行
# - "first_rules.yml"
...
#重启服务,加载配置
systemctl restart prometheus.service
#登录到prometheus的web界面,可以通过request_prcess_per_time指标查询我们想要的数据,效果如
下:

点击Status下面的Rules,查看效果

添加 Grafana图形


6.2 告警环境部署
6.2.1 告警介绍
官方文档
https://prometheus.io/docs/alerting/latest/overview/
Prometheus作为一个大数据量场景下的监控平台来说,数据收集是核心功能,虽然监控数据可视化了,也非常容易观察到运行状态。但是最能产生价值的地方就是对数据分析后的告警处理措施,因为我们很难做到时刻盯着监控并及时做出正确的决策,所以程序来帮巡检并自动告警,是保障业务稳定性的决定性措施。可以说任何一个监控平台如果没有告警平台,那么他就逊色不少甚至都不能称之为平台。
对于Prometheus平台来说,它就集成了报警功能,该功能主要是利用Alertmanager这个组件来实现功能的。Alertmanager作为一个独立的组件,负责接收并处理来自Prometheus Server(也可以是其它的客户端程序)的告警信息。Alertmanager可以对这些告警信息进行进一步的处理,比如当接收到大量重复告警时能够消除重复的告警信息,同时对告警信息进行分组并且路由到正确的通知方,Prometheus 内置了对邮件,Slack等多种通知方式的支持,同时还支持与Webhook的集成,以支持更多定制化的场景。
6.2.2 告警组件
告警能力在Prometheus的架构中被划分成两个独立的部分。
通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。
然后,Alertmanager管理这些告警,包括进行重复数据删除,分组和路由,以及告警的静默和抑制
当Alertmanager接收到 Prometheus 端发送过来的 Alerts 时,Alertmanager 会对 Alerts 进行去重复,分组,按标签内容发送不同报警组,包括:邮件,微信,Webhook。AlertManager还提供了静默和告警抑制机制来对告警通知行为进行优化。

6.2.3 告警特性
https://prometheus.io/docs/alerting/latest/alertmanager/

去重
将多个相同的告警,去掉重复的告警,只保留不同的告警
分组
分组机制可以将详细的告警信息合并成一个通知。在某些情况下,比如由于系统宕机导致大量的告警被同时触发,在这种情况下分组机制可以将这些被触发的告警合并为一个告警通知,避免一次性接受大量的告警通知,而无法对问题进行快速定位。
告警分组,告警时间,以及告警的接受方式可以通过Alertmanager的配置文件进行配置。
路由
将不同的告警定制策略路由发送至不同的目标
抑制
抑制可以避免当某种问题告警产生之后用户接收到大量由此问题导致的一系列的其它告警通知
同样通过Alertmanager的配置文件进行设置。
静默
静默提供了一个简单的机制可以快速根据标签对告警进行静默处理。如果接收到的告警符合静默的配置,Alertmanager则不会发送告警通知。
静默设置需要在Alertmanager的Web页面上进行设置。
6.2.4 邮件告警
6.2.4.1 邮箱配置
邮箱服务器开启smtp的授权码,每个邮箱开启授权码操作不同

6.2.4.2 Alertmanager 部署
官文文档
https://prometheus.io/docs/alerting/latest/configuration/
软件安装配置
#获取软件
wget
https://github.com/prometheus/alertmanager/releases/download/v0.23.0/alertmanage
r-0.23.0.linux-amd64.tar.gz
#解压软件
tar xf alertmanager-0.23.0.linux-amd64.tar.gz -C /usr/local/
ln-s /usr/local/alertmanager-0.23.0.linux-amd64 /usr/local/alertmanager
#准备工作
cd /usr/local/alertmanager
mkdir {bin,conf,data}
mv alertmanager amtool bin/
cp alertmanager.yml conf/
配置文件修改
]# cat /usr/local/alertmanager/conf/alertmanager.yml
# 全局配置
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.qq.com:25'
smtp_from: '29308620@qq.com'
smtp_auth_username: '29308620@qq.com'
smtp_auth_password: 'xxxxxxxxxxxxx'
smtp_hello: 'qq.com'
smtp_require_tls: false
# 路由配置
route:
group_by: ['alertname', 'cluster']
group_wait: 10s
group_interval: 10s
repeat_interval: 10s #此值不要过低
receiver: 'email'
# 收信人员
receivers:
- name: 'email'
email_configs:
- to: 'root@wangxiaochun.com'
send_resolved: true#问题解决后也会发送告警
# 抑制规则,如果不想用可以去掉
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
#属性解析:repeat_interval配置项,用于降低告警收敛,减少报警,发送关键报警,对于email来说,此
项不可以设置过低,否则将会由于邮件发送太多频繁,被smtp服务器拒绝
#语法检查
amtool check-config /usr/local/alertmanager/conf/alertmanager.yml
服务文件
]# cat /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=alertmanager project
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/alertmanager/bin/alertmanager --
config.file=/usr/local/alertmanager/conf/alertmanager.yml --
storage.path=/usr/local/alertmanager/data --web.listen-address=0.0.0.0:9093
ExecReload=/bin/kill -HUP$MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
#属性解析:最好配置 --web.listen-address ,因为默认的配置是:9093,有可能在启动时候报错
#启动服务
]# systemctl daemon-reload
]# systemctl enable --now alertmanager.service
]# systemctl status alertmanager.service
#端口检查
]# netstat -tnulp | egrep 'Pro|ale'
Proto Recv-Q Send-Q Local Address Foreign Address State
PID/Program name
tcp 0010.0.0.101:9093 0.0.0.0:* LISTEN
25490/alertmanager
tcp6 00 :::9094 :::* LISTEN
25490/alertmanager
udp6 00 :::9094 :::*
25490/alertmanager
#结果显示:当前主机上出现了两个端口9093(与prometheus交互端口)和9094(Alertmanager集群HA
mode使用)
可以通过访问 http://alertmanager_server:9093/ 来看 alertmanager 提供的 Web 界面


6.2.4.3 Prometheus 集成
配置修改
#修改配置文件,加载alertmanager配置属性
]# vim /usr/local/prometheus/conf/prometheus.yml
...
alerting:
alertmanagers:
- static_configs:
- targets: ["10.0.0.100:9093"]
...
#注意:alertmanager服务启动时候的监控开放主机地址必须保证正确,否则服务启动不起来
#检查语法
]# promtool check config /usr/local/prometheus/conf/prometheus.yml
#重启服务,加载配置
]# systemctl restart prometheus.service
浏览器访问prometheus的web界面查看Runtime信息,查看效果


6.3 告警规则
6.3.1 告警规则说明
警报规则可以实现基于Prometheus表达式语言定义警报条件,并将有关触发警报的通知发送到外部服务。 只要警报表达式在给定的时间点生成一个或多个动作元素,警报就被视为这些元素的标签集处于活动状态。
警报规则在Prometheus中的基本配置方式与记录规则基本一致。
规则文件示例
groups:
- name: example
rules:
- alert: HighRequestLatency
expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5
for: 10m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been
down for more than 1 minutes."
#属性解析:
alert #定制告警的动作名称
for expr #条件表达式被触发后,一直持续满足该条件长达此处的时间后才会告警
labels.severity #定义告警级别
annotations #自定义注释信息,注释信息中的变量需要从模板中或者系统中读取

在Prometheus中一条告警规则主要由以下几部分组成:
- 告警名称:用户需要为告警规则命名,当然对于命名而言,需要能够直接表达出该告警的主要内容告警规则:告警规则实际上主要由PromQL进行定义,其实际意义是当表达式(PromQL)查询结果持续多长时间(During)后出发告警
在Prometheus中,还可以通过Group(告警组)对一组相关的告警进行统一定义。这些定义都是通过 YAML文件来统一管理的。
6.3.2 告警规则案例: 邮件告警
6.3.2.1 案例说明
编写一个检查自定义metrics的接口的告警规则,在prometheus中我们可以借助于up指标来获取对应的状态效果,查询语句如下:
up{job="my_metric"}
#注意:如果结果是1表示服务正常,否则表示该接口的服务出现了问题。

6.3.2.2 配置告警规则
编写规则定义文件
#确认包含rules目录中的yml文件
cat /usr/local/prometheus/conf/prometheus.yml
rule_files:
-"../rules/*.yml"
#准备rule文件
vim /usr/local/prometheus/rules/prometheus_alert_rules.yml
groups:
- name: flask_web
rules:
- alert: InstanceDown
expr: up{job="my_metric"} ==0
for: 1m
labels:
severity: 1
annotations:
summary: "Instance {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }} job {{ $labels.job }} 已经停止1分钟以
上"
#属性解析:
{{ $labels.<labelname> }} 要插入触发元素的标签值
{{ $value }} 要插入触发元素的数值表达式值
这里的$name都是来源于模板文件中的定制内容,如果不需要定制的变动信息,可以直接写普通的字符串
#检查效果
promtool check rules prometheus_alert_rules.yml
Checking prometheus_alert_rules.yml
SUCCESS: 2 rules found
#重启prometheus服务
systemctl reload prometheus.service
浏览器查看prometheus的rules的页面查看效果

查看告警界面效果

告警状态
Inactive:正常效果
Pending:已触发阈值,但未满足告警持续时间(即rule中的for字段) Firing:已触发阈值且满足告警持续时间。
6.3.2.3 验证结果
停止自定义的flask服务,稍等1分钟后,查看告警效果。

等待时间超过for持续的标准后,就会改变告警的状态,效果如下

查看alertmanager的web效果

邮件告警效果

6.4 告警模板
6.4.1 告警模板说明
默认的告警信息界面有些简单,可以借助于告警的模板信息,对告警信息进行丰富。需要借助于 alertmanager的模板功能来实现。
使用流程:
分析关键信息
-
定制模板内容
-
alertmanager 加载模板文件
-
告警信息使用模板内容属性
6.4.2. 定制模板案例
6.4.2.1 定制模板
模板文件使用标准的Go语法,并暴露一些包含时间标签和值的变量
标签引用: {{ $label.<label_name> }}
指标样本值引用: {{ $value }}
为了显示效果,需要了解html相关技术,参考链接
https://www.w3school.com.cn/html/html_tables.asp
范例:
#建立邮件模板文件
mkdir /usr/local/alertmanager/tmpl
vim /usr/local/alertmanager/tmpl/email.tmpl
#基于jin2的模板内容
{{ define "test.html" }}
<table border="1">
<tr>
<th>报警项</th>
<th>实例</th>
<th>报警阀值</th>
<th>开始时间</th>
</tr>
{{ range $i, $alert := .Alerts }}
<tr>
<td>{{ index $alert.Labels "alertname" }}</td>
<td>{{ index $alert.Labels "instance" }}</td>
<td>{{ index $alert.Annotations "value" }}</td>
<td>{{ $alert.StartsAt }}</td>
</tr>
{{ end }}
</table>
{{ end }}
#属性解析
{{ define "test.html" }} 表示定义了一个 test.html 模板文件,通过该名称在配置文件中应用
上边模板文件就是使用了大量的jinja2模板语言。
$alert.xxx 其实是从默认的告警信息中提取出来的重要信息
6.4.2.2 应用模板
#更改配置文件
]# vim /usr/local/alertmanager/conf/alertmanager.yml
global:
...
templates:
-'../tmpl/*.tmpl'
route:
...
# 收信人员
receivers:
- name: 'email'
email_configs:
- to: 'root@wangxiaochun.com'
send_resolved: true
headers: { Subject: "[WARN] 报警邮件"} #添加此行,定制邮件标题
html: '{{ template "test.html" . }}'#添加此行,调用模板显示邮件正文
...
#属性解析:
{{}} 属性用于加载其它信息,所以应该使用单引号括住
{} 不需要使用单引号,否则服务启动不成功
#重启服务
]# systemctl restart alertmanager.service
6.4.2.3 更改规则
上面我们定制的邮件内容中包含阈值的部分,而我们在规则中并没有指定,所以需要修改一下规则文件,效果如下
]# vim /usr/local/prometheus/rules/prometheus_alert_tmpl.yml
groups:
- name: flask_web
rules:
- alert: InstanceDown
expr: up{job="my_metric"} ==0
for: 1m
labels:
severity: 1
annotations:
summary: "Instance {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }} job {{ $labels.job }} 已经停止1分钟以
上"
value: "{{$value}}"#只加此一行
#属性解析:这里在注释部分增加了一个value的属性信息,会从prometheus的默认信息中获取阈值
#annotations这部分内容不再显示邮件中,而按模板形式显示
#语法检查
promtool check rules /usr/local/prometheus/rules/prometheus_alert_tmpl.yml
promtool check config /usr/local/prometheus/conf/prometheus.yml
6.4.2.4 测试结果
关停flask服务

查看邮件效果

6.5 告警路由
6.5.1 告警路由说明
Alertmanager的route配置段支持定义“树”状路由表,入口位置称为根节点,每个子节点可以基于匹配条件定义出一个独立的路由分支
-
所有告警都将进入路由根节点,而后进行子节点遍历
-
若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止;否则,将继续匹配后续的子节点

上图所示:Alertmanager中的第一个Route是根节点,每一个match 都是子节点。 比如,我们之前定义的告警策略中,只有一个route,这意味着所有由Prometheus产生的告警在发送到 Alertmanager之后都会通过名为email的receiver接收。
# 路由示例
route:
group_by: ['alertname', 'cluster']
group_wait: 10s
group_interval: 10s
repeat_interval: 10s
receiver: 'email'
配置参数
# 默认信息的接收者,这一项是必须选项,否则程序启动不成功
[ receiver: <string> ]
# 分组时使用的标签,默认情况下,所有的告警都组织在一起,而一旦指定分组标签,则Alertmanager将按
这些标签进行分组;
[ group_by: '[' <labelname>, ... ']' ]
# 在匹配成功的前提下,是否继续进行深层次的告警规则匹配.
[ continue: <boolean> | default =false ]
# 基于字符串验证,判断当前告警中是否存在标签labelname并且其值等于label value,满足则进行内部
的后续处理。
match:
[ <labelname>: <labelvalue>, ... ]
# 基于正则表达式验证,判断当前告警标签的值是否满足正则表达式的内容,满足则进行内部的后续处理。
match_re:
[ <labelname>: <regex>, ... ]
# 发出一组告警通知的初始等待时长;允许等待一个抑制告警到达或收集属于同一组的更多初始告警,通常是
0到数分钟;
[ group_wait: <duration> | default = 30s ]
# 发送关于新告警的消息之前,需要等待多久;新告警将被添加到已经发送了初始通知的告警组中;一般在 5 分钟或以上; [ group_interval: <duration> | default = 5m ]
# 成功发送了告警后再次发送告警信息需要等待的时长,一般至少为3个小时;
[ repeat_interval: <duration> | default = 4h ]
# 子路由配置
routes:
[ - <route> ... ]
#注意:每一个告警都会从配置文件中顶级的route进入路由树,需要注意的是顶级的route必须匹配所有告
警, 不能有 match 和 match_re
配置示例
1)
#在prometheus上定制告警规则
groups:
- name: example
...
- name: nodes_alerts
rules:
- alert: DiskWillFillIn12Hours
expr: predict_linear(node_filesystem_free_bytes{mountpoint="/"}[1h],
12*3600)
for: 1m
labels:
severity: critital
annotations:
discription: Disk on {{ $label.instance }} will fill in approximately 12
hours.
- name: prometheus_alerts
rules:
- alert: PrometheusConfigReloadFailed
expr: prometheus_config_last_reload_successful ==0
for: 3m
labels:
serverity: warning
annotations:
description: Reloading Prometheus configuration has failed on {{
$labels.instance }}.
2)
#在 alertmanager 定制路由
global:
...
templates:
...
route:
group_by: ['instance']
...
receiver: email-receiver
routes:
- match:
severity: critical
reciver: leader-team
- match_re:
severity: ^(warning)$
receiver: ops-team
receivers:
- name: 'leader-team'
email_configs:
- to: '29308620@qq.com', 'admin@126.com'
- name: 'ops-team'
email_configs:
- to: 'root@wangxiaochun.com', 'li@163.com'
6.5.2 告警路由案例
对于我们定制的metric来说
如果是每分钟的QPS超过 500 的时候,将告警发给运维团队
如果是服务终止的话,发给管理团队
6.5.2.1 定制告警规则
#准备prometheus配置文件
grep-Ev'^$|^ *#' /usr/local/prometheus/conf/prometheus.yml
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is
every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is
every 1 minute.
alerting:
alertmanagers:
- static_configs:
- targets:
-10.0.0.100:9093 #指定alertmaanager地址
rule_files:
-"../rules/*.yml"#指定规则文件路径
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: 'node_exporter'
static_configs:
- targets: ['10.0.0.101:9100','10.0.0.102:9100','10.0.0.103:9100']
labels: {app: 'k8s-node'}
- job_name: 'my_metric'
static_configs:
- targets: ['10.0.0.101:8000']
labels: {app: 'flask_web'}
#配置告警规则
vim /usr/local/prometheus/rules/prometheus_alert_route.yml
groups:
- name: flask_web
rules:
- alert: InstanceDown
expr: up{job="my_metric"} ==0
for: 1m
labels:
severity: critical
annotations:
summary: "Instance {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }} job {{ $labels.job }} 已经停止1分钟以
上"
value: "{{$value}}"
- name: flask_QPS
rules:
- alert: InstanceQPSIsHight
expr: increase(request_count_total{job="my_metric"}[1m]) > 500
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} QPS 持续过高"
description: "{{ $labels.instance }} job {{ $labels.job }} QPS 持续过高"
value: "{{$value}}"
#指定flask_web规则的labels为 severity: critical
#指定flask_QPS规则的labels为 severity: warning
#重启prometheus服务
systemctl restart prometheus.service
#查看prometheus上的路由规则效果

6.5.2.2 定制路由分组
#指定路由分组
vim /usr/local/alertmanager/conf/alertmanager.yml
# 全局配置
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.qq.com:25'
smtp_from: '29308620@qq.com'
smtp_auth_username: '29308620@qq.com'
smtp_auth_password: 'efxqzcnxhqaebieb'
smtp_hello: 'qq.com'
smtp_require_tls: false
# 模板配置
templates:
-'../tmpl/*.tmpl'
# 路由配置
route:
group_by: ['instance', 'cluster']
group_wait: 10s
group_interval: 10s
repeat_interval: 10s
receiver: 'email'
routes:
- match:
severity: critical
receiver: 'leader-team'
- match_re:
severity: ^(warning)$
receiver: 'ops-team'
# 收信人员
receivers:
- name: 'email'
email_configs:
- to: 'root@wangxiaochun.com'
send_resolved: true
html: '{{ template "test.html" . }}'
headers: { Subject: "[WARN] 报警邮件"}
- name: 'leader-team'
email_configs:
- to: 'root@wangxiaochun.com'
html: '{{ template "test.html" . }}'
headers: { Subject: "[CRITICAL] 应用服务报警邮件"}
send_resolved: true
- name: 'ops-team'
email_configs:
- to: 'root@wangxiaochun.com'
html: '{{ template "test.html" . }}'
headers: { Subject: "[WARNNING] QPS负载报警邮件"}
send_resolved: true
#检查语法
amtool check-config /usr/local/alertmanager/conf/alertmanager.yml
#定义邮件模板文件
vim /usr/local/alertmanager/tmpl/email.tmpl
{{ define "test.html" }}
<table border="1">
<tr>
<th>报警项</th>
<th>实例</th>
<th>报警阀值</th>
<th>开始时间</th>
</tr>
{{ range $i, $alert := .Alerts }}
<tr>
<td>{{ index $alert.Labels "alertname" }}</td>
<td>{{ index $alert.Labels "instance" }}</td>
<td>{{ index $alert.Annotations "value" }}</td>
<td>{{ $alert.StartsAt }}</td>
</tr>
{{ end }}
</table>
{{ end }}
#服务生效
systemctl reload alertmanager.service
#查看prometheus上的alert的效果

6.5.2.3 测试效果
执行curl metric的脚本文件,调整循环访问的次数,让访问数量高于500。
查看prometheus告警效果和邮件效果

关闭python的web服务,查看prometheus告警效果和邮件效果

#更改告警规则的标签信息
vim /usr/local/prometheus/rules/prometheus_alert_route.yml
groups:
- name: flask_web
rules:
- alert: InstanceDown
...
labels:
severity: criticaL # 将符合要求的 critical改为criticaL,导致告警无法匹配admin-
team
#重启服务
#systemctl restart prometheus.service
#查看prometheus 默认的告警效果和邮件效果
#结果显示:将 severity的标签改为 crititaL 导致所有的子路由没有匹配,则默认的route生效

6.6 告警抑制
6.6.1 告警抑制说明
对于一种业务场景,有相互依赖的两种服务:A服务和B服务,一旦A服务异常,依赖A服务的B服务也会异常,从而导致本来没有问题的B服务也不断的发出告警。

Alertmanager的抑制机制可以避免当某种问题告警产生之后用户接收到大量由此问题导致的一系列的其它告警通知。例如当集群不可用时,用户可能只希望接收到一条告警,告知用户这时候集群出现了问题,而不是大量的如集群中的应用异常、中间件服务异常的告警通知。
当已经发送的告警通知匹配到target_match和target_match_re规则,当有新的告警规则如果满足 source_match或者定义的匹配规则,并且已发送的告警与新产生的告警中equal定义的标签完全相同, 则启动抑制机制,新的告警不会发送。
通过上面的配置,可以在alertname/operations/instance相同的情况下,high的报警会抑制warning级别的报警信息。
抑制是当出现其它告警的时候压制当前告警的通知,可以有效的防止告警风暴。 比如当机房出现网络故障时,所有服务都将不可用而产生大量服务不可用告警,但这些警告并不能反映真实问题在哪,真正需要发出的应该是网络故障告警。当出现网络故障告警的时候,应当抑制服务不可用告警的通知。
配置解析
#源告警信息匹配 -- 报警的来源
source_match:
[ <labelname>: <labelvalue>, ... ]
source_match_re:
[ <labelname>: <regex>, ... ]
#目标告警信息匹配 - 触发的其他告警
target_match:
[ <labelname>: <labelvalue>, ... ]
target_match_re:
[ <labelname>: <regex>, ... ]
#目标告警是否是被触发的 - 要保证业务是同一处来源
[ equal: '[' <labelname>, ... ']' ]
-同时告警目标上的标签与之前的告警标签一样,那么就不再告警
配置示例
#例如:
集群中的A主机节点异常导致NodeDown告警被触发,该告警会触发一个severity=critical的告警级别。
由于A主机异常导致该主机上相关的服务,会因为不可用而触发关联告警。
根据抑制规则的定义:
如果有新的告警级别为severity=critical,且告警中标签的node值与NodeDown告警的相同
则说明新的告警是由NodeDown导致的,则启动抑制机制,从而停止向接收器发送通知。
inhibit_rules: # 抑制规则
- source_match: # 源标签警报触发时会抑制含有目标标签的警报
alertname: NodeDown # 可以针对某一个特定的告警动作规则
severity: critical # 限定源告警规则的等级
target_match: # 定制要被抑制的告警规则的所处位置
severity: normal # 触发告警目标标签值的正则匹配规则,可以是正则表达式如:
".*MySQL.*"
equal: # 因为源告警和触发告警必须处于同一业务环境下,确保他们在同一个
业务中
- instance # 源告警和触发告警存在于相同的 instance 时,触发告警才会被抑
制。
# 格式二 equal: ['alertname','operations', 'instance']
#表达式
up{node="node01.wang.org",...} ==0
severity: critical
#触发告警
ALERT{node="node01.wang.org",...,severity=critical}
6.6.2 告警抑制案例
6.6.2.1 案例说明
对于当前的flask应用的监控来说,上面做了两个监控指标:
告警级别为 critical 的服务异常终止
告警级别为 warning 的 QPS访问量突然降低为0,这里以服务状态来模拟
当python服务异常终止的时候,不要触发同节点上的 QPS 过低告警动作。
6.6.2.2 告警规则
#准备告警规则
vim /usr/local/prometheus/rules/prometheus_alert_inhibit.yml
groups:
- name: flask_web
rules:
- alert: InstanceDown
expr: up{job="my_metric"} ==0
for: 1m
labels:
severity: critical
annotations:
summary: "Instance {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }} job {{ $labels.job }} 已经停止1分钟以
上"
value: "{{$value}}"
- name: flask_QPS
rules:
- alert: InstanceQPSIsHight
expr: increase(request_count_total{job="my_metric"}[1m]) > 500
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} QPS 持续过高"
description: "{{ $labels.instance }} job {{ $labels.job }} QPS 持续过高"
value: "{{$value}}"
- alert: InstanceQPSIsLow #判断是否QPS访问为0
expr: up{job="my_metric"} ==0
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} QPS 异常为零"
description: "{{ $labels.instance }} job {{ $labels.job }} QPS 异常为0"
value: "{{$value}}"
#定制告警对象
vim /usr/local/alertmanager/conf/alertmanager.yml
# 全局配置
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.qq.com:25'
smtp_from: '29308620@qq.com'
smtp_auth_username: '29308620@qq.com'
smtp_auth_password: 'efxqzcnxhqaebieb'
smtp_hello: 'qq.com'
smtp_require_tls: false
# 模板配置
templates:
-'../tmpl/*.tmpl'
# 路由配置
route:
group_by: ['instance', 'cluster']
group_wait: 10s
group_interval: 10s
repeat_interval: 10s
receiver: 'email'
routes:
- match:
severity: critical
receiver: 'leader-team'
- match_re:
severity: ^(warning)$
receiver: 'ops-team'
# 收信人员
receivers:
- name: 'email'
email_configs:
- to: 'root@wangxiaochun.com'
send_resolved: true
html: '{{ template "test.html" . }}'
headers: { Subject: "[WARN] 报警邮件"}
- name: 'leader-team'
email_configs:
- to: 'root@wangxiaochun.com'
html: '{{ template "test.html" . }}'
headers: { Subject: "[CRITICAL] 应用服务报警邮件"}
send_resolved: true
- name: 'ops-team'
email_configs:
- to: 'root@wangxiaochun.com'
html: '{{ template "test.html" . }}'
headers: { Subject: "[WARNNING] QPS负载报警邮件"}
send_resolved: true
#重启服务
systemctl restart prometheus.service alertmanager.service
#关停flask服务后,查看效果,显示有多个重复告警

6.6.2.3 启动抑制机制
#定制抑制
vim /usr/local/alertmanager/conf/alertmanager.yml
# 全局配置
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.qq.com:25'
smtp_from: '29308620@qq.com'
smtp_auth_username: '29308620@qq.com'
smtp_auth_password: 'dgezyimkdswwbhe'
smtp_hello: 'qq.com'
smtp_require_tls: false
# 模板配置
templates:
-'../tmpl/*.tmpl'
# 路由配置
route:
group_by: ['instance', 'cluster']
group_wait: 10s
group_interval: 10s
repeat_interval: 10s
receiver: 'email'
routes:
- match:
severity: critical
receiver: 'admin-team'
- match_re:
severity: ^(warning)$
receiver: 'supper-team'
# 收信人员
receivers:
- name: 'email'
email_configs:
- to: '29308620@qq.com'
send_resolved: true
html: '{{ template "test.html" . }}'
headers: { Subject: "[WARN] 报警邮件"}
- name: 'admin-team'
email_configs:
- to: '29308620@qq.com'
html: '{{ template "test.html" . }}'
headers: { Subject: "[CRITICAL] 应用服务报警邮件"}
send_resolved: true
- name: 'supper-team'
email_configs:
- to: '29308620@qq.com'
html: '{{ template "test.html" . }}'
headers: { Subject: "[WARNNING] QPS负载报警邮件"}
send_resolved: true
# 抑制措施 #上面不变,添加下面告警抑制配置
inhibit_rules:
- source_match:
severity: critical
target_match:
severity: warning
equal:
- instance
#重启alertmanager服务
systemctl restart alertmanager.service
6.6.2.4 验证结果
#关停服务后,查看效果
#结果显示:开启告警抑制之后,因为 critical导致的warning事件就不再告警了,从而减少了告警风暴现
象。

6.7 微信告警
6.7.1 微信告警说明
微信是国人非常常见的通信工具,而且通信的效率非常的高,下面介绍微信的告警方式。
就目前来说,使用微信告警的方式主要有以下三种:
用个人号发送告警 - 一般需要借助于专属的开发工具来实现
用公众号发送告警 - 借助于软件本身的机制来实现。
用企业号发送告警 - 借助于软件本身的机制来实现。这是以下实现的方式
对于公众号发送告警。但是很多个人公众号并没有开启了相关功能,无法测试很多功能,所以我们在测试微信公众号之前,先来采用官方体用的测试接口来实现告警功能。
测试的接口地址:
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
企业微信接口
#获取认证token
https://qyapi.weixin.qq.com/cgi-bin/gettoken
#发送告警信息
https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="企业微信token"
#帮助手册:
获取认证:https://developer.work.weixin.qq.com/document/10013
发送消息:https://developer.work.weixin.qq.com/document/path/90236
实现步骤
企业微信后台配置
创建企业微信、自定义告警部门
创建企业应用认证信息
Alertmanager配置告警通知人和告警模板
Prometheus配置告警规则
6.7.2 微信告警案例
6.7.2.1 企业微信配置
6.7.2.1.1 注册企业微信
微信告警首先得注册一个企业微信,然后才能实现微信告警。
浏览器访问下面链接,注册企业微信
https://work.weixin.qq.com/
使用个人微信扫码登录后,定制自己的企业信息
注意:注册一个企业,没有任何限制,无需认证


用浏览器进入管理后台

或者安装企业微信的PC端登录


查看到企业ID的值为 ww644a0d95807e476b
6.7.2.1.2 创建部门和人员
6.7.2.1.2.1 创建部门

注意: 创建的部门的部门ID为2

6.7.2.1.2.2 部门加入人员
方法1: 直接微信邀请,让相关人员自行扫码加入

方法2 手动添加人员

6.7.2.1.3 创建微信应用

上传Logo和指定应用名称,并选择范围

注意记下以下信息:
应用的 AgentId值1000004
应用的 Secret的值qYgLlipdHtZidsd8qAZaTKKkGkzIyWxuQSeQOk9Si0M

6.7.2.1.4 测试发送微信消息
可以给加入的员工发送微信消息



员工个人微信可以收到以下信息

6.7.2.2 微信告警消息命令
官方微信教程
https://developer.work.weixin.qq.com/document/path/90487
https://work.weixin.qq.com/api/doc/90000/90003/90487
.jpg)
官方微信API参考文档
https://developer.work.weixin.qq.com/document/path/91039
https://work.weixin.qq.com/api/doc/90000/90135/91039

总结相关信息如下
查看到企业ID的值: ww644a0d95807e476b
部门ID的值: 2
应用的 AgentId的值: 1000004
应用的 Secret的值:qYgLlipdHtZidsd8qAZaTKKkGkzIyWxuQSeQOk9Si0M
6.7.2.2.1 获取 Token
#获取通信token格式:
curl-H"Content-Type: application/json"-d'{"corpid":"企业id", "corpsecret": "应
用secret"}' https://qyapi.weixin.qq.com/cgi-bin/gettoken
范例:
#示例:
[root@prometheus ~]#curl -H "Content-Type: application/json" -d
'{"corpid":"ww644a0d95807e476b", "corpsecret":
"qYgLlipdHtZidsd8qAZaTKKkGkzIyWxuQSeQOk9Si0M"}' https://qyapi.weixin.qq.com/cgi-
bin/gettoken
# 返回 token
{"errcode":0,"errmsg":"ok","access_token":"NMaWPA8xfYmcN5v8so7TdqsBwym78Vs53X5Os
Oy69-Q6Kv3GGXGU_V-8keGaArYkurIXrKMJGrdFbhYy-QqmKsr5x61-wv6yXZy0kiooXE-
QfbDoNRumBSjiJg0AqkEOeBqaT1dc8_DryE-RGVD39J4Iu61TU3HWsyZVkGuRTU6ejM-
qauflSOuy5cbDSONNXi9zUPwUmlg4XkAobrLgOw","expires_in":7200}
6.7.2.2.2 命令发送测试信息
#发送信息信息要求Json格式如下:
Data = {
"toparty": 部门id,
"msgtype": "text",
"agentid": Agentid,
"text": {"content": "消息内容主题"},
"safe": "0"
}
#格式:
curl-H"Content-Type: application/json"-d'{"toparty": "部门id",
"msgtype":"text","agentid": "agentid", "text":{"content":"告警内容"}, "safe": "安全
级别"}' https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="企业微信
token"
范例:
# 利用上面的 token 发送信息 , 注意 :token 有时间期限
[root@prometheus ~]#curl -H "Content-Type: application/json" -d '{"toparty":
"2", "msgtype":"text","agentid": "1000004", "text":{"content":"PromAlert -
prometheus 告警测试"}, "safe": "0"}' https://qyapi.weixin.qq.com/cgi-
bin/message/send?access_token="NMaWPA8xfYmcN5v8so7TdqsBwym78Vs53X5OsOy69-
Q6Kv3GGXGU_V-8keGaArYkurIXrKMJGrdFbhYy-QqmKsr5x61-wv6yXZy0kiooXE-
QfbDoNRumBSjiJg0AqkEOeBqaT1dc8_DryE-RGVD39J4Iu61TU3HWsyZVkGuRTU6ejM-
qauflSOuy5cbDSONNXi9zUPwUmlg4XkAobrLgOw"
# 返回成功提示
{"errcode":0,"errmsg":"ok","msgid":"WpLDpQFMGSE843kRbNhgXZcjYGgCPvKRM-
uwZsq6dxIpvGVtDq3CVY9BHuCX6fJZxQe0cQ_XbSpKMYUyJtLCgg"}
手机微信收到下面信息

6.7.2.2.3 发送微信告警脚本
发送微信可以使用各种语言,下面使用shell脚本实现
cat wechat.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#FileName: wechat.sh
#URL: http://www.wangxiaochun.com
#Description: Send message from wechat for prometheus monitor
#Copyright (C): 2020 All rights reserved
#********************************************************************
CorpID="ww644a0d95807e476b"
Secret="qYgLlipdHtZidsd8qAZaTKKkGkzIyWxuQSeQOk9Si0M"
agentid=1000004#改为 AgentId 在创建的应用那里看
PartyID=2#通讯录中的部门ID
GURL="https://qyapi.weixin.qq.com/cgi-bin/gettoken?
corpid=$CorpID&corpsecret=$Secret"
Token=$(curl -s -G $GURL |awk -F\": '{print $4}'|awk -F\" '{print $2}')
#echo $Token
PURL="https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$Token"
function body(){
local userid=$1#发送的用户位于$1的字符串
local partyid=$PartyID
local msg=$(echo "$@" | cut -d" " -f2-)
printf '{\n'
printf '\t"touser": "'"$userid"\"",\n"
printf '\t"toparty": "'"$PartyID"\"",\n"
printf '\t"msgtype": "text",\n'
printf '\t"agentid": "'"$agentid"\"",\n"
printf '\t"text": {\n'
printf '\t\t"content": "'"$msg"\""\n"
printf '\t},\n'
printf '\t"safe":"0"\n'
printf '}\n'
}
curl--data-ascii"$(body $*)"$PURL
#添加执行权限
chmod+x wechat.sh
#发送测试微信,其中wangxiaochun为企业微信的帐号,并且不区分大小写
./wechat.sh wangxiaochun 微信告警测试标题微信告警测试信息内容
{"errcode":0,"errmsg":"ok","msgid":"TGvhsTpDOJtMR4-
VhJqudSvxsnPPPXmSuXbb2iXiXw9Hk43lbS1TQ19-MDvEMZmCE02GJL9zRlG49u-hQHaXJg"}
在手机企业微信APP中可以收到下面提示

6.7.2.3 Alertmanager 配置
6.7.2.3.1 定制告警的配置信息
cat /usr/local/alertmanager/conf/alertmanager.yml
# 全局配置
global:
resolve_timeout: 5m
#邮件信息
smtp_smarthost: 'smtp.qq.com:25'
smtp_from: '29308620@qq.com'
smtp_auth_username: '29308620@qq.com'
smtp_auth_password: 'dgezyimkdswwbhea'
smtp_hello: 'qq.com'
smtp_require_tls: false
#微信信息
wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
wechat_api_corp_id: 'ww644a0d95807e476b'
wechat_api_secret: 'qYgLlipdHtZidsd8qAZaTKKkGkzIyWxuQSeQOk9Si0M'
# 模板配置
templates:
-'../tmpl/*.tmpl'
# 路由配置,分级告警,critical级才发微信告警,一般只发邮件告警
route:
group_by: ['instance', 'cluster']
group_wait: 10s
group_interval: 10s
repeat_interval: 10s
receiver: 'email'
routes:
- match:
severity: critical
receiver: 'wechat'
# 收信人员
receivers:
- name: 'email'
email_configs:
- to: 'root@wangxiaochun.com'
send_resolved: true
html: '{{ template "test.html" . }}'
headers: { Subject: "[WARN] 报警邮件"}
- name: 'wechat'
wechat_configs:
- send_resolved: true
message: '{{ template "wechat.default.message" . }}'
to_party: '2'
agent_id: '1000004'
api_secret: 'qYgLlipdHtZidsd8qAZaTKKkGkzIyWxuQSeQOk9Si0M'
#上面的配置,关键的信息必须准确,否则无法实现告警
group_wait 初次发送告警延时
group_interval 距离第一次发送告警,等待多久再次发送告警
repeat_interval 告警重发时间
6.7.2.3.2 定制告警的模板配置信息
# vim /usr/local/alertmanager/tmpl/wechat.tmpl
{{ define "wechat.default.message" }}
{{- if gt (len .Alerts.Firing) 0-}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index0 }}
=========监控报警=========
告警状态:{{ .Status }}
告警级别:{{ .Labels.severity }}
告警类型:{{ $alert.Labels.alertname }}
故障主机: {{ $alert.Labels.instance }}
告警主题: {{ $alert.Annotations.summary }}
告警详情: {{ $alert.Annotations.message }}{{ $alert.Annotations.description}};
触发阀值:{{ .Annotations.value }}
故障时间: {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} #注意:
此为golang的时间Format,表示1234567
========== end ==========
{{- end }}
{{- end }}
{{- end }}
{{- if gt (len .Alerts.Resolved) 0-}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index0 }}
=========异常恢复=========
告警类型:{{ .Labels.alertname }}
告警状态:{{ .Status }}
告警主题: {{ $alert.Annotations.summary }}
告警详情: {{ $alert.Annotations.message }}{{ $alert.Annotations.description}};
故障时间: {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
恢复时间: {{ ($alert.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
{{- if gt (len $alert.Labels.instance) 0 }}
实例信息: {{ $alert.Labels.instance }}
{{- end }}
========== end ==========
{{- end }}
{{- end }}
{{- end }}
{{- end }}
#重启alertmanager服务
systemctl restart alertmanager
systemctl status alertmanager
#检查效果
ss -tnulp | grep alert
udp UNCONN 00 *:9094 *:*
users:(("alertmanager",pid=31732,fd=7))
tcp LISTEN 04096 *:9093 *:*
users:(("alertmanager",pid=31732,fd=8))
tcp LISTEN 04096 *:9094 *:*
users:(("alertmanager",pid=31732,fd=3))
6.7.2.4 Prometheus 集成配置
6.7.2.4.1 定制告警规则
#创建告警规则文件
vim /usr/local/prometheus/rules/prometheus_alert_route.yml
groups:
- name: flask_web
rules:
- alert: InstanceDown
expr: up{job="my_metric"} ==0
for: 10s
labels:
severity: critical #指定告警级别
annotations:
summary: "Instance {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }} job {{ $labels.job }} 已经停止1分钟以
上"
value: "{{$value}}"
- name: flask_QPS
rules:
- alert: InstanceQPSIsHight
expr: increase(request_count_total{job="my_metric"}[1m]) > 500
for: 10s
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} QPS 持续过高"
description: "{{ $labels.instance }} job {{ $labels.job }} QPS 持续过高"
value: "{{$value}}"
6.7.2.4.2 修改 Prometheus 配置文件
#在prometheus里面,配置告警规则文件生效
grep-Ev'^.*#|^$' /usr/local/prometheus/conf/prometheus.yml
global:
alerting:
alertmanagers:
- static_configs:
- targets:
-10.0.0.100:9093
rule_files:
-"../rules/*.yml"
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: 'node_exporter'
static_configs:
- targets: ['10.0.0.104:9100','10.0.0.105:9100','10.0.0.106:9100']
labels: {app: 'k8s-node'}
- job_name: 'my_metric'
static_configs:
- targets: ['10.0.0.101:8000']
labels: {app: 'flask_web'}
#重启服务
systemctl restart prometheus
systemctl status prometheus
#检查效果
ss -tnulp | grep prometheus
tcp LISTEN 04096 *:9090 *:*
users:(("prometheus",pid=57535,fd=8))
6.7.2.5 验证结果
6.7.2.5.1 停止和恢复 flask_web服务

查看prometheus的告警动作


查看企业微信的告警信息

恢复 flask_web服务,可以看到微信信息如下


6.7.2.5.2 高并发访问只触发邮件告警
#运行下面脚本触发高并发访问
cat curl_metrics.sh
#!/bin/bash
URL=http://127.0.0.1:8001/metrics
whiletrue;do
curl_num=$(($RANDOM%50+1))
sleep_num=$(($RANDOM%5+1))
for c_num in`seq $curl_num`;do
curl-s$URL &> /dev/null
done
#sleep $sleep_num
done
bash curl_metrics.sh

6.8 钉钉告警
Prometheus 不直接支持钉钉告警, 但对于prometheus来说,它所支持的告警机制非常多,尤其是通过 webhook,从而可以实现市面上大部分的实时动态的告警平台。
Alertmanager 的 webhook 集成了钉钉报警,钉钉机器人对文件格式有严格要求,所以必须通过特定的格式转换,才能发送给你钉钉的机器人。
在这里使用开源工具 prometheus-webhook-dingtalk 来进行prometheus和dingtalk的环境集成。 Github链接
https://github.com/timonwong/prometheus-webhook-dingtalk
工作原理

群机器人是钉钉群的高级扩展功能,通过选择机器人,并对通知群进行设置,就可以自动将机器人消息自动推送到钉钉群中,特别的高级智能化,由于机器人是将消息推送到群,需要预先建立好一个群实现
为了完成钉钉的告警实践,遵循以下的步骤
- 配置pc端钉钉机器人
测试钉钉环境
6.8.1 钉钉环境
6.8.1.1 安装钉钉和创建企业
因为手机端无法进行添加机器人的相关操作,所以需要提前在电脑上下载安装钉钉的pc版本。
下载安装钉钉

注册并登录钉钉后,创建专属的团队组织
点击右上角的内容,点击“创建企业/组织/团队”

按照顺序一次填写手机号信息


点击下一步,完善信息

点击下一步后,企业创建成功

6.8.1.2 创建钉钉的告警群
点击右上角的"+", 选择"发起群聊"

创建项目群或者管理群等类型中的一种,我们这里选择创建项目群


创建后效果


6.8.1.3 告警群中添加和配置机器人
点击有上角的设置找到"智能群助手",点击后,就可以看到"添加机器人"



选择添加机器人后,选择 "自定义通过webhook接入自定义服务"

创建机器人后,定制特有的关键字信息,便于后续接收信息

指定机器人名字并设置安全设置

注意:一定要记住分配的webhook地址:
https://oapi.dingtalk.com/robot/send?
access_token=60bc0c10b1cd38319cee7dab03a4e986781b1e9e1e10c847ef7d633a9d567a33
记住告警的错误关键字:PromAlert
6.8.1.4 钉钉测试
6.8.1.4.1 只采用关键字的测试效果
curl-H"Content-Type: application/json"-d'{"msgtype":"text","text":
{"content":"PromAlert - prometheus 告警测试"}}'
https://oapi.dingtalk.com/robot/send?
access_token=60bc0c10b1cd38319cee7dab03a4e986781b1e9e1e10c847ef7d633a9d567a33
#返回信息
{"errcode":0,"errmsg":"ok"}
#注意:只有包含定制的告警关键字的信息才会被发送成功。这里面测试的时候,没有开启加签
可以看到钉钉收到如下信息

6.8.1.4.2 采用关键字和加签的测试效果
在机器人的安全设置,选择"加签",复制加签信息

记录加签的信息:SEC2233b6ab300289ea5ede5b1a859d01bc7ea8a0ee3eaa1145b15b38b12dbd5558
如果采用了加签,这就要求,不仅仅要满足关键字的内容,还需要满足数据全流程认证加密的要求才可以正常发送
加签验证的注意事项
加签校验的特点在于:基于时间戳的会话认证,所以我们要基于加签的信息,生成配套的时间戳和base64的
秘钥生成,最后与我们的token生成标准的url地址
https://oapi.dingtalk.com/robot/send?access_token=钉钉token×tamp=时间戳信息
&sign=生成的秘钥
#定制生成的python脚本
vim create_sign.py
#!/usr/bin/python3
import time, hmac, hashlib, base64
import urllib.parse
# 生成时间戳
timestamp = str(round(time.time() * 1000))
# 传递当前的加签内容
secret ='SEC2233b6ab300289ea5ede5b1a859d01bc7ea8a0ee3eaa1145b15b38b12dbd5558'
# 对加签内容进行编码
secret_enc = secret.encode('utf-8')
# 对基础内容进行格式化定制,并进行编码
string_to_sign ='{}\n{}'.format(timestamp, secret)
string_to_sign_enc = string_to_sign.encode('utf-8')
# 基于编码后的进入进行digest摘要认证加密
hmac_code = hmac.new(secret_enc, string_to_sign_enc,
digestmod=hashlib.sha256).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
# 打印会话相关的时间戳和认证信息
print("Timestamp:",timestamp)
print("Sign: ",sign)
#运行脚本显示如下效果
python3 create_sign.py
Timestamp: 1650114717313
Sign: KAHQEy%2BV7mbs5oaEuXX%2FlBaimtGEQar5un2YgeYv7Dw%3D
加签情况下测试发送信息
curl"https://oapi.dingtalk.com/robot/send?
access_token=60bc0c10b1cd38319cee7dab03a4e986781b1e9e1e10c847ef7d633a9d567a33&ti
mestamp=1650114717313&sign=KAHQEy%2BV7mbs5oaEuXX%2FlBaimtGEQar5un2YgeYv7Dw%3D"-
H'Content-Type: application/json'-d'
{
"msgtype": "markdown",
"markdown": {
"title": "PromAlert 告警信息",
"text": "## 问题详情 \n### 问题级别: 严重\n### 问题类型: MySQL 服务\n### 查询
时间: 2022-02-22"
}
}'
#返回结果
{"errcode":0,"errmsg":"ok"}
#钉钉收到如下信息

6.8.2 钉钉告警实现
Prometheus 不直接支持钉钉告警,在这里使用开源工具 prometheus-webhook-dingtalk 来进行 Prometheus 和 dingtalk的环境集成。
注意: 以下环境假设 Prometheus 已经实现告警规则和相关功能
cat /usr/local/prometheus/conf/prometheus.yml
......
alerting:
alertmanagers:
- static_configs:
- targets:
-10.0.0.101:9093
......
rule_files:
-"../rules/*.yml"#指定规则文件路径
.....
- job_name: 'my_metric'
static_configs:
- targets: ['10.0.0.101:8000']
labels: {app: 'flask_web'}
6.8.2.1 prometheus-webhook-dingtalk 软件部署
#下载软件
wget https://github.com/timonwong/prometheus-webhook-
dingtalk/releases/download/v2.0.0/prometheus-webhook-dingtalk-2.0.0.linux-
amd64.tar.gz
#解压文件
tar xf prometheus-webhook-dingtalk-2.0.0.linux-amd64.tar.gz -C /usr/local/
ln-s /usr/local/prometheus-webhook-dingtalk-2.0.0.linux-amd64/
/usr/local/dingtalk
#准备文件和目录
cd /usr/local/dingtalk
mkdir bin conf
mv prometheus-webhook-dingtalk bin/
cp config.example.yml conf/config.yml
#编辑 config.yml 相关信息
vim /usr/local/dingtalk/conf/config.yml
targets:
webhook1:
url: https://oapi.dingtalk.com/robot/send?
access_token=60bc0c10b1cd38319cee7dab03a4e986781b1e9e1e10c847ef7d633a9d567a33
# secret for signature
secret: SEC2233b6ab300289ea5ede5b1a859d01bc7ea8a0ee3eaa1145b15b38b12dbd5558
# 查看命令帮助
/usr/local/dingtalk/bin/prometheus-webhook-dingtalk --help
usage: prometheus-webhook-dingtalk [<flags>]
Flags:
-h, --help Show context-sensitive help (also try --help-
long and --help-man).
--web.listen-address=":8060"
The address to listen on for web interface.
--web.enable-ui Enable Web UI mounted on /ui path
--web.enable-lifecycle Enable reload via HTTP request.
--config.file=config.yml Path to the configuration file.
--log.level=info Only log messages with the given severity or
above. One of: [debug, info, warn, error]
--log.format=logfmt Output format of log messages. One of: [logfmt,
json]
--version Show application version.
#尝试命令启动后,测试效果
/usr/local/dingtalk/bin/prometheus-webhook-dingtalk --
config.file=/usr/local/dingtalk/conf/config.yml --web.listen-
address=0.0.0.0:8060
#检查端口
ss -tnulp | egrep 'Pro|8060'
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
Process
tcp LISTEN 04096 *:8060 *:*
users:(("prometheus-webh",pid=281635,fd=3))
#测试发送信息,注意:需要取消钉钉中安全设置中的自定义关键字,只保留加签才能成功,否则提示"Unable
to talk to DingTalk"发送失败
curl"http://10.0.0.100:8060/dingtalk/webhook1/send"-H'Content-Type:
application/json'-d'
{
"msgtype": "markdown",
"markdown": {
"title": "PromAlert 告警信息",
"text": "## 问题详情 \n### 问题级别: 严重\n### 问题类型: MySQL 服务\n### 查询
时间: 2022-02-22"
}
}'
#返回结果
OK
#如果钉钉中安全设置中有自定义关键字,prometheus-webhook-dingtalk会提示下面错误
msg="Failed to send notification to DingTalk"respCode=310000respMsg="keywords
not in content
6.8.2.2 Alertmanager 配置
# vim /usr/local/alertmanager/conf/alertmanager.yml
global:
...
# 路由配置
route:
group_by: ['alertname', 'cluster']
group_wait: 10s
group_interval: 10s
repeat_interval: 10s
receiver: 'dingtalk'
# 收信人员
receivers:
- name: 'dingtalk'
webhook_configs:
- url: 'http://10.0.0.100:8060/dingtalk/webhook1/send'
send_resolved: true
#注意:当前此配置不支持钉钉中安全设置中有自定义关键字,只适用于加签
关闭flask_web服务触发故障后查看dingding的告警效果



重启flask-web应用,可以收到恢复信息

6.8.2.3 定制钉钉告警模板文件
6.8.2.3.1 确保钉钉中安全设置中有自定义关键字和加签

6.8.2.3.2 准备两个图片的外链接
图片用于在告警模板中显示,图片可以放在自已的网站或者利用云服务(比如: 七牛云)的对象存储功能实现
http://www.wangxiaochun.com/testdir/images/OK.png
http://www.wangxiaochun.com/testdir/images/ERROR.png
6.8.2.3.3 配置告警模板
#创建告警模板
vim /usr/local/dingtalk/contrib/templates/dingtalk.tmpl
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{
.Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " "
}} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with
.CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{
end }}{{ end }}
{{ define "__alertmanagerURL" }}{{ .ExternalURL }}/#/alerts?receiver={{
.Receiver }}{{ end }}
{{ define "__text_alert_list" }}{{ range . }}
**Labels**
{{ range .Labels.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}
**Annotations**
{{ range .Annotations.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html
}}
{{ end }}
**Source:** [{{ .GeneratorURL }}]({{ .GeneratorURL }})
{{ end }}{{ end }}
{{ define "___text_alert_list" }}{{ range . }}
---
**告警主题:** {{ .Labels.alertname | upper }}
**告警级别:** {{ .Labels.severity | upper }}
**触发时间:** {{ dateInZone "2006-01-02 15:04:05" (.StartsAt) "Asia/Shanghai" }}
**事件信息:** {{ range .Annotations.SortedPairs }} {{ .Value | markdown | html }}
{{ end }}
**事件标签:**
{{ range .Labels.SortedPairs }}{{ if and (ne (.Name) "severity") (ne (.Name)
"summary") (ne (.Name) "team") }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}{{ end }}
{{ end }}
{{ end }}
{{ define "___text_alertresovle_list" }}{{ range . }}
---
**告警主题:** {{ .Labels.alertname | upper }}
**告警级别:** {{ .Labels.severity | upper }}
**触发时间:** {{ dateInZone "2006-01-02 15:04:05" (.StartsAt) "Asia/Shanghai" }}
**结束时间:** {{ dateInZone "2006-01-02 15:04:05" (.EndsAt) "Asia/Shanghai" }}
**事件信息:** {{ range .Annotations.SortedPairs }} {{ .Value | markdown | html }}
{{ end }}
**事件标签:**
{{ range .Labels.SortedPairs }}{{ if and (ne (.Name) "severity") (ne (.Name)
"summary") (ne (.Name) "team") }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}{{ end }}
{{ end }}
{{ end }}
{{/* Default */}}
{{ define "_default.title" }}{{ template "__subject" . }}{{ end }}
{{ define "_default.content" }} [{{ .Status | toUpper }}{{ if eq .Status
"firing" }}:{{ .Alerts.Firing | len }}{{ end }}\] **[{{ index .GroupLabels
"alertname" }}]({{ template "__alertmanagerURL" . }})**
{{ if gt (len .Alerts.Firing) 0-}}

**========PromAlert 告警触发========**
{{ template "___text_alert_list" .Alerts.Firing }}
{{- end }}
{{ if gt (len .Alerts.Resolved) 0-}}

**========PromAlert 告警恢复========**
{{ template "___text_alertresovle_list" .Alerts.Resolved }}
{{- end }}
{{- end }}
{{/* Legacy */}}
{{ define "legacy.title" }}{{ template "__subject" . }}{{ end }}
{{ define "legacy.content" }} [{{ .Status | toUpper }}{{ if eq .Status "firing"
}}:{{ .Alerts.Firing | len }}{{ end }}\] **[{{ index .GroupLabels "alertname" }}]
({{ template "__alertmanagerURL" . }})**
{{ template "__text_alert_list" .Alerts.Firing }}
{{- end }}
{{/* Following names for compatibility */}}
{{ define "_ding.link.title" }}{{ template "_default.title" . }}{{ end }}
{{ define "_ding.link.content" }}{{ template "_default.content" . }}{{ end }}
#模板语言解析
添加图标格式: 
该图片地址必须是全网都能够访问的一个地址
日期时间不要乱改,这是golang语言的时间格式
6.8.2.4 应用告警模板
vim /usr/local/dingtalk/conf/config.yml
......
#添加下面五行
templates:
-'/usr/local/dingtalk/contrib/templates/dingtalk.tmpl'
default_message:
title: '{{ template "_ding.link.title" . }}'
text: '{{ template "_ding.link.content" . }}'
.......
targets:
webhook1:
url: https://oapi.dingtalk.com/robot/send?
access_token=60bc0c10b1cd38319cee7dab03a4e986781b1e9e1e10c847ef7d633a9d567a33
# secret for signature
secret: SEC2233b6ab300289ea5ede5b1a859d01bc7ea8a0ee3eaa1145b15b38b12dbd5558
#重启dingtalk服务
/usr/local/dingtalk/bin/prometheus-webhook-dingtalk --
config.file=/usr/local/dingtalk/conf/config.yml --web.listen-
address=0.0.0.0:8060
# 显示以下信息
level=info ts=2022-04-16T14:29:51.822Z caller=entry.go:26 component=web
http_scheme=http http_proto=HTTP/1.1 http_method=POST
remote_addr=10.0.0.101:54204 user_agent=Alertmanager/0.23.0
uri=http://10.0.0.100:8060/dingtalk/webhook1/send resp_status=200
resp_bytes_length=2resp_elapsed_ms=586.517974 msg="request complete"
6.8.2.5 测试验证
尝试关闭web服务和重启web服务,查看自定义告警文件信息

恢复web服务和重启web服务,查看自定义告警文件信息

7 服务发现
7.1 服务发现原理
7.1.1 服务发现介绍
Prometheus Server的数据抓取工作于Pull模型,因而,它必需要事先知道各Target的位置,然后才能从相应的Exporter或Instrumentation中抓取数据。
在不同的场景下,需要结合不同的机制来实现对应的数据抓取目的。
对于小型的系统环境来说,通过static_configs指定各Target便能解决问题,这也是最简单的配置方法,我们只需要在配置文件中,将每个Targets用一个网络端点(ip:port)进行标识;
- job_name: 'node_exporter'
static_configs:
- targets: ['10.0.0.101:9100']
对于中大型的系统环境或具有较强动态性的云计算环境来说,由于场景体量的因素,静态配置显然难以适用。

因此,Prometheus为此专门设计了一组服务发现机制,以便于能够基于服务注册中心自动发现、检测、分类可被监控的各Target,以及更新发生了变动的Target
各个节点会主动注册相关属性信息到服务注册中心,即使属性发生变动,注册中心的属性也会随之更改。
一旦节点过期了,或者失效了,服务注册中心,会周期性的方式自动将这些信息清理出去。 服务发现机制
对于prometheus的服务发现机制,这里面提供了二十多种服务发现机制,常见的几种机制如下:
| 方法 | 解析 |
|---|---|
| 基于文件的服务发现 | 简单来说,将各target记录到文件中,prometheus启动后,周期性刷新这个文件,从而获取最新的target |
| 基于 | |
| DNS的服务发现 | 针对一组DNS域名进行定期查询,以发现待监控的目标,并持续监视相关资源的变动 |
| 基于 API的服务发现 |
支持将API Server中Node、Service、Endpoint、Pod和Ingress等资源类型下相应的各资源对象视作target,并持续监视相关资源的变动。 |
| 基于 HTTP的服务发现 |
基于HTTP的服务发现提供了一种更通用的方式来配置静态目标,并用作插入自定义服务发现机制的接口。 它从包含零个或多个<static_config>列表的HTTP端点获取目标。 目标必须回复 HTTP 200响应。HTTP header Content-Type必须是application/json,body必须是有效的JSON。 |
7.1.2 服务发现原理
发现原理

Prometheus服务发现机制大致涉及到三个部分:
-
配置处理模块解析的prometheus.yml配置中scrape_configs部分,将配置的job生成一个个 Discoverer服务,不同的服务发现协议都会有各自的Discoverer实现方式,它们根据实现逻辑去发现target,并将其放入到targets列表中
-
DiscoveryManager组件内部有个定时周期触发任务,每5秒检查target列表,如果有变更则将 target列表中target信息放入到syncCh消息池中
-
scrape组件会监听syncCh消息池,这样需要监控的target信息就传递给scrape组件,然后reload将 target纳入监控开始抓取监控指标
配置处理部分会根据scrape_configs部分配置的不同协议类型生成不同Discoverer,然后根据它们内部不同的实现逻辑去发现target,discoveryManager组件则相当于一个搬运工,scrape组件则是一个使用者,这两个组件都对不同服务发现协议的差异无所感知。
指标的生命周期

在每个scrape_interval期间,Prometheus都会检查执行的作业(Job);
-
这些作业首先会根据Job上指定的发现配置生成target列表,此即服务发现过程
-
服务发现会返回一个Target列表,其中包含一组称为元数据的标签,这些标签都以
“__meta_”为前缀__
服务发现还会根据目标配置来设置其它标签,这些标签带有 “__” 前缀和后缀,包括__
“__scheme__” 、 “__address__” 和 “__metrics_path__” ,分别保存有target支持使用协议 (http或https,默认为http)
target的地址及指标的URI路径(默认为/metrics)
若URI路径中存在任何参数,则它们的前缀会设置为 “__param__”
-
这些目标列表和标签会返回给Prometheus,其中的一些标签也可以配置中被覆盖
-
配置标签会在抓取的生命周期中被重复利用以生成其他标签,例如,指标上的instance标签的默认值就来自于
__address__标签的值 -
对于发现的各目标,Prometheus提供了可以重新标记(relabel) 目标的机会
-
它定义在job配置段的relabel_config配置中,常用于实现如下功能
将来自服务发现的元数据标签中的信息附加到指标的标签上过滤目标
接下来是数据抓取、以及指标返回的过程
抓取而来的指标在保存之前,还允许用户对指标重新打标并过滤的方式
它定义在job配置段的metric_relabel_configs配置中,常用于实现如下功能
-
删除不必要的指标
-
从指标中删除敏感或不需要的标签
添加、编辑或修改指标的标签值或标签格式
7.2 文件服务
7.2.1 文件发现服务说明
基于文件的服务发现是仅仅略优于静态配置的服务发现方式,它不依赖于任何平台或第三方服务,因而也是最为简单和通用的实现方式
文件发现原理
-
Prometheus Server定期从文件中加载Target信息
-
文件可使用YAML和JSON格式,它含有定义的Target列表,以及可选的标签信息
-
YAML 适合于运维场景, JSON 更适合于开发场景
-
这些文件可由另一个系统生成,例如Ansible或Saltstack等配置管理系统,也可能是由脚本基于 CMDB定期查询生成
参考资料:
https://prometheus.io/blog/2015/06/01/advanced-service-discovery/#custom-service-
discovery
配置过程和格式
#1.准备主机节点列表文件,可以支持yaml格式和json格式
cat targets/prometheus*.yaml
- targets:
- master1:9100
labels:
app: prometheus
#2.配置文件自动加载实现自动发现
cat prometheus.yml
......
- job_name: ‘prometheus'
file_sd_configs:
- files: # 指定要加载的文件列表;
- targets/prometheus*.yaml # 文件加载支持glob通配符,支持yaml和json两种格
式
refresh_interval: 2m # 每隔2分钟重新加载一次文件中定义的Targets,默
认为5m
#注意:文件格式都是yaml格式
7.2.2 文件服务发现案例
7.2.2.1 案例: YAML 格式
范例: 通过yaml格式的文件发现,将所有的节点都采用自动发现机制
#创建目标目录
mkdir /usr/local/prometheus/conf/targets
cd /usr/local/prometheus/conf/targets
#添加linux主机目标
ls /usr/local/prometheus/conf/targets/
prometheues-flask.yml prometheues-node.yml prometheues-server.yml
#创建prometheus的服务配置
cat prometheues-server.yml
- targets:
-10.0.0.101:9090
labels:
app: prometheus-server
job: prometheus-server
cat prometheues-node.yml
- targets:
-10.0.0.101:9100
labels:
app: prometheus
job: prometheus
- targets:
-10.0.0.104:9100
-10.0.0.105:9100
labels:
app: node-exporter
job: node
cat prometheues-flask.yml
- targets:
-10.0.0.101:8000
labels:
app: flask-web
job: prometheus-flask
#修改prometheus的配置文件,让它自动加载文件中的节点信息
cd /usr/local/prometheus/conf
cp prometheus.yml{,.bak}
#编辑配置文件
#cat /usr/local/prometheus/conf/prometheus.yml
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is
every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is
every 1 minute.
# scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
rule_files:
scrape_configs:
- job_name: "prometheus"
file_sd_configs:
- files:
- targets/prometheues-server.yml
refresh_interval: 2m
- job_name: 'node_exporter'
file_sd_configs:
- files:
- targets/prometheues-node.yml
refresh_interval: 2m
- job_name: 'flask_web'
file_sd_configs:
- files:
- targets/prometheues-flask.yml
refresh_interval: 1m
#语法检查
promtool check config prometheus.yml
#重启服务
systemctl restart prometheus.service
#稍等几秒钟,到浏览器中查看监控目标
#结果显示:所有的节点都添加完毕了,而且每个节点都有自己的标签信息

#后续可以自由的编辑文件,无需重启prometheus服务,就可以做到自动发现的效果
cd /usr/local/prometheus/targets
vim prometheues-node.yml
#添加linux主机目标
# cat prometheues-node.yml
- targets:
-10.0.0.104:9100
-10.0.0.105:9100
-10.0.0.106:9100 #加此行
#文件保存后,稍等几秒钟,最慢1分钟,他会自动加载当前的配置文件里面的信息,查看一下浏览器
#结果显示:节点的自动服务发现成功了。以后,对所有节点批量管理的时候,借助于ansible等工具,就可
以非常轻松的搞定所有了

7.2.2.2 案例: JSON 格式
可以利用工具前面的YAML格式转换为JSON格式
http://www.json2yaml.com/
范例: json格式的文件发现
#创建目标目录
mkdir /usr/local/prometheus/conf/targets
cd /usr/local/prometheus/conf/targets
#编写定制的发现文件
cat prometheues-server.json
[
{
"target":[
"10.0.0.101:9090"
],
"labels":{
"app":"prometheus-server",
"job":"prometheus-server"
}
}
]
cat prometheues-node.json
[
{
"targets": [
"10.0.0.101:9100"
],
"labels": {
"app": "prometheus",
"job": "prometheus"
}
},
{
"targets": [
"10.0.0.104:9100",
"10.0.0.105:9100",
"10.0.0.106:9100"
],
"labels": {
"app": "node-exporter",
"job": "node"
}
}
]
cat prometheues-flask.json
[
{
"targets": [
"10.0.0.101:8000"
],
"labels": {
"app": "flask-web",
"job": "prometheus-flask"
}
}
]
#编辑prometheus配置文件
# cat /usr/local/prometheus/conf/prometheus.yml
。。。
scrape_configs:
- job_name: "prometheus"
file_sd_configs:
- files:
- targets/prometheues-server.json
refresh_interval: 10s
- job_name: 'node_exporter'
file_sd_configs:
- files:
- targets/prometheues-node.json
refresh_interval: 10s
- job_name: 'flask_web'
file_sd_configs:
- files:
- targets/prometheues-flask.json
refresh_interval: 10s
#检查语法
promtool check config prometheus.yml
#重启prometheus服务
systemctl restart prometheus
#效果如下

7.3 DNS服务
7.3.1 DNS服务发现说明
基于DNS的服务发现针对一组DNS域名进行定期查询,以发现待监控的目标
-
查询时使用的DNS服务器由/etc/resolv.conf文件指定;
-
该发现机制依赖于A、AAAA和SRV资源记录,且仅支持该类方法,尚不支持RFC6763中的高级DNS 发现方式;
自动生成的元数据标签:
__meta_dns_name
the record name that produced the discovered target.
__meta_dns_srv_record_target
the target field of the SRV record
__meta_dns_srv_record_port
the port field of the SRV record
#参考资料:
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dns_sd
_config
SRV记录
-
SRV记录是服务器资源记录的缩写,记录服务器提供的服务,SRV记录的作用是说明一个服务器能够提供什么样的服务。
-
在RFC2052中才对SRV记录进行了定义,很多老版本的DNS服务器并不支持SRV记录。
-
SRV 资源记录允许为单个域名使用多个服务器,轻松地将服务从一个主机移动到另一个主机,并将某些主机指定为服务的主服务器,将其他主机指定为备份
-
客户端要求特定域名的特定服务/协议,并获取任何可用服务器的名称
RFC2782中对于SRV的定义格式是:
_Service._Proto.Name TTL Class SRV Priority Weight Port Target
#格式解析:
Service 所需服务的符号名称,在Assigned Numbers或本地定义。
服务标识符前面加下划线(_),以避免与常规出现的DNS标签发生冲突。
Proto 所需协议的符号名称,该名称不区分大小写。_TCP和_UDP目前是该字段最常用的值
前面加下划线_,以防止与自然界中出现的DNS标签发生冲突。
Class 定制DNS记录类,它主要有以下三种情况:
对于涉及Internet的主机名、IP地址等DNS记录,记录的CLASS设置为IN。
其他两类用的比较少,比如CS(CSNET类)、CH(CHAOS类)、HS(Hesiod)等。
每个类都是一个独立的名称空间,其中DNS区域的委派可能不同。
Name 此RR所指的域名。在这个域名下SRV RR是唯一的。
Port 服务在目标主机上的端口。范围是0-65535。这是网络字节顺序中的16位无符号整数。
Target 目标主机的域名。域名必须有一个或多个地址记录,域名绝不能是别名。
敦促(但不强求)实现在附加数据部分中返回地址记录。
值为“.” 表示该域名明确无法提供该服务。
官方配置示例
#参考资料:https://prometheus.io/blog/2015/06/01/advanced-service-
discovery/#discovery-with-dns-srv-records
#定制job对象
job {
name: "api-server"
sd_name: "telemetry.eu-west.api.srv.example.org"
metrics_path: "/metrics"
}
#定制解析记录
scrape_configs:
- job_name: 'myjob'
dns_sd_configs:
- names:
-'telemetry.eu-west.api.srv.example.org'
-'telemetry.us-west.api.srv.example.org'
-'telemetry.eu-west.auth.srv.example.org'
-'telemetry.us-east.auth.srv.example.org'
relabel_configs:
- source_labels: ['__meta_dns_name']
regex: 'telemetry\.(.+?)\..+?\.srv\.example\.org'
target_label: 'zone'
replacement: '$1'
- source_labels: ['__meta_dns_name']
regex: 'telemetry\..+?\.(.+?)\.srv\.example\.org'
target_label: 'job'
replacement: '$1'
7.3.2 DNS服务发现案例
7.3.2.1 部署和配置 DNS
部署DNS环境
#安装软件
apt install bind9 bind9utils bind9-doc bind9-host -y
named -v
#查看部署软件
dpkg -L bind9 | grep named.conf
/etc/bind/named.conf
/etc/bind/named.conf.default-zones
/etc/bind/named.conf.local
/etc/bind/named.conf.options
#定制正向解析zone的配置
cat >> /etc/bind/named.conf.default-zones
//定制网站主域名的zone配置
zone "wang.org" {
type master;
file "/etc/bind/wang.org.zone";
};
#定制主域名的zone文件
vim /etc/bind/wang.org.zone
;
; BIND reverse data file for local loopback interface
;
$TTL604800
@ IN SOA ns.wang.org. admin.wang.org. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
IN NS master
master IN A 10.0.0.100
node1 IN A 10.0.0.101
node2 IN A 10.0.0.102
node3 IN A 10.0.0.103
flask IN A 10.0.0.101
#检查配置文件
named-checkconf
#重启dns服务
systemctl restart named
systemctl status named
#配置prometheus服务器的本地主机专属的dns域名服务器
vim /etc/netplan/01-netcfg.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
addresses:
-10.0.0.101/24
gateway4: 10.0.0.2
nameservers:
search: [wang.org,wang.com]
addresses: [10.0.0.100] #只保留当前的DNS服务器地址,不要再加其它DNS服务器地址,否则
DNS解析有问题
#应用网络配置
netplan apply
#确认dns解析效果
dig node1.wang.org
host node1.wang.org
nslookup node1.wang.org
7.3.2.2 配置 DNS服务支持 SRV 记录
#添加SRV记录
# vim /etc/bind/wang.org.zone
... ...
node1 IN A 10.0.0.101
node2 IN A 10.0.0.102
node3 IN A 10.0.0.103
flask IN A 10.0.0.101
#添加下面的SRV记录,对应上面的三条A记录
_prometheus._tcp.wang.org. 1H IN SRV 10109100 node1.wang.org.
_prometheus._tcp.wang.org. 1H IN SRV 10109100 node2.wang.org.
_prometheus._tcp.wang.org. 1H IN SRV 10109100 node3.wang.org.
#检查配置文件
named-checkconf
#重启DNS服务
systemctl restart named
systemctl status named
#测试解析
dig srv _prometheus._tcp.wang.org
host -t srv _prometheus._tcp.wang.org
nslookup -q=srv _prometheus._tcp.wang.org
7.3.2.3 配置 Prometheus 使用 DNS
# vim /usr/local/prometheus/conf/prometheus.yml
...
scrape_configs:
- job_name: "prometheus"
.......
#添加下面所有行
-
job_name: 'node_exporter_from_dns' # 实现批量主机解析 -
dns_sd_configs: - names: ['_prometheus._tcp.wang.org'] -
refresh_interval: 10s
- job_name: 'flask_from_dns'#实现单个主机定制的信息解析
dns_sd_configs:
- names: ['flask.wang.org']
type: A
port: 8000
refresh_interval: 10s
#重启prometheus
promtool check config /usr/local/prometheus/conf/prometheus.yml
systemctl restart prometheus
7.3.2.4 验证结果

7.3.2.5 添加和删除SRV记录
#删除node2和添加node4对应的SRV和A记录
[root@prometheus ~]#cat /etc/bind/wang.org.zone
$TTL 1D
@ IN SOA master admin (
1 ; serial |
|
|---|---|
1D ; refresh |
|
1H ; retry |
|
1W ; expire |
|
3H ) ; minimum |
|
NS |
master |
master A |
10.0.0.100 |
node1 IN A |
10.0.0.101 |
node3 IN A |
10.0.0.103 |
flask IN A |
10.0.0.101 |
_prometheus._tcp.wang.org. 1H IN SRV 10109100 node1.wang.org.
_prometheus._tcp.wang.org. 1H IN SRV 10109100 node3.wang.org.
_prometheus._tcp.wang.org. 1H IN SRV 10109100 node4.wang.org.
#注意:Ubuntu有DNS缓存,需要清除才能生效
[root@prometheus ~]#rndc reload;netplan apply
server reload successful
#确认结果
[root@prometheus ~]#host -t srv _prometheus._tcp.wang.org
_prometheus._tcp.wang.org has SRV record 10109100 node1.wang.org.
_prometheus._tcp.wang.org has SRV record 10109100 node3.wang.org.
_prometheus._tcp.wang.org has SRV record 10109100 node4.wang.org.
7.3.2.6 确认是否自动发现生效
登录 Prometheus 网站,查看是否生效

8 容器监控
8.1 cAdvisor 简介
对于一些容器类型的服务应用来说,可以借助于一些专用工具的方式来实现监控,比如docker类型的容器应用,我们就可以通过 cAdvisor 的方式来进行监控。
cadvisor(Container Advisor) 是 Google 开源的一个容器监控工具,它以守护进程方式运行,用于收集、聚合、处理和导出正在运行容器的有关信息。具体来说,该组件对每个容器都会记录其资源隔离参数、历史资源使用情况、完整历史资源使用情况的直方图和网络统计信息。它不仅可以搜集一台机器上所有运行的容器信息,还提供基础查询界面和http接口,方便其他组件如Prometheus进行数据抓取
cAdvisor使用Go语言开发,对Node机器上的资源及容器进行实时监控和性能数据采集,包括CPU使用情况、内存使用情况、网络吞吐量及文件系统使用情况,利用Linux的cgroups获取容器的资源使用信息,可用于对容器资源的使用情况和性能进行监控。
安装 cAdvisor 后,通过 http://cAdvisor-server:8080/metrics 暴露metrics
注意:一个cAdvisor仅对一台主机进行监控。
项目主页:http://github.com/google/cadvisor
下载地址:
https://github.com/google/cadvisor/releases/latest
https://github.com/google/cadvisor/archive/refs/tags/v0.39.3.tar.gz
在需要被监控docker的主机准备 docker 环境
#Ubuntu20.04安装docker
[root@ubuntu2004 ~]#apt -y install docker.io
[root@ubuntu2004 ~]#echo '{"registry-mirrors":
["https://si7y70hh.mirror.aliyuncs.com"], "insecure-registries":
["harbor.wang.org:80"]}' > /etc/docker/daemon.json
[root@ubuntu2004 ~]#systemctl restart docker
[root@ubuntu2004 ~]#docker info
Client:
Context: default
Debug Mode: false
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 20.10.12
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk
syslog
Swarm: inactive
Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2
Default Runtime: runc
Init Binary: docker-init
containerd version:
runc version:
init version:
Security Options:
apparmor
seccomp
Profile: default
Kernel Version: 5.4.0-89-generic
Operating System: Ubuntu 20.04.3 LTS
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 1.913GiB
Name: prometheus.wang.org
ID: GBDK:CT2I:25AK:WVJC:WUXV:44HZ:UETD:MTW6:33LD:MP2V:Q3AX:K6RJ
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
harbor.wang.org:80
127.0.0.0/8
Registry Mirrors:
https://si7y70hh.mirror.aliyuncs.com/
Live Restore Enabled: false
WARNING: No swap limit support
#或者通过以下安装脚本install_docker.sh安装
#!/bin/bash
# 安装依赖环境
env_base(){
apt-get update
apt-get install apt-transport-https ca-certificates curl gnupg lsb-release -y
}
# 配置软件源
docker_repo(){
curl-fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg |
sudo gpg --dearmor-o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg]
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | sudotee /etc/apt/sources.list.d/docker.list >
/dev/null
apt-get update
}
# 安装软件
docker_install(){
apt-get -y install docker-ce docker-ce-cli containerd.io
}
# 加速器配置
docker_speed(){
echo'{"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
"insecure-registries": ["harbor.wang.org:80"]}' > /etc/docker/daemon.json
systemctl restart docker
systemctl enable docker
}
# 主程序
main(){
env_base
docker_repo
docker_install
docker_speed
}
# 执行主程序
main
#在10.0.0.100 主机上安装docker环境
/bin/bash install_docker.sh
#容器的基本监控
docker stats container_name
8.2 安装 cAdvisor
8.2.1 源码编译安装 cAdvisor
官方文档
https://github.com/google/cadvisor/blob/master/docs/development/build.md
范例: 编译安装cadvisor
#安装go环境,必须在 1.14+ 版本,注意:不要使用1.18以上版
wget https://studygolang.com/dl/golang/go1.17.6.linux-amd64.tar.gz
tar -xf go1.17.6.linux-amd64.tar.gz -C /usr/local/
echo'export GOROOT=/usr/local/go' > /etc/profile.d/go.sh
echo'export PATH=$PATH:$GOROOT/bin' >> /etc/profile.d/go.sh
source /etc/profile.d/go.sh
go version
#获取源代码
wget https://github.com/google/cadvisor/archive/refs/tags/v0.39.3.tar.gz
tar xf v0.39.3.tar.gz -C /usr/local/
ln-s /usr/local/cadvisor-0.39.3 /usr/local/cadvisor
cd /usr/local/cadvisor
#获取软件依赖
go get-d github.com/google/cadvisor
go env -wGOPROXY=https://goproxy.cn
#查看go环境变量
go env
#Ubuntu系统
apt -y install gccmake libpfm4 libpfm4-dev jq
#rhel系列
yum -y install gccmake
#编译安装cadvisor
make build
#确认效果
./cadvisor --help
Usage of ./cadvisor:
-add_dir_header
If true, adds the file directory to the header of the log messages
-allow_dynamic_housekeeping
Whether to allow the housekeeping interval to be dynamic (default true)
-alsologtostderr
log to standard error as well as files
-application_metrics_count_limit int
Max number of application metrics to store (per container) (default 100)
.....
#启动cadvisor
./cadvisor -port=8080 &>>/var/log/cadvisor.log &
#浏览器访问 10.0.0.101:8080,可以查看cadvisor的默认ui页面的浏览器效果

#浏览器访问 10.0.0.100:8080/metrics,可以查看cadvisor的默认采集的容器指标效果

8.2.2 Docker 方式安装 cAdvisor 环境
#安装说明
https://github.com/google/cadvisor/
#版本
https://github.com/google/cadvisor/releases
#hub.docker.com只有旧版的cadvisor,如果获取cadvisor的最新版的docker镜像,需要科学上网
docker pull gcr.io/cadvisor/cadvisor:v0.37.0
docker pull google/cadvisor:v0.33.0 #docker仓库的cAdvisor镜像只有旧版本,而且不在更新
#启动容器
docker load -i cadvisor-v0.37.0.tar.gz
docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--volume=/dev/disk/:/dev/disk:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
--privileged \
--device=/dev/kmsg \
gcr.io/cadvisor/cadvisor:v0.37.0
#在线下载
docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--volume=/dev/disk/:/dev/disk:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
--privileged \
--device=/dev/kmsg \
google/cadvisor:v0.33.0
8.3 Prometheus 配置
修改 Prometheus 配置
#修改prometheus的配置文件,让它自动过滤文件中的节点信息
# vim /usr/local/prometheus/conf/prometheus.yml
...
- job_name: "metrics_from_docker"
static_configs:
- targets: ["10.0.0.101:8080"] #添加安装cAdvisor的主机
- targets: ["10.0.0.102:8080"]
#重启服务
systemctl restart prometheus.service
#稍等几秒钟,到浏览器中查看监控目标

8.4 Grafana 监控
安装 Grafana
[root@ubuntu2004 ~]#dpkg -i grafana_9.0.6_amd64.deb
Selecting previously unselected package grafana.
(Reading database ... 76356 files and directories currently installed.)
Preparing to unpack grafana_8.5.9_amd64.deb ...
Unpacking grafana (8.5.9) ...
dpkg: dependency problems prevent configuration of grafana:
grafana depends on libfontconfig1; however:
Package libfontconfig1 is not installed.
dpkg: error processing package grafana (--install):
dependency problems - leaving unconfigured
Processing triggers for systemd (245.4-4ubuntu3.11) ...
Errors were encountered while processing:
grafana
#提示依赖失败,执行下面修复依赖
[root@ubuntu2004 ~]#apt -y --fix-broken install
#或者执行解决依赖
[root@ubuntu2004 ~]#apt -y install ./grafana_9.0.6_amd64.deb
#启动服务
[root@ubuntu2004 ~]#systemctl enable --now grafana-server
[root@ubuntu2004 ~]#systemctl status grafana-server
#导入grafana的镜像模板文件
https://grafana.com/grafana/dashboards/193



#模板中没有看到标签的样式,在当前的dashboard上定制一个查询的变量名,点击当前dashboard右侧的齿
轮(编辑),编辑内容如下:
#过滤的标签:label_values(up,instance)
#筛选的值: .*:8080


输入以下信息
Query: label_values(up,instance)
Regex: .*:8080

在preview of values 后面有过滤出来的信息,点击最下面的update和左侧的save,再来查看当前的 dashboard,可以看到顶栏就有我们用于过滤信息的定制grafana内容了


可以查看到下面的主机的样式

9 各种 Exporter
Prometheus 指供了大量的 Exporter 实现各种应用的监控功能
Exporter 分类
应用内置: 软件内就内置了此Exporter,比如: Zookeeper,Gitlab,nginx等应用外置: 应用安装后,还需要单独安装对应的 Exporter,比如: MySQL,Redis等定制开发: 如有特殊需要,用户自行开发
Exporter 官方文档
https://prometheus.io/docs/instrumenting/exporters/

9.1 Node Exporter 监控服务
9.1.1 服务监控说明
对于一些服务应用来说,我们可以通过对于node_exporter的启动参数改造来实现更多功能的获取。
参数分析
#查看node_exporter命令的帮助信息,发现,它有很多扩展的参数,通过这些参数来实现更多的功能监控
[root@prometheus ~]#/usr/local/node_exporter/bin/node_exporter --help
usage: node_exporter [<flags>]
Flags:
-h, --help Show context-sensitive help (also try --help-
long and --help-man).
--collector.bcache.priorityStats
Expose expensive priority stats.
--collector.cpu.info Enables metric cpu_info
--collector.cpu.info.flags-include=COLLECTOR.CPU.INFO.FLAGS-INCLUDE
Filter the `flags` field in cpuInfo with a
value that must be a regular expression
--collector.cpu.info.bugs-include=COLLECTOR.CPU.INFO.BUGS-INCLUDE
Filter the `bugs` field in cpuInfo with a value
that must be a regular expression
--collector.diskstats.ignored-devices="^(ram|loop|fd|(h|s|v|xv)d[a-
z]|nvme\\d+n\\d+p)\\d+$"
Regexp of devices to ignore for diskstats.
.......
--collector.systemd #显示当前系统中所有的服务状态信息
--collector.systemd.unit-include #仅仅显示符合条件的systemd服务条目
--collector.systemd.unit-exclude #显示排除列表范围之外的服务条目
#注意:
上面三条仅显示已安装的服务条目,没有安装的服务条目是不会被显示的。
而且后面两个属性是依赖于第一条属性的
这些信息会被显示在 node_systemd_unit_state对应的metrics中
9.1.2 实战案例
9.1.2.1 修改 node_exporter 的配置文件
#在node1节点修改node_exporter配置文件
vim /lib/systemd/system/node_exporter.service
[Unit]
Description=node exporter project
After=network.target
[Service]
Type=simple
#只收集指定服务
ExecStart=/usr/local/node_exporter/bin/node_exporter --collector.systemd --
collector.systemd.unit-include=".*(ssh|mysql|node_exporter|nginx).*"
Restart=on-failure
[Install]
WantedBy=multi-user.target
#属性解析:
如果没有提前安装的服务,是不会被查看到的
服务名称的正则符号必须解析正确,否则无法匹配要现实的服务名称
#重启node_exporter服务
systemctl daemon-reload
systemctl restart node_exporter.service
9.1.2.2 修改 Prometheus 配置
#修改prometheus的配置文件,让它自动过滤文件中的节点信息
vim /usr/local/prometheus/conf/prometheus.yml
...
- job_name: "node_exporter_service"
static_configs:
- targets: ["10.0.0.104:9100"]
#重启服务
systemctl restart prometheus.service
#稍等几秒钟,到浏览器中查看监控目标
#结果显示:
每个服务都有五种状态,只有成功的状态才会显示值为1,其他状态为0
只有已安装的服务才会在这里显示,否则不显示


#在node1节点安装nginx服务后,再次观察可以看到下面结果
[root@node1 ~]#apt -y install nginx

9.2 MySQL 监控
9.2.1 MySQL 监控说明
prometheus提供了专属于mysql的服务监控工具 mysqld_exporter,我们可以借助于该模块,来实现数据库的基本监控。
#下载链接
https://prometheus.io/download/
#使用说明
https://github.com/prometheus/mysqld_exporter


9.2.2 案例
9.2.2.1 数据库环境准备
#安装数据库软件
apt -y install mysql-server
#更新mysql配置
sed-i's#127.0.0.1#0.0.0.0#' /etc/mysql/mysql.conf.d/mysqld.cnf
systemctl restart mysql
#为mysqld_exporter配置获取数据库信息的权限
mysql
mysql> CREATE USER 'exporter'@'localhost' IDENTIFIED BY '123456' WITH
MAX_USER_CONNECTIONS 3;
mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO
'exporter'@'localhost';
mysql> flush privileges;
9.2.2.2 mysqld_exporter 安装
#获取软件
wget
https://github.com/prometheus/mysqld_exporter/releases/download/v0.13.0/mysqld_e
xporter-0.13.0.linux-amd64.tar.gz
# 解压软件
tar xf mysqld_exporter-0.13.0.linux-amd64.tar.gz -C /usr/local
ln-s /usr/local/mysqld_exporter-0.13.0.linux-amd64 /usr/local/mysqld_exporter
cd /usr/local/mysqld_exporter/
mkdir bin
mv mysqld_exporter bin/
#在mysqld_exporter的服务目录下,创建 .my.cnf [隐藏]文件,为mysqld_exporter配置获取数据库
信息的基本属性
vim /usr/local/mysqld_exporter/.my.cnf
[client]
host=127.0.0.1
port=3306
user=exporter
password=123456
#修改node_exporter的服务启动文件
vim /lib/systemd/system/mysqld_exporter.service
[Unit]
Description=mysqld exporter project
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/mysqld_exporter/bin/mysqld_exporter --config.my-
cnf="/usr/local/mysqld_exporter/.my.cnf"
Restart=on-failure
[Install]
WantedBy=multi-user.target
#配置解析:在原来的配置文件基础上,添加了 --config.my-cnf属性
#重载并重启服务
systemctl daemon-reload
systemctl enable --now mysqld_exporter.service
systemctl status mysqld_exporter.service
#检查是否打开9104/tcp端口
ss -tnulp | grep mysql
tcp 000.0.0.0:3306 0.0.0.0:* LISTEN
24472/mysqld
tcp6 00 :::9104 :::* LISTEN
24838/mysqld_export
#结果显示:该组件对外暴露的端口是 9104 端口
9.2.2.3 修改 Prometheus 配置
#修改prometheus的配置文件,让它自动过滤文件中的节点信息
vim /usr/local/prometheus/conf/prometheus.yml
...
- job_name: "mertics_from_mysql"
static_configs:
- targets: ["10.0.0.106:9104"]
#重启服务
systemctl restart prometheus.service
#稍等几秒钟,到浏览器中查看监控目标


9.2.2.4 Grafana 图形展示
#导入grafana的镜像模板文件 https://grafana.com/grafana/dashboards/14057 或 7362 ,查
看效果



9.3 Haproxy 监控
Haproxy的监控有两种实现方式
借助于专用的haproxy_exporter组件来采集 haproxy的csv数据
-
haproxy_exporter 可以和 haproxy 处于不同的环境,不同主机等
-
借助于 haproxy本身的机制,暴露metrics指标
-
/metrics 和 /haproxy-status 是同时配置的
-
相当于zookeeper 的 /metrics
9.3.1 Haproxy_exporter 监控
9.3.1.1 Haproxy_exporter 介绍
对于负载均衡软件来说,prometheus提供了专用的监控组件haproxy-exporter来实现对于haproxy负载均衡软件的代理工作。
haproxy-exporter 本质上,它是根据对haproxy的状态页面uri地址获取到的csv内容进行了解析,从而获取我们需要监控到的数据
下载链接:https://prometheus.io/download/
官网地址:https://github.com/prometheus/haproxy_exporter

9.3.1.2 实战案例
9.3.1.2.1 准备 Haproxy 环境
#安装haproxy软件
apt -y install haproxy
#设定haproxy配置文件
cat /etc/haproxy/haproxy.cfg
...
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth admin:123456
#重启haproxy服务
systemctl restart haproxy.service
#浏览器访问 10.0.0.106:9999/haproxy-status 页面


#浏览器访问 10.0.0.106:9999/haproxy-status;csv 页面

9.3.1.2.2 安装 Haproxy Exporter 组件
#获取软件
wget
https://github.com/prometheus/haproxy_exporter/releases/download/v0.13.0/haproxy
_exporter-0.13.0.linux-amd64.tar.gz
#解压软件
tar xf haproxy_exporter-0.13.0.linux-amd64.tar.gz -C /usr/local/
ln-s /usr/local/haproxy_exporter-0.13.0.linux-amd64 /usr/local/haproxy_exporter
cd /usr/local/haproxy_exporter/
mkdir bin
mv haproxy_exporter bin/
#修改haproxy_exporter的服务启动文件
vim /lib/systemd/system/haproxy_exporter.service
[Unit]
Description=haproxy exporter project
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/haproxy_exporter/bin/haproxy_exporter --haproxy.scrape-
uri="http://admin:123456@10.0.0.106:9999/haproxy-status;csv"
Restart=on-failure
[Install]
WantedBy=multi-user.target
#配置解析:在原来的配置文件基础上,添加了 --haproxy.scrape-uri属性来指定haproxy状态值的获取
#重载并重启服务
systemctl daemon-reload
systemctl enable --now haproxy_exporter.service
systemctl status haproxy_exporter.service
#检查是否监听9101/tcp端口
ss -ntlp|grep haproxy
LISTEN 04920.0.0.0:9999 0.0.0.0:*
users:(("haproxy",pid=124021,fd=7))
LISTEN 04096 *:9101 *:*
users:(("haproxy_exporte",pid=126538,fd=3))
9.3.1.2.3 修改 Prometheus 配置
#修改prometheus的配置文件,让它自动过滤文件中的节点信息
vim /usr/local/prometheus/conf/prometheus.yml
...
- job_name: "mertics_from_haproxy"
static_configs:
- targets: ["10.0.0.104:9101"]
#重启服务
systemctl restart prometheus.service
#稍等几秒钟,到浏览器中查看监控目标


9.3.1.2.4 Grafana 图形展示
导入grafana的镜像模板文件 https://grafana.com/grafana/dashboards/2428 ,查看效果



9.3.2 Haproxy 内置功能实现监控
haproxy自从2.X 版本开始,就提供了专用的暴露数据的功能,只需要在编译安装haproxy的时候,开启该功能即可,然后,就可以按照传统的prometheus监控目标的方式来进行监控了。
9.3.2.1 编译安装 haproxy
#安装依赖软件
apt update
apt -y install gccmake libssl-dev libpcre3 libpcre3-dev zlib1g-dev
libreadline-dev libsystemd-dev
#获取lua软件
wget http://www.lua.org/ftp/lua-5.4.3.tar.gz
tar zxf lua-5.4.3.tar.gz -C /usr/local/
cd /usr/local/lua-5.4.3
make all test
cd
#获取软件
wget https://www.haproxy.org/download/2.5/src/haproxy-2.5.0.tar.gz
tar xf haproxy-2.5.0.tar.gz -C /usr/local/src
cd /usr/local/src/haproxy-2.5.0/
# 定制编译变量
make-j$(nproc)ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1USE_OPENSSL=1
USE_ZLIB=1USE_SYSTEMD=1USE_CPU_AFFINITY=1USE_PROMEX=1USE_LUA=1
LUA_INC=/usr/local/lua-5.4.3/src/ LUA_LIB=/usr/local/lua-5.4.3/src/
PREFIX=/usr/local/haproxy
#解析:
-j$(nproc)指的是cpu的核数
#在 HAProxy 2.0.x - 2.3.x ,使用 EXTRA_OBJS 参数来进行 make 构建
EXTRA_OBJS="contrib/prometheus-exporter/service-prometheus.o"
#在 HAProxy 2.4.x 版本,使用 USE_PROMEX 参数来进行 make 构建:
makeTARGET=linux-glibc USE_PROMEX=1
#编译安装
make install PREFIX=/usr/local/haproxy
# 定制命令软连接
ln-s /usr/local/haproxy/sbin/haproxy /usr/local/sbin/
/usr/local/sbin/haproxy -v
9.3.2.2 定制 Haproxy 服务功能
# 创建相关的配置文件目录
mkdir-p /etc/haproxy/ /var/lib/haproxy
# 准备错误文件
cp-r /usr/local/src/haproxy-2.5.0/examples/errorfiles /usr/local/haproxy/
ln-s /usr/local/haproxy/errorfiles /etc/haproxy/errorfiles
#准备配置文件
vim /etc/haproxy/haproxy.cfg
global
maxconn 100000
chroot /usr/local/haproxy
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
daemon
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local7 debug
defaults
option http-keep-alive
option forwardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
frontend stats
bind *:9999
stats enable
stats uri /haproxy-status
stats refresh 10s
http-request use-service prometheus-exporter if { path /metrics } #添加此行实
现/metrics暴露
#配置解析:http-request 属性表明,开启了一个专属的metrics的url地址
#准备service服务启动文件
vim /lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c-q
ExecStart=/usr/local/haproxy/sbin/haproxy -Ws-f /etc/haproxy/haproxy.cfg -p
/var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2$MAINPID
[Install]
WantedBy=multi-user.target
#属性解析:
-Ws代表haproxy启动的模式是 Master/Workers 的进程模式
-USR2是 haproxy的master-worker模式下自定义的软stop信号,可以通过 man haproxy 方式查看
#启动服务
systemctl daemon-reload
systemctl enable --now haproxy
systemctl status haproxy
#查看服务状态
pstree -p |grep haproxy
|-haproxy(15128)---haproxy(15130)---{haproxy}(15132)
s -tnulp | grep haproxy
tcp LISTEN 040960.0.0.0:9999 0.0.0.0:*
users:(("haproxy",pid=30582,fd=6))
#浏览器访问 http://10.0.0.106:9999/haproxy-status 页面

浏览器访问:http://10.0.0.106:9999/metrics 页面

9.3.2.3 修改 Prometheus 配置
#修改prometheus的配置文件,让它自动过滤文件中的节点信息
vim /usr/local/prometheus/conf/prometheus.yml
...
- job_name: "mertics_from_haproxy"
static_configs:
- targets: ["10.0.0.106:9999"]
#重启服务
systemctl restart prometheus.service
#稍等几秒钟,到浏览器中查看监控目标


9.3.2.4 Grafana 图形展示
#导入grafana的镜像模板文件 https://grafana.com/grafana/dashboards/12693 ,查看效果
#注意:两种方式的haproxy的grafana的模板不一样,使用的底层机制不太一样



9.4 Java 应用监控
对于 Java 应用, 可以借助于专门的jmx exporter方式来暴露相关的指标数据
#下载链接:
https://prometheus.io/download/
#官方地址:
https://github.com/prometheus/jmx_exporter
9.4.1 准备 Java 环境
#包安装Tomcat
[root@ubuntu2004 ~]#apt install tomcat9
#二进制安装Tomcat
#软件准备
mkdir-p /data/softs
cd /data/softs
#下载java或者上传java
#最新java8下载地址:
https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html
#安装java
tar xf jdk-8u121-linux-x64.tar.gz -C /usr/local
cd /usr/local/
ln-s jdk1.8.0_121 java
# 配置 java 环境变量
echo'export JAVA_HOME=/usr/local/java' >> /etc/profile.d/java.sh
echo'export JRE_HOME=$JAVA_HOME/jre' >> /etc/profile.d/java.sh
echo'export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar' >>
/etc/profile.d/java.sh
echo'export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH' >> /etc/profile.d/java.sh
source /etc/profile.d/java.sh
#检查效果
java -version
#获取软件tomcat
cd /data/softs
wget https://downloads.apache.org/tomcat/tomcat-9/v9.0.56/bin/apache-tomcat-
9.0.56.tar.gz
#解压软件
tar xf /data/softs/apache-tomcat-9.0.56.tar.gz -C /usr/local/
ln-s /usr/local/apache-tomcat-9.0.56 /usr/local/tomcat
#定制环境变量
echo'PATH=$PATH:/usr/local/tomcat/bin' >> /etc/profile.d/tomcat.sh
source /etc/profile.d/tomcat.sh
#尝试启动tomcat
catalina.sh start
#检查效果
netstat -tnulp | grep java
tcp6 00127.0.0.1:8005 :::* LISTEN
29447/java
tcp6 00 :::8080 :::* LISTEN
29447/java
9.4.2 准备 Jmx Exporter
#获取软件
wget
https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.16.1
/jmx_prometheus_javaagent-0.16.1.jar
#可能需要科学上网
wget
https://raw.githubusercontent.com/prometheus/jmx_exporter/master/example_configs
/tomcat.yml
#转移文件
#包安装tomcat
mv jmx_prometheus_javaagent-0.16.1.jar /usr/share/tomcat9/
mv tomcat.yml /usr/share/tomcat9/
#二进制安装tomcat
cp jmx_prometheus_javaagent-0.16.1.jar /usr/local/tomcat/bin/
cp tomcat.yml /usr/local/tomcat/bin/
#文件内容
cat tomcat.yml
---
lowercaseOutputLabelNames: true
lowercaseOutputName: true
rules:
- pattern: 'Catalina<type=GlobalRequestProcessor, name=\"(\w+-\w+)-(\d+)\"><>
(\w+):'
name: tomcat_$3_total
labels:
port: "$2"
protocol: "$1"
help: Tomcat global $3
type: COUNTER
- pattern: 'Catalina<j2eeType=Servlet, WebModule=//([-a-zA-Z0-9+&@#/%?
=~_|!:.,;]*[-a-zA-Z0-9+&@#/%=~_|]), name=([-a-zA-Z0-9+/$%~_-|!.]*),
J2EEApplication=none, J2EEServer=none><>
(requestCount|maxTime|processingTime|errorCount):'
name: tomcat_servlet_$3_total
labels:
module: "$1"
servlet: "$2"
help: Tomcat servlet $3 total
type: COUNTER
- pattern: 'Catalina<type=ThreadPool, name="(\w+-\w+)-(\d+)"><>
(currentThreadCount|currentThreadsBusy|keepAliveCount|pollerThreadCount|connecti
onCount):'
name: tomcat_threadpool_$3
labels:
port: "$2"
protocol: "$1"
help: Tomcat threadpool $3
type: GAUGE
- pattern: 'Catalina<type=Manager, host=([-a-zA-Z0-9+&@#/%?=~_|!:.,;]*[-a-zA-Z0-
9+&@#/%=~_|]), context=([-a-zA-Z0-9+/$%~_-|!.]*)><>
(processingTime|sessionCounter|rejectedSessions|expiredSessions):'
name: tomcat_session_$3_total
labels:
context: "$2"
host: "$1"
help: Tomcat session $3 total
type: COUNTER
#修改tomcat的启动脚本 catalina.sh
#包安装tomcat
vim /usr/share/tomcat9/bin/catalina.sh
JAVA_OPTS="-javaagent:/usr/share/tomcat9/jmx_prometheus_javaagent-
0.16.1.jar=2022:/usr/share/tomcat9/tomcat.yml"
# OS specific support. $var _must_ be set to either true or false.
#二进制安装tomcat
vim /usr/local/tomcat/bin/catalina.sh
......
# OS specific support. $var _must_ be set to either true or false.
JAVA_OPTS="$JAVA_OPTS$JSSE_OPTS"
JAVA_OPTS="-javaagent:/usr/local/tomcat/bin/jmx_prometheus_javaagent-
0.16.1.jar=2022:/usr/local/tomcat/bin/tomcat.yml"
#重启tomcat
catalina.sh stop
catalina.sh start
#查看效果
ss -tnulp | grep java
tcp LISTEN 01 [::ffff:127.0.0.1]:8005 *:*
users:(("java",pid=59676,fd=66))
tcp LISTEN 050 *:2181 *:*
users:(("java",pid=928,fd=60))
tcp LISTEN 03 *:2022 *:*
users:(("java",pid=59676,fd=13))
tcp LISTEN 050 *:40651 *:*
users:(("java",pid=928,fd=45))
tcp LISTEN 050 *:8080 *:*
users:(("java",pid=928,fd=52))
tcp LISTEN 050 *:7000 *:*
users:(("java",pid=928,fd=47))
#浏览器访问:
http://10.0.0.106:2022/metrics

9.4.3 修改 Prometheus 配置
#修改prometheus的配置文件,让它自动过滤文件中的节点信息
vim /usr/local/prometheus/conf/prometheus.yml
...
- job_name: "mertics_from_tomcat"
static_configs:
- targets: ["10.0.0.106:2022"]
#重启服务
systemctl restart prometheus.service
#稍等几秒钟,到浏览器中查看监控目标


9.4.4 Grafana 图形展示
#导入grafana的镜像模板文件 https://grafana.com/grafana/dashboards/8704 ,查看效果

注意:默认job为java , 需要修改job名称为前面prometheus中配置的job名称 mertics_from_tomcat


10 Kubernetes 集成 Prometheus

10.1 Operator 部署 Prometheus
github 参考链接
https://github.com/prometheus-operator/kube-prometheus

10.1.1 获取代码
cd /usr/local
wget https://github.com/prometheus-operator/kube-
prometheus/archive/refs/tags/v0.9.0.tar.gz
#或者:
git clone -b v0.9.0 https://github.com/prometheus-operator/kube-prometheus.git
#解压代码
tar xf v0.9.0.tar.gz
cd /usr/local/kube-prometheus-0.9.0/manifests/
10.1.2 修改配置
#创建命名空间
kubectl create ns monitoring
#修改prometheus的service
vim /usr/local/kube-prometheus-0.9.0/manifests/prometheus-service.yaml
...
spec:
ports:
- name: web
port: 9090
targetPort: web
nodePort: 30090#加下面两行
type: NodePort
...
#修改grafana的service
vim /usr/local/kube-prometheus-0.9.0/manifests/grafana-service.yaml
...
spec:
ports:
- name: http
port: 3000
targetPort: http
nodePort: 30030#加下面两行
type: NodePort
...
#修改alertmanager的service
vim /usr/local/kube-prometheus-0.9.0/manifests/alertmanager-service.yaml
...
spec:
ports:
- name: web
port: 9093
targetPort: web
nodePort: 30093#加下面两行
type: NodePort
...
#修改依赖镜像,将相关镜像都改为私有仓库里面的镜像
cd /usr/local/kube-prometheus-0.9.0/manifests/
sed-i-e's#quay.io/brancz/kube-rbac-
proxy:v0.11.0#harbor.wang.org:80/helm/kube-rbac-proxy:v0.11.0#'-e
's#quay.io/prometheus/node-exporter:v1.2.2#harbor.wang.org:80/helm/node-
exporter:v1.2.2#'-e's#k8s.gcr.io/prometheus-adapter/prometheus-
adapter:v0.9.0#harbor.wang.org:80/helm/prometheus-adapter:v0.9.1#'-e
's#quay.io/prometheus/prometheus:v2.29.1#harbor.wang.org:80/helm/prometheus:2.30
.2-debian-10-r3#'-e
's#quay.io/prometheus/alertmanager:v0.22.2#harbor.wang.org:80/helm/alertmanager:
0.23.0-debian-10-r41#'-e's#quay.io/prometheus/blackbox-
exporter:v0.19.0#harbor.wang.org:80/helm/blackbox-exporter:v0.19.0#'-e
's#jimmidyson/configmap-reload:v0.5.0#harbor.wang.org:80/helm/configmap-
reload:v0.5.0#'-e"s#k8s.gcr.io/kube-state-metrics/kube-state-
metrics:v2.1.1#harbor.wang.org:80/helm/kube-state-metrics:v2.2.0#"-e
's#grafana/grafana:8.1.1#harbor.wang.org:80/helm/grafana:8.1.1#'-e
's#quay.io/prometheus-operator/prometheus-
operator:v0.49.0#harbor.wang.org:80/helm/prometheus-operator:0.51.2-debian-10-
r1#'-e's#quay.io/prometheus-operator/prometheus-config-
reloader:v0.49.0#harbor.wang.org:80/helm/prometheus-config-reloader:v0.49.0#'
*.yaml setup/*.yaml
[root@prometheus manifests]#grep image: *.yaml setup/*.yaml
alertmanager-alertmanager.yaml: image:
harbor.wang.org:80/helm/alertmanager:0.23.0-debian-10-r41
blackbox-exporter-deployment.yaml: image:
harbor.wang.org:80/helm/blackbox-exporter:v0.19.0
blackbox-exporter-deployment.yaml: image:
harbor.wang.org:80/helm/configmap-reload:v0.5.0
blackbox-exporter-deployment.yaml: image: harbor.wang.org:80/helm/kube-
rbac-proxy:v0.11.0
grafana-deployment.yaml: image: harbor.wang.org:80/helm/grafana:8.1.1
kube-state-metrics-deployment.yaml: image: harbor.wang.org:80/helm/kube-
state-metrics:v2.2.0
kube-state-metrics-deployment.yaml: image: harbor.wang.org:80/helm/kube-
rbac-proxy:v0.11.0
kube-state-metrics-deployment.yaml: image: harbor.wang.org:80/helm/kube-
rbac-proxy:v0.11.0
node-exporter-daemonset.yaml: image: harbor.wang.org:80/helm/node-
exporter:v1.2.2
node-exporter-daemonset.yaml: image: harbor.wang.org:80/helm/kube-rbac-
proxy:v0.11.0
prometheus-adapter-deployment.yaml: image:
harbor.wang.org:80/helm/prometheus-adapter:v0.9.1
prometheus-prometheus.yaml: image: harbor.wang.org:80/helm/prometheus:2.30.2-
debian-10-r3
setup/prometheus-operator-deployment.yaml: image:
harbor.wang.org:80/helm/prometheus-operator:0.51.2-debian-10-r1
setup/prometheus-operator-deployment.yaml: image:
harbor.wang.org:80/helm/kube-rbac-proxy:v0.11.0

10.1.3 启动
#启动项目
cd /usr/local/kube-prometheus-0.9.0
kubectl apply -f manifests/setup/
kubectl apply -f manifests/
#检查效果
[root@prometheus ~]#kubectl get pods -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-main-0 1/2 Running 2 (2m59s ago) 11m
alertmanager-main-1 2/2 Running 0 11m
alertmanager-main-2 1/2 Running 2 (61s ago) 11m
blackbox-exporter-84dd4585c7-8g6rx 3/3 Running 3 (67s ago) 11m
grafana-cd5769bb6-zgmzx 1/1 Running 1 (67s ago) 11m
kube-state-metrics-5f4467bcb6-jck6v 3/3 Running 3 (61s ago) 11m
node-exporter-54q5x 2/2 Running 0 11m
node-exporter-hrxts 2/2 Running 13 (61s ago) 11m
node-exporter-kmtgk 2/2 Running 0 11m
node-exporter-lccvb 2/2 Running 14 (3m5s ago) 11m
node-exporter-rdtsc 2/2 Running 13 (2m32s ago) 11m
node-exporter-ss2m5 2/2 Running 0 11m
prometheus-adapter-67c6947497-55csz 1/1 Running 1 (3m4s ago) 11m
prometheus-adapter-67c6947497-lvk5v 1/1 Running 0 11m
prometheus-k8s-0 2/2 Running 2 (3m ago) 11m
prometheus-k8s-1 2/2 Running 0 11m
prometheus-operator-9f859c859-jr7gq 2/2 Running 2 (61s ago) 12m
[root@prometheus ~]#kubectl get svc -n monitoring
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
AGE
alertmanager-main NodePort 10.105.67.238 <none>
9093:30093/TCP 12m
alertmanager-operated ClusterIP None <none>
9093/TCP,9094/TCP,9094/UDP 12m
blackbox-exporter ClusterIP 10.109.208.248 <none>
9115/TCP,19115/TCP 12m
grafana NodePort 10.99.20.248 <none>
3000:30030/TCP 12m
kube-state-metrics ClusterIP None <none>
8443/TCP,9443/TCP 12m
node-exporter ClusterIP None <none> 9100/TCP
12m
prometheus-adapter ClusterIP 10.98.36.176 <none> 443/TCP
12m
prometheus-k8s NodePort 10.98.248.0 <none>
9090:30090/TCP 12m
prometheus-operated ClusterIP None <none> 9090/TCP
12m
prometheus-operator NodePort 10.111.4.57 <none>
8443:30443/TCP 12m
[root@prometheus ~]#kubectl get ep -n monitoring
NAME ENDPOINTS
AGE
alertmanager-main 10.244.3.7:9093
12m
alertmanager-operated 10.244.3.7:9094,10.244.3.7:9094,10.244.3.7:9093
12m
blackbox-exporter 10.244.4.2:9115,10.244.4.2:19115
12m
grafana 10.244.4.4:3000
12m
kube-state-metrics 10.244.5.2:8443,10.244.5.2:9443
12m
node-exporter 10.0.0.101:9100,10.0.0.102:9100,10.0.0.103:9100 +3
more... 12m
prometheus-adapter 10.244.3.8:6443,10.244.4.6:6443
12m
prometheus-k8s 10.244.3.9:9090,10.244.5.3:9090
12m
prometheus-operated 10.244.3.9:9090,10.244.5.3:9090
12m
prometheus-operator 10.244.5.6:8443
12m
[root@prometheus ~]#kubectl -n monitoring get all |
|---|
NAME READY STATUS RESTARTS AGE |
pod/alertmanager-main-01/2 Running3 (41s ago) 13m |
pod/alertmanager-main-12/2 Running0 13m |
pod/alertmanager-main-21/2 Running3 (39s ago) 13m |
pod/blackbox-exporter-84dd4585c7-8g6rx3/3 Running3 (2m48s ago) 13m |
pod/grafana-cd5769bb6-zgmzx1/1 Running1 (2m48s ago) 13m |
pod/kube-state-metrics-5f4467bcb6-jck6v3/3 Running3 (2m42s ago) 13m |
pod/node-exporter-54q5x2/2 Running0 13m |
pod/node-exporter-hrxts2/2 Running13 (2m42s ago) 13m |
pod/node-exporter-kmtgk2/2 Running0 13m |
pod/node-exporter-lccvb2/2 Running14 (4m46s ago) 13m |
pod/node-exporter-rdtsc2/2 Running13 (4m13s ago) 13m |
pod/node-exporter-ss2m5 |
2/2 Running0 13m |
|---|---|
pod/prometheus-adapter-67c6947497-55 |
csz1/1 Running1 (4m45s ago) 13m |
pod/prometheus-adapter-67c6947497-lv |
k5v1/1 Running0 13m |
pod/prometheus-k8s-0 |
2/2 Running2 (4m41s ago) 13m |
pod/prometheus-k8s-1 |
2/2 Running0 13m |
pod/prometheus-operator-9f859c859-jr |
7gq2/2 Running2 (2m42s ago) 13m |
NAME TYPE |
CLUSTER-IP EXTERNAL-IP |
PORT(S) AGE |
|
service/alertmanager-main Node |
Port10.105.67.238 <none> |
9093:30093/TCP 13m |
|
service/alertmanager-operated Clus |
terIP None <none> |
9093/TCP,9094/TCP,9094/UDP 13m |
|
service/blackbox-exporter Clus |
terIP10.109.208.248 <none> |
9115/TCP,19115/TCP 13m |
|
service/grafana Node |
Port10.99.20.248 <none> |
3000:30030/TCP 13m |
|
service/kube-state-metrics Clus |
terIP None <none> |
8443/TCP,9443/TCP 13m |
|
service/node-exporter Clus |
terIP None <none> |
9100/TCP 13m |
|
service/prometheus-adapter Clus |
terIP10.98.36.176 <none> |
443/TCP 13m |
|
service/prometheus-k8s Node |
Port10.98.248.0 <none> |
9090:30090/TCP 13m |
|
service/prometheus-operated Clus |
terIP None <none> |
9090/TCP 13m |
|
service/prometheus-operator Node |
Port10.111.4.57 <none> |
8443:30443/TCP 13m |
|
NAME DESIR |
ED CURRENT READY UP-TO-DATE AVAILABLE |
NODE SELECTOR AGE |
|
daemonset.apps/node-exporter6 |
6666 |
kubernetes.io/os=linux 13m |
|
NAME |
READY UP-TO-DATE AVAILABLE AGE |
deployment.apps/blackbox-exporter |
1/111 13m |
deployment.apps/grafana |
1/111 13m |
deployment.apps/kube-state-metrics |
1/111 13m |
deployment.apps/prometheus-adapter |
2/222 13m |
deployment.apps/prometheus-operator |
1/111 13m |
NAME |
DESIRED CURRENT READY AGE |
replicaset.apps/blackbox-exporter-84 |
dd4585c7111 13m |
replicaset.apps/grafana-cd5769bb6 |
111 13m |
replicaset.apps/kube-state-metrics-5 |
f4467bcb6111 13m |
replicaset.apps/prometheus-adapter-6 |
7c6947497222 13m |
replicaset.apps/prometheus-operator- |
9f859c859111 13m |
NAME |
READY AGE |
statefulset.apps/alertmanager-main |
1/3 13m |
statefulset.apps/prometheus-k8s |
2/2 13m |
10.2 基本使用
10.2.1 登录 Prometheus
访问prometheus的浏览器地址: 10.0.0.101:30090

结果显示:这里有大量自动监控到的节点信息
10.2.2 尝试进行数据的采集
例如查询K8S集群中每个POD的CPU使用情况,可以使用如下查询条件查询:
提示:metrics的指标名称 container_cpu_usage_seconds_total
sum(rate(container_cpu_usage_seconds_total{image!="", pod!=""}[1m] )) by (pod)

10.2.3 访问 Alertmanager
访问alertmanager的浏览器地址: 10.0.0.101:30093

10.2.4 Grafana 展示
访问grafana的浏览器地址: 10.0.0.101:30030,首次登录时账号密码默认为:admin/admin

首次登录需要修改密码


#结果显示:自动帮我们定制好大量prometheus的数据库连接地址,我们可以直接使用它,具体代码如下:
cat /usr/local/kube-prometheus-0.9.0/manifests/prometheus-adapter-
deployment.yaml
...
spec:
...
spec:
containers:
- args:
---cert-dir=/var/run/serving-cert
---config=/etc/adapter/config.yaml
---logtostderr=true
---metrics-relist-interval=1m
---prometheus-url=http://prometheus-
k8s.monitoring.svc.cluster.local:9090/
---secure-port=6443
...
点击左侧"+"弹框里面的import",将https://grafana.com/dashboards/8919 添加到prometheus里面, 效果如下



10.3 Ingress 定制
10.3.1 配置Ingress代理
#获取配置文件,可能需要科学上网才能下载
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-
v1.0.3/deploy/static/provider/baremetal/deploy.yaml
#修改镜像
grep image: deploy.yaml
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-
ingress-
controller:v1.0.3@sha256:4ade87838eb8256b094fbb5272d7dda9b6c7fa8b759e6af5383c130
0996a7452
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-
webhook-
certgen:v1.0@sha256:f3b6b39a6062328c095337b4cadcefd1612348fdd5190b1dcbcb9b9e90bd
8068
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-
webhook-
certgen:v1.0@sha256:f3b6b39a6062328c095337b4cadcefd1612348fdd5190b1dcbcb9b9e90bd
8068
#部署ingress controller服务
kubectl apply -f deploy.yaml
#定制ingress代理
cat > ingress-prometheus.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-prometheus
namespace: monitoring
annotations:
kubernetes.io/ingress.class: "nginx"
prometheus.io/http_probe: "true"
spec:
rules:
- host: alert.localprom.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: alertmanager-main
port:
number: 9093
- host: grafana.localprom.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
- host: prom.localprom.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prometheus-k8s
port:
number: 9090
EOF
#应用资源配置文件
kubectl apply -f ingress-prometheus.yaml
#配置ingress的域名映射
# vim /etc/hosts
10.0.0.101 grafana.localprom.com alert.localprom.com prom.localprom.com
#查看效果
kubectl get ingress -n monitoring
NAME CLASS HOSTS
ADDRESS PORTS AGE
ingress-prometheus <none>
alert.localprom.com,grafana.localprom.com,prom.localprom.com 80
26s
kubectl describe ingress ingress-prometheus -n monitoring
Name: ingress-prometheus
Namespace: monitoring
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-
backend" not found>)
Rules:
Host Path Backends
----------------
alert.localprom.com
/ alertmanager-main:9093
(10.244.3.7:9093,10.244.5.4:9093,10.244.5.5:9093)
grafana.localprom.com
/ grafana:3000 (10.244.4.4:3000)
prom.localprom.com
/ prometheus-k8s:9090
(10.244.3.9:9090,10.244.5.3:9090)
Annotations: kubernetes.io/ingress.class: nginx
prometheus.io/http_probe: true
Events:
Type Reason Age From Message
-------------------------
Normal Sync 32s nginx-ingress-controller Scheduled for sync
10.3.2 访问测试
#浏览器分别访问:如下地址
prom.localprom.com
alert.localprom.com
grafana.localprom.com

10.4 Kubernetes 组件
默认情况下,prometheus没有监控到 controller 和 scheduler的信息

prometheus 要监控k8s的组件,需要关注一下几点:
Kubernetes必须开放controller和scheduler的监听地址,要定制专用的endpoint和svc资源对象 Prometheus是根据 kubernetes-serviceMonitorKubeScheduler.yaml和kubernetesserviceMonitorKubeControllerManager.yaml 文件来进行监控的
所以,定制的svc关联出来的 labels 必须要与kube-prometheus的值一致
10.4.1 开放相关地址
#修改kube-controller-manager的监听地址
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
grep bind /etc/kubernetes/manifests/kube-controller-manager.yaml
---bind-address=0.0.0.0
#修改kube-scheduler的监听地址
vim /etc/kubernetes/manifests/kube-scheduler.yaml
grep bind /etc/kubernetes/manifests/kube-scheduler.yaml
---bind-address=0.0.0.0
10.4.2 定制采集 Controller 数据
cat > kube-controller-namager-svc-ep.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: kube-controller-manager
namespace: kube-system
labels:
app.kubernetes.io/name: kube-controller-manager
spec:
type: ClusterIP
clusterIP: None
ports:
- name: http-metrics
port: 10252
targetPort: 10252
protocol: TCP
- name: https-metrics
port: 10257
targetPort: 10257
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: kube-controller-manager
namespace: kube-system
labels:
app.kubernetes.io/name: kube-controller-manager
subsets:
- addresses:
- ip: 10.0.0.101
ports:
- name: http-metrics
port: 10252
protocol: TCP
- name: https-metrics
port: 10257
protocol: TCP
EOF
#属性解析:这里面的 addresses 应该是master的节点地址
#执行资源定义文件
kubectl apply -f kube-controller-namager-svc-ep.yaml
#查看效果
kubectl get ep -n kube-system
10.4.3 定制采集 Scheduler 数据
cat > kube-scheduler-svc-ep.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: kube-scheduler
namespace: kube-system
labels:
app.kubernetes.io/name: kube-scheduler
spec:
type: ClusterIP
clusterIP: None
ports:
- name: http-metrics
port: 10251
targetPort: 10251
protocol: TCP
- name: https-metrics
port: 10259
targetPort: 10259
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: kube-scheduler
namespace: kube-system
labels:
app.kubernetes.io/name: kube-scheduler
subsets:
- addresses:
- ip: 10.0.0.101
ports:
- name: http-metrics
port: 10251
protocol: TCP
- name: https-metrics
port: 10259
protocol: TCP
EOF
#属性解析:这里面的 addresses 应该是master的节点地址
#执行资源定义文件
kubectl apply -f kube-scheduler-svc-ep.yaml
#查看效果
kubectl get ep -n kube-system
10.4.4 查看效果


结果显示:新增加了两个服务,如果这两个服务不正常的话,只有一个原因,controller或者scheduler 的服务不正常,需要确保这两个服务式正常的。