普罗米修斯查询训练营
首先/第一,
这是普罗米修斯万圣节日历2017年第16天的文章。
请问大家有用过 Prometheus 吗?很好用的,Prometheus。
收集数据并随意查询,当发现可疑行为时,喜悦难以言表。
这种”不知道是什么,但感觉很厉害”的感觉,可说是鲜艳夺目,犹如现代的IT曼陀罗。
用于引用 Prometheus 中积累的各种度量标准的参考是使用一种名为 PromQL 的专有查询语言进行的。虽然一旦熟悉就不会有太多困扰,但由于需要在时间序列度量标准中进行全方位的探索,所以我想在查询道场从基础开始学习。
如果你不知道「Prometheus」到底是什么,那么你可以这样问。
-
- Prometheus入門から運用まで徹底解説
次世代監視の大本命! Prometheus を実運用してみた ( @sugitak )
请先阅读这份出色的资料。
关于环境
在这篇文章中使用的Prometheus版本是2.0。
您可以通过查看Prometheus的[状态] -> [运行时和构建信息] -> [构建信息]来确认当前运行的版本。
文章を参照してください。
自分のマシンでprometheusを動かしてみよう ( @tjinjin )
如果您想尝试环境搭建,可以参考这篇文章。只要能成功安装Docker,就会感到非常轻松。
我自己以Rancher社区目录为基础,在多台设备上搭建了Prometheus 2.0环境。
由于Prometheus仍在不断发展中,因此关于它可以在谷歌上找到的文章版本相当多样化。
我认为仍然有很多人只是随意地复制粘贴运行,然后发现是1系列的版本,所以请注意版本。
如果想要使用最新的Web文章,无论是什么类型的文章,可以参考prometheus/prometheus – GitHub或prom/prometheus – DockerHub。截至到2017年12月16日,最新版本是2.0.0。
了解数据
在Prometheus中查询意味着有要搜索的数据。在学习具体查询之前,让我们首先大致了解一下Prometheus可以收集到哪些数据。
1-1. 确认数据收集设置
Prometheus使用了Pull型架构,所以在服务器端保存了要收集的数据的信息。
可以通过 [Status] -> [Targets] 查看要收集的数据列表,让我们先来看一下。
由于Rancher社区目录已经设置了几个出口器,所以可以看到相当多的目标。
这取决于在prometheus.yml中定义的scrape_configs的配置。
该配置可以在[状态] -> [配置]中查看。
例如,如果是在第二个HostMetrics中可见,则
scrape_configs:
- job_name: HostsMetrics
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
dns_sd_configs:
- names:
- node-exporter
refresh_interval: 15s
type: A
port: 9100
是这样定义的。我希望你在这里注意的是 dns_sd_configs 的部分。通过查看上面的图像,可以看出 HostMetrics 的目标具体有3个,但在设置中似乎并没有看到有3个。在这里实际发挥作用的正是 dns_sd_configs,将其作为 node-exporter 的名称用于收集目标。
您可以通过 static_configs 参数来静态配置目标,也可以通过支持的服务发现机制之一来动态发现目标。
如果理解了”sd”代表”service discovery”的缩略意味,那么对于其工作过程的想象会变得更加容易。除了”dns_sd_config”,还可以查看”CONFIGURATION”页面。
-
- ec2_sd_config
-
- azure_sd_config
-
- gce_sd_config
-
- openstack_sd_config
- kubernetes_sd_config
似乎可以发现许多不同的事物。
1-2. 数据样本的确认
那么,让我们来看一些实际收集到的数据吧。
一个简单的方法是从Prometheus的界面随便执行一个查询试试看。
当您在查询窗口中输入指标名称(部分名称)时,会提供与其匹配的指标建议。
这些指标建议非常灵活,从图例中可以看出,提供的建议不仅包含了包含”node_memory_free”的指标,还包括了包含字符 “n/o/d/e/_/m/r/y/f”的指标。
选择候选项并点击“执行”按钮后,您可以在“控制台”选项卡中确认实际数据,并在“图表”选项卡中查看图表。
在Element中,Metrix的名称后面会出现各种标签,这是查询中一个重要的要点,稍后会进行解释。
默认显示是最近1小时的图表,但您可以通过[ – ] [ + ]更改显示时间段,也可以通过[◀◀] [▶▶]更改显示起始时间。
除此之外,还有一种方法是直接进入Prometheus容器,参考抓取目标的Endpoint。通过这种方法,您可以实时了解每个Endpoint的度量数据。当抓取出现问题时,我们也会采取这种方法进行故障排除。
# PrometheusコンテナのIDを調べる
$ sudo docker ps -f name=prometheus
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4965fc87373 prom/prometheus:v2.0.0 "/.r/r /bin/promet..." 4 hours ago Up 4 hours r-Prometheus-prometheus-1-736c0be3
29e30fcc5a55 infinityworks/prom-conf:19 "/bin/sh" 4 hours ago Up 4 hours r-Prometheus-prometheus-prom-conf-1-1e026d96
# Prometheusコンテナに接続(bashがないのでshにつなぐ)
$ sudo docker exec -it f4965fc87373 /bin/sh
# PrometheusメトリクスのEndpointを参照(curlがないのでwgetを使って標準出力に出している)
$ wget http://127.0.0.1:9090/metrics -qO -
Connecting to 127.0.0.1:9090 (127.0.0.1:9090)
go_gc_duration_seconds{quantile="0"} 2.046e-05
go_gc_duration_seconds{quantile="0.25"} 8.5385e-05
go_gc_duration_seconds{quantile="0.5"} 0.000147534
go_gc_duration_seconds{quantile="0.75"} 0.000350681
go_gc_duration_seconds{quantile="1"} 0.010048808
go_gc_duration_seconds_sum 0.087973045
go_gc_duration_seconds_count 173
(略)
我认为可以大致了解到正在收集什么样的数据。
1-3. 对数据结构的理解
我想你剛才已經簡單檢查了數據,但現在讓我們再次看看數據。
在这里有三个数据(元素)出现,它们的区别体现在 node_memory_MemFree 后面的 { } 中。
这些被包含在其中的项目称为标签,并且可以看出这些数据有 instance 标签和 job 标签。
按照时间顺序排列,Prometheus处理所谓时序数据。根据数据模型的提及,每个数据都具有公共的标记(labels),可以用于查询和过滤。
-
- timestamp
-
- metric name
- label
将进行识别。
在图表中只显示了三个数据点,但这只是显示了最近的数据,实际上,即使是相同的指标和标签,数据也是如下所示的叠加。
因此,确定度量标准并形象化数据时
縦 の広がり: 同じメトリクス/同じ時間だが ラベルの違うもの
横 の広がり: 同じメトリクス/同じラベルだが 時間の違うもの
“对于这种感觉的重要性日益凸显。”
了解查询
那么现在让我们实际上来写一个查询吧。
查询数据
让我们首先选择合适的数据,这是很自然的。让我们尝试以下的查询。
# インスタンスをどれか1つ指定
node_memory_MemFree{instance="10.42.216.232:9100"}
这样一来,数据被筛选出来,只显示具有指定标签的数据。
如果在查询中将标签条件放在{ }中,只有具有该标签的数据会被返回。标签条件可以使用正则表达式,并将=~作为比较运算符。
# =~ で比較すると正規表現の指定になる
node_memory_MemFree{instance=~"^10.42.*:9100"}
在SQL中,可以把WHERE子句写在{}之中,就像这样。
此外,Prometheus的实现是使用Go语言,因此在PromQL中的正则表达式和转义处理遵循Go语言的规范(正则表达式/字符串)。
如果对转义感到困惑,请阅读Go语言相关的文档。
2-2. 进行数据计算
接下来,让我们进行数据计算试试吧。
# 加減乗除(+-*/)
node_memory_MemFree{instance="10.42.216.232:9100"} + 1000
node_memory_MemFree{instance="10.42.216.232:9100"} - 1000
node_memory_MemFree{instance="10.42.216.232:9100"} * 1000
node_memory_MemFree{instance="10.42.216.232:9100"} / 1000
# 剰余計算(%)
node_memory_MemFree{instance="10.42.216.232:9100"} % 1000
# べき乗計算
node_memory_MemFree{instance="10.42.216.232:9100"} ^ 2
根据数据来看,有时可能很难直观地理解其规模感,所以在这种情况下,经常会通过将其乘以1000倍或除以1/1000来对齐位数。
而且,还可以进行数据之间的计算。
# TotalからFreeを引くと使用中が出る
node_memory_MemTotal - node_memory_MemFree
# さらにTotalで割ると使用率が出る
( node_memory_MemTotal - node_memory_MemFree ) / node_memory_MemTotal
如果有类似”node_memory_MemUsed”这样的东西,我们就不需要这样做了。即使没有这样的东西,Prometheus也很好的一点是可以通过数据之间的计算来轻松补充。
2-3. 进行数据汇总
使用函数可以对列出的数据进行汇总。
# 最大/最小
max(node_memory_MemFree)
min(node_memory_MemFree)
# 合計/平均
sum(node_memory_MemFree)
avg(node_memory_MemFree)
如果没有特定的标签限制查询时,会出现三条数据,上述查询对它们分别提供了”最大值”、”最小值”、”总和”和”平均值”。
由于先前的 node_memory_MemFree 数据没有价值,因此我们将使用 node_filesystem_files_free 数据从这里开始。
最近出现了一些变化。根据文件系统的不同使用了fstype,在挂载点mountpoint上显示了数据。让我们尝试按挂载点来汇总数据。
# mountpointラベルごとにmaxの値を集計
max(node_filesystem_files) by (mountpoint)
看起来结果是这样的。
由于原始数据中混合了 fstype=”ext4″ 和 fstype=”overlay”,因此我们需要将它们分开显示。
# mountpointとfstypeラベルごとにmaxの値を集計
max(node_filesystem_files) by (mountpoint, fstype)
结果是这样的。考虑到 fstype 的统计结果增加了一个。
在中国,可以自由地通过(标签名称)来更改汇总的范围。
试用方便的函数
到目前为止,在这里
-
- メトリクス
-
- ラベル
-
- 参照
-
- 計算
- 集計
我认为你已经理解了这种思维方式以及如何使用它来进行查询。到目前为止,我认为你已经能够进行大部分数据探索并基于此进行图形创建。但是因为Prometheus中有许多有用的函数,所以我想介绍其中的一些。
3-0. 区间向量和瞬时向量
我以後再解釋這個問題,但根據表達語言資料類型,Prometheus的數據有以下4種類型。
-
- Instant vector
-
- Range vector
-
- Scalar
- String (ただし2.0時点では未使用)
到目前为止的查询中,我们使用了Instant vector和Scalar,Instant vector用于对每个元素返回一个值,并用于中间计算。
# Instant vectorにScalarを足す
node_memory_MemFree + 100
以下的查询是针对称为“Range vector”的类型,因为这一点之前没有解释清楚,但您可以尝试一下以更快地理解。
# 直近1分間のデータを表示する
node_memory_MemFree[1m]
每个元素都有4个数据。
尽管查询指定了1分钟,但是获得的数据似乎有4个。
这是因为 node_memory_MemFree 指标的抓取间隔为15秒。
scrape_configs:
- job_name: HostsMetrics
scrape_interval: 15s ★ここ
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
dns_sd_configs:
- names:
- node-exporter
refresh_interval: 15s
type: A
port: 9100
以指定时间范围获取一系列数据的数据类型被称为Range vector。由于许多函数的参数是Range vector,因此我们先解释了这个概念。
3-1. 三角函数
现在我来解释一下如何使用Range vector函数。
- delta(Range vector)
在Delta函数中,可以取给定的Range向量数据的差分。
# 直近1時間での空きメモリ量の差
delta(node_memory_MemFree[1h])
在Range vector中,它包含了指定时间范围内的大量数据,而delta函数计算的是该时间段内的第一个值与最后一个值之间的差值。
因此,在上述查询中,我们是通过当前值减去1小时之前的值来计算差值。
如果查询结果是负数的话,可以推断出”最近1小时内可用内存减少了”。
3-2. 比率函数
- rate(Range vector)
rate函数是针对相同的Range值,返回当前值相对于期间内平均值的比例。
# idle状態のCPUが直近5分平均に比べてどれくらい増えているか
rate(node_cpu{mode="idle"}[5m])
作为典型示例,你可以在官方示例查询中找到一个使用HTTP请求计数的例子。
# 5分平均のリクエスト数からどれくらい増えているか
rate(http_requests_total{job="api-server"}[5m])
如果您观察这个数值,就可以看到每秒请求数的增加或减少。
顺便提一下,类似的函数中还有一个称为 irate 的函数,但它是将最后两个时间点的平均值与当前值进行比较。
在平稳的情况下,rate 和 irate 的运动方式是相同的,但是当存在非常瞬间的尖峰时,rate 可能无法做出反应,因此 irate 似乎选择最后两个点作为比较对象。
愤怒只应在绘制波动剧烈、迅速变动的计数器时使用。对于警报和缓慢移动的计数器,请使用速率,因为速率的微小变化可以重新设置FOR子句,而仅由罕见的尖峰组成的图表很难阅读。
3-3. 变化函数
- changes(Range vector)
changes函数用于计算给定的Range向量中发生了多少次值的变化。
通常情况下,它会被用于计算状态更改发生了多少次的案例中。
# healthステータスが1時間で何回変化したか
changes(rancher_service_health_status{health_state="healthy"}[1h])
3-4. 其他选项
下面提供了中国人的翻译版本:
这只是一个像小玩笑一样的函数。它可以用来微调结果或者在交互式研究中提供帮助的感觉。
ceil(Instant vector)
与えられたInstant vectorの切り上げを行う関数。 floor が切り下げ。四捨五入なら round 。
abs(Instant vector)
与えられたInstant vectorの絶対値を返す関数。
sort(Instant vector)
結果を昇順でソートする。降順ソートは sort_desc 。
最后
你对整体数据的理解和基本查询的写法都明白了吗?
普罗米修斯还有其他的功能,比如进行对数计算的log2函数,利用线性回归进行线性预测的predict_linear函数,以及进行微分的deriv函数等等。
这个查询本身还有很多深奥的东西,包括如何利用它们来监控系统,似乎还有很大的深入空间。
非常有意义。
-
- クエリを使ってダッシュボードを作成する
参考: prometheusとgrafanaを入れたみたが、どうグラフとか出すといいのか?
収集データを追加する
Prometheus – exporters
参考: prometheusのexporter紹介シリーズ1〜blackbox_exporter
按此方式,我们将需要面对监视问题。
结束了。