✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生k8s,Prometheus监控,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:Prometheus监控系统零基础到进阶
景天的主页:景天科技苑
文章目录
1、Prometheus的特点
1.1 多维数据模型
Prometheus 采⽤多维度的数据模型,可以对不同维度的数据进⾏监控和分析,同时PromQL可以对数据进⾏复杂的计算、过滤和查询等操作。
当使⽤Prometheus 监控⼀个 Web 服务时,通常需要收集的数据包括:服务地址以及端⼝、请求uri、请求的⽅法、请求的次数、以及请求状态码等指标。
在 Prometheus 的多维数据模型中,我们可以通过定义不同的标签来为"同⼀个指标"添加不同的维度。
例如,我们可以定义 http_total 为⼀个指标名称,它⽤于记录 HTTP 的总请求数,同时使⽤实例(instance)、路径(path)、⽅法(method)等标签来为该指标添加不同的维度。
假设我们有两个实例,分别是 ip1 和 ip2,我们可以⽤以下⽅式记录数据:
# 这⾥我们记录了每个实例上的 HTTP 请求总数,并通过不同的标签来记录请求、路径以及⽅法等
http_total{instance="ip1", path="/api", method="GET"} 500
http_total{instance="ip1", path="/api", method="POST"} 200
http_total{instance="ip2", path="/user", method="GET"} 1000
http_total{instance="ip2", path="/user", method="POST"} 300
有了这些指标对应的数据后,我们就可以通过PromQL来对数据进⾏各种统计和分析,例如,可以查询ip1这个实例上的 HTTP 请求数的总和
sum(http_total{instance="ip1"})
# 结果展示
{} 700
当然也可以查询某个路径上的请求⽅法分布情况,
例如:统计所有http请求中
path=“/api” 的总次数,然后基于method标签进⾏分组,可以拿到请求/api这个接⼝,GET⽅法请求了多少次,POST⽅法请求了多少次。
sum (http_total{path="/api"}) by (method)
# 结果展示
{method="GET"} 500
{method="POST"} 200
总之,通过多维数据模型,我们可以为每个指标添加不同的维度,同时也可以根据不同的维度进⾏数据的灵活查询与聚合等操作。
1.2 强⼤的PromQL
PromQL(Prometheus Query Language)是 Prometheus 的核⼼特性,它提供了强⼤且灵活的查询功能。相⽐之下,许多传统的监控系统只能进⾏简单的数据过滤和阈值判断,⽽缺乏类似的查询语⾔。
当我们需要特定的数据在原始数据中没有时,许多监控系统会在数据采集阶段(即在源头收集数据的阶段)进⾏处理。然⽽,数据采集阶段并不适合进⾏所有的计算场景。
以机器内存监控为例,我们可以从 /proc/meminfo 获得各种相关数据,如 MemAvailable 和 MemTotal 。但是操作系统并不直接提供“内存使⽤率”相关的指标。
在Zabbix中,你需要在数据源(被监控端)预先计算出内存使⽤率,然后传递给Zabbix服务器进⾏监控和告警。
而在Prometheus中,我们可以利⽤其查询语⾔PromQL在中⼼服务器上直接计算内存使⽤率: MemAvailable / MemTotal * 100 ,这种设计理念使Prometheus在处理复杂计算和告警场景
时具有更⾼的灵活性。
数据采集阶段专注于收集原始数据,⽽复杂的计算由中⼼服务器(即Prometheus)处理。
通过PromQL可以轻松解决如下问题:
预测在12⼩时后,磁盘空间是否会被占满?
CPU占⽤率前5位的服务有哪些?(过滤)
过去1分钟的系统负载超过了其 CPU 核⼼数两倍的实例有哪些?
4.3 ⾼效的数据存储
Prometheus 使⽤专⽤的时间序列数据库。这种数据库⾮常强⼤,能够“容纳和处理”数以百万计的监控指标。这些监控指标,都按照时间顺序排列并储存,每个数据点都配有⼀个时间戳。
所有的监控数据都精确地记录在这个时间点上。所以当你想要查看某个特定时间点的数据时,你可以直接提取对应的时间点,快速地找到所需的数据。⽆需遍历整个数据库。
Prometheus不仅拥有⾼效的查询能⼒,⽽且还具有出⾊的存储效率,这主要
得益于它所采⽤的压缩算法。该算法使得每个数据点所占⽤的存储空间约3.5字节。
这种优化的存储⽅式⼤幅的降低了IO操作,以及存储的成本。
根据官⽅的数据,百万条的时间序列数据,每30秒记录⼀次,并且需要保留60天的历史数据,仅需要200GB左右的存储空间。这种⾼效的存储⽅式使Prometheus能够轻松处理⼤规模数据,同时维持低成本。
1.4 多种服务发现
在实际应⽤中,我们监控的实例或者服务经常会发⽣动态变化,如容器实例的
创建和销毁等,因此Prometheus提供了多种服务发现⽅式来应对这种挑战。
这些⽅式包括:
1、静态服务配置:可以通过配置⽂件指定固定地址和端⼝,对⽬标服务进⾏监控。
2、基于配置⽂件的发现机制:以配置⽂件作为发现的源头,通过监控这些⽂件的变动来动态调整监控⽬标的增加或减少。
通常会配合如像Ansible这样的⼯具⼀起使⽤,对配置⽂件进⾏批量更新,只需要让Prometheus
重新加载这些配置,就能⾃动适应新的监控环境。
3、基于注册中⼼的发现机制:在微服务架构中,常常会使⽤Consul等服务注册中⼼来管理所有的服务。
Prometheus可以读取Consul中的服务列表,从⽽⾃动发现并开始监控所有注册的服务。
4、基于公有云API的发现机制:当你需要监控公有云上的RDS服务时,⼀条条配置⾮常麻烦,这个时候就可以使⽤Prometheus基于公有云的OpenAPI进⾏服务发现。
例如,配置Prometheus⾃动拉取AWS账号下所有RDS实例的列表,从⽽实现对所有数据库实例的监控
5、基于 Kubernetes 的发现机制:在Kubernetes环境中,Prometheus可以通过调⽤kube-apiserver获取集群中的Node、Pod、Endpoint、Ingress等信息。
例如,如果你在Kubernetes集群中部署了⼀个新的应⽤,Prometheus可以⾃动发现并开始监控这个新的Pod。
6、基于 DNS、HTTP等等服务发现,使⽤的不多,就不⼀⼀展开
https://prometheus.io/docs/prometheus/latest/configuration/configuration/
1.5 可扩展的架构
Prometheus⽀持横向扩展,可以通过部署多个实例、使⽤ “远程存储“ 或者使⽤Prometheus联邦等⽅式实现⾼可⽤和⾼性能的监控系统。
例如,为了应对⼤规模监控需求,可以部署多个Prometheus实例并将它们配置为监控不同的服务或资源。
同时,可以使⽤Prometheus将这些实例的数据汇总到⼀个中⼼实例中,实现统⼀的监控视图。
1.6 总结
综上所述Prometheus 具有灵活性、强⼤的查询语⾔、服务发现⾃动化、数据采集⾼效、架构可扩展等特点,是⼀款⾮常适合⽤于⼤规模监控系统的开源软件。
2、Prometheus数据采集
2.1 Prometheus数据采集⽅式
在传统的Zabbix监控系统中,通常是需要在被监控的节点上安装Agent代理程序。由Agent代理程序定期收集指标数据,并将其发送到监控服务器,完成数据采集。
在Prometheus中,被监控端⽆需安装专⻔的Agent。它只需要“被监控端通过HTTP协议开放出符合Prometheus规范的指标数据”,Prometheus就能够顺利完成数据抓取。
但是,并不是所有的应⽤或服务都能直接⽀持HTTP协议并提供符合Prometheus所兼容的指标格式。
因此,Prometheus设计了三种主要的数据抓取机制,即Instrumentation、Exporter和PushGateway
1、 Instrumentation :被监控端通过HTTP暴露出Prometheus格式的数据,Prometheus就可以直接采集,这就是所谓的Instrumentation。像 Kubernetes、Haproxy、Zookeeper、RabbitMQ、Etcd 等应⽤程序原⽣就⽀持暴露指标,可以直接被Prometheus所监控。
对于Python、Java、Go这些开发语⾔编写的业务应⽤,开发⼈员可以直接引⽤Prometheus客户端库来编写代码,让应⽤程序原⽣就能⽀持暴露需要监控的指标数据,这些指标数据可以直接被Prometheus采集。
这就相当于应⽤程序本身具备了与Prometheus 通信的能⼒,⽆需额外的中间件来转换数据。
2、 Exporter(导出器) :有些应⽤程序并不原⽣⽀持通过 HTTP 协议暴露指标数据。对于这类应⽤,我们可以使⽤ Exporter 来代为采集指标。
Exporter 是⼀个独⽴的运⾏程序,负责从⽬标应⽤中采集原始格式的数据,并将其转换为 Prometheus 可以理解的格式,然后通过HTTP协议暴露出来,供Prometheus抓取指标。
简单来说,Exporter 就像⼀个翻译官,将⽬标应⽤程序的数据翻译成 Prometheus 可以读懂的语⾔。
3、PushGateway(推送⽹关) :对于那些⽣命周期较短或者不⽅便被Prometheus 主动拉取数据的应⽤程序(如短暂运⾏的脚本任务)可以使⽤PushGateway。
让这些短暂运⾏的脚本程序,将对应的指标数据主动推送到PushGateway,然后 Prometheus 从 PushGateway 中抓取(pull)这些数据。PushGateway 就像⼀个中间站,存储这些短暂任务产⽣的指标数据,等待Prometheus 来抓取。
数据抓抓取:
Prometheus仅支持Pull模型,主动抓去,并不支持Push
Instrumentation:haproxy、
exporter:类似于zabbix-agent、node_exporter、mysqld_exporter、nginx_exporter、jvm_exporter、tomcat_...
pushgateway: 它支持短暂的脚本--push给 pushgateway <--- pull --- prometheus
2.2 Prometheus作业与实例
在Prometheus中,被监控的每⼀个对象都称为实例(Instance) 实例代表着⼀个独⽴的监控⽬标,它由IP地址加端⼝号组合⽽成,如 localhost:9090 。
在Prometheus的配置中,这些实例也可以被称
为”⽬标(Target)“或者“端点(Endpoint)”
为了⽅便管理这些⽬标实例,我们通常会将功能相似或者类型相同的(实例Instance)归纳到⼀个“作业(Job)”中。
实例(Instances):实例指的是⼀个被监控的端点。它通常是指向⼀个运⾏的服务或应⽤程序的进程,每个实例都以host:port进⾏标识。例如,⼀个MySQL数据库服务运⾏在 10.0.0.51:3306 上,那么它就是⼀个实例。
作业(Jobs):作业是⼀组具有相同类型的实例集合。例如,多个分布在不同服务器上MySQL应⽤,你可以将这些实例归类为同⼀个 mysql 的Job作业,而后按照Job分组后的维度进⾏分析。
在Prometheus的数据模型中,job和instance是两个核⼼的标签,它们会⾃动
附加到所有收集的时间序列数据上。如下所示:
# 查询
cpu_usage
# 结果
cpu_usage{job="node-exporter",instance="10.0.0.7"} 14.04
cpu_usage{job="node-exporter",instance="10.0.0.8"} 12.04
cpu_usage{job="node-exporter",instance="10.0.0.9"} 16.04
3、Prometheus架构
3.1 Prometheus⽣态组件
Prometheus最为核⼼的功能就是“数据采集”和“数据存储”。但是,仅有这两项功能并不能构成⼀个完整的监控系统。
因此,Prometheus需要与其他的组件进⾏结合,从而实现数据的分析、展示和告警,因此⼀个完整意义上的监控系统⼤体需要如下5个组成部分:
1、数据采集:Prometheus采⽤Pull模式主动向被监控端抓取指标数据。被监控端可以是直接暴露出的应⽤程序指标数据,也可以是通过安装Exporter来抓取和暴露应⽤程序的数据。只要是以Prometheus格式提供的指标数据,都可以被Prometheus抓取。
2、数据存储:Prometheus会将抓取到的数据,存储在本地的时间序列数据库中,以防止数据丢失。
3、数据查询和分析:Prometheus内置了强⼤的查询语⾔PromQL,⽤户可以通过PromQL查询存储在Prometheus上的时序数据,进⾏实时查询和分析。
同时PromQL⽀持多种聚合操作和数学运算,可以对数据进⾏深⼊分析。
4、告警系统:Prometheus的告警分为了两个部分组成,告警规则和Alertmanager。
告警规则定义在Prometheus服务器中,根据⽤户指定的条件触发告警。当告警触发时,Prometheus服务器会将告警信息发送给Alertmanager。
Alertmanager会对告警信息进⾏去重、分组,然后将告警消息通过媒介发送给接收者(如邮件、钉钉等)。
5、数据可视化:Prometheus内置了⼀个简单的图形界⾯,⽤户可以在Web浏览器中使⽤PromQL查询时序数据,并将查询结果以图形的形式展示出来。
此外,Prometheus还可以与第三⽅可视化⼯具(如Grafana)集成,提供更丰富的可视化功能。
3.2 Prometheus⼯作逻辑
了解Prometheus⽣态中的各个组件后,我们可以概括其⼯作流程:⽬标发现、数据抓取、存储、分析、告警和展示。
这些步骤共同构成了Prometheus强⼤的监控和告警系统。
1、⽬标发现:在开始监控之前,Prometheus需要确定监控⽬标。它可以通过静态的配置⽂件指定,或者利⽤服务发现机制动态地发现需要监控的服务。
例如,在Kubernetes环境中,Prometheus能够⾃动识别并监控集群中的服务,
确保随着集群的变化,监控⽬标始终是最新的。
2、数据抓取:有了明确的监控⽬标后,Prometheus通过HTTP协议定期从这些⽬标的 /metrics 端点抓取指标数据。这些端点暴露了各种监控指标。
3、数据存储:数据抓取后会存储在本地的时间序列数据库中。
4、数据分析:数据⼀旦被存储,就可以⽤PromQL查询语⾔,对其进⾏分析。
⽆论是实时监控还是历史数据分析,PromQL都能提供丰富的数据聚合功能,以洞察系统的状况。
5、告警:Prometheus根据预定义的规则进⾏评估。当监控的指标达到告警阈值时,Prometheus会将告警信息发送给Alertmanager,由Alertmanager进⾏告警处理并通知。
6、数据可视化:Prometheus⾃带了简单的UI。但对于更⾼级的数据可视化需求,通常会整合Grafana这样的⼯具来为⽤户提供直观的数据展现⽅式。
4、Prometheus数据模型
4.1 数据模型基础
Prometheus中最为重要的是,对指标进⾏抓取和存储,这些存储下来的数据可以帮助我们分析趋势,或预测未来。
为了更有⾼效的存储和查询这些数据,Prometheus使⽤了⼀种叫"时间序列"的数据格式进⾏存储,所谓时间序列就是按照时间顺序记录所采集到的指标以及指标数据。
而每个时间序列都是由“⼀个指标名称加⼀堆标签”所组成的⼀条唯⼀序列标识,其格式 :
<metric_name>{<label_name>=<label_value>, <label_name>=<label_value>, ...} @<timestamp> <value>
举个例⼦:我们连续记录和测量“植物的⾼度”。在这个例⼦中:
1、metrics_name:记录“植物的⾼度”。
2、label_name和label_value:记录植物的其他信息,例如植物的种类为向⽇葵,所种植的位置是阳台,等等信息,这些这些额外的信息就被称为标签,它们会附加在指标上,帮助我们更好地分类和理解数据的意义。
3、timestamp和value:每次测量植物的⾼度,会记录下测量的⽇期(即时间戳)和那⼀天植物的⾼度(即值)。
通过这种⽅式,Prometheus可以跟踪,随时间变化的任何指标,并且可以通过标签来分类和组织这些数据。
4.2 指标名称MetricName
在监控系统中,我们需要抓取的指标⾮常多,如CPU使⽤率、内存使⽤情况、⽹络流量等。我们使⽤ MetricsName 来区分这些不同指标。
这些指标名称⼀般由⼩写字⺟、数字和下划线构成。例如, cpu_usage 这个指标代表CPU的使⽤率,它的值为 15.05 ,则表示当前CPU的使⽤率为 15.05% 。
但是,cpu_usage 这个指标并没有具体表明它是针对是哪个节点的 CPU 使⽤率,也没有指出是哪个 CPU 核⼼的使⽤率。
因此,为了区分,并确定不同节点上各个 CPU 核⼼的使⽤率,我们需要引⼊label(标签)这⼀机制。
4.3 指标标签Labels
标签以键值对的形式存在,为指标添加了详细信息和上下⽂(元数据)。例如,在我们之前提及的指标 cpu_usage 中,为了区分来⾃不同节点的 CPU使⽤情况,我们可以利⽤标签。
给每个节点的指标添加⼀个 instance 标签,就可以在查询和分析时,区分开每个节点的cpu使⽤率。
假设我们现在两个节点,名称分别为 node01.oldxu.net 和 node02.oldxu.net ,我们可以为各⾃的 cpu_usage 指标添加指定的 instance 标签:
当然标签除了区分节点之外,我们还可以使⽤标签来继续描述其他维度,例如CPU的各个核⼼的使⽤率。
我们可以添加⼀个 core 的标签来区分每个节点的CPU核⼼使⽤情况:
通过使⽤标签,我们能在 Prometheus 中查询和分析数据。例如,我们想查询node1上各个CPU核⼼使⽤情况,或者查询node02节点CPU的第0个核⼼使⽤情况
# 查询node01节点的各CPU核⼼使⽤率
cpu_usage{instance="node01.oldxu.net"}
# 结果
cpu_usage{instance="node01.oldxu.net",core="0"} 7.535
cpu_usage{instance="node01.oldxu.net",core="1"} 7.535
# 查询node02节点,核⼼为0的CPU使⽤率
cpu_usage{instance="node02.oldxu.net",core="0"}
# 结果
cpu_usage{instance="node01.oldxu.net",core="0"} 8.025