指标是表示系统整体健康状况以及您认为对于监控、警报或可观测性重要的任何其他特定信息的主要方式。 Prometheus 是一个领先的开源指标检测、收集和存储工具包 于 2012 年在 SoundCloud 构建。此后,它从云原生计算基金会毕业,并成为 Kubernetes 监控的事实标准。以下文章对其进行了详细介绍:
然而,这些文章都没有关注如何在 Kubernetes 上使用 Prometheus。本文
- 描述 Prometheus 的架构和数据模型,以帮助您了解其工作原理和功能
- 提供有关在 Kubernetes 集群中设置 Prometheus 并使用它来监控集群和应用程序的教程
架构
虽然了解 Prometheus 的工作原理对于有效使用它可能不是必需的,但它可能会有所帮助,尤其是在您考虑将其用于生产环境时。《Prometheus 文档》提供了此图表以及有关 Prometheus 基本要素以及各个部分如何连接在一起的详细信息。

对于大多数用例,您应该了解 Prometheus 的三个主要组件
- Prometheus 服务器抓取并存储指标。请注意,它使用持久层,这是服务器的一部分,但文档中未明确提及。服务器的每个节点都是自治的,不依赖于分布式存储。稍后,在考虑使用专用时序数据库来存储 Prometheus 数据而不是依赖服务器本身时,我将重新讨论这一点。
- Web UI 允许您访问、可视化和绘制存储的数据。Prometheus 提供自己的 UI,但您也可以配置其他可视化工具(如 Grafana)以使用 PromQL(Prometheus 查询语言)访问 Prometheus 服务器。
- Alertmanager 从客户端应用程序(尤其是 Prometheus 服务器)发送警报。它具有用于重复数据删除、分组和路由警报的高级功能,并且可以通过 PagerDuty 和 OpsGenie 等其他服务进行路由。
理解 Prometheus 的关键在于它基本上依赖于从定义的端点抓取或拉取指标。这意味着您的应用程序需要公开一个指标可用的端点,并指示 Prometheus 服务器如何抓取它(这将在下面的教程中介绍)。对于许多不容易添加 Web 端点的应用程序(例如 Kafka 和 Cassandra(使用 JMX exporter)),都有导出器。
数据模型
现在您已经了解了 Prometheus 如何工作以抓取和存储指标,接下来要学习的是 Prometheus 支持的指标类型。以下部分信息(用引号标记)来自 Prometheus 文档的“指标类型”部分。
计数器和仪表盘
两种最简单的指标类型是 计数器 和 仪表盘。在开始使用 Prometheus(或更广泛地使用时序监控)时,这些是最容易理解的类型,因为很容易将它们与您可以想象监控的值联系起来,例如您的应用程序正在使用的系统资源量或它已处理的事件数。
“计数器是一种累积指标,它表示一个单调递增的计数器,其值只能增加或在重新启动时重置为零。例如,您可以使用计数器来表示已处理的请求数、已完成的任务数或错误数。”
由于您无法减少计数器,因此它只能且应该仅用于表示累积指标。
“仪表盘是一种指标,它表示一个可以任意上下波动的单个数值。仪表盘通常用于测量值,如 [CPU] 或当前内存使用率,但也用于可以上下波动的“计数”,如并发请求数。”
直方图和摘要
Prometheus 支持两种更复杂的指标类型:直方图 和 摘要。考虑到它们都跟踪观测值的数量和观测值的总和,这里有很多混淆的机会。您可能选择使用它们的原因之一是您需要计算观测值的平均值。请注意,它们在数据库中创建多个时间序列;例如,它们都创建一个带有 _sum 后缀的观测值总和。
“直方图对观测值(通常是请求持续时间或响应大小之类的内容)进行采样,并在可配置的桶中对其进行计数。它还提供所有观测值的总和。”
这使其成为跟踪延迟等事物的绝佳选择,延迟可能具有针对其定义的服务级别目标 (SLO)。来自 文档
您可能有一个 SLO,要求在 300 毫秒内处理 95% 的请求。在这种情况下,配置一个直方图,使其桶的上限为 0.3 秒。然后,您可以直接表示在 300 毫秒内处理的请求的相对数量,并在值降至 0.95 以下时轻松发出警报。以下表达式按作业计算过去 5 分钟内处理的请求。请求持续时间是使用名为 http_request_duration_seconds 的直方图收集的。
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m])) by (job) / sum(rate(http_request_duration_seconds_count[5m])) by (job)
回到定义
“与直方图类似,摘要对观测值(通常是请求持续时间和响应大小之类的内容)进行采样。虽然它也提供观测值的总计数和所有观测值的总和,但它会在滑动时间窗口内计算可配置的分位数。”
摘要和直方图之间的本质区别在于,摘要在客户端计算流式 φ 分位数并直接公开它们,而直方图公开分桶的观测计数,并且从直方图的桶中计算分位数发生在服务器端,使用 histogram_quantile() 函数。
如果您仍然感到困惑,我建议采取以下方法
- 大多数情况下,对于简单的时序指标,请使用仪表盘。
- 对于您知道会单调递增的事物,请使用计数器,例如,如果您要计算某事发生的次数。
- 对于具有简单桶的延迟测量,请使用直方图,例如,一个桶用于“低于 SLO”,另一个桶用于“高于 SLO”。
这对于绝大多数用例来说应该足够了,对于更高级的场景,您应该依靠统计分析专家来帮助您。
现在您已经基本了解了 Prometheus 是什么、它的工作原理以及它可以收集和存储的数据类型,您就可以开始本教程了。
Prometheus 和 Kubernetes 动手教程
本教程涵盖以下内容
- 在您的集群中安装 Prometheus
- 下载示例应用程序并查看代码
- 构建和部署应用程序并对其生成负载
- 访问 Prometheus UI 并查看基本指标
本教程假设
- 您已经部署了 Kubernetes 集群。
- 您已配置 kubectl 命令行实用程序以进行访问。
- 您具有 cluster-admin 角色(或至少具有创建命名空间和部署应用程序的足够权限)。
- 您正在运行基于 Bash 的命令行界面。如果您运行其他操作系统或 shell 环境,请调整本教程。
如果您尚未运行 Kubernetes,则此 Minikube 教程 是在您的笔记本电脑上设置它的简便方法。
如果您现在准备好了,让我们开始吧。
安装 Prometheus
在本节中,您将克隆示例存储库并使用 Kubernetes 的配置文件将 Prometheus 部署到专用命名空间。
- 在本地克隆示例存储库并将其用作您的工作目录
$ git clone https://github.com/yuriatgoogle/prometheus-demo.git $ cd prometheus-demo $ WORKDIR=$(pwd)
- 为 Prometheus 部署创建一个专用命名空间
$ kubectl create namespace prometheus
- 为您的命名空间授予集群读取器角色
$ kubectl apply -f $WORKDIR/kubernetes/clusterRole.yaml clusterrole.rbac.authorization.k8s.io/prometheus created clusterrolebinding.rbac.authorization.k8s.io/prometheus created
- 创建一个包含抓取和警报规则的 Kubernetes configmap
$ kubectl apply -f $WORKDIR/kubernetes/configMap.yaml -n prometheus configmap/prometheus-server-conf created
- 部署 Prometheus
$ kubectl create -f prometheus-deployment.yaml -n prometheus deployment.extensions/prometheus-deployment created
- 验证 Prometheus 正在运行
$ kubectl get pods -n prometheus NAME READY STATUS RESTARTS AGE prometheus-deployment-78fb5694b4-lmz4r 1/1 Running 0 15s
查看基本指标
在本节中,您将访问 Prometheus UI 并查看正在收集的指标。
- 使用端口转发在本地启用对 Prometheus UI 的 Web 访问
注意: 您的 prometheus-deployment 将具有与此示例不同的名称。查看并替换上一个命令输出中的 pod 名称。$ kubectl port-forward prometheus-deployment-7ddb99dcb-fkz4d 8080:9090 -n prometheus Forwarding from 127.0.0.1:8080 -> 9090 Forwarding from [::1]:8080 -> 9090
- 在浏览器中转到 http://localhost:8080
您现在可以查询 Prometheus 指标了!
- 一些基本的机器指标(如 CPU 核心数和内存)立即可用。例如,在表达式字段中输入 machine_memory_bytes,切换到“Graph”视图,然后单击“Execute”以查看指标图表

- 集群中运行的容器也会被自动监控。例如,输入 rate(container_cpu_usage_seconds_total{container_name="prometheus"}[1m]) 作为表达式,然后单击“Execute”以查看 Prometheus 的 CPU 使用率

现在您已经知道如何安装 Prometheus 并使用它来衡量一些开箱即用的指标,现在是进行一些实际监控的时候了。
黄金信号
正如 Google SRE 书籍的“监控分布式系统”章节中所述
“监控的四个黄金信号是延迟、流量、错误和饱和度。如果您只能衡量面向用户的系统的四个指标,请关注这四个。”
该书对所有四个信号都进行了详尽的描述,但本教程侧重于最容易作为用户幸福度代理的三个信号
- 流量: 您正在接收多少请求
- 错误率: 您可以成功处理多少请求
- 延迟: 您可以多快地处理成功请求
您可能已经意识到,Prometheus 不会为您测量这些指标;您必须检测您部署的任何应用程序以发出这些指标。以下是一个示例实现。
打开 $WORKDIR/node/golden_signals/app.js 文件,这是一个用 Node.js 编写的示例应用程序(回想一下,我们之前克隆了 yuriatgoogle/prometheus-demo 并导出了 $WORKDIR)。首先查看第一部分,其中定义了要记录的指标
// total requests - counter
const nodeRequestsCounter = new prometheus.Counter({
name: 'node_requests',
help: 'total requests'
});
第一个指标是一个计数器,它将为每个请求递增;这就是计算请求总数的方式
// failed requests - counter
const nodeFailedRequestsCounter = new prometheus.Counter({
name: 'node_failed_requests',
help: 'failed requests'
});
第二个指标是另一个计数器,它为每个错误递增,以跟踪失败请求的数量
// latency - histogram
const nodeLatenciesHistogram = new prometheus.Histogram({
name: 'node_request_latency',
help: 'request latency by path',
labelNames: ['route'],
buckets: [100, 400]
});
第三个指标是一个直方图,用于跟踪请求延迟。基于延迟 SLO 为 100 毫秒的非常基本的假设,您将创建两个桶:一个用于 100 毫秒,另一个用于 400 毫秒延迟。
下一节处理传入的请求,为每个请求递增总请求指标,当出现(人为诱发的)错误时递增失败请求,并为每个成功请求记录延迟直方图值。我选择不记录错误的延迟;该实现细节由您决定。
app.get('/', (req, res) => {
// start latency timer
const requestReceived = new Date().getTime();
console.log('request made');
// increment total requests counter
nodeRequestsCounter.inc();
// return an error 1% of the time
if ((Math.floor(Math.random() * 100)) == 100) {
// increment error counter
nodeFailedRequestsCounter.inc();
// return error code
res.send("error!", 500);
}
else {
// delay for a bit
sleep.msleep((Math.floor(Math.random() * 1000)));
// record response latency
const responseLatency = new Date().getTime() - requestReceived;
nodeLatenciesHistogram
.labels(req.route.path)
.observe(responseLatency);
res.send("success in " + responseLatency + " ms");
}
})
本地测试
现在您已经了解了如何实现 Prometheus 指标,请查看运行应用程序时会发生什么。
- 安装所需的软件包
$ cd $WORKDIR/node/golden_signals $ npm install --save
- 启动应用程序
$ node app.js
- 打开两个浏览器标签页:一个访问 http://localhost:8080,另一个访问 http://localhost:8080/metrics。
- 当您转到 /metrics 页面时,您可以看到 Prometheus 指标正在被收集和更新,每次您重新加载主页时都会更新

您现在可以部署示例应用程序到您的 Kubernetes 集群并测试您的监控。
在 Kubernetes 上部署监控到 Prometheus
现在是时候看看指标是如何在部署在您的集群中的 Prometheus 实例中记录和表示的,通过
- 构建应用程序镜像
- 将其部署到您的集群
- 对应用程序生成负载
- 观察记录的指标
构建应用程序镜像
示例应用程序提供了一个 Dockerfile,您将使用它来构建镜像。本节假设您具有
- 本地安装并配置了 Docker
- 一个 Docker Hub 帐户
- 创建了一个存储库
如果您使用 Google Kubernetes Engine 运行您的集群,则可以使用 Cloud Build 和 Google Container Registry 代替。
- 切换到应用程序目录
$ cd $WORKDIR/node/golden_signals
- 使用此命令构建镜像
$ docker build . --tag=<Docker username>/prometheus-demo-node:latest
- 确保您已登录到 Docker Hub
$ docker login
- 使用此命令将镜像推送到 Docker Hub
$ docker push <username>/prometheus-demo-node:latest
- 验证镜像是否可用
$ docker images
部署应用程序
现在应用程序镜像已在 Docker Hub 中,您可以将其部署到您的集群并运行应用程序。
- 修改 $WORKDIR/node/golden_signals/prometheus-demo-node.yaml 文件以从 Docker Hub 拉取镜像
spec: containers: - image: docker.io/<Docker username>/prometheus-demo-node:latest
- 部署镜像
$ kubectl apply -f $WORKDIR/node/golden_signals/prometheus-demo-node.yaml deployment.extensions/prometheus-demo-node created
- 验证应用程序正在运行
$ kubectl get pods NAME READY STATUS RESTARTS AGE prometheus-demo-node-69688456d4-krqqr 1/1 Running 0 65s
- 使用负载均衡器公开应用程序
$ kubectl expose deployment prometheus-node-demo --type=LoadBalancer --name=prometheus-node-demo --port=8080 service/prometheus-demo-node exposed
- 确认您的服务具有外部 IP 地址
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.39.240.1 <none> 443/TCP 23h prometheus-demo-node LoadBalancer 10.39.248.129 35.199.186.110 8080:31743/TCP 78m
生成负载以测试监控
现在您的服务已启动并正在运行,请使用 Apache Bench 对其生成一些负载。
- 将您的服务的 IP 地址作为变量获取
$ export SERVICE_IP=$(kubectl get svc prometheus-demo-node -ojson | jq -r '.status.loadBalancer.ingress[].ip')
- 使用 ab 生成一些负载。您可能希望在单独的终端窗口中运行此操作。
$ ab -c 3 -n 1000 http://${SERVICE_IP}:8080/
查看指标
在负载运行时,再次访问集群中的 Prometheus UI 并确认正在收集“黄金信号”指标。
- 建立与 Prometheus 的连接
$ kubectl get pods -n prometheus NAME READY STATUS RESTARTS AGE prometheus-deployment-78fb5694b4-lmz4r 1/1 Running 0 15s $ kubectl port-forward prometheus-deployment-78fb5694b4-lmz4r 8080:9090 -n prometheus Forwarding from 127.0.0.1:8080 -> 9090 Forwarding from [::1]:8080 -> 9090
注意: 确保将第二个命令中的 pod 名称替换为第一个命令的输出。
- 在浏览器中打开 http://localhost:8080

- 使用此表达式测量请求速率
rate(node_requests[1m])

- 使用此表达式测量您的错误率
rate(node_failed_requests[1m])

- 最后,使用此表达式验证您的延迟 SLO。请记住,您设置了两个桶,100 毫秒和 400 毫秒。此表达式返回满足 SLO 的请求百分比
sum(rate(node_request_latency_bucket{le="100"}[1h])) / sum(rate(node_request_latency_count[1h]))

opensource.com
大约 10% 的请求在 SLO 范围内。这是您应该预期的,因为代码会在 0 到 1,000 毫秒之间的随机毫秒数内休眠。因此,大约 10% 的时间,它会在超过 100 毫秒内返回,并且此图表显示您无法满足延迟 SLO。
总结
恭喜!您已完成本教程,希望您对 Prometheus 的工作原理、如何使用自定义指标检测您的应用程序以及如何使用它来衡量您的 SLO 合规性有了更好的理解。本系列的下一篇文章将介绍另一种使用 OpenCensus 的指标检测方法。
评论已关闭。