3-Prometheus Server配置详解
1. Prometheus Server 启动参数介绍
Prometheus命令参数可通过./prometheus -h查询。
--version #显示版本信息
--confi.file="xxxxxxxxx" #指定配置文件
--web.listen-address=“0.0.0.0:9090” #ui、api、telemetry监听地址信息
--web.config.file="" #TLS或身份验证配置文件
--web.read-timeout=5m #页面读取请求最大超时时间
--web.max-connections=512 #同时访问Prometheus页面的最大连接数 , 默认为512
--web.external-url=<URL> #Prometheus对外提供的url(eg: Prometheus通过反向代理提供服务)。用于生成一个相对和绝对的链接返回给Prometheus本身。如果这个url有路径部分 , 它将用于Prometheus所有HTTP端点的前缀。如果省略了 , 则相关的url组件将自动派生。
--web.route-prefix=<path> #Web端点内部路由的前缀。默认路径 : web.external-url
--web.user-assets=<path> #静态资源路径 , 可以在/user下找到
--web.enable-lifecycle #通过HTTP请求启用关闭和重新加载
--web.enable-admin-api #启用管理控制操作的api端点
--web.console.templates="consoles" #到控制台模板目录的路径 , 可以在consoles/目录下找到。
--web.console.libraries="console_libraries" #控制台库目录的路径
–web.page-title=”Prometheus时间序列采集和处理服务器” #Prometheus实例的文件标题。
--web.cors.origin=".*" #正则表达式为CORS原点。它已完全锚定。例子:“https ?: / / (domain1 | domain2) \。com”
--storage.tsdb.path="data/" #数据存储的基本路径
--storage.tsdb.min-block-duration=2h #在持久化之前数据块的最短保存期
--storage.tsdb.max-block-duration=<duration> #在持久化之前数据块的最大保存期(默认为保存期的10%)
--storage.tsdb.retention=STORAGE.TSDB.RETENTION
#样品保存的时间。此标志已被弃用 , 请使用“storage.tsdb.retention”。时间”。——storage.tsdb.retention。时间= STORAGE.TSDB.RETENTION。保存样品的时间。当设置此标志时 , 它将覆盖“storage.tsdb.retention”。如果既没有这个标志 , 也没有“storage.tsdb”。保留”也不“storage.tsdb.retention。设置大小 , 保留时间默 认为15d。支持单位:y, w, d, h, m, s, ms。
--storage.tsdb.retention.time=STORAGE.TSDB.RETENTION.TIME
#样品保存的时间。此标志已被弃用 , 请使用“storage.tsdb.retention”。时间”。——storage.tsdb.retention。时间= STORAGE.TSDB.RETENTION。保存样品的时间。当设置此标志时 , 它将覆盖“storage.tsdb.retention”。如果既没有这个标志 , 也没有“storage.tsdb”。保留”也不“storage.tsdb.retention。设置大小 , 保留时间默 认为15d。支持单位:y, w, d, h, m, s, ms。
--storage.tsdb.retention.size=
#STORAGE.TSDB.RETENTION。大小[实验]块可以存储的最大字节数。需要一个单位 , 支持单位:B, KB, MB, GB, TB, PB, EB。例:“512 mb”。这个标志是实验性的 , 可以在以后的版本中更改。——storage.tsdb。不要在数据目录中创建lockfile。
--storage.tsdb.no-lockfile #不在数据目录中创建lockfile。
–storage.tsdb.allow-overlapping-blocks #允许重叠块 , 从而支持垂直压缩和垂直查询合并。
–storage.tsdb.wal-compression #压缩tsdb WAL。
–storage.remote.flush-deadline= #关闭或重新加载配置时需要等待多长时间刷新样例。
–storage.remote.read-sample-limit=5e7 #在单个查询中通过远程读接口返回的最大样本总数。0意味着没有限制。对于流响应类型 , 此限制将被忽略。
–storage.remote.read-concurrent-limit=10 #并发远程读调用的最大数量。0意味着没有限制。
–storage.remote.read-max-bytes-in-frame=1048576 #在编组前流化远程读取响应类型的单个帧中的最大字节数。请注意 , 客户端可能也有帧大小的限制。默认情况下为1MB。
–rules.alert.for-outage-tolerance=1h #忍受Prometheus故障恢复“for”警报状态的最大时间。
--rules.alert.for-grace-period=10m #警报和恢复“for”状态之间的最小持续时间。仅对配置的“for”时间大于宽限期的警报进行维护。
–rules.alert.resend-delay=1m #在向Alertmanager重新发送警报之前等待的最短时。间。
--alertmanager.notification-queue-capacity=10000 #等待报警通知队列的大小。
--alertmanager.timeout=10s #发送警报到Alertmanager的超时时间。
--query.lookback-delta=5m #允许在表达式求值期间检索度量值的delta差值。
--query.timeout=2m #一个查询在终止之前可以执行的最长时间(如果超过2min , 就会自动kill掉)。
--query.max-concurrency=20 #并发执行的最大查询数 , 默认为20。
–query.max-samples=50000000 #单个查询可以加载到内存中的最大样本数。注意 , 如果查询尝试将比这个更多的样本加载到内存中 , 那么查询将会失败 , 因此这也限制了查询可以返回的样本数量。
--enable-feature= #逗号分隔要启用的功能名称 , 有效选项 : agent、examplar-storage、expand-external-labels、memory--snapshot-on-shutdown、promql-at-modifier、promql-negative-offset、remote-write-reciver、extra-scrape-metrics、new-service-discovery-manager , 详情请查看https://prometheus.io/docs/prometheus/latest/feature_flags/。
--log.level=info #开启打印日志级别(debug,info,warn,error,fatal)。默认为info。
--log.format=logfmt #日志消息的输出格式。其中一个:[logfmt, json]。参数特殊用法
未设置参数
--web.enable-lifecycle时 , 执行curl -X POST http://localhost:9090/-/reload会报错。# curl -X POST http://localhost:9090/-/reloadLifecycle API is not enabled.启动设置参数
--web.enable-lifecycle就可以用命令curl -X POST http://localhost:9090/-/reload重新加载配置文件了。# ./prometheus --config.file ./prometheus.yml --web.enable-lifecycle # curl -X POST http://localhost:9090/-/reload调整日志级别
启动
prometheus时 , 把参数--log.level=info带上。# ./prometheus --config.file ./prometheus.yml --web.enable-lifecycle --log.level=info 2> prom.log &查看日志文件
# tail -f prom.log level=info ts=2023-02-14T15:22:57.725Z caller=head.go:577 component=tsdb msg="WAL segment loaded" segment=43 maxSegment=46 level=info ts=2023-02-14T15:22:57.736Z caller=head.go:577 component=tsdb msg="WAL segment loaded" segment=44 maxSegment=46 level=info ts=2023-02-14T15:22:57.737Z caller=head.go:577 component=tsdb msg="WAL segment loaded" segment=45 maxSegment=46 level=info ts=2023-02-14T15:22:57.737Z caller=head.go:577 component=tsdb msg="WAL segment loaded" segment=46 maxSegment=46 level=info ts=2023-02-14T15:22:57.737Z caller=head.go:583 component=tsdb msg="WAL replay completed" checkpoint_replay_duration=5.246341ms wal_replay_duration=44.623041ms total_replay_duration=50.886206ms level=info ts=2023-02-14T15:22:57.739Z caller=main.go:849 fs_type=XFS_SUPER_MAGIC level=info ts=2023-02-14T15:22:57.739Z caller=main.go:852 msg="TSDB started" level=info ts=2023-02-14T15:22:57.739Z caller=main.go:979 msg="Loading configuration file" filename=./prometheus.yml level=info ts=2023-02-14T15:22:57.742Z caller=main.go:10
2. Prometheus Server 配置介绍
Prometheus的配置文件是prometheus.yml , 在启动时指定相关的文件 , 可对配置内容进行加载。
该配置文件分为四个模块 :
global: 全局配置alerting: 告警配置rule_files: 规则配置scrape_configs: 目标拉取配置
prometheus.yml配置内容如下 :
global:
scrape_timeout: 10s
alerting:
alertmanagers:
- scheme: http
timeout: 10s
static_configs:
- targets:
- localhost:9093
rule_files:
- "cpu_rules.yml"
- "mem_rules.yml"
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: 'node-exporter'
static_configs:
- targets:
- '192.168.0.3:9100'
- job_name: 'node'
scrape_interval: 8s
static_configs:
- targets: ['127.0.0.1:9100', '127.0.0.12:9100']2.1 global模块
用于定义prometheus的全局配置。
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
evaluation_interval: 15s # By default, scrape targets every 15 seconds.
scrape_timeout: 10s # is set to the global default (10s).
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'codelab-monitor'scrape_interval字段含义 : 全局默认的数据拉取间隔。
配置方法
scrape_interval: <duration>默认
1m。scrape_timeout字段含义 : 全局默认的单次数据拉取超时 , 当报
context deadline exceeded错误时需要在特定的job下配置该字段。配置方法
scrape_timeout: <duration>默认
10s。evaluation_interval字段含义 : 全局默认的规则(主要是报警规则)拉取间隔。
配置方法
evaluation_interval: <duration>默认
1m。external_labels字段含义 : 服务端在与其他系统对接所携带的标签。
配置方法
<labelname>: <labelvalue> ...无默认值 , 可选参数。
2.2 alerting模块
用于设置Prometheus与Alertmanager的通信 , 在Prometheus的整体架构中 , Prometheus会根据配置的告警规则触发警报并发送到独立的Alertmanager组件 , Alertmanager将对告警进行管理并发送给相关的用户。
通常可以使用运行参数 -alertmanager.xxx 来配置 Alertmanager , 但是这样不够灵活 , 不能做到动态更新加载 , 以及动态定义告警属性。
所以 alerting 配置主要用来解决这个问题 , 它能够更好的管理 Alertmanager, 主要包含 2 个参数 :
alert_relabel_configs: 动态修改alert属性的规则配置。alertmanagers: 用于动态发现Alertmanager的配置。
配置文件结构大概为 :
# Alerting specifies settings related to the Alertmanager.
alerting:
alert_relabel_configs:
[ - <relabel_config> ... ]
alertmanagers:
[ - <alertmanager_config> ... ]其中 alertmanagers 为 alertmanager_config 数组。
配置文件结构大概为 :
# Per-target Alertmanager timeout when pushing alerts.
[ timeout: <duration> | default = 10s ]
# Prefix for the HTTP path alerts are pushed to.
[ path_prefix: <path> | default = / ]
# Configures the protocol scheme used for requests.
[ scheme: <scheme> | default = http ]
# Sets the `Authorization` header on every request with the
# configured username and password.
basic_auth:
[ username: <string> ]
[ password: <string> ]
# Sets the `Authorization` header on every request with
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
[ bearer_token: <string> ]
# Sets the `Authorization` header on every request with the bearer token
# read from the configured file. It is mutually exclusive with `bearer_token`.
[ bearer_token_file: /path/to/bearer/token/file ]
# Configures the scrape request's TLS settings.
tls_config:
[ <tls_config> ]
# Optional proxy URL.
[ proxy_url: <string> ]
# List of Azure service discovery configurations.
azure_sd_configs:
[ - <azure_sd_config> ... ]
# List of Consul service discovery configurations.
consul_sd_configs:
[ - <consul_sd_config> ... ]
# List of DNS service discovery configurations.
dns_sd_configs:
[ - <dns_sd_config> ... ]
# List of EC2 service discovery configurations.
ec2_sd_configs:
[ - <ec2_sd_config> ... ]
# List of file service discovery configurations.
file_sd_configs:
[ - <file_sd_config> ... ]
# List of GCE service discovery configurations.
gce_sd_configs:
[ - <gce_sd_config> ... ]
# List of Kubernetes service discovery configurations.
kubernetes_sd_configs:
[ - <kubernetes_sd_config> ... ]
# List of Marathon service discovery configurations.
marathon_sd_configs:
[ - <marathon_sd_config> ... ]
# List of AirBnB's Nerve service discovery configurations.
nerve_sd_configs:
[ - <nerve_sd_config> ... ]
# List of Zookeeper Serverset service discovery configurations.
serverset_sd_configs:
[ - <serverset_sd_config> ... ]
# List of Triton service discovery configurations.
triton_sd_configs:
[ - <triton_sd_config> ... ]
# List of labeled statically configured Alertmanagers.
static_configs:
[ - <static_config> ... ]
# List of Alertmanager relabel configurations.
relabel_configs:
[ - <relabel_config> ... ]scheme字段含义 : 配置如何访问
alertmanager, 可使用http或https。配置方法
- scheme: httptimeout字段含义 : 配置与
alertmanager连接的超时时间配置方法
timeout: 10sstatic_configs字段含义 : 配置
alertmanager的地址信息targets :
alertmanager服务地址指定 , 数组类型 , 可配置多个。
2.3 rule_files模块
用于指定告警规则的文件路径 , 文件格式为yml , 支持多个文件以及文件目录。
配置文件结构大致为 :
rule_files:
- "cpu_rules.yml"
- "mem_rules.yml"Prometheus的告警规则都是通过yml文件进行配置 , 对于用惯了图形界面的同学来说 , 可能不会太习惯。但配置化也是Promtheus的特点之一 , 这种方式提供了开放性的定制化功能 , 可以根据自己需要进行各类规则的定制化配置。
2.3 scrape_configs模块
用于指定Prometheus抓取的目标信息。每一个拉取配置主要包含以下参数 :
job_name : 任务名称
honor_labels : 用于解决拉取数据标签有冲突 , 当设置为 true, 以拉取数据为准 , 否则以服务配置为准
params : 数据拉取访问时带的请求参数
scrape_interval : 拉取时间间隔
scrape_timeout: 拉取超时时间
metrics_path : 拉取节点的 metric 路径
scheme : 拉取数据访问协议
sample_limit : 存储的数据标签个数限制 , 如果超过限制 , 该数据将被忽略 , 不入存储;默认值为0 , 表示没有限制
relabel_configs : 拉取数据重置标签配置
metric_relabel_configs : metric 重置标签配置完整scrape_configs的配置为
# The job name assigned to scraped metrics by default.
job_name: <job_name>
# How frequently to scrape targets from this job.
[ scrape_interval: <duration> | default = <global_config.scrape_interval> ]
# Per-scrape timeout when scraping this job.
[ scrape_timeout: <duration> | default = <global_config.scrape_timeout> ]
# The HTTP resource path on which to fetch metrics from targets.
[ metrics_path: <path> | default = /metrics ]
# honor_labels controls how Prometheus handles conflicts between labels that are
# already present in scraped data and labels that Prometheus would attach
# server-side ("job" and "instance" labels, manually configured target
# labels, and labels generated by service discovery implementations).
#
# If honor_labels is set to "true", label conflicts are resolved by keeping label
# values from the scraped data and ignoring the conflicting server-side labels.
#
# If honor_labels is set to "false", label conflicts are resolved by renaming
# conflicting labels in the scraped data to "exported_<original-label>" (for
# example "exported_instance", "exported_job") and then attaching server-side
# labels. This is useful for use cases such as federation, where all labels
# specified in the target should be preserved.
#
# Note that any globally configured "external_labels" are unaffected by this
# setting. In communication with external systems, they are always applied only
# when a time series does not have a given label yet and are ignored otherwise.
[ honor_labels: <boolean> | default = false ]
# Configures the protocol scheme used for requests.
[ scheme: <scheme> | default = http ]
# Optional HTTP URL parameters.
params:
[ <string>: [<string>, ...] ]
# Sets the `Authorization` header on every scrape request with the
# configured username and password.
basic_auth:
[ username: <string> ]
[ password: <string> ]
# Sets the `Authorization` header on every scrape request with
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
[ bearer_token: <string> ]
# Sets the `Authorization` header on every scrape request with the bearer token
# read from the configured file. It is mutually exclusive with `bearer_token`.
[ bearer_token_file: /path/to/bearer/token/file ]
# Configures the scrape request's TLS settings.
tls_config:
[ <tls_config> ]
# Optional proxy URL.
[ proxy_url: <string> ]
# List of Azure service discovery configurations.
azure_sd_configs:
[ - <azure_sd_config> ... ]
# List of Consul service discovery configurations.
consul_sd_configs:
[ - <consul_sd_config> ... ]
# List of DNS service discovery configurations.
dns_sd_configs:
[ - <dns_sd_config> ... ]
# List of EC2 service discovery configurations.
ec2_sd_configs:
[ - <ec2_sd_config> ... ]
# List of OpenStack service discovery configurations.
openstack_sd_configs:
[ - <openstack_sd_config> ... ]
# List of file service discovery configurations.
file_sd_configs:
[ - <file_sd_config> ... ]
# List of GCE service discovery configurations.
gce_sd_configs:
[ - <gce_sd_config> ... ]
# List of Kubernetes service discovery configurations.
kubernetes_sd_configs:
[ - <kubernetes_sd_config> ... ]
# List of Marathon service discovery configurations.
marathon_sd_configs:
[ - <marathon_sd_config> ... ]
# List of AirBnB's Nerve service discovery configurations.
nerve_sd_configs:
[ - <nerve_sd_config> ... ]
# List of Zookeeper Serverset service discovery configurations.
serverset_sd_configs:
[ - <serverset_sd_config> ... ]
# List of Triton service discovery configurations.
triton_sd_configs:
[ - <triton_sd_config> ... ]
# List of labeled statically configured targets for this job.
static_configs:
[ - <static_config> ... ]
# List of target relabel configurations.
relabel_configs:
[ - <relabel_config> ... ]
# List of metric relabel configurations.
metric_relabel_configs:
[ - <relabel_config> ... ]
# Per-scrape limit on number of scraped samples that will be accepted.
# If more than this number of samples are present after metric relabelling
# the entire scrape will be treated as failed. 0 means no limit.
[ sample_limit: <int> | default = 0 ]案例如下 :
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: 'node-exporter'
static_configs:
- targets:
- '192.168.0.3:9100'Prometheus对于监控数据的抓取是通过配置job的方式进行操作。在job里面指定了一组目标抓取所必须的信息 , 例如目标地址、端口、标签和验证信息等。抓取的时间间隔使用上面global模块配置的时间 , 也可在该job中单独指定。
在实际环境中 , 通常会根据抓取目标的类型不同 , 如Mysql、mongodb、kafka等 , 分成多个job来进行。
默认配置只有一个监控目标 , 即prometheus server本身 , 端口为9090 , 如果不指定路径 , 默认会从/metrics路径抓取。
2.4 远程可写存储
remote_write 主要用于可写远程存储配置 , 主要包含以下参数 :
url: 访问地址
remote_timeout: 请求超时时间
write_relabel_configs: 标签重置配置, 拉取到的数据 , 经过重置处理后 , 发送给远程存储。一份完整的配置大致为:
# The URL of the endpoint to send samples to.
url: <string>
# Timeout for requests to the remote write endpoint.
[ remote_timeout: <duration> | default = 30s ]
# List of remote write relabel configurations.
write_relabel_configs:
[ - <relabel_config> ... ]
# Sets the `Authorization` header on every remote write request with the
# configured username and password.
basic_auth:
[ username: <string> ]
[ password: <string> ]
# Sets the `Authorization` header on every remote write request with
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
[ bearer_token: <string> ]
# Sets the `Authorization` header on every remote write request with the bearer token
# read from the configured file. It is mutually exclusive with `bearer_token`.
[ bearer_token_file: /path/to/bearer/token/file ]
# Configures the remote write request's TLS settings.
tls_config:
[ <tls_config> ]
# Optional proxy URL.
[ proxy_url: <string> ]注意 : remote_write 属于试验阶段 , 慎用 , 因为在以后的版本中可能发生改变。
2.5 远程可读存储
remote_read 主要用于可读远程存储配置 , 主要包含以下参数 :
url: 访问地址
remote_timeout: 请求超时时间一份完整的配置大致为:
# The URL of the endpoint to query from.
url: <string>
# Timeout for requests to the remote read endpoint.
[ remote_timeout: <duration> | default = 30s ]
# Sets the `Authorization` header on every remote read request with the
# configured username and password.
basic_auth:
[ username: <string> ]
[ password: <string> ]
# Sets the `Authorization` header on every remote read request with
# the configured bearer token. It is mutually exclusive with `bearer_token_file`.
[ bearer_token: <string> ]
# Sets the `Authorization` header on every remote read request with the bearer token
# read from the configured file. It is mutually exclusive with `bearer_token`.
[ bearer_token_file: /path/to/bearer/token/file ]
# Configures the remote read request's TLS settings.
tls_config:
[ <tls_config> ]
# Optional proxy URL.
[ proxy_url: <string> ]注意 : remote_read 属于试验阶段 , 慎用 , 因为在以后的版本中可能发生改变。
2.6 服务发现
在 Prometheus 的配置中 , 一个最重要的概念就是数据源 target , 而数据源的配置主要分为静态配置和动态发现, 大致为以下几类 :
static_configs: 静态服务发现
dns_sd_configs: DNS 服务发现
file_sd_configs: 文件服务发现
consul_sd_configs: Consul 服务发现
serverset_sd_configs: Serverset 服务发现
nerve_sd_configs: Nerve 服务发现
marathon_sd_configs: Marathon 服务发现
kubernetes_sd_configs: Kubernetes 服务发现
gce_sd_configs: GCE 服务发现
ec2_sd_configs: EC2 服务发现
openstack_sd_configs: OpenStack 服务发现
azure_sd_configs: Azure 服务发现
triton_sd_configs: Triton 服务发现3. Prometheus Server 数据管理
3.1 数据存储方式
prometheus采用time-series(时间序列)的方式以一种自定义格式存储在本地硬盘 , 本地TSDB以每两小时为间隔来分block ( 块 ) 存储 , 每一块又分为多个chunk文件 , chunk文件存放着采集的T-S数据 , metadata和索引文件 ( index ) 。index文件是对metrics和labels进行索引 , 之后存储在chunk , chunk作为存储的基本单位。
prometheus平时将采集的数据先都存在内存中 , 以类似缓存的方式用于加快搜索和访问 , 当出现宕机时 , prometheus的保护机制WAL可以将数据定期存入硬盘chunk中 , 并在重新启动时恢复到内存中。
通过启动参数--storage.tsdb.path=“/data”指定tsdb路径 , 即采集数据存放路径 , wal目录下数据相当于对存放在内存中的近期数据的冷备。
3.2 Prometheus数据采集方式
prometheus的客户端主要有两种采集方式 :
pull主动拉取push被动推送
pull方式
被监控主机需要安装各类exporters , exporter以守护进程方式运行 , 在主机系统上采集数据 , exporter本身也是一个http_server , 可以对http请求作出相应 , 返回metrics数据 ( K/V metrics ) 。prometheus server通过pull方式 ( HTTP get ) 去访问每个节点上的exporter并采样监控数据并进行存储。
push方式
客户端或者服务端安装pushgateway插件 , 使用运维自行开发的各种脚本把监控数据组织成K/V的形式 metrics形式发送给pushgateway , 之后pushgateway再推送给prometheus。
3.2.1 数据格式
数据模型
在Prometheus监控中 , 对于采集到服务端的指标 , 我们称其为metrics数据。metrics指标为时间序列数据 , 它们按相同的时序 , 以时间维度来存储连续数据的集合 , 其存储结构为K/V类型。
Metrics是一种采样数据的总称 ( metrics并不代表某一种具体的数据格式 , 是一种对于度量计算单位的抽象 ) , 其有自定义的一套数据格式 , 不论是日常运维管理还是监控开发 , 都需要了解掌握其数据结构。
Prometheus 存储的是时序数据, 即按照相同时序(相同的名字和标签) , 以时间维度存储连续的数据的集合。
时序索引
时序(
time series) 是由名字(Metric) , 以及一组key/value标签定义的 , 具有相同的名字以及标签属于相同时序。时序的名字由
ASCII字符 , 数字 , 下划线 , 以及冒号组成 , 它必须满足正则表达式[a-zA-Z_:][a-zA-Z0-9_:]*, 其名字应该具有语义化 , 一般表示一个可以度量的指标 , 例如:http_requests_total, 可以表示http请求的总数。时序的标签可以使
Prometheus的数据更加丰富 , 能够区分具体不同的实例 , 例如http_requests_total{method="POST"}可以表示所有http中的POST请求。标签名称由
ASCII字符 , 数字 , 以及下划线组成 , 其中__开头属于Prometheus保留 , 标签的值可以是任何Unicode字符 , 支持中文。时序样本
按照某个时序以时间维度采集的数据 , 称之为样本 , 其值包含 :
一个
float64值一个毫秒级的
unix时间戳
数据格式
Prometheus的时间序列统一使用以下格式来表示。
<metric name>{<label name>=<label value>, ...}数据格式案例 :
http_response_total{method="GET",endpoint="/api/tracks"} 100http_response_total为指标名称{}里面为标签 , 它标明了当前指标样本的特征和维度数值
100则是该样本的具体值。
数据信息可通过curl localhost:9100/metrics获取。
3.2.2 数据类型
metrics数据类型包含 : gauges、counts、histograms、Summary。
gauges最简单的度量指标 , 只有一个简单的返回值 ( 瞬时状态 ) , 例如监控磁盘或者内存的使用量 , 那么就应该使用
gauges格式来度量。Gauge数据类型的特点 :Gauge常规数值 , 例如 温度变化、内存使用变化。可变大 , 可变小。
重启进程后 , 会被重置
案例 :
memory_usage_bytes{host="master-01"} 100 < 抓取值 memory_usage_bytes{host="master-01"} 30 memory_usage_bytes{host="master-01"} 50 memory_usage_bytes{host="master-01"} 80 < 抓取值counts从数据量为
0开始累积计算 , 在理想状态下只能永远增长 , 不会降低 , 例如对用户访问量的采样数据。Counter数据类型的特点 :Counter用于累计值 , 例如 记录 请求次数、任务完成数、错误发生次数。一直增加 , 不会减少。
重启进程后 , 会被重置。
案例 :
http_response_total{method="GET",endpoint="/api/tracks"} 100 10秒后抓取 : http_response_total{method="GET",endpoint="/api/tracks"} 100histograms统计数据的分布情况 , 比如最小值、最大值、中间值 , 还有中位数、75百分位、90百分位、95百分位、98百分位、99百分位、99.9百分位的值 , 代表的是一种近似的百分比估值。例如
Http_response_time(http响应时间 ) 代表是一次用户http请求在系统传输和执行过程中总共花费的时间。通过histogram类型可以分别统计出全部用户的响应时间中=0.05秒的有多少、00.05秒的有多少、>2秒的有多少。Summary通过计算分位数(
quantile)显示指标结果 , 可用于统计一段时间内数据采样结果 , 如中位数(quantile=0.5) 、9分位数 (quantile=0.9) 等。summary与histogram类型选择Summary结构有频繁的全局锁操作 , 对高并发程序性能存在一定影响。histogram仅仅是给每个桶做一个原子变量的计数就可以了 , 而summary要每次执行算法计算出最新的X分位value是多少 , 算法需要并发保护。会占用客户端的cpu和内存。不能对
Summary产生的quantile值进行aggregation运算 ( 例如sum,avg等 ) 。例如有两个实例同时运行 , 都对外提供服务 , 分别统计各自的响应时间。最后分别计算出的0.5-quantile的值为60和80, 这时如果简单的求平均(60+80)/2, 认为是总体的0.5-quantile值 , 那么就错了。summary的百分位是提前在客户端里指定的 , 在服务端观测指标数据时不能获取未指定的分为数。而histogram则可以通过promql随便指定 , 虽然计算的不如summary准确 , 但带来了灵活性。histogram不能得到精确的分为数 , 设置的bucket不合理的话 , 误差会非常大。会消耗服务端的计算资源。
对比得到的结论是是 :
如果需要聚合 (
aggregate) , 选择histograms。如果比较清楚要观测的指标的范围和分布情况 , 选择
histograms。如果需要精确的分为数选择summary。
3.2.3 存储目录结构
存储原理
prometheus按照block块的方式来存储数据 , 每2小时为一个时间单位 , 首先会存储到内存中 , 当到达2小时后 , 会自动写入磁盘中。为防止程序异常而导致数据丢失 , 采用了WAL机制 , 即2小时内记录的数据存储在内存中的同时 , 还会记录一份日志 , 存储在block下的wal目录中。当程序再次启动时 , 会将wal目录中的数据写入对应的block中 , 从而达到恢复数据的效果。当删除数据时 , 删除条目会记录在tombstones 中 , 而不是立刻删除。
prometheus数据目录中的每个block都是一个独立的数据库 , 采用的存储方式为被称"时间分片。其优势是可以提高查询效率 , 查哪个时间段的数据 , 只需要打开对应的block即可 , 无需打开多余数据。
数据存储目录
./data
├── 01BKGV7JBM69T2G1BGBGM6KB12
│ └── meta.json
├── 01BKGTZQ1SYQJTR4PB43C8PD98
│ ├── chunks
│ │ └── 000001
│ ├── tombstones
│ ├── index
│ └── meta.json
├── chunks_head
│ └── 000001
└── wal # 预写日志
├── 000000002
└── checkpoint.00000001
└── 0000000001BKGV7JBM69T2G1BGBGM6KB12:block ID, 这类命名的目录是一个完整的block。meta.json: 是这个block的元信息。chunks: 目录下存储每一个Block中的所有的Chunk, 目录下每个文件都是一个chunk数据单元。Index: 文件是该Chunk的索引文件。tombstones: 数据删除记录文件 , 记录的是删除信息。wal: 保存了内存里最近2小时的数据 , 用于重启后恢复最近两小时里内存的数chunks_head: 磁盘内存映射头块checkpoint:checkpoint机制会将wal清理过后的数据做过滤写成新的段 , 然后checkpoint文件被命名为创建checkpoint的最后一个段号checkpoint.X。
3.2.4 文件格式解析
meta.json{ "ulid": "01EM6Q6A1YPX4G9TEB20J22B2R", "minTime": 1602237600000, "maxTime": 1602244800000, "stats": { "numSamples": 553673232, "numSeries": 1346066, "numChunks": 4440437 }, "compaction": { "level": 1, "sources": [ "01EM65SHSX4VARXBBHBF0M0FDS", "01EM6GAJSYWSQQRDY782EA5ZPN" ] }, "version": 1 }内容解析 :
version: 告诉我们如何解析元文件。minTime,maxTime: 是块中存在的所有块中的绝对最小和最大时间戳。stats: 告诉块中存在的Series、Samples和Chunks的数量。compaction: 讲述区块的历史。sources: 告诉这个块是从哪些块创建的 ( 即合并形成这个块的块 ) 。如果它是从Head块创建的 , 则sources设置为自身 (01EM6Q6A1YPX4G9TEB20J22B2R在这种情况下 ) 。level: 告诉这个块已经到了多少代。
chunks_head/chunks文件的最大大小保持在
128MiB。┌──────────────────────────────┐ │ magic(0x0130BC91) <4 byte> │ ├──────────────────────────────┤ │ version(1) <1 byte> │ ├──────────────────────────────┤ │ padding(0) <3 byte> │ ├──────────────────────────────┤ │ ┌──────────────────────────┐ │ │ │ Chunk 1 │ │ │ ├──────────────────────────┤ │ │ │ ... │ │ │ ├──────────────────────────┤ │ │ │ Chunk N │ │ │ └──────────────────────────┘ │ └──────────────────────────────┘magic: 将此文件标识为块文version: 告诉我们如何解析这个文件padding: 适用于任何未来的标题Chunk 1 - Chunk N: 是块列表
单个块的格式 :
┌─────────────────────┬───────────────────────┬───────────────────────┬───────────────────┬───────────────┬──────────────┬────────────────┐ | series ref <8 byte> | mint <8 byte, uint64> | maxt <8 byte, uint64> | encoding <1 byte> | len <uvarint> | data <bytes> │ CRC32 <4 byte> │ └─────────────────────┴───────────────────────┴───────────────────────┴───────────────────┴───────────────┴──────────────┴────────────────┘series ref: 它是用于访问内存中series的series IDmint和maxt: 块的样本中看到的最小和最大时间戳encoding: 是用于压缩块的编码len: 是从这里开始的字节数data, 是压缩块的实际字节数。CRC32: 是上述chunk内容的校验和 , 用于校验数据的完整性。
数据块如何被读取?
series ref为8个字节。前4个字节告诉文件块所在的文件号 , 最后4个字节告诉文件中块开始的偏移量 , 如果块在文件中00093并且series ref从文件中的字节偏移开始1234: 那么该块的引用将是(93 << 32) | 1234( 左移位 , 然后按位或 ) 。
block/chunks该
chunks目录包含一系列编号的文件 , 每个文件的上限为512MiB。文件格式。单个chunk的时间跨度默认是2小时 ,Prometheus后台会有合并操作 , 把时间相邻的block合到一起。┌──────────────────────────────┐ │ magic(0x85BD40DD) <4 byte> │ ├──────────────────────────────┤ │ version(1) <1 byte> │ ├──────────────────────────────┤ │ padding(0) <3 byte> │ ├──────────────────────────────┤ │ ┌──────────────────────────┐ │ │ │ Chunk 1 │ │ │ ├──────────────────────────┤ │ │ │ ... │ │ │ ├──────────────────────────┤ │ │ │ Chunk N │ │ │ └──────────────────────────┘ │ └──────────────────────────────┘magic: 将此文件标识为块文件version: 告诉我们如何解析这个文件padding: 适用于任何未来的标题Chunk 1 - Chunk N: 是块列表
单个块的格式 :
┌───────────────┬───────────────────┬──────────────┬────────────────┐ │ len <uvarint> │ encoding <1 byte> │ data <bytes> │ CRC32 <4 byte> │ └───────────────┴───────────────────┴──────────────┴────────────────┘作用 : 这里面存的是时序数据 , 文件中的块由
uint64从index文件中引用 ,uint64由文件内偏移量 ( 低4个字节 ) 和段序列号 ( 高4个字节 ) 组成。即 :index中的数据条目有一个64bit的引用记录 , 其中四个字节存数据在哪个文件 ( 段文件序列号 ) , 另外四个字节存文件内偏移量 , 这样就能找到每个记录对应的chunk数据在哪个文件的哪个位置。这里的
chunk和上面的head chuank相比 , 少了series ref,mint和maxt, 为什么不需要呢?因为series ref,mint和maxt的信息在index文件里面有 , 我们就是根据index文件里的series ref,mint和maxt来查找chunk里的数据的 , 因此这里不需要存储。index:┌────────────────────────────┬─────────────────────┐ │ magic(0xBAAAD700) <4b> │ version(1) <1 byte> │ ├────────────────────────────┴─────────────────────┤ │ ┌──────────────────────────────────────────────┐ │ │ │ Symbol Table │ │ │ ├──────────────────────────────────────────────┤ │ │ │ Series │ │ │ ├──────────────────────────────────────────────┤ │ │ │ Label Index 1 │ │ │ ├──────────────────────────────────────────────┤ │ │ │ ... │ │ │ ├──────────────────────────────────────────────┤ │ │ │ Label Index N │ │ │ ├──────────────────────────────────────────────┤ │ │ │ Postings 1 │ │ │ ├──────────────────────────────────────────────┤ │ │ │ ... │ │ │ ├──────────────────────────────────────────────┤ │ │ │ Postings N │ │ │ ├──────────────────────────────────────────────┤ │ │ │ Label Offset Table │ │ │ ├──────────────────────────────────────────────┤ │ │ │ Postings Offset Table │ │ │ ├──────────────────────────────────────────────┤ │ │ │ TOC │ │ │ └──────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────┘内容解析 :
magic: 编号将该文件标识为索引文件version: 告诉我们如何解析这个文件TOC: 该索引的入口点 , 它代表索引目录。
TOC┌─────────────────────────────────────────┐ │ ref(symbols) <8b> │ -> Symbol Table ├─────────────────────────────────────────┤ │ ref(series) <8b> │ -> Series ├─────────────────────────────────────────┤ │ ref(label indices start) <8b> │ -> Label Index 1 ├─────────────────────────────────────────┤ │ ref(label offset table) <8b> │ -> Label Offset Table ├─────────────────────────────────────────┤ │ ref(postings start) <8b> │ -> Postings 1 ├─────────────────────────────────────────┤ │ ref(postings offset table) <8b> │ -> Postings Offset Table ├─────────────────────────────────────────┤ │ CRC32 <4b> │ └─────────────────────────────────────────┘作用解析 :
toc数据告诉了索引的各个组成部分到底从哪里开始 ( 文件中的字节偏移量 ) , 上面的索引格式中已经标记了每个参考指向的内容。下一个组件的起点也显示了各个组件的终点在哪里。由于TOC是固定大小 , 因此文件的最后52个字节可以作为TOC。Symbol Table此部分包含已删除重复字符串的排序列表 , 这些字符串可在此块中所有系列的标签对中找到。例如 , 如果系列是{a="y", x="b"} , 那么符号就是"a", "b", "x", "y"。
┌────────────────────┬─────────────────────┐ │ len <4b> │ #symbols <4b> │ ├────────────────────┴─────────────────────┤ │ ┌──────────────────────┬───────────────┐ │ │ │ len(str_1) <uvarint> │ str_1 <bytes> │ │ │ ├──────────────────────┴───────────────┤ │ │ │ . . . │ │ │ ├──────────────────────┬───────────────┤ │ │ │ len(str_n) <uvarint> │ str_n <bytes> │ │ │ └──────────────────────┴───────────────┘ │ ├──────────────────────────────────────────┤ │ CRC32 <4b> │ └──────────────────────────────────────────┘len: 这部分的占用字节数symbols: 这部分存储的符号数len(str_n) <uvarint> │ str_n <bytes>: 是一个符号的长度和内容
作用 : 索引中的其他部分可以为任何字符串引用此符号表 , 从而显着减小索引大小。 符号在文件中开始的字节偏移量 ( 即 的开头
len(str_i)) 形成了相应符号的引用 , 该符号可以在其他地方使用 , 而不是实际的字符串。 当需要实际字符串时 , 可以使用偏移量从该表中获取它。Series┌───────────────────────────────────────┐ │ ┌───────────────────────────────────┐ │ │ │ series_1 │ │ │ ├───────────────────────────────────┤ │ │ │ . . . │ │ │ ├───────────────────────────────────┤ │ │ │ series_n │ │ │ └───────────────────────────────────┘ │ └───────────────────────────────────────┘每个系列条目都是
16字节对齐的 , 这意味着系列开始的字节偏移量可以被 16 整除。因此 , 我们将系列的ID设置为offset/16偏移量指向系列条目开始的位置。 此ID用于引用该系列 , 并且每当您想要访问该系列时 , 您都可以通过执行 获取索引中的位置ID*16。每个
series条目都包含系列的标签集和对属于该系列的所有块的引用 :┌──────────────────────────────────────────────────────┐ │ len <uvarint> │ ├──────────────────────────────────────────────────────┤ │ ┌──────────────────────────────────────────────────┐ │ │ │ labels count <uvarint64> │ │ │ ├──────────────────────────────────────────────────┤ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ │ │ ref(l_i.name) <uvarint32> │ │ │ │ │ ├────────────────────────────────────────────┤ │ │ │ │ │ ref(l_i.value) <uvarint32> │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ ... │ │ │ ├──────────────────────────────────────────────────┤ │ │ │ chunks count <uvarint64> │ │ │ ├──────────────────────────────────────────────────┤ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ │ │ c_0.mint <varint64> │ │ │ │ │ ├────────────────────────────────────────────┤ │ │ │ │ │ c_0.maxt - c_0.mint <uvarint64> │ │ │ │ │ ├────────────────────────────────────────────┤ │ │ │ │ │ ref(c_0.data) <uvarint64> │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ │ │ c_i.mint - c_i-1.maxt <uvarint64> │ │ │ │ │ ├────────────────────────────────────────────┤ │ │ │ │ │ c_i.maxt - c_i.mint <uvarint64> │ │ │ │ │ ├────────────────────────────────────────────┤ │ │ │ │ │ ref(c_i.data) - ref(c_i-1.data) <varint64> │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ ... │ │ │ └──────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────┤ │ CRC32 <4b> │ └──────────────────────────────────────────────────────┘含义解析 :
labels count: 这个series数据里有多少个label对。ref(l_i.name)和ref(l_i.value): 不存储实际的字符串本身 , 而是使用符号表中的符号引用 , 利用这个引用去查符号表就可以。chunks count: 这个series对应的时序数据由多少个chunk块来存放mint,maxt,ref: 这三个就是前面说的chunk相比head chunk少的三个数据就是存放在这里 , 在查询series的时候 , 会根据index中这个series的chunk列表中每个chunk的mint,maxt,ref, 然后到chunk文件去查。这里ref是八个字节 , 里面四个字节记录了数据在哪个chunk文件 , 四个字节记录了文件在那个chunk文件里的偏移量。
在索引中保存
mintandmaxt允许查询跳过查询时间范围不需要的块 , 上面在记录mint,maxt的时候 , 你可以看到除了第一个mint记录的是完整的时间戳 , 后面的其他mint,maxt记录的全是相对上一个数据的时间增量 , 以节省记录的空间 , 即第一个mint是varint, 后面的全是uvarint, 因为增量肯定是正数 , 使用uvarint, 可以节省很多前缀0。Label Offset Table和Label Index i这两个不再使用了;它们是为向后兼容而编写的 , 但不会从最新的
Prometheus版本中读取Postings Offset Table和Postings i,Postings 1- N存储了Postings列表 ,Postings Offset Table记录这些条目的偏移量。Postings是一个series ID, 在index文件的上下文中 , 它是series条目在文件中开始的偏移量除16, 因为它是16字节对齐的。一个
Postings的结构 :┌────────────────────┬────────────────────┐ │ len <4b> │ #entries <4b> │ ├────────────────────┴────────────────────┤ │ ┌─────────────────────────────────────┐ │ │ │ ref(series_1) <4b> │ │ │ ├─────────────────────────────────────┤ │ │ │ ... │ │ │ ├─────────────────────────────────────┤ │ │ │ ref(series_n) <4b> │ │ │ └─────────────────────────────────────┘ │ ├─────────────────────────────────────────┤ │ CRC32 <4b> │ └─────────────────────────────────────────┘entries是下面series列表的数量 ,ref(series_1)是series ID, 也是series ref, 也就是引用。具体Postings如何与Postings Offset Table一起配合记录。// Postings Offset Table ┌─────────────────────┬──────────────────────┐ │ len <4b> │ #entries <4b> │ ├─────────────────────┴──────────────────────┤ │ ┌────────────────────────────────────────┐ │ │ │ n = 2 <1b> │ │ │ ├──────────────────────┬─────────────────┤ │ │ │ len(name) <uvarint> │ name <bytes> │ │ │ ├──────────────────────┼─────────────────┤ │ │ │ len(value) <uvarint> │ value <bytes> │ │ │ ├──────────────────────┴─────────────────┤ │ │ │ offset <uvarint64> │ │ │ └────────────────────────────────────────┘ │ │ . . . │ ├────────────────────────────────────────────┤ │ CRC32 <4b> │ └────────────────────────────────────────────┘Postings Offset Table作用存储
label-pair对的名字和值以及offset, 即label-pair对的posting位置 , 可以通过offset查询label-pair对在哪个posting中。posting中记录了label-pair对对应的series的内容 , 可通过series里面的ref查询chunk中的时序数据 , 互相对应。
3.3 作业与实例
Prometheus 中 , 将任意一个独立的数据源 ( target ) 称之为实例 ( instance ) 。包含相同类型的实例的集合称之为作业 ( job ) 。 如下是一个含有四个重复实例的作业 :
- job: api-server
- instance 1: 1.2.3.4:5670
- instance 2: 1.2.3.4:5671
- instance 3: 5.6.7.8:5670
- instance 4: 5.6.7.8:5671自生成标签和时序
Prometheus 在采集数据的同时 , 会自动在时序的基础上添加标签 , 作为数据源 ( target ) 的标识 , 以便区分 :
job: The configured job name that the target belongs to.
instance: The <host>:<port> part of the target's URL that was scraped.如果其中任一标签已经在此前采集的数据中存在 , 那么将会根据 honor_labels设置选项来决定新标签。
对每一个实例而言 , Prometheus 按照以下时序来存储所采集的数据样本 :
up{job="<job-name>", instance="<instance-id>"}: 1 表示该实例正常工作
up{job="<job-name>", instance="<instance-id>"}: 0 表示该实例故障
scrape_duration_seconds{job="<job-name>", instance="<instance-id>"} 表示拉取数据的时间间隔
scrape_samples_post_metric_relabeling{job="<job-name>", instance="<instance-id>"} 表示采用重定义标签 ( relabeling ) 操作后仍然剩余的样本数
scrape_samples_scraped{job="<job-name>", instance="<instance-id>"} 表示从该数据源获取的样本数其中 up 时序可以有效应用于监控该实例是否正常工作。
参考链接
构建企业级监控平台系列 ( 十三 ) : Prometheus Server 配置详解 (qq.com)