监控系统-Prometheus(普罗米修斯)(三) Prometheus中的指标(Metrics)
Prometheus整体架构分为Server端和Exporter端,而Exporter通常是基于官方的SDK开发(例如Go SDK)。
监控系统-Prometheus(普罗米修斯)(三) Prometheus中的指标(Metrics)
Prometheus 四大度量指标和应用
参考URL: https://www.jianshu.com/p/fa5f911003c6
云原生基金会(CNCF)中的项目Prometheus已经成为最受欢迎的开源监控软件,并有效地成为指标监控的行业标准。
Prometheus定义了一个度量说明格式和一个远程写入协议,社区和许多供应商都采用这个协议来说明和收集度量成为事实上的标准。
OpenMetrics是另一个CNCF项目,它建立在Prometheus导出格式的基础上,为收集度量标准提供了一个与厂商无关的标准化模型,旨在成为互联网工程任务组(IEFT)的一部分。
一、Prometheus指标类型
Prometheus整体架构分为Server端和Exporter端,而Exporter通常是基于官方的SDK开发(例如Go SDK)。
这里要明确一个概念:数据指标类型只是Client端的一个概念,用于维护Metric的生产,以方便在业务上有所区分。
Prometheus 的客户端库中提供了四种核心的指标类型。客户端可以根据不同的数据类型调用不同的 API 接口,实际在 Prometheus server 中并不对指标类型进行区分,而是简单地把这些指标统一视为无类型的时间序列 Metric<Label01,Label02> value, timestamp.。时间戳是由监控后端(例如Prometheus)或代理在抓取指标时添加的。
Prometheus使用拉取模型来收集这些指标;也就是说,Prometheus主动抓取暴露指标的HTTP端点。这些端点可以是由被监控的组件自然暴露。
Prometheus可以抓取Prometheus暴露格式和OpenMetrics格式的指标。
-
Counter (计数器): 只增不减的累计计数器。
在应用场景中,像是请求次数、错误数量等等,就非常适合用 Counter 来做指标类型,另外 Counter 类型,只有在被采集端重新启动时才会归零。 -
Gauge (仪表盘):可增可减的仪表盘,表示单个数值。
在应用场景中,像是 Go 应用程序运行时的 Goroutine 的数量就可以用该类型来表示,在系统中统计 CPU、Memory 等等时很常见,而在业务场景中,业务队列的数量也可以用 Gauge 来统计,实时观察队列数量,及时发现堆积情况,因为其是浮动的数值,并非固定的,侧重于反馈当前的情况 -
Histogram(累积直方图): 汇总采样的分布情况.
在大多数情况下人们都倾向于使用某些量化指标的平均值,例如 CPU 的平均使用率、页面的平均响应时间。 -
Summary(摘要): 跟踪数据总和、数据个数等统计信息
每种类型都有其适合的使用场景。
1. Prometheus的GaugeVec、Gauge类型指标
GaugeVec
- 一个指标向量(Metric Vector),支持多维标签的 Gauge 指标集合。
- 允许使用相同指标名称和帮助文本的多个 Gauge 指标实例。
- 通过不同的标签维度区分每个指标时间序列。
- 使用场景:需要对同一指标进行分组的情况,如对节点、实例化维度的监控指标。
Gauge
- 单一的仪表盘类型指标,代表一个 floats64 的当前值。
- 不支持标签,只有一个简单的指标名称和时间序列。
- 使用场景:不需要区分维度,直接反映单一指标当前值的情况。
区别
- GaugeVec 支持标签,Gauge 不支持。
- GaugeVec 代表多个时间序列,Gauge 代表单一时间序列。
- GaugeVec 需要先注册再使用,Gauge 可以直接使用。
适用场景
- 需要标签的监控指标使用 GaugeVec。
- 简单的无标签指标使用 Gauge。
如果有多个 agent 需要监控,使用 GaugeVec 是很好的选择。GaugeVec 的标签机制很适合需要对多个对象进行同类指标监控的场景
主要原因:
- 针对每个 agent,指标都是一样的,如 CPU 使用率、内存使用等。
- 但需要区分每个 agent 的指标。
- GaugeVec 支持通过标签进行区分。
- 可以定义一个 agent_id 标签,用于标识每个 agent。
- 在上报指标时,通过不同的 agent_id 标签值,指标会自动归类到不同的时间序列里。
- 在 Prometheus 查询和 Dashboard 中,可以根据 agent_id 过滤和分组。
二、心跳数据转换为Prometheus的gauge类型指标实战demo
来自开源项目elkeid:
var agentGauge = map[string]*prometheus.GaugeVec{
"cpu": initPrometheusAgentCpuGauge(),
"rss": initPrometheusAgentRssGauge(),
"du": initPrometheusAgentDuGauge(),
"read_speed": initPrometheusAgentReadSpeedGauge(),
"write_speed": initPrometheusAgentWriteSpeedGauge(),
"tx_speed": initPrometheusAgentTxSpeedGauge(),
"rx_speed": initPrometheusAgentRxSpeedGauge(),
}
这段代码定义了一个名为agentGauge的map,它存储了一组Prometheus的GaugeVec类型指标。
GaugeVec是Prometheus提供的一种特殊指标,它是一个gauge vector(仪表盘向量),可以在一个gauge指标上配置多维标签,从而对指标进行分组。
- 定义了一个map,key是字符串,value是*prometheus.GaugeVec类型。
- key表示这个指标的名称,如"cpu"。
- value是对应的GaugeVec变量,在init函数中初始化。
func initPrometheusAgentCpuGauge() *prometheus.GaugeVec {
prometheusOpts := prometheus.GaugeOpts{
Name: "elkeid_ac_agent_cpu",
Help: "Elkeid AC agent cpu",
}
vec := prometheus.NewGaugeVec(prometheusOpts, []string{"agent_id", "name"})
prometheus.MustRegister(vec)
return vec
}
这段代码实现了初始化一个 Prometheus GaugeVec 类型指标的功能。
- 创建 GaugeOpts 对象,设置指标的名称和注释信息。
- 使用 NewGaugeVec 方法,根据 GaugeOpts 和标签键列表创建 GaugeVec 对象。
- 调用 prometheus.MustRegister 注册该指标。
- 返回创建的 GaugeVec 对象。
func metricsAgentHeartBeat(agentID, name string, detail map[string]interface{}) {
if detail == nil {
return
}
for k, v := range agentGauge {
if cpu, ok := detail[k]; ok {
if fv, ok2 := cpu.(float64); ok2 {
v.With(prometheus.Labels{"agent_id": agentID, "name": name}).Set(fv)
}
}
}
}
这段代码的作用是将agent心跳的数据转换为Prometheus的gauge类型指标。
- 接收参数:
- agentID:agent的ID
- name:agent的名称
- detail:心跳详情,是map类型
- 遍历预定义的agentGauge指标map:
- agentGauge事先定义了一组GaugeVec指标
- 在detail中查找对应key的字段:
- 如cpu,rss等
- 如果找到,取出值并转换成float64:
- Prometheus指标需要float64值
- 调用GaugeVec的With方法设置标签:
- 这里设置了agent_id和name,用于区分不同agent
- 调用Set方法设置GaugeVec的值:
- 即该agent的该指标的值
-
重复上述过程转换所有指标
-
例如心跳的数据中:
- cpu的值是0.00216669
- 按上述流程转换后,会设置两个GaugeVec指标的值:
- agent_cpu{agent_id=“1ea7…”, name=“agent-1”} 0.00216669
这样就可以从心跳数据中提取监控指标了。
metricsAgentHeartBeat函数仅更新Prometheus指标而不存储心跳数据的设计。该函数的核心关注点是将心跳数据转换为Prometheus指标并发布,以实现监控。持久化存储是另一个关注点,所以由其他模块负责。
这种分离设计是从代码整洁、解耦、效率、扩展性等角度考虑,将不同的功能关注点分离到合适的模块中。
将心跳数据转换为Prometheus指标并发布,以实现监控。持久化存储是另一个关注点,可以由其他模块负责。
使用了 Prometheus Go client 库的 promhttp.Handler() 来暴露 metrics 接口
router.GET("/metrics", func(c *gin.Context) {
promhttp.Handler().ServeHTTP(c.Writer, c.Request)
})
这段代码使用 Prometheus 的 promhttp 包在 Gin 框架中暴露 metrics 接口的示例,这段代码对 Prometheus 来说很重要,它使得应用的 metrics 数据可以被端外的 Prometheus server 拉取。
- 定义了一个 /metrics 的 HTTP GET 请求路由
- 在请求处理函数中调用 promhttp.Handler().ServeHTTP
- 这会使用 Prometheus 默认的 handler 来处理该请求
- 并返回以 Prometheus 格式编码的 metrics 数据
- 接口就会返回类似如下格式的数据:
# HELP http_requests_total Total number of HTTP requests made.
# TYPE http_requests_total counter
http_requests_total{method="post",code="200"} 1027 1395066363000
http_requests_total{method="post",code="400"} 3 1395066363000
三、配置 Prometheus 来获取自定义的指标
前面的demo,在代码中直接使用 Prometheus sdk client 暴露指标。接下来我需要配置 Prometheus 直接抓取指标的 HTTP 接口。
demo:
- job_name: ac
scheme: https
tls_config:
insecure_skip_verify: true
static_configs:
- targets:
- '127.0.0.1:6752'
这个配置作用就是让Prometheus从 127.0.0.1:6752 这个地址获取指标数据
- job_name:任务名称,这里是ac
- scheme:使用https协议
- tls_config:因为是自签名证书,所以跳过证书验证
- static_configs:静态目标配置
- targets:配置抓取目标地址,这里是127.0.0.1:6752
如何判断自定义端点是否正常工作
很简单,我们访问自定义端口即可,例如:
直接在浏览器中访问该接口,检查响应:
https://x.x.x.x:{你定义端点端口号}/metrics
或,检查响应体是否包含预期的指标信息。例如:
curl -I http://localhost:8080/metrics
如何判断Prometheus是否成功获取和存储了自定义指标
- 在Prometheus UI状态页面(Status -> Targets)检查目标job的状态是否是UP。
- 在Prometheus UI的Graph页面绘图你的指标,如果可以绘图表示Prometheus获取并存储了这些指标。
- 通过Prometheus HTTP API查询指标数据,如果可以获取到则成功。例如:
curl http://localhost:9090/api/v1/query?query=your_metric_name
如何查看Prometheus 监听的端口
- 通过Prometheus的配置文件查看。在prometheus.yml中会配置监听的端口,默认是9090:
global:
scrape_interval: 15s
external_labels:
monitor: 'prometheus'
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- 使用netstat命令查看。在Prometheus服务器上运行:
$ sudo netstat -plnt | grep prometheus
tcp 0 0 127.0.0.1:9090 0.0.0.0:* LISTEN 7558/prometheus
- 使用ss命令查看。在Prometheus服务器运行:
$ sudo ss -plnt | grep prometheus
LISTEN 0 128 127.0.0.1:9090 *:* users:(("prometheus",pid=7558,fd=4))
- 通过Prometheus HTTP API访问,默认是
http://localhost:9090
。如果能访问表示端口开启。 - 查看Prometheus进程,端口列会显示监听的端口:
$ ps -ef | grep prometheus
prometh+ 7558 99 01:42 ? 00:00:07 prometheus --config.file=/path/to/prometheus.yml
四、metrics接口的安全性
关于保证接口安全性,可以考虑以下几点:
- 修改默认端口,避免使用常见端口。
- 可以添加基本认证,在代码中检查请求Header的Authorization信息。
- 使用HTTPS加密传输 metrics 数据。
- 限制metrics接口的访问IP,只允许Prometheus服务器的IP访问。
- 使用防火墙策略,只开放Prometheus服务器的IP访问metrics端口。
- 不要暴露metrics接口到公网,只在内网暴露,由Prometheus内网抓取。
- 定期轮换访问metrics接口的API密钥。
- 检查Prometheus的配置,不要采集无关的metrics接口。
- 合理设置Prometheus的访问控制,只允许相关团队访问。
综合采取上述措施,可以加强metrics接口的安全性,防止数据泄露或被利用。 (
五、grafana配置指标面板
TODO
添加metric数据源,grafana支持很多种数据源图形的配置,这里我们选择Prometheus
使用go_client 的两个案例来说明 Counter和Gague的使用。并且结合Grafana配置出炫酷的图形。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)