1 配置文件
Prometheus通过命令行和配置文件进行配置,命令行配置不能修改的系统参数(例如存储位置,要保留在磁盘和内存中的数据量等),但配置文件定义了与抓取作业及其实例相关的所有内容,以及哪些规则文件的加载。
Prometheus可以在运行时重新加载其配置。 如果新配置格式不正确,则更改将不会应用。 通过向Prometheus进程发送SIGHUP或向/-/reload端点发送HTTP POST请求(启用–web.enable-lifecycle)来触发配置重载,这还将重新加载所有已配置的规则文件。
在启动时可以使用--config.file
参数指定要加载的配置文件。例如下面的全局配置指定在所有其他配置上下文中有效的参数,或者指定其他具体配置的默认值。
global:
# 默认情况下抓取目标的频率.
[ scrape_interval: <duration> | default = 1m ]
# 抓取超时时间.
[ scrape_timeout: <duration> | default = 10s ]
# 评估规则的频率.
[ evaluation_interval: <duration> | default = 1m ]
# 与外部系统通信时添加到任何时间序列或警报的标签(联合,远程存储,Alertma# nager).即添加到拉取的数据并存到数据库中
external_labels:
[ <labelname>: <labelvalue> ... ]
# 规则文件指定了一个globs列表.
# 从所有匹配的文件中读取规则和警报.
rule_files:
[ - <filepath_glob> ... ]
# 抓取配置列表.
scrape_configs:
[ - <scrape_config> ... ]
# 警报指定与Alertmanager相关的设置.
alerting:
alert_relabel_configs:
[ - <relabel_config> ... ]
alertmanagers:
[ - <alertmanager_config> ... ]
# 与远程写入功能相关的设置.
remote_write:
[ - <remote_write> ... ]
# 与远程读取功能相关的设置.
remote_read:
[ - <remote_read> ... ]
其他具体的配置参数可以看官方文档:https://prometheus.io/docs/prometheus/latest/configuration/configuration/
2 规则
Prometheus支持两种类型的规则,这些规则可以定期配置,然后定期评估:记录规则(recored rule)和 警报规则(alert rule)。规则文件是yaml格式,通过Prometheus配置中的rule_files字段加载指定文件, 规则文件使用YAML。
通过将SIGHUP发送到Prometheus进程,可以在运行时重新加载规则文件。 kill -1 pid
向指定进程发送SIGHUP信号
通过promtool工具可以对规则文件对语法进行检测,一般下载来整个Prometheus已经包含了promtool工具
promtool check rules /path/to/example.rules.yml
2.1 recored rule
recored rule允许预先计算经常需要或计算上复杂的表达式,并将其结果保存为一组新的时间序列。
groups:
- name: example
rules:
# 要输出的时间序列的名称
- record: job:http_inprogress_requests:sum
# 要评估的PromQL表达式
expr: sum(http_inprogress_requests) by (job)
2.2 alert rule
警报规则基于Prometheus表达式定义警报条件,并将有关触发警报的通知发送到外部服务。 每当警报表达式在给定时间点生成一个或多个向量元素时,警报将视为这些元素的标签集的活动状态。
groups:
- name: example
rules:
# 警报的名称
- alert: HighErrorRate
# 要评估的PromQL表达式。 每个评估周期都会在当前时间进行评估,并且所有结果时间序列都会成为待处理/触发警报。
expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5
for: 10m
labels:
severity: page
annotations:
summary: High request latency
3 PromQL
Prometheus提供一个函数式的表达式语言PromQL (Prometheus Query Language),可以使用户实时地查找和聚合时间序列数据。表达式计算结果可以在图表中展示,也可以在表达式浏览器中以表格形式展示,或者作为数据源提供给API请求
在Prometheus的表达式语言中,任何表达式或者子表达式都可以归为四种类型:
- instant vector瞬时向量:它是指在同一时刻,抓取的所有度量指标数据。这些度量指标数据的key都是相同的,也即相同的时间戳,返回瞬时向量的表达式是唯一可以直接绘制图形的类型
- range vector范围向量:它是指在任何一个时间范围内,抓取的所有度量指标数据
- scalar 标量:一个简单的浮点值
- string 字符串:一个当前没有被使用的简单字符串
3.1 字面量
字符串可以用单引号,双引号或反引号指定为文字。
"this is a string"
'these are unescaped: \n \\ \t'
`these are not unescaped: \n ' " \t"'`
标量浮点值可以直接写成形式 -[.(digits)]。
-2.43
3.2时间序列选择器
瞬时向量选择器允许在给定时间戳(即时)为每个选择一组时间序列和单个样本值
# 选择所有时间序列度量名称为http_requests_total的样本数据
http_requests_total
# 选择具有http_requests_total度量标准名称的时间系列,该名称也将job标签设置为prometheus,并将其group标签设置为canary
http_requests_total{job="prometheus",group="canary"}
# 度量指标名称为http_requests_total,正则表达式匹配标签environment为staging, testing, development的值,且http请求方法不等于GET
http_requests_total{environment=~"staging|testing|development",method!="GET"}
范围向量的工作方式与即时向量相同,不同之处在于它们从当前即时选择回采样范围。 在语法上,范围持续时间附加在向量选择器末尾的方括号([])中,指定为每个结果范围向量元素提取多长时间值
选择在过去5分钟内为度量标准名称为http_requests_total且job标签设置为prometheus的所有时间序列记录的所有值:
http_requests_total{job="prometheus"}[5m]
offset偏移修饰符允许在查询中改变单个瞬时向量和范围向量中的时间偏移
# 返回过去相对于当前查询评估时间5分钟的http_requests_total值:
http_requests_total offset 5m
4 API
在Prometheus服务器上的/api/v1
下可以访问当前稳定的HTTP API,API返回是JSON格式,每个请求成功的返回值都是以2xx开头的编码。如果API处理的是无效请求,返回一个JSON错误对象,并返回下面的错误码:
- 400 Bad Request。当参数错误或者丢失时。
- 422 Unprocessable Entity。当一个表达式不能被执行时。
- 503 Service Unavailable。当查询超时或者中断时。
在 query请求时可以指定参数如下
- query=: Prometheus表达式查询字符串。
- time=<rfc3339 | uninx_timestamp>:执行时间戳,如果time缺省,则用当前服务器时间表示执行时刻
- timeout=: 执行超时时间设置,可选项,默认由-query.timeout标志设置
4.1 请求监测数据
如下所示为一个query请求指定时间点up参数的数据
$ curl 'http://localhost:9090/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z'
{
"status": "success",
"data":{
"resultType": "vector",
"result" : [
{
"metric" : {
"__name__" : "up",
"job" : "prometheus",
"instance" : "localhost:9090"
},
"value": [ 1435781451.781, "1" ]
},
{
"metric" : {
"__name__" : "up",
"job" : "node",
"instance" : "localhost:9100"
},
"value" : [ 1435781451.781, "0" ]
}
]
}
}
同理,可以使用/api/v1/query_range
接口请求一段时间内的数据
- query=: Prometheus表达式查询字符串。
- start=<rfc3339 | unix_timestamp>: 开始时间戳。
- end=<rfc3339 | unix_timestamp>: 结束时间戳。
- step=: 以持续时间格式查询分辨率步长或浮点秒数。
- timeout=:评估超时,默认为-query.timeout标志的值并受其限制。
4.2 请求元数据
通过/api/v1/series
接口可以对元数据信息进行查询,通过match[]
参数可以指定选择器
$ curl -g 'http://localhost:9090/api/v1/series?match[]=up&match[]=process_start_time_seconds{job="prometheus"}'
{
"status" : "success",
"data" : [
{
"__name__" : "up",
"job" : "prometheus",
"instance" : "localhost:9090"
},
{
"__name__" : "up",
"job" : "node",
"instance" : "localhost:9091"
},
{
"__name__" : "process_start_time_seconds",
"job" : "prometheus",
"instance" : "localhost:9090"
}
]
}
4.3 查询目标
通过/api/v1/targets
可以查询Prometheus监控的目标信息
$ curl http://localhost:9090/api/v1/targets
{
"status": "success",
"data": {
"activeTargets": [
{
"discoveredLabels": {
"__address__": "127.0.0.1:9090",
"__metrics_path__": "/metrics",
"__scheme__": "http",
"job": "prometheus"
},
"labels": {
"instance": "127.0.0.1:9090",
"job": "prometheus"
},
"scrapeUrl": "http://127.0.0.1:9090/metrics",
"lastError": "",
"lastScrape": "2017-01-17T15:07:44.723715405+01:00",
"health": "up"
}
],
"droppedTargets": [
{
"discoveredLabels": {
"__address__": "127.0.0.1:9100",
"__metrics_path__": "/metrics",
"__scheme__": "http",
"job": "node"
},
}
]
}
}
还有一些用于查询的API接口,可以详见https://prometheus.io/docs/prometheus/latest/querying/api/
# 查询配置规则信息
curl http://localhost:9090/api/v1/rules
# 查询所有活动警报的列表
curl http://localhost:9090/api/v1/alerts
# 查询运行时信息
curl http://localhost:9090/api/v1/status/runtimeinfo
4.4 管理API
Prometheus提供了一些用于管理的API如下
# 健康检测,始终返回200,应用于检查Prometheus的运行状况。
curl http://localhost:9090/-/healthy
# 准备检查,当Prometheus准备服务流量(即响应查询)时,返回200
GET /-/ready
# 重载:请求对配置和规则文件的重新加载。 默认情况下它是禁用的,可以通过--web.enable-lifecycle标志启用
curl -X POST http://localhost:9090/-/reload
# 也可以通过将SIGHUP发送到Prometheus进程来触发配置重载。
kill -HUP pid
# 退出,Prometheus的正常关闭。 默认情况下它是禁用的,可以通过--web.enable-lifecycle标志启用
PUT /-/quit
POST /-/quit
5 存储
Prometheus本身自带时间序列数据库,可以将数据存储到本地磁盘,但也可选择将数据存放到远端TSDB
采集的样本按每两个小时的时间段保存到一个子目录下,包含该时间窗口的所有时间序列样本、元数据文件和索引文件。目录结构如下所示:
./data
├── 01BKGTZQ1SYQJTR4PB43C8PD98
│ ├── chunks
│ │ └── 000001
│ ├── tombstones
│ ├── index
│ └── meta.json
├── 01BKGV7JC0RY8A6MACW02A2PJD
│ ├── chunks
│ │ └── 000001
│ ├── tombstones
│ ├── index
│ └── meta.json
└── wal
├── 00000002
└── checkpoint.000001
预写日志文件以128MB段存储在wal目录中,这些文件包含尚未压缩的原始数据,因此它们比常规块文件大得多,在崩溃后重新启动Prometheus服务器时重放预写日志(WAL)防止数据丢失。
通过API进行删除操作时,删除记录存储在单独的逻辑删除文件中,而不是立即从块文件中删除数据
在启动时可以通过如下参数对存储特性进行设置:
- –storage.tsdb.path: 这决定了Prometheus写入数据库的位置。 默认为data/。
- –storage.tsdb.retention.time: 这决定了何时删除旧数据,默认为15d
- –storage.tsdb.retention.size: [EXPERIMENTAL]这确定了存储块可以使用的最大字节数
- –storage.tsdb.wal-compression: 此标志启用预写日志(WAL)的压缩。
Prometheus的本地存储在可伸缩性和持久性方面受到单个节点的限制,因此提供了相关接口用于写入或者读取远程存储
- Prometheus可以将提取的样本以标准格式写入远程URL。
- Prometheus可以以标准化格式从远程URL读取(返回)样本数据。
关于远程读写的配置文档详见:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write
6 集群部署
当监控的节点和数据量增大时,我们希望以集群的方式对节点进行监控
- 长期存储:1 个月左右的数据存储,每天可能新增几十G,希望存储的维护成本足够小,有容灾和迁移。最好是存放在云上的 TSDB 或者对象存储、文件存储上。
- 无限拓展:我们有上百集群,几千节点,上万个服务,单机 Prometheus 无法满足,且为了隔离性,最好按功能做 Shard,如 Node机器监控与 K8S POD 资源等业务监控分开、主机监控与日志监控也分开,者按业务类型分开。
- 全局视图:按类型分开之后,虽然数据分散了,但监控视图需要整合在一起,一个Grafana 里n个面板就可以看到所有地域+集群的监控数据,操作更方便,不用多个Grafana的Dashboard 切来切去。
- 无侵入性:不会因为增加监控业务而重新加载Prometheus配置,因为重新加载Prometheus配置对Prometheus稳定是有风险的。
6.1 高可用HA
图中的P1和P2表示重复部署两套 Prometheus 采集完全一样的数据,外边挂负载均衡,从而实现系统的高可用
6.2 联邦集群
联邦集群:即 Federation,允许Prometheus服务器从另一台Prometheus服务器抓取选定的时间序列。当需要监控的节点和数据量很大时,可以按照功能进行分区,不同的 Shard 采集不同的数据,由 Global 节点来统一存放,解决监控数据规模的问题。
在Prometheus服务器上,/federate
路径允许检索该服务器中所选时间序列集的当前值。 通过match[]
可以指定一个瞬时向量选择器,如up或{job=“api-server”}, 可以指定多个选择器
要将指标从一个服务器联合到另一个服务器,请将目标Prometheus服务器配置为从源服务器的/federate端点进行采集。例如,以下scrape_config将抓取source-prometheus-{1,2,3}:9090的Prometheus服务器中job="prometheus"的数据
scrape_configs:
- job_name: 'federate'
scrape_interval: 15s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{job="prometheus"}'
- '{__name__=~"job:.*"}'
static_configs:
- targets:
- 'source-prometheus-1:9090'
- 'source-prometheus-2:9090'
- 'source-prometheus-3:9090'
6.3 Thanos
Thanos用于结合Prometheus来实现监控集群的可扩展性和高可用
Thanos的组成部分有:
- Sidecar:作为一个单独的进程和已有的Prometheus实例运行在一个server上。Sidecar可以视为一个Proxy组件,所有对Prometheus的访问都通过Sidecar来代理进行。通过Sidecar还可以将采集到的数据直接备份到云端对象存储服务器。
- Query负责找到对应的集群并通过Sidecar获取数据,它实现了一套Prometheus官方的HTTP API从而保证对外提供与Prometheus一致的数据源接口。Query可以实现对高可部署的Prometheus的数据进行合并从而保证多次查询结果的一致性,通过同一个查询接口请求不同集群的数据
- Store是用于对历史数据进行存取的对象存储空间,Sidecar在完成数据备份后,Prometheus会清理掉本地数据保证本地空间可用,这时可以通过Store,实现了一套和Sidecar完全一致的API提供给Query用于查询Sidecar备份到云端对象存储的数据。
- Comactor读取对象存储的数据,对其进行压缩以及降采样再上传到对象存储,这样在查询大时间范围数据时就可以只读取压缩和降采样后的数据,极大地减少了查询的数据量,从而加速查询。
因此其工作原理为:
Sidecar监控prometheus本地block的chunks文件,当chunks文件有增加时thanos sidecar会将chunks数据通过grpc上传到Store,接收到的数据落入云存储;当Grafana向thanos query发起查询请求时,会从各个thanos sidecar拉取本地数据,并且通过thanos store从云存储上拉取历史数据,最后数据在thanos query进行汇总和去重返回给grafana。
如图所示,使用zookeeper进行服务发现和管理,当新增一台机器上报的metrics只需在zookeeper注册上报信息,prometheus自动发现新增的metrics,不需要重启prometheus或者重新加载prometheus配置
以上架构具有:
- 可靠性:thanos sidecar 会记录已经拉取过的prometheus chunk文件,在prometheus新生成chunk文件的时候thanos sidecar会通过thanos store同步chunk数据到S3云存储,实现了metrics数据无限期保留,保证了数据的可靠性。
- 稳定性:Prometheus数据拉取和数据查询拆分,不会因为大查询导致Prometheus内存暴增后服务挂掉,影响数据拉取,出现metrics数据断层。
- 可维护性:运维和开发人员不用修改prometheus配置,所有操作通过业务控制台维护zookeeper数据完成。
- 可伸缩性:一台Prometheus node节点只拉取几十台服务器的metrics数据,随着业务规模的变化灵活调整Prometheus node节点的数量。