[TOC]
参考
- http://dockone.io/article/9269
- http://dockone.io/article/5716
- https://www.jianshu.com/p/fb5c82de935d
- https://github.com/prometheus/prometheus
- https://yunlzheng.gitbook.io/prometheus-book
- https://prometheus.io/docs/introduction/overview/
- https://github.com/samber/awesome-prometheus-alerts
监控目的
在《SRE:Google运维解密》一书中指出,监控系统需要能够有效的支持白盒监控和黑盒监控。通过白盒能够了解其内部的实际运行状态,通过对监控指标的观察能够预判可能出现的问题,从而对潜在的不确定因素进行优化。而黑盒监控,常见的如HTTP探针,TCP探针等,可以在系统或者服务在发生故障时能够快速通知相关的人员进行处理。通过建立完善的监控体系,从而达到以下目的:
- 长期趋势分析:通过对监控样本数据的持续收集和统计,对监控指标进行长期趋势分析。例如,通过对磁盘空间增长率的判断,我们可以提前预测在未来什么时间节点上需要对资源进行扩容。
- 对照分析:两个版本的系统运行资源使用情况的差异如何?在不同容量情况下系统的并发和负载变化如何?通过监控能够方便的对系统进行跟踪和比较。
- 告警:当系统出现或者即将出现故障时,监控系统需要迅速反应并通知管理员,从而能够对问题进行快速的处理或者提前预防问题的发生,避免出现对业务的影响。
- 故障分析与定位:当问题发生后,需要对问题进行调查和处理。通过对不同监控指标以及历史数据的分析,能够找到并解决根源问题。
- 数据可视化:通过可视化仪表盘能够直接获取系统的运行状态、资源使用情况、以及服务运行状态等直观的信息。
而对于上一代监控系统而言,在使用过程中往往会面临以下问题:
- 与业务脱离的监控:监控系统获取到的监控指标与业务本身也是一种分离的关系。好比客户可能关注的是服务的可用性、服务的SLA等级,而监控系统却只能根据系统负载去产生告警;
- 运维管理难度大:Nagios这一类监控系统本身运维管理难度就比较大,需要有专业的人员进行安装,配置和管理,而且过程并不简单;
- 可扩展性低: 监控系统自身难以扩展,以适应监控规模的变化;
- 问题定位难度大:当问题产生之后(比如主机负载异常增加)对于用户而言,他们看到的依然是一个黑盒,他们无法了解主机上服务真正的运行情况,因此当故障发生后,这些告警信息并不能有效的支持用户对于故障根源问题的分析和定位。
在上述需求中,我们可以提取出以下对于一个完善的监控解决方案的几个关键词:数据分析、趋势预测、告警、故障定位、可视化。
除此以外,当前越来越多的产品公司迁移到云或者容器的情况下,对于监控解决方案而言还需要另外一个关键词:云原生。
Prometheus
简介
Prometheus已经被广泛应用于数据中心监控,尤其是和Kubernetes结合的容器监控。本文主要从架构分析到落地实践,详细介绍Prometheus原理和使用。对比Prometheus与其他监控工具(Zabbix、Open-Falcon)的特点与使用场景。然后介绍Prometheus与Kubernetes集成,主要从监控和自动伸缩两个方面。最后通过企业案例,分享实践经验和注意事项。
Kubernetes从2014年开源以来,迅速成为容器管理的领头羊,它是Google Borg系统的开源实现。和Kubernetes一起火起来的还有另一个开源项目Prometheus,它是Google BorgMon的开源实现。
2016年,由Google发起的Linux基金会旗下的原生云基金会(Cloud Native Computing Foundation)将Prometheus纳入其第二大开源项目。Prometheus在开源社区也十分活跃,在GitHub上拥有两万多Star,并且系统每隔一两周就会有一个小版本的更新。
Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库。从字面上理解,Prometheus由两个部分组成,一个是监控报警系统,另一个是自带的时序数据库(TSDB)。
上图是Prometheus整体架构图,左侧是各种符合Prometheus数据格式的exporter,除此之外为了支持推动数据类型的Agent,可以通过Pushgateway组件,将Push转化为Pull。Prometheus甚至可以从其它的Prometheus获取数据,组建联邦集群。Prometheus的基本原理是通过HTTP周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口并且符合Prometheus定义的数据格式,就可以接入Prometheus监控。
上侧是服务发现,Prometheus支持监控对象的自动发现机制,从而可以动态获取监控对象。
图片中间是Prometheus Server,Retrieval模块定时拉取数据,并通过Storage模块保存数据。PromQL为Prometheus提供的查询语法,PromQL模块通过解析语法树,调用Storage模块查询接口获取监控数据。图片右侧是告警和页面展现,Prometheus将告警推送到alertmanger,然后通过alertmanger对告警进行处理并执行相应动作。数据展现除了Prometheus自带的WebUI,还可以通过Grafana等组件查询Prometheus监控数据。
数据类型
理解时间序列
在Node Exporter的/metrics接口中返回的每一行监控数据,在Prometheus下称为一个样本。采集到的样本由以下三部分组成:
- 指标(metric):指标和一组描述当前样本特征的labelsets唯一标识;
- 时间戳(timestamp):一个精确到毫秒的时间戳,一般由采集时间决定;
- 样本值(value): 一个folat64的浮点型数据表示当前样本的值。
Prometheus会将所有采集到的样本数据以时间序列(time-series)的方式保存在内存数据库中,并且定时保存到硬盘上。每条time-series通过指标名称(metrics name)和一组标签集(labelset)命名。如下所示,可以将time-series理解为一个以时间为X轴的二维矩阵:
这种多维度的数据存储方式,可以衍生出很多不同的玩法。 比如,如果数据来自不同的数据中心,那么我们可以在样本中添加标签来区分来自不同数据中心的监控样本,例如:
1 | node_cpu{cpu="cpu0",mode="idle", dc="dc0"} |
从内部实现上来看Prometheus中所有存储的监控样本数据没有任何差异,均是一组标签,时间戳以及样本值。
从存储上来讲所有的监控指标metric都是相同的,但是在不同的场景下这些metric又有一些细微的差异。 例如,在Node Exporter返回的样本中指标node_load1反应的是当前系统的负载状态,随着时间的变化这个指标返回的样本数据是在不断变化的。而指标node_cpu所获取到的样本数据却不同,它是一个持续增大的值,因为其反应的是CPU的累积使用时间,从理论上讲只要系统不关机,这个值是会无限变大的。
为了能够帮助用户理解和区分这些不同监控指标之间的差异,Prometheus定义了4中不同的指标类型(metric type):Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)
Counter:只增不减的计数器
Counter是一个简单但有强大的工具,例如我们可以在应用程序中记录某些事件发生的次数,通过以时序的形式存储这些数据,我们可以轻松的了解该事件产生速率的变化。PromQL内置的聚合操作和函数可以用户对这些数据进行进一步的分析:
例如,通过rate()函数获取HTTP请求量的增长率:
1 | rate(http_requests_total[5m]) |
Gauge:可增可减的仪表盘
与Counter不同,Gauge类型的指标侧重于反应系统的当前状态。因此这类指标的样本数据可增可减。常见指标如:node_memory_MemFree(主机当前空闲的内容大小)、node_memory_MemAvailable(可用内存大小)都是Gauge类型的监控指标。
通过Gauge指标,用户可以直接查看系统的当前状态:
1 | node_memory_MemFree |
对于Gauge类型的监控指标,通过PromQL内置函数delta()可以获取样本在一段时间返回内的变化情况。例如,计算CPU温度在两个小时内的差异:
1 | delta(cpu_temp_celsius{host="zeus"}[2h]) |
还可以使用deriv()计算样本的线性回归模型,甚至是直接使用predict_linear()对数据的变化趋势进行预测。例如,预测系统磁盘空间在4个小时之后的剩余情况:
1 | predict_linear(node_filesystem_free{job="node"}[1h], 4 * 3600) |
使用Histogram和Summary分析数据分布情况
在大多数情况下人们都倾向于使用某些量化指标的平均值,例如CPU的平均使用率、页面的平均响应时间。这种方式的问题很明显,以系统API调用的平均响应时间为例:如果大多数API请求都维持在100ms的响应时间范围内,而个别请求的响应时间需要5s,那么就会导致某些WEB页面的响应时间落到中位数的情况,而这种现象被称为长尾问题。
为了区分是平均的慢还是长尾的慢,最简单的方式就是按照请求延迟的范围进行分组。例如,统计延迟在010ms之间的请求数有多少而1020ms之间的请求数又有多少。通过这种方式可以快速分析系统慢的原因。Histogram和Summary都是为了能够解决这样问题的存在,通过Histogram和Summary类型的监控指标,我们可以快速了解监控样本的分布情况。
例如,指标prometheus_tsdb_wal_fsync_duration_seconds的指标类型为Summary。 它记录了Prometheus Server中wal_fsync处理的处理时间,通过访问Prometheus Server的/metrics地址,可以获取到以下监控样本数据:
1 | prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.5"} 0.012352463 |
从上面的样本中可以得知当前Promtheus Server进行wal_fsync操作的总次数为216次,耗时2.888716127000002s。其中中位数(quantile=0.5)的耗时为0.012352463,9分位数(quantile=0.9)的耗时为0.014458005s。
Prometheus对于数据的存储方式就意味着,不同的标签就代表着不同的特征维度。用户可以通过这些特征维度对查询,过滤和聚合样本数据。
例如,通过node_load1,查询出当前时间序列数据库中所有名为node_load1的时间序列:
1 | node_load1 |
如果找到满足某些特征维度的时间序列,则可以使用标签进行过滤:
1 | node_load1{instance="localhost:9100"} |
通过以标签为核心的特征维度,用户可以对时间序列进行有效的查询和过滤,当然如果仅仅是这样,显然还不够强大,Prometheus提供的丰富的聚合操作以及内置函数,可以通过PromQL轻松回答以下问题:
当前系统的CPU使用率?
1
avg(irate(node_cpu{mode!="idle"}[2m])) without (cpu, mode)
CPU占用率前5位的主机有哪些?
1
topk(5, avg(irate(node_cpu{mode!="idle"}[2m])) without (cpu, mode))
预测在4小时候后,磁盘空间占用大致会是什么情况?
1
predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600)
其中avg(),topk()等都是PromQL内置的聚合操作,irate(),predict_linear()是PromQL内置的函数,irate()函数可以计算一段时间返回内时间序列中所有样本的单位时间变化率。predict_linear函数内部则通过简单线性回归的方式预测数据的变化趋势。
以Grafana为例,在Grafana中可以通过将Promtheus作为数据源添加到系统中,后再使用PromQL进行数据可视化。在Grafana v5.1中提供了对Promtheus 4种监控类型的完整支持,可以通过Graph Panel,Singlestat Panel,Heatmap Panel对监控指标数据进行可视化。
数据采集
Prometheus通过HTTP接口的方式从各种客户端获取数据,这些客户端必须符合Prometheus监控数据格式,通常有两种方式,一种是侵入式埋点监控,通过在客户端集成,如果Kubernetes API直接通过引入Prometheus go client,提供/metrics接口查询kubernetes API各种指标;另一种是通过exporter方式,在外部将原来各种中间件的监控支持转化为Prometheus的监控数据格式,如redis exporter将Reids指标转化为Prometheus能够识别的HTTP请求。
HTTP返回Header和Body如上图所示,指标前面两行#是注释,标识指标的含义和类型。指标和指标的值通过空格分割,开发者通常不需要自己拼接这种个数的数据, Prometheus提供了各种语言的SDK支持。
Prometheus并没有采用json的数据格式,而是采用text/plain纯文本的方式 ,这是它的特殊之处。
Exporter
Prometheus为了支持各种中间件以及第三方的监控提供了exporter,大家可以把它理解成监控适配器,将不同指标类型和格式的数据统一转化为Prometheus能够识别的指标类型。
譬如Node exporter主要通过读取Linux的/proc以及/sys目录下的系统文件获取操作系统运行状态,reids exporter通过Reids命令行获取指标,mysql exporter通过读取数据库监控表获取MySQL的性能数据。他们将这些异构的数据转化为标准的Prometheus格式,并提供HTTP查询接口。
数据存储
Prometheus提供了两种数据持久化方式:一种是本地存储,通过Prometheus自带的TSDB(时序数据库),将数据保存到本地磁盘,为了性能考虑,建议使用SSD。但本地存储的容量毕竟有限,建议不要保存超过一个月的数据。Prometheus本地存储经过多年改进,自Prometheus 2.0后提供的V3版本TSDB性能已经非常高,可以支持单机每秒1000w个指标的收集。
Prometheus本地数据存储能力一直为大家诟病,但Prometheus本地存储设计的初衷就是为了监控数据的查询,Facebook发现85%的查询是针对26小时内的数据。所以Prometheus本地时序数据库的设计更多考虑的是高性能而非分布式大容量。
另一种是远端存储,适用于大量历史监控数据的存储和查询。通过中间层的适配器的转化,Prometheus将数据保存到远端存储。适配器实现Prometheus存储的remote write和remote read接口,并把数据转化为远端存储支持的数据格式。目前,远端存储主要包括OpenTSDB、InfluxDB、Elasticsearch、M3DB等,其中M3DB是目前非常受欢迎的后端存储。
PromQL
Prometheus数据展现除了自带的WebUI还可以通过Grafana,他们本质上都是通过HTTP + PromQL的方式查询Prometheus数据。和关系型数据库的SQL类似,Prometheus也内置了数据查询语言PromQL,它提供对时间序列数据丰富的查询,聚合以及逻辑运算的能力。
数据运算包括了:
- +(加法)
- -(减法)
- *(乘法)
- /(除法)
- %(求余)
- ^(幂运算)
聚合包括了:
- sum(求和)
- min(最小值)
- max(最大值)
- avg(平均值)
- stddev(标准差)
- stdvar(标准差异)
- count(计数)
- count_values(对value进行计数)
- bottomk(后n条)
- topk(前n条)
- quantile(分布统计)
如果需要获取某个时刻的数据可以通过curl ‘http://Prometheus地址:9090/api/v1/query?query=up&time=xx'查询监控数据,其中query参数就是一个PromQL表达式。除此之外,还支持范围查询query_range,需要额外添加下面的参数:start(起始时间)、end(结束时间)、step=(查询步长)
当接收到请求参数后,通过PromQL引擎解析PromQL,确定查询的数据序列和时间范围,通过tsdb接口获取对应数据块(chunks),最后根据聚合函数处理监控数据并返回。
告警
如果监控数据达到告警阈值Prometheus Server会通过HTTP将告警发送到告警模块alertmanger。Prometheus告警配置也是通过yaml文件,核心是上面的expr表达式(告警规则)和查询一样也是一个PromQL表达式。 for代表持续时间,如果在for时间内持续触发Prometheus才发出告警
告警组件alertmanger地址是在Prometheus的配置文件中指定,告警经过alertmanger去重、抑制等操作,最后执行告警动作,目前支持邮件、slack、微信和webhook,如果是对接钉钉,便可以通过webhook方式触发钉钉的客户端发送告警。
联邦
为了扩展单个Prometheus的采集能力和存储能力,Prometheus引入了“联邦”的概念。多个Prometheus节点组成两层联邦结构,如图所示,上面一层是联邦节点,负责定时从下面的Prometheus节点获取数据并汇总,部署多个联邦节点是为了实现高可用以及数据汇聚存储。下层的Prometheus节点又分别负责不同区域的数据采集,在多机房的事件部署中,下层的每个Prometheus节点可以被部署到单独的一个机房,充当代理。
Improbable开源的Thanos提供了Prometheus集群化能力,感兴趣的朋友可以深入了解一下。
其他监控分布式
熟悉zabbix的朋友可能知道,zabbix中有主动模式和被动模式,主动模式可以实现agent节点自动向server节点汇报,这样就减轻了server端的压力。被动模式中也有一种添加代理节点方式实现分布式监控,实现跨机房异地监控目标。具体方法可以参考本人zabbix监控文章。
prometheus联邦机制
prometheus的分布式类似于nginx的负载均衡模式,主节点配置文件可以配置从节点的地址池,主节点只要定时向从节点拉取数据即可,主节点的作用就是存贮实时数据,并提供给grafana 使用。而从节点作用就是分别从不同的各个采集端中抽取数据,可以实现分机器或者分角色。这种由一个中心的prometheus负则聚合多个prometheus数据中的监控模式,称为prometheus联邦集群。
例如:集群规模200台,两个从节点,可以每台机器监控100台,也可以每台机器监控200台,但是分别监控不同角色,第一个从节点监控hdfs,第二个节点监控hbase这种方式,反正想怎么监控就看个人配置了。
部署配置
分布式的部署就是找多台机器分别部署prometheus,部署方式都是一致,只有配置文件不同。
联邦集群核心在于每一个prometheus server都包含一个用于获取当前实例中监控样本的接口 /federate 。对于中心prometheus server无论是从其他prometheus实例还是node_exporter采集端获取数据,事实上没有任何差异的。
参数 | 作用 |
---|---|
honor_labels | 防止采集到监控指标冲突,配置true可以确保采集到指标冲突时自动忽略冲突指标;配置false会自动将冲突指标替换为exported_的形式。还可以添加标签区分不同监控目标 |
metrics_path | 联邦集群用于获取监控样本参数配置 /federate |
match[ ] | 指定需要获取的时间序列,个人认为也就是填写从节点的角色标签或者环境变量。可以填写job=”zookeeper”或者name=~“instance.*”,模糊匹配可以使用通配符。将你想要展示的角色或者变量写入prometheus主节点才可以获取从节点上信息,否则无法获取 |
static_configs | 在此填写从节点地址池即可 |
主节点配置文件:
1 | # my global config |
从节点1配置文件:
1 | # my global config |
从节点2配置文件
1 | # my global config |
服务发现与云原生:以Kubernetes为例
Prometheus有两种方式配置监控对象,一种是通过静态文件配置,另一种是动态发现机制。
目前动态发现目前已经支持Kubernetes、etcd、Consul等多种服务,动态发现可以减少运维人员手动配置,在容器运行环境中尤为重要,容器集群通常在几千甚至几万的规模,如果每个容器都需要单独配置监控项不仅需要大量工作量,而且容器经常变动,后续维护更是异常麻烦。针对Kubernetes环境的动态发现,Prometheus通过Watch Kubernetes API动态获取当前集群所有主机、容器以及服务的变化情况。
对于Kubernetes而言,如上图所示,我们可以把当中所有的资源分为几类:
- 基础设施层(Node):集群节点,为整个集群和应用提供运行时资源
- 容器基础设施(Container):为应用提供运行时环境
- 用户应用(Pod):Pod中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能
- 内部服务负载均衡(Service):在集群内,通过Service在集群暴露应用功能,集群内应用和应用之间访问时提供内部的负载均衡。
- 外部访问入口(Ingress):通过Ingress提供集群外的访问入口,从而可以使外部客户端能够访问到部署在Kubernetes集群内的服务。
因此,在不考虑Kubernetes自身组件的情况下,如果要构建一个完整的监控体系,我们应该考虑,以下5个方面:
- 集群节点状态监控:从集群中各节点的kubelet服务获取节点的基本运行状态;
- 集群节点资源用量监控:通过Daemonset的形式在集群中各个节点部署Node Exporter采集节点的资源使用情况;
- 节点中运行的容器监控:通过各个节点中kubelet内置的cAdvisor中获取个节点中所有容器的运行状态和资源使用情况;
- 从黑盒监控的角度在集群中部署Blackbox Exporter探针服务,检测Service和Ingress的可用性;
- 如果在集群中部署的应用程序本身内置了对Prometheus的监控支持,那么我们还应该找到相应的Pod实例,并从该Pod实例中获取其内部运行状态的监控指标。
而对于Prometheus这一类基于Pull模式的监控系统,显然也无法继续使用的static_configs的方式静态的定义监控目标。而对于Prometheus而言其解决方案就是引入一个中间的代理人(服务注册中心),这个代理人掌握着当前所有监控目标的访问信息,Prometheus只需要向这个代理人询问有哪些监控目标控即可, 这种模式被称为服务发现。
Prometheus提供了对Kubernetes的完整支持,通过与Kubernetes的API进行交互,Prometheus可以自动的发现Kubernetes中所有的Node、Service、Pod、Endpoints以及Ingress资源的相关信息。
通过服务发现找到所有的监控目标后,并通过Prometheus的Relabling机制对这些资源进行过滤,metrics地址替换等操作,从而实现对各类资源的全自动化监控。
例如,通过以下流程任务配置,可以自动从集群节点的kubelet服务中内置的cAdvisor中获取容器的监控数据:
1 | - job_name: 'kubernetes-cadvisor' |
由或者是通过集群中部署的blackbox exporter对服务进行网络探测:
1 | - job_name: 'kubernetes-services' |
规模化监控解决方案
Prometheus周期性的从Target中获取监控数据并保存到本地的time-series中,并且通过PromQL对外暴露数据查询接口。 内部周期性的检查告警规则文件,产生告警并有Alertmanager对告警进行后续处理。
那么问题来了,这里Prometheus是单点,Alertmanager也是单点。 这样的结构能否支持大规模的监控量?
对于Prometheus而言,要想完全理解其高可用部署模式,首先我们需要理解Prometheus的数据存储机制。
如上所示,Prometheus 2.x采用自定义的存储格式将样本数据保存在本地磁盘当中。按照两个小时为一个时间窗口,将两小时内产生的数据存储在一个块(Block)中,每一个块中包含该时间窗口内的所有样本数据(chunks),元数据文件(meta.json)以及索引文件(index)。
当前时间窗口内正在收集的样本数据,Prometheus则会直接将数据保存在内存当中。为了确保此期间如果Prometheus发生崩溃或者重启时能够恢复数据,Prometheus启动时会从写入日志(WAL)进行重播,从而恢复数据。此期间如果通过API删除时间序列,删除记录也会保存在单独的逻辑文件当中(tombstone)。
通过时间窗口的形式保存所有的样本数据,可以明显提高Prometheus的查询效率,当查询一段时间范围内的所有样本数据时,只需要简单的从落在该范围内的块中查询数据即可。而对于历史数据的删除,也变得非常简单,只要删除相应块所在的目录即可。
对于单节点的Prometheus而言,这种基于本地文件系统的存储方式能够让其支持数以百万的监控指标,每秒处理数十万的数据点。为了保持自身管理和部署的简单性,Prometheus放弃了管理HA的复杂度。
因此首先,对于这种存储方式而言,我们需要明确的几点:
- Prometheus本身不适用于持久化存储长期的历史数据,默认情况下Prometheus只保留15天的数据。
- 本地存储也意味着Prometheus自身无法进行有效的弹性伸缩。
而当监控规模变得巨大的时候,对于单台Prometheus而言,其主要挑战包括以下几点:
- 服务的可用性,如何确保Prometheus不会发生单点故障;
- 监控规模变大的意味着,Prometheus的采集Job的数量也会变大(写)操作会变得非常消耗资源;
- 同时也意味着大量的数据存储的需求。
简单HA:服务可用性
由于Prometheus的Pull机制的设计,为了确保Prometheus服务的可用性,用户只需要部署多套Prometheus Server实例,并且采集相同的Exporter目标即可。
基本的HA模式只能确保Prometheus服务的可用性问题,但是不解决Prometheus Server之间的数据一致性问题以及持久化问题(数据丢失后无法恢复),也无法进行动态的扩展。因此这种部署方式适合监控规模不大,Promthues Server也不会频繁发生迁移的情况,并且只需要保存短周期监控数据的场景。
基本HA + 远程存储
在基本HA模式的基础上通过添加Remote Storage存储支持,将监控数据保存在第三方存储服务上。
当Prometheus在获取监控样本并保存到本地的同时,会将监控数据发送到Remote Storage Adaptor,由Adaptor完成对第三方存储的格式转换以及数据持久化。
当Prometheus查询数据的时候,也会从Remote Storage Adaptor获取数据,合并本地数据后进行数据查询。
在解决了Prometheus服务可用性的基础上,同时确保了数据的持久化,当Prometheus Server发生宕机或者数据丢失的情况下,可以快速的恢复。 同时Prometheus Server可能很好的进行迁移。因此,该方案适用于用户监控规模不大,但是希望能够将监控数据持久化,同时能够确保Prometheus Server的可迁移性的场景。
基本HA + 远程存储 + 联邦集群
当单台Prometheus Server无法处理大量的采集任务时,用户可以考虑基于Prometheus联邦集群的方式将监控采集任务划分到不同的Prometheus实例当中即在任务级别功能分区。
这种部署方式一般适用于两种场景:
场景一:单数据中心 + 大量的采集任务
这种场景下Prometheus的性能瓶颈主要在于大量的采集任务,因此用户需要利用Prometheus联邦集群的特性,将不同类型的采集任务划分到不同的Prometheus子服务中,从而实现功能分区。例如一个Prometheus Server负责采集基础设施相关的监控指标,另外一个Prometheus Server负责采集应用监控指标。再有上层Prometheus Server实现对数据的汇聚。
场景二:多数据中心
这种模式也适合与多数据中心的情况,当Prometheus Server无法直接与数据中心中的Exporter进行通讯时,在每一个数据中部署一个单独的Prometheus Server负责当前数据中心的采集任务是一个不错的方式。这样可以避免用户进行大量的网络配置,只需要确保主Prometheus Server实例能够与当前数据中心的Prometheus Server通讯即可。 中心Prometheus Server负责实现对多数据中心数据的聚合。
高可用方案选择
上面的部分,根据不同的场景演示了3种不同的高可用部署方案。当然对于Prometheus部署方案需要用户根据监控规模以及自身的需求进行动态调整,下表展示了Prometheus和高可用有关3个选项各自解决的问题,用户可以根据自己的需求灵活选择。
对于Alertmanager而言,Alertmanager集群之间使用Gossip协议相互传递状态,因此对于Prometheus而言,只需要关联多个Alertmanager实例即可,关于Alertmanager集群的详细详细可以参考:https://github.com/yunlzheng/p … ty.md
配置文件解析
Prometheus通过命令行标志和配置文件进行配置。 虽然命令行标志配置了不可变的系统参数(例如存储位置,保留在磁盘和内存中的数据量等),但配置文件定义了与抓取作业及其实例相关的所有内容,以及哪些规则文件 载入。
要查看所有可用的命令行参数,执行./prometheus -h
Prometheus可以在运行时重新加载其配置。 如果新配置格式不正确,则不会应用更改。 通过向Prometheus进程发送SIGHUP或向/-/reload
端点发送HTTP POST请求(启用--web.enable-lifecycle
标志时)来触发配置重新加载。 这也将重新加载任何已配置的规则文件。
配置文件
要指定要加载的配置文件,
请使用–config.file标志。
该文件以YAML格式编写,由下面描述的方案定义。 括号表示参数是可选的。 对于非列表参数,该值设置为指定的默认值。
通用占位符定义如下:
:一个可以取值为true或false的布尔值 :与正则表达式匹配的持续时间[0-9] +(ms | [smhdwy]) :与正则表达式匹配的字符串[a-zA-Z _] [a-zA-Z0-9 _] * :一串unicode字符 :当前工作目录中的有效路径 :由主机名或IP后跟可选端口号组成的有效字符串 :有效的URL路径 :一个可以取值http或https的字符串 :常规字符串 :一个秘密的常规字符串,例如密码 :在使用前进行模板扩展的字符串
其他占位符是单独指定的。
全局配置指定在所有其他配置上下文中有效的参数。 它们还可用作其他配置节的默认值
1 | global: |
目标可以通过
此外,
其中
1 | # 默认分配给已抓取指标的job名称。 |
1 | # 用于验证API服务器证书的CA证书。 |
基于DNS的服务发现配置允许指定一组DNS域名,这些域名会定期查询以发现目标列表。 要联系的DNS服务器从/etc/resolv.conf
中读取。
此服务发现方法仅支持基本的DNS A,AAAA和SRV记录查询,但不支持RFC6763中指定的高级DNS-SD方法。
在重新标记阶段,元标签__meta_dns_name
在每个目标上可用,并设置为生成已发现目标的记录名称。
1 | # 要查询的DNS域名列表。 |
其中
Kubernetes SD配置允许从Kubernetes的RESTAPI中检索scrape目标,并始终与群集状态保持同步。
可以配置以下role
类型之一来发现目标
node
node角色发现每个群集节点有一个目标,其地址默认为Kubelet的HTTP端口。 目标地址默认为NodeInternalIP,NodeExternalIP,NodeLegacyHostIP和NodeHostName的地址类型顺序中Kubernetes节点对象的第一个现有地址。
可用元标签:
- __meta_kubernetes_node_name:节点对象的名称。
- _meta_kubernetes_node_label
:节点对象中的每个标签。
_meta_kubernetes_node_annotation`:节点对象中的每个注释。 - _meta_kubernetes_node_address
:每个节点地址类型的第一个地址(如果存在)。
此外,节点的instance标签将设置为从API服务器检索的节点名称。
service
service角色为每个服务发现每个服务端口的目标。 这对于服务的黑盒监控通常很有用。 该地址将设置为服务的Kubernetes DNS名称和相应的服务端口。
可用元标签:
- __meta_kubernetes_namespace:服务对象的命名空间。
- _meta_kubernetes_service_annotation
:服务对象的注释。 - __meta_kubernetes_service_cluster_ip:服务的群集IP地址。 (不适用于ExternalName类型的服务)
- __meta_kubernetes_service_external_name:服务的DNS名称。 (适用于ExternalName类型的服务)
- _meta_kubernetes_service_label
:服务对象的标签。 - __meta_kubernetes_service_name:服务对象的名称。
- __meta_kubernetes_service_port_name:目标服务端口的名称。
- __meta_kubernetes_service_port_number:目标的服务端口号。
- __meta_kubernetes_service_port_protocol:目标服务端口的协议。
pod
pod角色发现所有pod并将其容器暴露为目标。 对于容器的每个声明端口,将生成单个目标。 如果容器没有指定端口,则会创建每个容器的无端口目标,以通过重新标记手动添加端口。
可用元标签:
- __meta_kubernetes_namespace:pod对象的命名空间。
- __meta_kubernetes_pod_name:pod对象的名称。
- __meta_kubernetes_pod_ip:pod对象的pod IP。
- _meta_kubernetes_pod_label
:pod对象的标签。 - _meta_kubernetes_pod_annotation
:pod对象的注释。 - __meta_kubernetes_pod_container_name:目标地址指向的容器的名称。
- __meta_kubernetes_pod_container_port_name:容器端口的名称。
- __meta_kubernetes_pod_container_port_number:容器端口号。
- __meta_kubernetes_pod_container_port_protocol:容器端口的协议。
- __meta_kubernetes_pod_ready:对于pod的就绪状态,设置为true或false。
- __meta_kubernetes_pod_phase:在生命周期中设置为Pending,Running,Succeeded,Failed或Unknown。
- __meta_kubernetes_pod_node_name:将pod安排到的节点的名称。
- __meta_kubernetes_pod_host_ip:pod对象的当前主机IP。
- __meta_kubernetes_pod_uid:pod对象的UID。
- __meta_kubernetes_pod_controller_kind:对象类型的pod控制器。
- __meta_kubernetes_pod_controller_name:pod控制器的名称。
endpoints
endpoints角色从列出的服务端点发现目标。 对于每个端点地址,每个端口发现一个目标。 如果端点由pod支持,则pod的所有其他容器端口(未绑定到端点端口)也会被发现为目标。
可用元标签:
- __meta_kubernetes_namespace:端点对象的命名空间。
- __meta_kubernetes_endpoints_name:端点对象的名称。对于直接从端点列表中发现的所有目标(不是从底层pod中另外推断的那些),附加以下标签:
- __meta_kubernetes_endpoint_ready:对端点的就绪状态设置为true或false。
- __meta_kubernetes_endpoint_port_name:端点端口的名称。
- __meta_kubernetes_endpoint_port_protocol:端点端口的协议。
- __meta_kubernetes_endpoint_address_target_kind:端点地址目标的种类。
- __meta_kubernetes_endpoint_address_target_name:端点地址目标的名称。
如果端点属于某个服务,则会附加角色:服务发现的所有标签。
对于由pod支持的所有目标,将附加角色的所有标签:pod发现。
ingress
ingress角色发现每个入口的每个路径的目标。 这通常用于黑盒监控入口。 地址将设置为入口规范中指定的主机。
可用元标签:
- __meta_kubernetes_namespace:入口对象的名称空间。
- __meta_kubernetes_ingress_name:入口对象的名称。
- _meta_kubernetes_ingress_label
:入口对象的标签。 - _meta_kubernetes_ingress_annotation
:入口对象的注释。 - __meta_kubernetes_ingress_scheme:入口的协议方案,如果设置了TLS配置,则为https。 默认为http。
- __meta_kubernetes_ingress_path:来自入口规范的路径。 默认为/。
有关Kubernetes发现的配置选项,请参见下文:
1 | # 访问Kubernetes API的信息。 |
其中``必须是endpoints
,service
,pod
,node
或ingress
。
有关为Kubernetes配置Prometheus的详细示例,请参阅此示例Prometheus配置文件。
您可能希望查看第三方Prometheus操作,它可以在Kubernetes上自动执行Prometheus设置。
static_config允许指定目标列表和它们的公共标签集。 这是在scrape配置中指定静态目标的规范方法。
1 | # 静态配置指定的目标。 |
重新标记是一种强大的工具,可以在抓取目标之前动态重写目标的标签集。 每个抓取配置可以配置多个重新标记步骤。 它们按照它们在配置文件中的出现顺序应用于每个目标的标签集。
最初,除了配置的每目标标签之外,目标的作业标签设置为相应的scrape配置的job_name
值。 __address__
标签设置为目标的<host>:<port>
地址。 重新标记后,如果在重新标记期间未设置实例标签,则实例标签默认设置为__address__
的值。 __scheme__
和__metrics_path__
标签分别设置为目标的方案和度量标准路径。 __param_<name>
标签设置为名为
在重新标记阶段,可以使用带有__meta_
前缀的附加标签。 它们由提供目标的服务发现机制设置,并在不同机制之间变化。
在目标重新标记完成后,将从标签集中删除以__
开头的标签。
如果重新标记步骤仅需临时存储标签值(作为后续重新标记步骤的输入),请使用__tmp
标签名称前缀。 保证Prometheus本身不会使用此前缀。
1 | # 源标签从现有标签中选择值。 它们的内容使用已配置的分隔符进行连接,并与已配置的正则表达式进行匹配,以进行替换,保留和删除操作。 |
- replace:将regex与连接的source_labels匹配。 然后,将target_label设置为replacement,将匹配组引用(${1},${2},…)替换为其值。 如果正则表达式不匹配,则不进行替换。
- keep:删除regex与连接的source_labels不匹配的目标。
- drop:删除regex与连接的source_labels匹配的目标。
- hashmod:将target_label设置为连接的source_labels的哈希模数。
- labelmap:将regex与所有标签名称匹配。 然后将匹配标签的值复制到替换时给出的标签名称,替换为匹配组引用(${1},{2},…)替换为其值。
- labeldrop:将regex与所有标签名称匹配。匹配的任何标签都将从标签集中删除。
- labelkeep:将regex与所有标签名称匹配。任何不匹配的标签都将从标签集中删除。
必须小心使用labeldrop和labelkeep,以确保在删除标签后仍然对指标进行唯一标记。
度量重新标记应用于样本,作为摄取前的最后一步。 它具有与目标重新标记相同的配置格式和操作。 度量标准重新标记不适用于自动生成的时间序列,例如up
。
一个用途是将黑名单时间序列列入黑名单,这些时间序列太昂贵而无法摄取。
警报重新标记在发送到Alertmanager之前应用于警报。 它具有与目标重新标记相同的配置格式和操作。 外部标签后应用警报重新标记。
这样做的一个用途是确保具有不同外部标签的HA对Prometheus服务器发送相同的警报。
alertmanager_config
部分指定Prometheus服务器向其发送警报的Alertmanager实例。 它还提供参数以配置如何与这些Alertmanagers进行通信。
Alertmanagers可以通过static_configs
参数静态配置,也可以使用其中一种支持的服务发现机制动态发现。
此外,relabel_configs
允许从发现的实体中选择Alertmanagers,并对使用的API路径提供高级修改,该路径通过__alerts_path__
标签公开。
write_relabel_configs
是在将样本发送到远程端点之前应用于样本的重新标记。 在外部标签之后应用写入重新标记。 这可用于限制发送的样本。
有一个如何使用此功能的小型演示。
1 | # 要发送样本的端点的URL. |
有一个与此功能集成的列表。
1 | # 要发送样本的端点的URL. |
有一个与此功能集成的列表。
Prometheus API
清理prometheus数据
确保 prometheus 启动的时候, 加了参数 –web.enable-admin-api
清理这个key的全部的数据
1
2curl -X POST \
-g 'http://192.168.2.100:9090/api/v1/admin/tsdb/delete_series?match[]=up&match[]=mysql_global_status_threads_running{instance="test-db13:9104",job="mysql"}'清理这个key指定时间段的数据 (清理的时间戳区间:1557903714 到 155790395 )
1
2curl -X POST \
-g 'http://192.168.2.100:9090/api/v1/admin/tsdb/delete_series?start=1557903714&end=1557903954&match[]=mysql_global_status_threads_running{instance="test-db13:9104",job="mysql"}'