什么是Prometheus?
Prometheus是一个开源的系统监控和告警工具包,最初由SoundCloud构建。自2012年创建以来,许多公司和组织已经采用了Prometheus,该项目拥有非常活跃的开发人员和用户社区。现在它是一个独立的开源项目,独立于任何公司维护。为了强调这一点,并澄清项目的治理结构,Prometheus于2016年加入了云原生计算基金会,成为继Kubernetes之后的第二个托管项目。
Prometheus以时间序列数据的形式收集和存储其度量指标,即度量信息与记录时的时间戳一起存储,并附带可选的键值对标签。
有关Prometheus的更详细概述,请参见媒体部分链接的资源。
特性 Prometheus的主要特性包括:
- 多维数据模型,通过度量名称和键/值对标识时间序列数据
- PromQL,一种灵活的查询语言,利用这种多维性
- 不依赖分布式存储;单个服务器节点是自治的
- 通过HTTP的拉取模型进行时间序列收集
- 通过中介网关支持推送时间序列
- 通过服务发现或静态配置发现目标
- 支持多种图形和仪表板模式
什么是度量指标?
度量指标是数值测量,在通俗术语中。术语时间序列指的是随时间变化的记录。用户想要测量的内容因应用程序而异。对于一个Web服务器,它可能是请求时间;对于数据库,它可能是活动连接或活动查询的数量,等等。
度量指标在理解您的应用程序为何以某种方式工作方面起着重要作用。假设您正在运行一个Web应用程序并发现它运行缓慢。要了解您的应用程序发生了什么,您将需要一些信息。例如,当请求数量很高时,应用程序可能会变慢。如果您有请求计数度量指标,您可以确定原因并增加服务器数量以处理负载。
组件 Prometheus生态系统由多个组件组成,其中许多是可选的:
- 主Prometheus服务器,用于抓取和存储时间序列数据
- 用于仪器应用程序代码的客户端库
- 用于支持短期作业的推送网关
- 用于服务如HAProxy、StatsD、Graphite等的特殊用途导出器
- 用于处理告警的告警管理器
- 各种支持工具
大多数Prometheus组件都是用Go编写的,使它们易于构建和部署为静态二进制文件。
架构 这张图展示了Prometheus及其一些生态系统组件的架构:
Prometheus从被监控的作业中抓取度量指标,对于短期作业,也可以通过中介推送网关直接或间接抓取。它将所有抓取到的样本本地存储,并在这些数据上运行规则,以从现有数据中聚合并记录新的时序数据,或生成告警。Grafana或其他API消费者可以用来可视化收集到的数据。
何时适用?
Prometheus非常适合记录任何纯数值的时间序列。它既适用于以机器为中心的监控,也适用于监控高度动态的服务导向架构。在微服务的世界里,它对多维数据收集和查询的支持是一个特别的强项。
Prometheus被设计为可靠,是在中断期间您可以依赖的系统,允许您快速诊断问题。每个Prometheus服务器都是独立的,不依赖于网络存储或其他远程服务。即使您的基础设施的其他部分出现问题,您也可以依赖它,而且您不需要设置复杂的基础设施来使用它。
何时不适用?
Prometheus重视可靠性。即使在故障条件下,您也总是可以查看关于您系统的可用统计数据。如果您需要100%的准确性,例如用于按请求计费,Prometheus不是一个好选择,因为收集的数据可能不够详细和完整。在这种情况下,您最好使用其他系统来收集和分析计费数据,而将Prometheus用于其余的监控工作
入门指南
这个指南是一个“Hello World”风格的教程,它展示了如何安装、配置和使用一个简单的Prometheus实例。您将下载并本地运行Prometheus,配置它来抓取自身和一个示例应用程序的数据,然后通过查询、规则和图表来使用收集到的时间序列数据。
下载并安装
tar xvfz prometheus-*.tar.gz
cd prometheus-*
在启动Prometheus之前,我们先来配置它。
配置Prometheus监控自身 Prometheus通过抓取目标的HTTP端点来收集度量指标。由于Prometheus以相同的方式公开关于自身的数据,它也可以抓取和监控自身的健康状况。
虽然一个只收集关于自身数据的Prometheus服务器并没有太大用处,但它是一个很好的开始示例。将以下基本的Prometheus配置保存为名为prometheus.yml
的文件:
global:
scrape_interval: 15s # 默认情况下,每15秒抓取目标一次。
# 在与外部系统(联邦、远程存储、Alertmanager)通信时,将这些标签附加到任何时间序列或告警上。
external_labels:
monitor: 'codelab-monitor'
# 一个抓取配置,包含一个要抓取的端点:
# 这里就是Prometheus本身。
scrape_configs:
# 作业名称被添加为标签`job=<job_name>`到从这个配置中抓取的任何时间序列上。
- job_name: 'prometheus'
# 覆盖全局默认设置,每5秒从这个作业抓取目标一次。
scrape_interval: 5s
static_configs:
- targets: ['localhost:9090']
有关配置选项的完整规范,请参阅配置文档。
启动Prometheus 要使用您新创建的配置文件启动Prometheus,请转到包含Prometheus二进制文件的目录并运行:
# 启动Prometheus。
# 默认情况下,Prometheus将其数据库存储在./data(标志--storage.tsdb.path)。
./prometheus --config.file=prometheus.yml
Prometheus应该启动了。您还应该能够在localhost:9090上浏览到关于自身的状态页面。给它几秒钟的时间,让它从自身的HTTP度量端点收集关于自身的数据。
您也可以通过导航到它的度量端点:localhost:9090/metrics来验证Prometheus是否在提供关于自身的度量。
使用表达式浏览器 让我们探索Prometheus已经收集的关于自身的数据。要使用Prometheus内置的表达式浏览器,请导航到http://localhost:9090/graph并在“Graph”标签中选择“Table”视图。
正如您可以从localhost:9090/metrics中收集的,Prometheus导出的关于自身的一个度量指标名为prometheus_target_interval_length_seconds
(目标抓取之间的实际时间)。在表达式控制台中输入以下内容,然后点击“Execute”:
prometheus_target_interval_length_seconds
这应该返回多个不同的时间序列(每个都有记录的最新值),每个都有度量指标名称prometheus_target_interval_length_seconds
,但带有不同的标签。这些标签表示不同的延迟百分位数和目标组间隔。
如果我们只对99百分位的延迟感兴趣,我们可以使用这个查询:
prometheus_target_interval_length_seconds{quantile="0.99"}
要计算返回的时间序列数量,您可以编写:
count(prometheus_target_interval_length_seconds)
有关表达式语言的更多信息,请参阅表达式语言文档。
使用图形界面 要绘制表达式,请导航到http://localhost:9090/graph并使用“Graph”标签。
例如,输入以下表达式以绘制在自抓取的Prometheus中每秒创建的块的速率:
rate(prometheus_tsdb_head_chunks_created_total[1m])
尝试使用图形范围参数和其他设置进行实验。
启动一些示例目标 让我们为Prometheus抓取添加额外的目标。
Node Exporter被用作示例目标,有关使用它的更多信息,请参见这些说明。
tar -xzvf node_exporter-*.*.tar.gz
cd node_exporter-*.*
# 在不同的终端中启动3个示例目标:
./node_exporter --web.listen-address 127.0.0.1:8080
./node_exporter --web.listen-address 127.0.0.1:8081
./node_exporter --web.listen-address 127.0.0.1:8082
您现在应该有示例目标在http://localhost:8080/metrics、http://localhost:8081/metrics和http://localhost:8082/metrics上监听。
配置Prometheus监控示例目标 现在我们将配置Prometheus来抓取这些新目标。让我们将所有三个端点分组到一个名为node
的作业中。我们将假设前两个端点是生产目标,而第三个代表金丝雀实例。在Prometheus中模拟这一点,我们可以将多个端点组添加到一个作业中,为每个目标组添加额外的标签。在这个例子中,我们将为第一组目标添加group="production"
标签,而为第二组添加group="canary"
。
为了实现这一点,请在您的prometheus.yml
的scrape_configs
部分添加以下作业定义,并重新启动您的Prometheus实例:
yaml
scrape_configs:
- job_name: 'node'
# 覆盖全局默认设置,每5秒从这个作业抓取目标一次。
scrape_interval: 5s
static_configs:
- targets: ['localhost:8080', 'localhost:8081']
labels:
group: 'production'
- targets: ['localhost:8082']
labels:
group: 'canary'
转到表达式浏览器并验证Prometheus现在是否有关于这些示例端点暴露的时间序列的信息,例如node_cpu_seconds_total
。
配置规则以聚合抓取的数据到新的时序 虽然在我们的示例中不是问题,但当计算成千上万的时间序列的聚合查询时,如果临时计算,可能会变慢。为了使这更有效,Prometheus可以通过配置的记录规则将表达式预记录到新的持久时间序列中。假设我们对记录每秒钟CPU时间(node_cpu_seconds_total
)感兴趣,该时间在每个实例上所有CPU上平均(但保留作业、实例和模式维度),测量窗口为5分钟。我们可以这样写:
shell
avg by (job, instance, mode) (rate(node_cpu_seconds_total[5m]))
尝试绘制这个表达式。
要将这个表达式产生的时序记录到一个名为job_instance_mode:node_cpu_seconds:avg_rate5m
的新度量指标中,创建一个包含以下记录规则的文件,并将其保存为prometheus.rules.yml
:
yaml
groups:
- name: cpu-node
rules:
- record: job_instance_mode:node_cpu_seconds:avg_rate5m
expr: avg by (job, instance, mode) (rate(node_cpu_seconds_total[5m]))
要使Prometheus采用这个新规则,请在您的prometheus.yml
中添加一个rule_files
语句。配置现在应该看起来像这样:
global:
scrape_interval: 15s # 默认情况下,每15秒抓取目标一次。
evaluation_interval: 15s # 每15秒评估规则一次。
# 将这些额外的标签附加到这个Prometheus实例收集的所有时间序列上。
external_labels:
monitor: 'codelab-monitor'
rule_files:
- 'prometheus.rules.yml'
scrape_configs:
- job_name: 'prometheus'
# 覆盖全局默认设置,每5秒从这个作业抓取目标一次。
scrape_interval: 5s
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
# 覆盖全局默认设置,每5秒从这个作业抓取目标一次。
scrape_interval: 5s
static_configs:
- targets: ['localhost:8080', 'localhost:8081']
labels:
group: 'production'
- targets: ['localhost:8082']
labels:
group: 'canary'
使用新配置重新启动Prometheus,并验证通过表达式浏览器或图形化它,现在是否可以通过查询一个新的时间序列job_instance_mode:node_cpu_seconds:avg_rate5m
。
重新加载配置 如配置文档中所述,可以通过使用SIGHUP信号而不重启进程来重新加载Prometheus实例的配置。如果您在Linux上运行,可以使用kill -s SIGHUP <PID>
来执行此操作,将<PID>
替换为您的Prometheus进程ID。
优雅地关闭您的实例 虽然Prometheus在突然的进程故障情况下确实有恢复机制,但建议使用SIGTERM信号来干净地关闭Prometheus实例。如果您在Linux上运行,可以使用kill -s SIGTERM <PID>
来执行此操作,将<PID>
替换为您的Prometheus进程ID