目录
operator 部署及冒烟测试
部署 prometheus stack
通过 charts/kube-prometheus-stack 安装。
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus -n monitor prometheus-community/kube-prometheus-stack
我们看看 helm chart 都部署了哪些组件,可以看到除了 prometheus-0
之外,还部署了 alertmanager、grafana、kube-state-metrics、node-exporter。
lr90@sj ~ % kubectl get pods -n monitor
NAME READY STATUS RESTARTS AGE
alertmanager-prometheus-kube-prometheus-alertmanager-0 2/2 Running 0 61s
prometheus-grafana-6854b47bf4-ttg6c 3/3 Running 0 11m
prometheus-kube-prometheus-operator-7f8d744cd7-64nk6 1/1 Running 0 11m
prometheus-kube-state-metrics-f699c577d-tk245 1/1 Running 0 11m
prometheus-prometheus-kube-prometheus-prometheus-0 2/2 Running 0 58s
prometheus-prometheus-node-exporter-9hft2 1/1 Running 0 11m
部署完成之后,可以访问 grafana 看一下,其中 grafana 用户 admin
的用户名密码在 prometheus-grafana
secret 中,需要将 grafana 的 3000 端口 port-forward 到本地,port-forward 之后,就可以通过 127.0.0.1:3000 来访问 grafana 了。
lr90@sj ~ % kubectl port-forward pod/prometheus-grafana-6854b47bf4-ttg6c -nmonitor 3000:3000
Forwarding from 127.0.0.1:3000 -> 3000
安装部署参考 prometheus 文档 Installing Prometheus Operator
部署测试组件
这部分参考 prometheus-operator getting-started,
使用本文 附录-> prometheus 测试应用 中的 yaml 来部署测试应用,部署完成之后,使用 servicemonitor 来暴露应用的指标,在 servicemonitor 资源中,其 selector 选中的是 service 的 label。
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: example-app
labels:
team: frontend
spec:
selector:
matchLabels:
app: example-app
endpoints:
- port: web
附录中的测试应用暴露了 8080 端口,并且内置了 http_requests_total 指标,我们可以通过访问 8080 端口来增加这个指标的值。
配置 servicemonitor 之后,我们需要配置集群中的 prometheus
cr,使其能够选择我们的 servicemonitor。可以将 serviceMonitorSelector 设置为空 {}
表示选择所有的 servicemonitor,配置完之后,可以在 grafana 的 explore 界面查看 metrics 了。
serviceMonitorSelector:
matchLabels:
team: frontend
测试用用产生的指标如下,其中 instance=”10.244.0.14:8080” 表示的是 pod 的 ip 以及端口。
http_requests_total{
code="200",
container="example-app",
endpoint="web",
instance="10.244.0.14:8080",
job="example-app",
method="get",
namespace="default",
pod="example-app-5ffc85cf6d-nb9g6",
service="example-app"
}
指标拉取配置
servicemonitor relabel
servicemonitor 是最常用定义指标 target 的方式。这里介绍如何通过 servicemonitor 中的 relabel 来实现指标过滤。首先看几个例子: 1)丢弃 ip 为 10.244.0.18 的 pod 的指标;2)将 annotation env 添加到 metric 的 label 中。
spec:
endpoints:
- interval: 30s
path: /metrics
port: web
relabelings:
- action: drop
regex: 10\.244\.0\.18
sourceLabels:
- __meta_kubernetes_pod_ip
- action: replace
regex: (.+)
sourceLabels:
- __meta_kubernetes_pod_annotation_env
targetLabel: environment
在 prometheus 监控系统中,通过 drop 指标可以避免监控系统基数太高的问题,参考 cardinality-analysis。 导致基数太高的 label 有 user_id、txn_id 等。如果 pod 的 name 作为 label,但是 pod 的生命周期很短,并且会频繁创建,也会导致基数过高。
上面的 __meta_kubernetes_pod_ip 以及 __meta_kubernetes_pod_annotation_env 是 prometheus 默认添加的元数据 label,参考 kubernetes_sd_config,这部分 tag 最终不会添加到 metrics 中。关于 relabel 的配置,可以参考文档 relabel_config,在 relabel 中有比较常用的两个 action 是 keep(白名单)以及 drop(黑名单),用来选择要保留的 metrics。
其他 scrape 配置
除了使用 servicemonitor 之外,prometheus 还支持使用 podmonitor、scrapeConfigNamespaceSelector/scrapeConfigSelector、AdditionalScrapeConfigs,这里不再叙述。
指标数据存储
数据目录结构
默认情况下,prometheus 的指标数据是存储在本地磁盘中的,数据目录是 /prometheus(或者是 /data),其目录结构如下。每隔两个小时,prometheus 会将采集的指标归档为一个目录,如下的 01JR7YGGGDDT5PZYP689PWCEZD,在这个目录中,有一些文件,其中:meta.json 存储的是元数据,包括该 block的开始时间、结束时间、时序数量、采样次数等;chunks 是指标按 512M 分组的一个的一个 segment;tombstones 是通过 api 被逻辑删除的采样;index 是采样指标的索引,用来查找 chunks 中的数据。
/prometheus $
.
├── 01JR7QMRYQ4MDK4J1QV57JWFC2
├── 01JR7YGFRQ3KZST9XHX457PBTV
├── 01JR7YGGGDDT5PZYP689PWCEZD
│ ├── chunks
│ │ └── 000001
│ ├── index
│ ├── meta.json
│ └── tombstones
├── chunks_head
│ ├── 000005
│ └── 000006
├── lock
├── queries.active
└── wal
├── 00000002
├── 00000003
├── 00000004
├── 00000005
└── checkpoint.00000001
└── 00000000
除了被归档在磁盘上的指标之外,prometheus 还将最近的 2 小时的数据保存在内存中(称为 head block),并通过 wal 来保证内存中数据的可靠性,当 prometheus 重启的时候,可以通过重放 wal 来恢复内存中的数据。wal 即上面目录中的 wal 目录,另外 chunks_head 目录是 head block 的内存 mmap 映射,能有效减少 prometheus 的内存使用。
磁盘数据量预测
官方文档中提到了一个公式用来预测需要的磁盘空间,一般来说,可以认为每个采样使用 2bytes 数据量。
needed_disk_space = retention_time_seconds * ingested_samples_per_second * bytes_per_sample
每秒的采样数可以通过下面 promQL 查询,那么假设每秒的采样数为 100000,并且数据量保留 15d,那么需要的磁盘空间为:15*24*3600 * 100000 * 2
bytes,也就是 241GB 左右。
rate(prometheus_tsdb_head_samples_appended_total[5m])
tsdb status
通过 prometheus 提供的 http api TSDB Stats 我们查看 tsdb 的 status,其输出内容如 附录-tsdb status。
lr90@sj ~ % kubectl port-forward pod/prometheus-prometheus-kube-prometheus-prometheus-0 -n monitor 9090:9090
Forwarding from 127.0.0.1:9090 -> 9090
Forwarding from [::1]:9090 -> 9090
curl http://localhost:9090/api/v1/status/tsdb
通过 tsdb status 的输出,我们可以分析出监控系统中的高基数 label。输出解释如下:
- headStats: TSDB head block 的状态,包括:numSeries:指标时序的数量;chunkCount: chunk 的数量,一个 head block chunk 包含 120 个采样点,大概占用 1.5KB 空间,可以根据此数据大概估计下 headblock 的内存使用(以及 prometheus 内存使用量); minTime/maxTime: headblock 开始/结束时间(毫秒时间戳)。
- seriesCountByMetricName: 按指标名称统计的序列数(包含所有block),是全局数据,不仅仅是 head block,通过这个字段的输出,我们可以看出哪些 metrics 指标的时序数列最多。
- labelValueCountByLabelName: 按指标名统计的时序数量。
- memoryInBytesByLabelName: 标签名称的内存占用,我们可以通过这个字段分析哪些 label 占用了最多的内存,从而可以考虑要不要合并或者删除这个 label。
- seriesCountByLabelPair: 按标签键值对统计的序列数。
tsdb status 能帮我们大概了解 headblock 的状态,以及整个 tsdb 指标统计数据,能够帮我们分析高基数 metric 以及高基数 label。
附录
prometheus 测试应用
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-app
spec:
replicas: 3
selector:
matchLabels:
app: example-app
template:
metadata:
labels:
app: example-app
spec:
containers:
- name: example-app
image: quay.io/brancz/prometheus-example-app:v0.5.0
ports:
- name: web
containerPort: 8080
---
kind: Service
apiVersion: v1
metadata:
name: example-app
labels:
app: example-app
spec:
selector:
app: example-app
ports:
- name: web
port: 8080
tsdb-status 输出示例
{
"status": "success",
"data": {
"headStats": {
"numSeries": 35213,
"numLabelPairs": 4678,
"chunkCount": 74340,
"minTime": 1744077600015,
"maxTime": 1744083107444
},
"seriesCountByMetricName": [
{
"name": "apiserver_request_body_size_bytes_bucket",
"value": 2464
},
{
"name": "apiserver_request_duration_seconds_bucket",
"value": 2313
},
{
"name": "etcd_request_duration_seconds_bucket",
"value": 2268
},
{
"name": "apiserver_request_sli_duration_seconds_bucket",
"value": 1344
},
{
"name": "apiserver_response_sizes_bucket",
"value": 1280
},
{
"name": "apiserver_watch_list_duration_seconds_bucket",
"value": 1044
},
{
"name": "apiserver_watch_cache_read_wait_seconds_bucket",
"value": 812
},
{
"name": "grafana_http_request_duration_seconds_bucket",
"value": 533
},
{
"name": "apiserver_watch_events_sizes_bucket",
"value": 522
},
{
"name": "apiserver_admission_controller_admission_duration_seconds_bucket",
"value": 385
}
],
"labelValueCountByLabelName": [
{
"name": "__name__",
"value": 1690
},
{
"name": "name",
"value": 562
},
{
"name": "le",
"value": 280
},
{
"name": "type",
"value": 147
},
{
"name": "resource",
"value": 145
},
{
"name": "method",
"value": 118
},
{
"name": "handler",
"value": 89
},
{
"name": "id",
"value": 64
},
{
"name": "endpoint",
"value": 58
},
{
"name": "kind",
"value": 58
}
],
"memoryInBytesByLabelName": [
{
"name": "__name__",
"value": 1717702
},
{
"name": "service",
"value": 980816
},
{
"name": "instance",
"value": 875600
},
{
"name": "id",
"value": 661414
},
{
"name": "namespace",
"value": 646711
},
{
"name": "endpoint",
"value": 603621
},
{
"name": "job",
"value": 596381
},
{
"name": "pod",
"value": 565117
},
{
"name": "resource",
"value": 337527
},
{
"name": "name",
"value": 241314
}
],
"seriesCountByLabelValuePair": [
{
"name": "namespace=default",
"value": 21008
},
{
"name": "endpoint=https",
"value": 20344
},
{
"name": "service=kubernetes",
"value": 20029
},
{
"name": "job=apiserver",
"value": 20026
},
{
"name": "instance=172.18.0.2:6443",
"value": 20025
},
{
"name": "namespace=monitor",
"value": 9033
},
{
"name": "version=v1",
"value": 7857
},
{
"name": "component=apiserver",
"value": 6375
},
{
"name": "node=kind-control-plane",
"value": 5664
},
{
"name": "service=prometheus-kube-prometheus-kubelet",
"value": 5526
}
]
}
}
promtool analyze 输出
使用 promtool tsdb analyze ./
命令可以分析某一个 block 的时序情况,默认是最近的一个 block,其输出如下。通过 promtool tsdb list ./prometheus
可以查看所有的 block 列表,并会列出每个 block 的开始时间、结束时间、指标数等。
analyze 的输出总体跟 curl http://localhost:9090/api/v1/status/tsdb
一致,只不过前者是 headblock,后者是具体某一个压缩到磁盘上的 block。
/prometheus $ promtool tsdb analyze ./
Block ID: 01JRGYY32CQ7R3KK5T7V6ZECC0
Duration: 5h59m59.993s
Series: 2157655
Label names: 299
Postings (unique label pairs): 22630
Postings entries (total label pairs): 34891393
Label pairs most involved in churning:
666707 job=kubernetes-service-endpoints
619624 lifecycle_apps_kruise_io_state=Normal
240355 matrixorigin_io_component=LogSet
224689 namespace=mo-checkin-regression-21639
222948 namespace=mo-cus-reg
222775 matrixorigin_io_namespace=mo-checkin-regression-21639
222775 matrixorigin_io_cluster=mo-checkin-regression
221313 matrixorigin_io_namespace=mo-cus-reg
221313 matrixorigin_io_cluster=mo-customer-test
208924 matrixorigin_io_component=CNSet
176433 namespace=mo-search-nightly-b209783e7-20250410
175535 matrixorigin_io_cluster=nightly-regression-dis
174522 matrixorigin_io_namespace=mo-search-nightly-b209783e7-20250410
161779 matrixorigin_io_instance=mo-checkin-regression
153154 matrixorigin_io_instance=mo-customer-test
95765 matrixorigin_io_instance=nightly-regression-dis
90306 service=mo-customer-test-log-metric
86171 matrixorigin_io_component=DNSet
84454 controller_revision_hash=mo-customer-test-log-7ccfbf468f
84172 matrixorigin_io_component=ProxySet
Label names most involved in churning:
732177 __name__
731892 namespace
731420 instance
731357 service
731357 job
726282 node
704448 pod
655139 controller_revision_hash
621355 le
619624 matrixorigin_io_instance
619624 matrixorigin_io_cluster
619624 matrixorigin_io_component
619624 matrixorigin_io_namespace
619624 lifecycle_apps_kruise_io_state
356795 type
326527 statefulset_kubernetes_io_pod_name
304661 pod_template_hash
293096 apps_kruise_io_cloneset_instance_id
208924 matrixone_cloud_cn_uuid
100018 label
Most common label pairs:
1754818 job=kubernetes-service-endpoints
1515944 lifecycle_apps_kruise_io_state=Normal
854946 matrixorigin_io_cluster=nightly-regression-dis
601184 matrixorigin_io_component=LogSet
583457 matrixorigin_io_component=CNSet
466659 matrixorigin_io_instance=nightly-regression-dis
423796 namespace=mo-cus-reg
420522 matrixorigin_io_namespace=mo-cus-reg
420522 matrixorigin_io_cluster=mo-customer-test
388307 service=nightly-regression-dis-tp-cn
388287 matrixorigin_io_instance=nightly-regression-dis-tp
343553 service=nightly-regression-dis-log-metric
300211 service=mo-ob-opensource-tke-kube-kubelet
300206 job=kubelet
300206 endpoint=https-metrics
291194 matrixorigin_io_instance=mo-customer-test
264058 namespace=kube-system
242530 namespace=mo-checkin-regression-21639
240476 matrixorigin_io_namespace=mo-checkin-regression-21639
240476 matrixorigin_io_cluster=mo-checkin-regression
Label names with highest cumulative label value length:
315982 id
143647 name
117214 mountpoint
103990 path
87318 container_id
62497 __name__
39672 uid
25846 pod
18432 pod_uid
16509 type
10711 resource
10370 address
9654 image_id
7416 rule_group
5789 owner_name
5556 le
5110 ip
5039 pod_ip
4933 instance
4668 resource_prefix
Highest cardinality labels:
3051 id
2567 name
1744 __name__
1134 container_id
1102 uid
996 path
994 mountpoint
989 pod
678 type
610 address
512 pod_uid
462 le
431 resource
402 ip
395 pod_ip
357 device
319 interface
302 lease
298 lease_holder
280 instance
Highest cardinality metric names:
185000 mo_txn_statement_duration_seconds_bucket
125800 mo_fs_read_write_duration_bucket
88800 mo_task_short_duration_seconds_bucket
88800 mo_logtail_update_partition_duration_seconds_bucket
81400 mo_frontend_accept_connection_duration_bucket
59200 mo_frontend_create_account_duration_bucket
59200 mo_task_mo_table_stats_duration_bucket
59200 mo_frontend_resolve_duration_bucket
51800 mo_txn_tn_side_duration_seconds_bucket
38628 mo_rpc_write_latency_duration_seconds_bucket
38628 mo_rpc_write_duration_seconds_bucket
37000 mo_frontend_pub_sub_duration_bucket
37000 mo_task_transfer_duration_bucket
37000 mo_txn_commit_duration_seconds_bucket
37000 mo_fs_s3_conn_duration_seconds_bucket
29600 mo_logtail_apply_duration_seconds_bucket
29600 mo_txn_unlock_duration_seconds_bucket
29600 mo_frontend_cdc_duration_bucket
24960 kube_resourcequota
23384 mo_rpc_backend_done_duration_seconds_bucket
wal 目录结构
下面 wal 的总大小大概约 2GB,如果 wal 目录过大,可能导致 prometheus 在重启后重放 wal 时 oom。
/prometheus/wal $ du -sh ./*
128.0M ./00060295
128.0M ./00060296
127.9M ./00060297
127.7M ./00060298
128.0M ./00060299
127.9M ./00060300
128.0M ./00060301
67.3M ./00060302
128.0M ./00060303
127.9M ./00060304
127.9M ./00060305
128.0M ./00060306
128.0M ./00060307
128.0M ./00060308
128.0M ./00060309
127.8M ./00060310
128.0M ./00060311
120.4M ./00060312
68.3M ./checkpoint.00060294