在前三篇文章中,我们建立了可观测性的理论框架,理解了 LGTM 栈的整体架构,并掌握了 OpenTelemetry 的统一插桩标准。但指标监控的"最后一公里"仍然需要深入 Prometheus------它是云原生指标监控的事实标准,也是 LGTM 栈中 Mimir 的数据来源。本文从 Prometheus 的核心架构出发,系统讲解四种指标类型的设计与使用场景、Exporter 开发实战、以及 Kubernetes 服务发现配置,帮你掌握从"指标设计"到"指标采集"的完整技能。
一、Prometheus 核心架构
Prometheus 是一个基于 Pull 模型 的监控系统------它主动从目标服务拉取指标数据,而非等待服务推送。这种设计让服务发现和健康检查变得简单。
核心组件:
Prometheus Server:核心服务,负责抓取、存储和查询指标数据
Exporters:暴露指标的程序(Node Exporter 暴露主机指标,应用自身暴露业务指标)
Alertmanager:处理告警规则的分组、抑制和通知
服务发现(Service Discovery) :动态发现监控目标(Kubernetes、Consul、文件等)
Pull 模型的优势:服务无需感知 Prometheus 的存在;Prometheus 可以通过健康检查判断目标是否可用;便于水平扩展和联邦部署。
二、四种指标类型的设计与使用场景
Prometheus 提供了四种指标类型,每种类型服务于不同的监控目的:
Counter(计数器) :只增不减的累计值。用于统计请求总数、错误总数、处理的任务数等。必须单调递增,不能用于递减或归零的场景。典型用法:http_requests_total。
Gauge(仪表盘) :可增可减的瞬时值。用于测量当前并发数、内存使用量、温度、队列长度等。典型用法:go_goroutines、http_requests_in_flight。
Histogram(直方图) :对观测值进行采样和分桶统计。用于测量请求延迟分布、响应大小等。Histogram 自动生成 _count、_sum 和 _bucket 三个指标。典型用法:http_request_duration_seconds。
Summary(摘要) :类似 Histogram,可计算分位数。与 Histogram 的主要区别在于分位数在客户端计算。建议优先使用 Histogram,因为它更灵活且支持聚合。
指标命名规范:推荐采用 _ 格式。例如 order_service_http_requests_total、api_gateway_request_duration_seconds。
三、自定义 Exporter 开发实战
当需要监控的应用本身不暴露 /metrics 端点时,可以编写自定义 Exporter。Go 语言是 Exporter 开发的首选。
3.1 项目初始化
bash
mkdir custom-exporter && cd custom-exporter
go mod init custom-exporter
go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/promhttp
3.2 定义和注册指标
go
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
// Counter:累计指标
ordersCreated = promauto.NewCounter(
prometheus.CounterOpts{
Name: "orders_created_total",
Help: "Total number of orders created",
},
)
// Gauge:瞬时指标
ordersInFlight = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "orders_in_flight",
Help: "Current number of orders being processed",
},
)
// Histogram:分布指标
orderDuration = promauto.NewHistogram(
prometheus.HistogramOpts{
Name: "order_duration_seconds",
Help: "Order processing duration in seconds",
Buckets: []float64{0.01, 0.05, 0.1, 0.5, 1, 2, 5},
},
)
// CounterVec:带标签的指标
ordersByStatus = promauto.NewCounterVec(
prometheus.CounterOpts{
Name: "orders_by_status_total",
Help: "Total number of orders by status",
},
[]string{"status"},
)
)
func main() {
// 暴露 /metrics 端点
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":9090", nil)
}
3.3 采集业务数据并更新指标
go
func processOrder() {
ordersInFlight.Inc() // 增加并发计数
defer ordersInFlight.Dec() // 处理完成后减少
start := time.Now()
// 业务逻辑...
duration := time.Since(start).Seconds()
ordersCreated.Inc() // 累计订单数
orderDuration.Observe(duration) // 记录耗时
ordersByStatus.WithLabelValues("completed").Inc() // 按状态统计
}
四、Kubernetes 服务发现配置
在 Kubernetes 环境中,Pod 动态创建和销毁,静态配置无法应对这种变化。Prometheus 的 Kubernetes 服务发现 机制可以自动发现集群中的 Pod、Service、Node 等资源。
4.1 基本配置(prometheus.yml)
yaml
scrape_configs:
# 自动发现所有 Pod
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
# 只采集带有 prometheus.io/scrape: "true" 注解的 Pod
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
# 从注解中读取指标路径和端口
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
4.2 ServiceMonitor(推荐方式)
在 Prometheus Operator 生态中,ServiceMonitor 是更声明式的配置方式:
yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: order-service
spec:
selector:
matchLabels:
app: order-service
endpoints:
- port: metrics
path: /metrics
interval: 15s
ServiceMonitor 将监控目标声明为 Kubernetes 资源,与 Prometheus 的配置解耦,更适合 GitOps 工作流。
五、小结
Prometheus 核心架构:基于 Pull 模型,通过服务发现动态发现目标
四种指标类型:Counter(累计值)、Gauge(瞬时值)、Histogram(分布统计)、Summary(客户端分位数)
指标命名规范:_
Exporter 开发:使用 prometheus/client_golang 定义和注册指标,暴露 /metrics 端点
Kubernetes 服务发现:通过 kubernetes_sd_configs 自动发现 Pod,结合 relabel 进行精细控制
ServiceMonitor:Prometheus Operator 中的声明式监控目标配置