1 监控基本概念
1.1 什么是监控
监控就是持续不间断地对系统或服务进⾏监视,以确保我们的系统或服务⼀直处于正常运⾏的状态。
当然要想保证系统时刻处于健康的状态,我们需要配置对应的监控策略,便于我们及时检测到系统中可能出现的各种问题,如CPU使⽤率激增、内存耗尽或磁盘空间不⾜等。当这些问题被发现时,监控系统可以警告通知我们,这样我们就可以迅速介⼊,⽽后对出现的问题进⾏诊断和解决,从⽽保证系统的稳定性和可靠性。
同时,监控在整个运维过程、以及整个产品⽣命周期中都⾮常重要,它具有以下⼏个特性:
1、事前预警:监控能够在故障发⽣前发出警报,帮助我们提前发现问题,规避问题。
例如,我们设定了当内存使⽤率超过80%时,就触发告警。⼀旦达到阈值,监控系统会通过邮件、微信、钉钉、⻜书、如流、短信等媒介,发送告警通知。这样,相关⼈员可以及时介⼊,进⾏故障处理,避免因内存耗尽导致系统崩溃,从⽽有效地降低故障率。
2、事后追溯:利⽤监控获取到的数据,来快速分析故障所产⽣的原因。
例如,当⽹站服务出现反应迟钝时,我们可以对⼀些关键指标数据进⾏分析,如数据库查询的延迟、CPU负载、磁盘IO、等等。这些异常变动可能就是引发问题的关键线索。有了这样的线索后,我们能更迅速地追查和定位问题。
3、趋势分析:根据监控指标返回的数据,我们可以了解到系统性能以及资源使⽤的变化趋势。基于这些数据,我们可以预测未来可能出现的问题。
例如,我们有⼀个1TB的硬盘。通过监控,发现每天的数据增量约为30GB。那么在这种情况下,我们就可以利⽤趋势分析来预测硬盘会在何时满载。通过简单的计算就能得出,硬盘⼤约在33天后被填满(剩余的天数)。这样分析的信息极其有⽤,因为我们可以提前采取⾏动,例如,提前清理⽆⽤的数据,或者增加更多的存储空间,以防⽌硬盘被填满。
4、对⽐分析:通过对⽐不同时间段下的监控数据,分析系统在不同的情况下的表现。
例如,⽹站在正常⼯作⽇,每分钟处理100次交易。但在周末或⼤促期间,交易量可能飙升⾄每分钟1000次。这种激增可能导致系统响应缓慢,数据库查询效率下降,甚⾄⻚⾯加载延迟。在这种情况下,我们可以对⽐这两个时间段的数据,详细观察系统在⾼交易量时的负载表现,分析问题可能出在哪⾥,是数据库延迟,服务器资源不⾜,还是代码执⾏效率低下。有了这些具体信息,我们就能针对性地采取优化措施,例如,提升数据库查询效率,增加服务器资源,或优化代码等,以提升系统性能,并保证其稳定运⾏。
5、数据可视化:将数据以图形的⽅式展示,使我们能够更容易地了解系统的当前状态和性能。
例如:我们可以通过可视化⼯具⽣成的动态图表,来实时展示集群的负载、内存的使⽤、磁盘I/O等关键指标。这些直观的图形使我们能够洞察到系统状态的变化和趋势。同时数据可视化以图形的⽅式提供了⽐数字更清晰、更易理解的信息,极⼤地提⾼了我们分析性能指标的效率,从⽽加强了故障排查和性能优化的能⼒。
PS:总之,监控是⽤来确保系统稳定、⾼效运⾏的关键⼿段,它帮助我们提前发现问题、定位问题,以及解决问题。
1.2 监控的⽬标
在复杂的IT环境中,我们需要监控的⽬标⾮常之多,如:硬件、⽹络设施、操作系统、应⽤程序及相关的业务等。为了帮助我们更有效地进⾏监控,我们将这些监控的⽬标划分为如下⼏个主要的类别:
1.3 监控的⽅式
在了解了需要监控的各类⽬标后,我们需要选择合适的监控⽅式才能有效地跟踪和管理这些⽬标。监控系统主要包含两种监控⽅式:⽩盒监控和⿊盒监控。
⽩盒监控:这种监控⽅式主要关注"问题的根本原因",它通过分析系统内部暴露的各种指标,来发现可能产⽣的问题。
例如,在使⽤Redis时,我们可以利⽤info命令获取众多的内部指标数据,从⽽了解Redis的当前运⾏状态。假如Redis所关联的从节点发⽣了宕机的情况,那么相应的指标就会显示 redis slave down ,这样,我们就能够迅速地定位并解决问题。因此,⽩盒监控主要是通过分析内部指标,并通过这些指标反馈的信息来找出问题的根源。
⿊盒监控:这种监控⽅式主要关注"问题的表⾯现象",通常,它会通过TCP、HTTP等探针的⽅式模拟⽤户的请求,来获取服务的指标数据(例如,响应时间、站点可⽤性等)。
例如,Redis所关联的从节点发⽣宕机时,⿊盒监控可能会返回像 Connecti on refused 或Connection timeout 这样的提示等信息,⽽不会像⽩盒监控那样提示redis slave down 。因此,⿊盒监控的主要⽬标是站在⽤户的⻆度,关注他们在实际使⽤过程中可能遇到的问题,⽽不会去探究问题的根源。
PS:因此,⽩盒监控和⿊盒监控是两种相辅相成的⽅法,它们让我们能够从不同⻆度深⼊理解系统的运⾏状况。当我们将这两种监控⽅式结合使⽤时,可以更全⾯地了解系统的当前运⾏状况,提前发现并解决问题,从⽽更好地维护和优化系统,同时也能保障业务的稳定运⾏。
2 著名的监控⽅法论
2.1 ⽅法论的重要性
我们前⾯讨论了要监控的⽬标和监控的⽅式。思考⼀下,如果我们有100台主机,每台主机运⾏200个应⽤,每个应⽤⼜有上百个指标需要追踪。这就意味着我们需要处理⼆⼗万个监控的指标。那么在这种情况下,若对所有指标都设置告警,我们很快就会被告警信息淹没。所以,我们需要明确应⽤的哪些指标是最关键的,应优先关注,并在出现异常情况下触发告警。
解决这个问题的⽅法是引⼊⼀些成熟的监控⽅法论。这些⽅法论帮助我们识别出最重要的指标,让我们可以将注意⼒集中在这些指标上,并在这些指标出现异常时触发告警。⽬前,业界⼴泛采⽤的监控⽅法论包括Google的四个⻩⾦指标、以及RED⽅法和USE⽅法。
2.2 四个⻩⾦指标
Google 的四个⻩⾦指标着眼点在“服务监控”,这四个指标分别是“延迟、流量、错误、饱和度”。
1、延迟(Latency):指⼀个服务完成请求所需的时间。
例如,你在⼀个购物⽹站点击了“查看商品列表”的按钮,从你点击按钮到商品列表完全显示在你的屏幕上,假设所需的时间是1秒,那么我们就说这个服务的延迟是1秒。然⽽,这个延迟计算需要考虑的是成功的请求还是失败的请求,因为⼀个失败的请求可能很快就返回了,但这并不意味着服务实际响应快。因此,我们需要分别统计成功请求的延迟和失败请求的延迟,以准确反映服务的性能。
2、流量(Traffic):有时也称为吞吐量,是指服务在单位时间内能处理的请求数量或MySQL能处理的事务数量。
例如,⽹站在5秒内处理了1000个请求,那么我们就说这个服务的流量或吞吐量每5s能达到1000个请求。这个指标可以帮助我们了解服务的处理能⼒,并为资源分配、性能优化等提供决策依据。
3、错误(Errors):指⼀个服务请求错误的"次数"或"错误的占⽐率"。
例如,在10000个请求中,有100个请求因为某些原因(如服务器内部错误、返回内容不符合预期、请求超时等)处理失败,那么我们就可以说这个服务的错误数是100,或者失败错误率是1%(100/10000)。监控错误数或错误率可以帮助我们及时发现和定位服务的问题,提⾼服务的可靠性和⽤户的满意度。
4、饱和度(Saturation):⽤于衡量资源的使⽤程度,通常是指⼀个服务有多“满”。
例如,⼀台Web服务每秒能处理1000个请求。如果当前Web服务每秒只处理100个请求,那么它的饱和度为10%(100/1000)。这意味着Web服务⽬前不够饱和,还有⼤量的处理能⼒未被使⽤。但如果Web服务每秒处理了700个请求,那么其饱和度就达到了70%(700/1000)。这意味着这个Web服务真正的发挥了作⽤。同时我们也需要关注对应的指标,如果请求量持续增⻓,则会达到Web服务的最⼤处理能⼒,可能会导致Web服务⽆法快速地响应新的请求。
2.3 USE⽅法
USE⽅法是由Netflix的内核和性能⼯程师提出的系统性能分析⽅法。它主要着眼于“系统资源”的使⽤情况,这三个指标分别是“使⽤率、饱和度、错误”。
1、使⽤率(Utilization):⽤于衡量系统资源使⽤情况。
例如,CPU在过去的60秒内有30秒被⽤来执⾏指令,那么我们可以说这个CPU的使⽤率是50%。这⾥的资源主要包括但不限于:CPU,内存,⽹络,磁盘等。⼀旦使⽤率达到了100%,通常表明系统已经发⽣了瓶颈。
2、饱和度(Saturation):⽤于衡量系统资源的队列⻓度(不同于4⼤⻩⾦信号)
CPU的饱和度:在Linux系统中,可以通过查看系统的平均负载来观察CPU的饱和度。平均负载是指在⼀定时间间隔内,运⾏队列中的进程数(包括正在运⾏的和等待运⾏的)。如果平均负载的值持续⾼于CPU的核⼼数,那么可以认为CPU的饱和度较⾼,可能需要增加CPU资源或优化系统的处理能⼒。
磁盘的饱和度:在Linux系统中,可以使⽤ iostat -x 命令查看aqu-sz(Average Queue Size,平均队列⼤⼩)字段来观察磁盘的饱和度。aqu-sz表示在给定的时间段内采样设备请求队列的平均⻓度。如果aqu-sz的值持续较⾼,可能意味着磁盘已经饱和,磁盘I/O操作的需求超过了其处理能⼒,可能需要更换更⾼IO的磁盘。
3、错误(Errors):⽤于衡量资源事件错误计数。
例如:⼀个程序尝试使⽤malloc()函数分配内存,但系统没有⾜够的内存可供分配,那么malloc()将返回⼀个错误,那么我们就可以追踪malloc()失败的次数。
其次,在⽹络接⼝的数据包传输过程中,由于接收缓冲区满了,⽆法容纳新到来的数据包,导致了86个数据包被丢弃(drop)。这种丢包事件也被视为错误(Errors)
2.4 RED⽅法
RED ⽅法是由 Weave Cloud 提出的⼀种专为云原⽣应⽤和微服务架构设计的性能监控⽅法。它基于 Google 的四个⻩⾦指标(即延迟,流量,错误,饱和)的原则,结合了请求率、错误数、请求处理时间。因此,RED ⽅法能够有效地帮助⽤户衡量云原⽣以及微服务应⽤下的⽤户体验问题。
1、(Request)Rate:系统每秒钟接收的请求数。 ⽽google指标中的流量是指系统单位时间内处理的请求数,或是请求的总量。
2、(Request)Errors:每秒失败的请求数。
3、(Request)Duration:处理每个请求所花费的时⻓。⽽google指标中的延迟是指系统从接收请求到响应请求所花费的时间。在某些情况下,Duration可能更关注单个请求的处理时间,⽽延迟可能更关注系统的整体响应时间。
3 Prometheus介绍
3.1 Prometheus是什么
Prometheus 是由SoundCloud 使⽤时序数据库(简称TSDB)但它的功能并⾮局限于TSDB,因为它还⽀持对⽬标(如服务器、应⽤程序等)进⾏监控;
因此,我们也可以理解Prometheus是⼀款开源的“监控系统”,但仅仅依托Prometheus不⾜以⽀撑整个监控系统,它需要结合⽣态内其他的组件来构建⼀个完整的IT监控系统。例如:AleartManager、Grafana、PushGateway 等等
3.2 什么是时序数据
所谓时序数据,指的是,按照固定时间周期对“某个或某些指标”进⾏“反复测量”从⽽得到测量的“数据集合”。这些数据随着时间的推移,会形成⼀个连续的序列,因此被称为时序数据。如果我们将这些数据绘制在图形上,通常会有⼀个 数据轴(Y轴)表示数据值,⼀个时间轴(X轴)表示测量的时间点。
3.3 Prometheus时序数据
在Prometheus中,时序数据主要包括三个部分:指标名称、标签集、时序数据(时间戳、数据)
1、指标名称
例如,监控服务器的CPU使⽤率,对应的指标名称可以是 cpu_usage、memory_MemTotal 等指标名称是被监控端提供的。
2、标签集
标签集⽤于区分不同的数据源或实例。
假设我们有两台服务器,⼀台是Web服务器,另⼀台是db数据库服务器。为了区分这两台服务器的CPU使⽤率数据,我们可以为它们添加不同的标签,例如: cpu_usage{type="web"} 和cpu_usage{type="db"} 。
3、时序数据
指按照按固定时间间隔,采集对应指标名称,从⽽获取到对应指标的数据。
例如,每分钟采集⼀次CPU使⽤率( cpu_usage )。每个数据点包括采集CPU使⽤率的时间戳( 2023.03.30 10:00:01 ),以及该时间点采集到的样本值( 50% )
PS:每⼀个“指标名称和标签组合”都会形成⼀条独⽴的时间序列。这就表示,即使我们只探测了⼀个指标 cpu_usage ,但是它具有不同的标签值,就会产⽣两条分别代表不同实例的时间序列。在这些时间序列中,每⼀个特定的数据点被称为⼀个'样本'。每个样本都包含指标名称、标签、时间戳以及对应的指标值。
4 Prometheus的特点
4.1 多维数据模型
Prometheus 采⽤多维度的数据模型,可以对不同维度的数据进⾏监控和分析,同时PromQL可以对数据进⾏复杂的计算、过滤和查询等操作。当使⽤Prometheus 监控⼀个 Web 服务时,通常需要收集的数据包括:服务地址以及端⼝、请求uri、请求的⽅法、请求的次数、以及请求状态码等指标。
在我们可以通过定义不同的标签来为"同⼀个指标"添加不同的维度。例如,我们可以定义http_total 为⼀个指标名称,它⽤于记录(instance)、路径(path)、⽅法(method)等标签来为该指标添加不同的维度。
假设我们有两个实例,分别是
# 这⾥我们记录了每个实例上的 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
总之,通过多维数据模型,我们可以为每个指标添加不同的维度,同时也可以根据不同的维度进⾏数据的灵活查询与聚合等操作。
4.2 强⼤的PromQL
PromQL(Prometheus Query Language)是相⽐之下,许多传统的监控系统只能进⾏简单的数据过滤和阈值判断,⽽缺乏类似的查询语⾔。
当我们需要特定的数据在原始数据中没有时,许多监控系统会在数据采集阶段(即在源头收集数据的阶段)进⾏处理。然⽽,数据采集阶段并不适合进⾏所有的计算场景。
以机器内存监控为例,我们可以从 /proc/meminfo 获得各种相关数据,如MemAvailable 和MemTotal 。但是操作系统并不直接提供“内存使⽤率”相关的指标。
在Zabbix中,你需要在数据源(被监控端)预先计算出内存使⽤率,然后传递给Zabbix服务器进⾏监控和告警。⽽在Prometheus中,我们可以利⽤其查询语⾔PromQL在中⼼服务器上直接计算内存使⽤率: MemAvailable / MemTotal * 100 ,这种设计理念使Prometheus在处理复杂计算和告警场景时具有更⾼的灵活性。数据采集阶段专注于收集原始数据,⽽复杂的计算由中⼼服务器(即Prometheus)处理。
通过PromQL可以轻松解决如下问题:
- 预测在12⼩时后,磁盘空间是否会被占满?
- CPU占⽤率前5位的服务有哪些?(过滤)
- 过去1分钟的系统负载超过了其 CPU 核⼼数两倍的实例有哪些?
4.3 ⾼效的数据存储
Prometheus 使⽤专⽤的时间序列数据库。这种数据库⾮常强⼤,能够“容纳和处理”数以百万计的监控指标。这些监控指标,都按照时间顺序排列并储存,每个数据点都配有⼀个时间戳。所有的监控数据都精确地记录在这个时间点上。所以当你想要查看某个特定时间点的数据时,你可以直接提取对应的时间点,快速地找到所需的数据。⽆需遍历整个数据库。
指标名称
| cpu 数据cpu1 数据cpu2 数据cpu3
| memory 数据mem1 数据mem2 数据mem3
| network 数据net1 数据net2 数据net3
| process 数据pro1 数据pro2 数据pro3
| nginx 数据ng1 数据ng2 数据ng3
|------------------------------------------------------> 时间戳
时间点1 时间点2 时间点3
Prometheus不仅拥有⾼效的查询能⼒,⽽且还具有出⾊的存储效率,这主要得益于它所采⽤的压缩算法。该算法使得每个数据点所占⽤的存储空间约3.5字节。这种优化的存储⽅式⼤幅的降低了IO操作,以及存储的成本。根据官⽅的数据,百万条的时间序列数据,每30秒记录⼀次,并且需要保留60天的历史数据,仅需要200GB左右的存储空间。这种⾼效的存储⽅式使Prometheus能够轻松处理⼤规模数据,同时维持低成本。
4.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/)
4.5 可扩展的架构
Prometheus⽀持横向扩展,可以通过部署多个实例、使⽤ “远程存储“ 或者使⽤Prometheus联邦等⽅式实现⾼可⽤和⾼性能的监控系统。
例如,为了应对⼤规模监控需求,可以部署多个Prometheus实例并将它们配置为监控不同的服务或资源。同时,可以使⽤Prometheus将这些实例的数据汇总到⼀个中⼼实例中,实现统⼀的监控视图。
4.6 总结
综上所述Prometheus 具有灵活性、强⼤的查询语⾔、服务发现⾃动化、数据采集⾼效、架构可扩展等特点,是⼀款⾮常适合⽤于⼤规模监控系统的开源软件。
5 Prometheus数据采集
5.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 中抓取这些数据。
PushGateway 就像⼀个中间站,存储这些短暂任务产⽣的指标数据,等待Prometheus 来抓取。
5.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
6 Prometheus架构
6.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)集成,提供更丰富的可视化功能。
6.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这样的⼯具来为⽤户提供直观的数据展现⽅式。
6.3 Prometheus原理
Prometheus的基本原理是:
- 通过HTTP协议周期性抓取被监控组件的状态,
- 任意组件只要提供对应的HTTP接口就可以接入监控。
- 不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,
- 比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter。
7 Prometheus数据模型
7.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可以跟踪,随时间变化的任何指标,并且可以通过标签来分类和组织这些数据。
7.2 指标名称MetricName
在监控系统中,我们需要抓取的指标⾮常多,如CPU使⽤率、内存使⽤情况、⽹络流量等。我们使⽤ MetricsName 来区分这些不同指标。这些指标名称⼀般由⼩写字⺟、数字和下划线构成。例如,cpu_usage 这个指标代表CPU的使⽤率,它的值为 15.05 ,则表示当前CPU的使⽤率为15.05% 。
但是,cpu_usage 这个指标并没有具体表明它是针对是哪个节点的 CPU 使⽤率,也没有指出是哪个 CPU 核⼼的使⽤率。因此,为了区分,并确定不同节点上各个 CPU 核⼼的使⽤率,我们需要引⼊label(标签)这⼀机制。
7.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
8 Prometheus的指标类型
8.1 什么是指标类型
指标是用来衡量性能、消耗、效率和许多其他软件属性随时间的变化趋势。它们允许工程师通过警报和仪表盘来监控一系列测量值的演变(如CPU或内存使用量、请求持续时间、延迟等)。指标在IT监控领域有着悠久的历史,并被工程师广泛使用,与日志和链路追踪一起被用来检测系统是否有不符合预期的表现。 在其最基本的形式中,一个指标数据点是由以下三个部分构成:
- 一个指标名称
- 收集该数据点的时间戳
- 一个由数字表示的测量值
在过去的十年里,随着系统变得越来越复杂,出现了维度度量的概念,也就是说,度量还包括一组标签或标识(即维度),以提供额外的上下文。支持维度指标的监控系统允许工程师通过查询特定的指标名称,并通过标签进行过滤和分组,从而轻易地在多个组件和维度上汇总和分析一个指标。 Prometheus定义了一个度量说明格式和一个远程写入协议,社区和许多供应商都采用这个协议来说明和收集度量成为事实上的标准。OpenMetrics是另一个CNCF项目,它建立在Prometheus导出格式的基础上,为收集度量标准提供了一个与厂商无关的标准化模型,旨在成为互联网工程任务组(IEFT)的一部分。 最近,另一个CNCF项目OpenTelemetry出现了,它的目标是提供一个新的标准,能够统一指标、链路跟踪和日志的收集,使跨领域的遥测信号收集和关联更容易。 我们希望你在读完这些文章后,你能理解每个标准之间的差异,这样你就能决定哪一个能更好地满足你当前(和未来)的需求。
Prometheus 的客户端库中提供了四种核心的指标类型。但这些类型只是在客户端库(客户端可以根据不同的数据类型调用不同的)和在线协议中,实际在Prometheus server 中并不对指标类型进行区分,而是简单地把这些指标统一视为无类型的时间序列。
Prometheus 会将所有采集到的样本数据以 时间序列的方式保存,每条时间序列通过指标名称和一组标签集命名。
在时间序列中的每一个点称为一个 样本(sample),样本由以下三部分组成:
- 指标(metric):指标名称和描述当前样本特征的标签集。
- 时间戳(timestamp):一个精确到毫秒的时间戳。
- 样本值(value): 一个 float64 的浮点型数据表示当前样本的值。
一个规范的指标数据一般包含以下三个部分:
- # HELP,说明该指标的用途。
- # TYPE,说明该指标的数据类型。
- 具体采集的指标。
其中指标的具体格式如下:
<指标名称>{<标签名称>=<标签值>, ...} 数据
8.2 Counter
计数器,只能增加不能减小,常用于表示发生的错误数、已完成的任务数、服务的请求数。
安装并且启动好prometheus后,可以访问http://localhost:9090/metrics来看到prometheus自己的指标。
8.3 Gauge
仪表盘,记录瞬时值,是什么值就是什么,可大可小,常用于记录CPU的LOAD值、内存使用率、磁盘使用率、线程数、连接数等类似的指标。
8.4 Histogram
直方图,按照样本的指标值的区间进行分组,统计样本的指标值出现在各区间的次数,可以清晰的知道指标值的区间分布规律,常用于请求响应时间的区间分布、请求响应的字节数大小区间分布等类似数据。要获取样本的指标值的分位数需要在服务端进行计算,会消耗服务端的计算资源。
直方图包含3种类型的指标:
- 样本的指标值的在分组中的数量,命名为_bucket{le=""},表示指标值小于等于上边界的所有样本的数量。
- 所有样本的指标值的总和,命名为_sum。
- 样本总数,命名为_count。
安装并且启动好prometheus后,可以访问http://localhost:9090/metrics来看到prometheus自己的指标。下面的例子来自prometheus自带的http请求耗时的histogram信息,可以看出请求路径为“/”的http请求中,响应时间小于0.1秒的有3个,小于0.2秒的有3,小于0.4秒的有3个,小于1秒的有3个,总的请求次数为3次,总的请求耗时为0.000225066秒。
8.5 Summary
摘要,和histogram类似,记录一段时间内样本的指标值的分布结果,由客户端计算好样本指标值的分位数结果,服务端可以直接展示,不需要消耗计算资源。
summary类型的样本也会提供3种指标,假设指标名称为。
- 样本值的分位数分布情况,命名为{quantile="<>"}。
- 所有样本值的大小总和,命名为_sum。
- 样本总数,命名为_count。
安装并且启动好prometheus后,可以访问http://localhost:9090/metrics来看到prometheus自己的指标。下面的例子来自prometheus自带的GC的summary信息,可以看出GO语言的GC总次数是30,GC的总耗时是0.020594128秒,其中的中位数为(quantile="0.5")的耗时为0.000147255秒,也就是说30次GC中有50%的次数是小于0.000147255秒的。