一、Prometheus和Grafana是什么
通常来说,对于一个运行时的复杂系统,如果系统出了问题是很难排查的。因为你是不太可能在运行时一边检查代码一边调试的。因此,你需要在各种关键点加上监控,通过监控获取的数据,指导我们进一步工作,解决问题。
用开车作为例子:车子本身是一个极其复杂的系统,而当你的车在高速上以 120 公里的速度狂奔时出现了噪音,你是不可能这时候边开车边打开发动机盖子来查原因的。通常来说,好一点的车会有内置电脑,在车子出问题时,告诉你左边轮胎胎压有问题,或是发动机缺水了之类。而这些检测,就是系统监控的一个例子。
对于车辆本身,驾驶员关心的指标如下:
- 我的速度是多少 - 速度仪表盘
- 我的油、发动机水温等等关键指标是多少 - 其它仪表盘
通过仪表盘,你不一定能清楚地了解车子出问题的具体原因,但至少可以给你一个大概的方向。比如说,如果水温很高时出现了问题,你大概率可以尝试加点水降温来尝试是否解决问题。
把上面的车类比计算机系统或者一个软件系统:Grafana就是仪表盘,它和车辆的速度表、水温表是一类的,通过这些表盘你可以实时了解系统运行情况。而Prometheus作为一个时序数据库,其实它和大家熟知的Mysql是一类的东西,都是存储数据,提供查询的,它存储了计算机系统在各个时间点上的监控数据。而Grafana仪表盘上的数据,就是通过查询Prometheus获取的。
二、监控系统组成
1.Grafana
是一个监控仪表系统,由Grafana Labs公司开源的的一个系统监测 (System Monitoring) 工具。帮助用户简化监控的复杂度,用户只需要提供需要监控的数据,它就可以生成各种可视化仪表。同时它还支持报警功能,可以在系统出现问题时通知用户。并且Grafana不仅仅只支持Prometheus作为查询的数据库,它还支持如下:
- Prometheus
- Graphite
- OpenTSDB
- InfluxDB
- MySQL/PostgreSQL
- Microsoft SQL Serve
- 等等
2.Prometheus
Prometheus是一个时间序列数据库。但是,它不仅仅是一个时间序列数据库。它涵盖了可以绑定的整个生态系统工具集及其功能。Prometheus主要用于对基础设施的监控,包括服务器(CPU、MEM等)、数据库(MYSQL、PostgreSQL等)、Web服务等,几乎所有东西都可以通过Prometheus进行监控。而它的数据,则是通过配置,建立与数据源的联系来获取的。
虽然Grafana可以从多种数据(如Prometheus、MySQL/PostgreSQL、OpenTSDB)等等中获取数据,不过Prometheus天生就是为了监控而生,所以我们用的最多的还是Prometheus。这也是我们的标配哦~
3.数据源
在Prometheus的架构设计中,Prometheus并不直接服务监控特定的目标,就比如我们监控linux系统,Prometheus不会自己亲自去监控linux的各项指标。其主要任务负责数据的收集,存储并且对外提供数据查询支持。
因此为了能够监控到某些东西,如主机的CPU使用率,我们需要使用到Exporter。Exporter是一个相对开放的概念,不是专门指某一个程序。它可以是一个独立运行的程序,独立于监控目标以外(如Node Exporter程序,独立于操作系统,却能获取到系统各类指标)。也可以是直接内置在监控目标中的代码(如在项目代码层面接入普罗米修斯API,实现指标上报)。总结下来就是,只要能够向Prometheus提供标准格式的监控样本数据,那就是一个Exporter。
而Prometheus周期性的从Exporter暴露的HTTP服务地址(通常是/metrics)拉取监控样本数据。
对于大家常见的监控主机运行的指标如CPU, 内存,磁盘等信息,我们可以为linux系统下载Node Exporter程序,该程序会监控linux各项指标,并通过:http://<IP>:9100/metrics
来展示各项指标。而其给我们返回的内容如下图所示:
看完本图,大家肯定还是对图中的各种内容比较疑惑。不过大家不用着急,我会在下一个章节给大家解释~
4.工作原理
现在我们有了以下3个部分:
- Exporter 监控工具,获取数据
- Prometheus 普罗米修斯时序数据库,用来存储和查询你的监控数据
- Grafana 仪表盘 监控流程
三、Prometheus基本概念
在上一节中,我们访问Node Exporter暴露的HTTP服务,获取到了一系列的监控指标。而这些监控指标便是Prometheus可以采集到当前主机所有监控指标的样本数据。这里再把图放一遍,并进行解释。
- 图中以#开头相当于注释,我们不用太关注。
- 图中以非#开头的每一行则表示当前Node Exporter采集到的一个监控样本。
- 对于图中可见的node_cooling_device_max_state和node_cpu_guest_seconds_total,代表了当前监控样本的名称。
- 紧跟指标后大括号中的键值对中的键被称为标签,它与键值对的值共同组成筛选条件,相当于Mysql里的Where后面的内容。键值对整体反映了当前样本的一些特征和维度。
- 而右大括号后的值则是该监控样本监控下的具体值。
1.样本(sample)
Prometheus会将所有采集到的样本数据以时间序列(time-series)的方式保存在内存数据库中,并且定时保存到硬盘上。时间序列保存方式是指按照时间戳和值的序列顺序存放,也称之为向量(vector)。 每条时间序列通过指标名称(metrics name)和一组标签集(labelset)命名。如下图所示,可以将向量理解为一个以时间为X轴,值为Y轴的数字矩阵:
在时间序列中的每一个点(即图上的小黑点)称为一个样本(sample),样本由以下三部分组成:
- 指标(metric):metric name和描述当前样本特征的labelsets,也就是图中的
A{a="x",b="y"}
; - 时间戳(timestamp):一个精确到毫秒的时间戳,也就是小黑点对应的x轴的值;
- 样本值(value): 一个float64的浮点型数据表示当前样本的值,即小黑点对应的y轴的值;
即样本可表示为:
代码语言:txt复制A{a="x",b="y"}@1434417560938 => 94355
其中1434417560938是时间戳,94355是值。
2.指标(Metric)
在形式上,所有的指标(Metric)都通过如下格式标示:
代码语言:txt复制<metric name>{<label name>=<label value>, ...}
指标的名称(metric name)可以反映被监控样本的含义(比如,httprequest_total - 表示当前系统接收到的HTTP请求总量)。指标名称只能由ASCII字符、数字、下划线以及冒号组成并必须符合正则表达式[a-zA-Z:]a-zA-Z0-9_:*。
3.标签(label)
标签反映了当前样本的特征维度,通过这些维度Prometheus可以对样本数据进行过滤,聚合等。标签的名称只能由ASCII字符、数字以及下划线组成并满足正则表达式a-zA-Z_*。
其中以_作为前缀的标签,是系统保留的关键字,只能在系统内部使用。标签的值则可以包含任何Unicode编码的字符。
四、PromQL
ps:本文只对PromQL做一个简单介绍,提供常用方法,如果要深入了解,可以查看:prometheus-book。
Prometheus通过指标名称(metrics name)以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而label则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤,聚合,统计从而产生新的计算后的一条时间序列。
PromQL是Prometheus内置的数据查询语言,其提供对时间序列数据丰富的查询,聚合以及逻辑运算能力的支持。并且被广泛应用在Prometheus的日常应用当中,包括对数据查询、可视化、告警处理当中。可以这么说,PromQL是Prometheus所有应用场景的基础,理解和掌握PromQL是Prometheus入门的第一课。
1.查询时间序列
当Prometheus通过Exporter采集到相应的监控指标样本数据后,我们就可以通过PromQL对监控样本数据进行查询。当我们直接使用监控指标名称查询时,可以查询该指标下的所有时间序列(不带筛选条件)。如:
代码语言:txt复制http_requests_total
等同于:
代码语言:txt复制http_requests_total{}
该表达式会返回指标名称为http_requests_total的所有时间序列。
PromQL还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。
完全匹配:
PromQL支持使用=和!=两种完全匹配模式:
- 通过使用label=value可以选择那些标签满足表达式定义的时间序列;http_requests_total{instance="localhost:9090"}反之使用instance!="localhost:9090"则可以排除这些时间序列~
- 反之使用label!=value则可以根据标签匹配排除时间序列; 例如,如果我们只需要查询所有http_requests_total时间序列中满足标签instance为localhost:9090的时间序列,则可以使用如下表达式:
不完全匹配:
除了使用完全匹配的方式对时间序列进行过滤以外,PromQL还可以支持使用正则表达式作为匹配条件,多个表达式之间使用|进行分离:
- 使用label=~regx表示选择那些标签符合正则表达式定义的时间序列;
- 反之使用label!~regx进行排除。
例如,如果想查询多个环节下的时间序列序列可以使用如下表达式:
代码语言:txt复制http_requests_total{environment=~"staging|testing|development",method!="GET"}
2.范围查询
直接通过类似于PromQL表达式http_requests_total查询时间序列时,返回值中只会包含该时间序列中的最新的一个样本值,这样的返回结果我们称之为瞬时向量。而相应的这样的表达式称之为瞬时向量表达式。
而如果我们想过去一段时间范围内的样本数据时,我们则需要使用区间向量表达式。区间向量表达式和瞬时向量表达式之间的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器[]进行定义。通过区间向量表达式查询到的结果我们称为区间向量。
例如,通过以下表达式可以选择最近5分钟内的所有样本数据:
代码语言:txt复制http_requests_total{}[5m]
该表达式将会返回查询到的时间序列中最近5分钟的所有样本数据。
除了使用m表示分钟以外,PromQL的时间范围选择器支持其它时间单位:
代码语言:txt复制s - 秒
m - 分钟
h - 小时
d - 天
w - 周
y - 年
3.时间位移操作
在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准:
代码语言:txt复制http_request_total{} # 瞬时向量表达式,选择当前最新的数据
http_request_total{}[5m] # 区间向量表达式,选择以当前时间为基准,5分钟内的数据
而如果我们想查询,5分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢? 这个时候我们就可以使用位移操作,位移操作的关键字为offset。
可以使用offset时间位移操作:
代码语言:txt复制http_request_total{} offset 5m
http_request_total{}[1d] offset 1d
4.使用聚合操作
一般来说,如果描述样本特征的标签(label)在并非唯一的情况下,通过PromQL查询数据,会返回多条满足这些特征维度的时间序列。而PromQL提供的聚合操作可以用来对这些时间序列进行处理,形成一条新的时间序列。
支持的聚合函数有:
代码语言:txt复制sum (求和)
min (最小值)
max (最大值)
avg (平均值)
stddev (标准差)
stdvar (标准方差)
count (计数)
count_values (对value进行计数)
bottomk (后n条时序)
topk (前n条时序)
quantile (分位数)
使用聚合操作的语法如下:
代码语言:txt复制<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
根据上面的函数,我们就可以通过聚合函数进行如下查询:
代码语言:txt复制# 查询系统所有http请求的总量
sum(http_request_total)
# 按照label:mode计算主机CPU的平均使用时间
avg(node_cpu) by (mode)
# count_values用于时间序列中每一个样本值出现的次数。count_values
# 会为每一个唯一的样本值输出一个时间序列,并且每一个时间序列包含一个额外的标签。
count_values("count", http_requests_total)
五、搭建仪表盘
注意:注意:搭建方式依托于腾讯云TSF服务(腾讯微服务平台),即监控的内容是我们在腾讯云上搭建的集群的各项指标,接下来的例子我们以golang代码里接入普罗米修斯,代码层面实现指标上报这种模式为例。如果不借助腾讯云,部分内容可能会有出入。如只是简单使用,监控一些服务器资源等信息,可自行安装Prometheus、Grafana和Node-exporter等,具体方法参照:配置 Prometheus 服务器监控和 Grafana 看板
1.购买普罗米修斯服务
登陆腾讯云,在“云产品”处搜索“普罗米修斯”,进入Prometheus服务页面购买服务。特别注意单个普罗米修斯服务只能在单个vpc(私有网络)下使用的,所以购买时一定要确认清楚自己需要监控的服务所在的vpc,即对应下图框内“网络”的第一个下拉框。而第二个“子网”下拉框,则描述了新购买的普罗米修斯服务所安装的子网。
Grafana密码按照平台要求设置并牢记,这个密码在后面登陆Grafana用户界面用得上。
2.TSF服务部署
在部署我们的TSF服务时,需要注意将普罗米修斯上报端口(即容器端口)映射到主机端口上,这样普罗米修斯才能获取到对应的上报数据。
3.安装集成容器服务组件
接下来就需要到容器中安装监控组件啦。
第一步,进入腾讯云”控制台“,在“云产品”处搜索tke(容器服务),进入容器服务集群列表。这时候找到在TSF(腾讯微服务平台)上创建的集群对应的同名容器集群,点击集群名称,再点击“基本信息”,往下找到“内网访问”,开启它,并按照描述在访问机上配置域名。
第二步,回到普罗米修斯控制台,点击新购买的Prometheus服务的名称,进入到服务详情。点击“集成容器服务“,找到和之前在TSF服务中创建的“集群”同名的“容器集群”,点击任务栏右侧的“安装”按钮,安装监控服务。
ps:这一步就相当于在安装数据源,也就相当于前文提到的Node Exporter这个角色。不过在腾讯云上,安装的东西会更多,让我们能监控更多内容~
第二步,在新版本里,我们只需要在“容器服务”-“Prometheus监控”-“集群监控”里将我们的集群与Prometheus进行关联即可。这里要注意的是集群与Prometheus需要在同一个VPC(私有网络)之下,如果不同的私有网络可能会有额外费用,需要额外设置等。
4.服务发现配置
在上面的步骤执行完后,我们的集群”监控状态“变成了“已安装”,继续点击集群名称,在“服务发现”Tab页点击“新建”按钮。接下来按下图提示来新建服务发现吧。服务发现的上报端口,也就是我们在“TSF服务部署”那一步中开放的容器端口。
在新版本里,集群监控不仅支持yaml方式,还支持了简单版的采集配置,yaml方式依旧可以按照上面的方式类似,这里再介绍一下配置的方式。如下图,点击“数据采集配置”。
选择“自定义监控”-“新增”按钮,就可以通过简单的配置实现自定义的监控啦~
至此,只要对应部署组的服务中上报了metrics(基于golang代码里接入普罗米修斯,代码层面实现指标上报),且容器创建时,开放了上报端口,则数据就会被采集到Prometheus。后续我们在Grafana上选择Prometheus作为数据源,便能获取到服务的监控信息。
5.Grafana配置数据源
在Prometheus服务页面点击下图红框内按钮,进入Grafana。账号为admin,密码为之前购买普罗米修斯时设置的Grafana密码。
进入Grafana后,按照以下步骤建立数据源:
- 点击 Grafana Logo 打开侧边栏。
- 在侧边栏内,点击「Data Sources」。
- 选择「Add New」。
- 选择「Prometheus」作为数据源。
- 设置 Prometheus 服务的 URL(
http://<Prometheus服务的ip>:9090/
)。 - 点击 「Add」即可测试连接并保存为新的数据源。
6.创建仪表盘
首先明确我们接下来是在创建golang的web服务的仪表盘,如果读者只是想监控服务器状态等,完全可以从官方的](https://grafana.com/dashboards?dataSource=prometheus)导入一些现成的看板。
首先明确一下Grafana中的几个组件:
- Folder:Dashboards的文件夹。如果我们的服务包含了很多个监控单元(比如:后台、数据库、中间件等),我们就可以把这些单元的看板放在同一个文件夹中,从而归档整理。这个是可选的,如果我们的服务就一个Dashboards,完全没必要新建一个文件夹。
- Dashboards:看板,也就是白板,上面可以放很多仪表盘。
- Panel:仪表盘,具体的监控数据及图形化展示。
它们之间的关系如下图所示:
在理解了这几个基本概念后,加上我们之前学习到的PromQL,我们就可以开始创建仪表盘啦~
在Dashboards上点击“add new pannel”进入仪表盘编辑模式,在这里我们找到自己服务,并找到下挂的Metrics(指标),选择后即可在pannel上展示出对应的数据,如果还需要展示别的指标,可以点击下方的“ Query”按钮,即可继续添加指标。如果需要对指标进行操作,比如聚合计算,那么我们只需要在Metrics后的文本栏中对内容进行修改。编辑完成后,点击保存,即得到了一个仪表盘~
参考资料
- Grafana 教程 - 构建你的第一个仪表盘
- 腾讯云官方文档
- prometheus-book
本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
原作者: yuann,欢迎转载,但请注明出处。
原文链接:《一文搞懂Prometheus、Grafana(含腾讯云上实战)》
发布日期:2021-01-06