Prometheus监控学习笔记之全面学习Prometheus

0x00 概述

Prometheus是继Kubernetes后第2个正式加入CNCF基金会的项目,容器和云原生领域事实的监控标准解决方案。在这次分享将从Prometheus的基础说起,学习和了解Prometheus强大的数据处理能力,了解如何使用Prometheus进行白盒和黑盒监控,以及Prometheus在规模化监控下的解决方案等。最后将从0开始构建完整的Kubernetes监控架构。

0x01 监控的目标

在《SRE:Google运维解密》一书中指出,监控系统需要能够有效的支持白盒监控和黑盒监控。通过白盒能够了解其内部的实际运行状态,通过对监控指标的观察能够预判可能出现的问题,从而对潜在的不确定因素进行优化。而黑盒监控,常见的如HTTP探针,TCP探针等,可以在系统或者服务在发生故障时能够快速通知相关的人员进行处理。通过建立完善的监控体系,从而达到以下目的:

  • 长期趋势分析:通过对监控样本数据的持续收集和统计,对监控指标进行长期趋势分析。例如,通过对磁盘空间增长率的判断,我们可以提前预测在未来什么时间节点上需要对资源进行扩容。
  • 对照分析:两个版本的系统运行资源使用情况的差异如何?在不同容量情况下系统的并发和负载变化如何?通过监控能够方便的对系统进行跟踪和比较。
  • 告警:当系统出现或者即将出现故障时,监控系统需要迅速反应并通知管理员,从而能够对问题进行快速的处理或者提前预防问题的发生,避免出现对业务的影响。
  • 故障分析与定位:当问题发生后,需要对问题进行调查和处理。通过对不同监控指标以及历史数据的分析,能够找到并解决根源问题。
  • 数据可视化:通过可视化仪表盘能够直接获取系统的运行状态、资源使用情况、以及服务运行状态等直观的信息。

而对于上一代监控系统而言,在使用过程中往往会面临以下问题:

  • 与业务脱离的监控:监控系统获取到的监控指标与业务本身也是一种分离的关系。好比客户可能关注的是服务的可用性、服务的SLA等级,而监控系统却只能根据系统负载去产生告警;
  • 运维管理难度大:Nagios这一类监控系统本身运维管理难度就比较大,需要有专业的人员进行安装,配置和管理,而且过程并不简单;
  • 可扩展性低: 监控系统自身难以扩展,以适应监控规模的变化;
  • 问题定位难度大:当问题产生之后(比如主机负载异常增加)对于用户而言,他们看到的依然是一个黑盒,他们无法了解主机上服务真正的运行情况,因此当故障发生后,这些告警信息并不能有效的支持用户对于故障根源问题的分析和定位。

在上述需求中,我们可以提取出以下对于一个完善的监控解决方案的几个关键词:数据分析、趋势预测、告警、故障定位、可视化。
除此以外,当前越来越多的产品公司迁移到云或者容器的情况下,对于监控解决方案而言还需要另外一个关键词:云原生

0x02 主要内容

今天将从以下几个方面来介绍下一代监控解决方案Prometheus是如何解决以上问题的:

    1. 初识Prometheus

    2. 让数据会说话:PromQL与可视化

    3. Alertmanager与告警处理;

    4. 白盒与黑盒监控

    5. 规模化监控解决方案

    6. 从0开始监控Kubernetes集群

0x03 初识Prometheus

Prometheus受启发于Google的Brogmon监控系统(相似的Kubernetes是从Google的Brog系统演变而来),从2012年开始由前Google工程师在Soundcloud以开源软件的形式进行研发,并且于2015年早期对外发布早期版本。2016年5月继Kubernetes之后成为第二个正式加入CNCF基金会的项目,同年6月正式发布1.0版本。2017年底发布了基于全新存储层的2.0版本,能更好地与容器平台、云平台配合。

https://prometheus.io/download/获取最新的node exporter版本的二进制包后直接运行即可:

$ node_exporter
INFO[0000] Starting node_exporter (version=0.15.2, branch=HEAD, revision=98bc64930d34878b84a0f87dfe6e1a6da61e532d)  source="
node_exporter.go:43"
INFO[0000] Enabled collectors:                           source="node_exporter.go:50"
INFO[0000]  - time                                       source="node_exporter.go:52"
INFO[0000]  - meminfo                                    source="node_exporter.go:52"
INFO[0000]  - textfile                                   source="node_exporter.go:52"
INFO[0000]  - filesystem                                 source="node_exporter.go:52"
INFO[0000]  - netdev                                     source="node_exporter.go:52"
INFO[0000]  - cpu                                        source="node_exporter.go:52"
INFO[0000]  - diskstats                                  source="node_exporter.go:52"
INFO[0000]  - loadavg                                    source="node_exporter.go:52"
INFO[0000] Listening on :9100                            source="node_exporter.go:76"

访问http://localhost:9100/metrics,可以看到Node Exporter获取到的当前主机的所有监控数据,如下所示:

每一个监控指标之前都会有一段类似于如下形式的信息:

# HELP node_cpu Seconds the cpus spent in each mode.
# TYPE node_cpu counter
node_cpu{cpu="cpu0",mode="idle"} 362812.7890625
# HELP node_load1 1m load average.
# TYPE node_load1 gauge
node_load1 3.0703125

Node Exporter通过指标名称和标签返回了当前主机的监控样本数据。

https://prometheus.io/download/找到最新版本的Prometheus Sevrer软件包,目前这里采用最新的稳定版本2.x.x。

创建配置文件prometheus.yml,如下所示:

global:
scrape_interval:     15s
scrape_configs:
- job_name: 'node'
static_configs:
  - targets: ['localhost:9100']
- job_name: 'prometheus'
static_configs:
  - targets: ['localhost:9090']

并启动Prometheus:

$ prometheus --config.file=prometheus.yml --storage.tsdb.path=/data/prometheus
......
level=info ts=2018-03-11T13:38:06.317645234Z caller=main.go:486 msg="Server is ready to receive web requests."
level=info ts=2018-03-11T13:38:06.317679086Z caller=manager.go:59 component="scrape manag

访问http://localhost:9090,进入到Prometheus Server。通过指标名称node_load1,可以找到当前采集到的主机负载的样本数据。

在上述的例子中,我们主要使用到了Node Exporter实例去获取主机的监控数据,一个运行的Node Exporter实例称为一个Target。Promthues周期性的从Node Exporter实例中获取监控样本,并保存到Promtheus基于本地磁盘实现的时间序列数据库中。

在实际的应用场景中Exporter可以分为两类:

  • 独立运行的:类似于Node Exporter这种,它并不直接产生数据,它只负责从数据源中获取数据,并以Prometheus支持的格式返回监控数据即可。
  • 集成到应用中的:为了能够更好的监控系统的内部运行状态,有些开源项目如Kubernetes,ETCD等直接在内部集成了对Prometheus的支持,通过内部埋点的形式,可以更好的监控服务的内部运行状态。

0x04 让数据说话:PromQL与数据可视化

4.1 理解时间序列

在Node Exporter的/metrics接口中返回的每一行监控数据,在Prometheus下称为一个样本。采集到的样本由以下三部分组成:

  • 指标(metric):指标和一组描述当前样本特征的labelsets唯一标识;
  • 时间戳(timestamp):一个精确到毫秒的时间戳,一般由采集时间决定;
  • 样本值(value): 一个folat64的浮点型数据表示当前样本的值。

 Prometheus会将所有采集到的样本数据以时间序列(time-series)的方式保存在内存数据库中,并且定时保存到硬盘上。每条time-series通过指标名称(metrics name)和一组标签集(labelset)命名。如下所示,可以将time-series理解为一个以时间为X轴的二维矩阵:

 

这种多维度的数据存储方式,可以衍生出很多不同的玩法。 比如,如果数据来自不同的数据中心,那么我们可以在样本中添加标签来区分来自不同数据中心的监控样本,例如:

node_cpu{cpu="cpu0",mode="idle", dc="dc0"} 

从内部实现上来看Prometheus中所有存储的监控样本数据没有任何差异,均是一组标签,时间戳以及样本值。

从存储上来讲所有的监控指标metric都是相同的,但是在不同的场景下这些metric又有一些细微的差异。 例如,在Node Exporter返回的样本中指标node_load1反应的是当前系统的负载状态,随着时间的变化这个指标返回的样本数据是在不断变化的。而指标node_cpu所获取到的样本数据却不同,它是一个持续增大的值,因为其反应的是CPU的累积使用时间,从理论上讲只要系统不关机,这个值是会无限变大的。

为了能够帮助用户理解和区分这些不同监控指标之间的差异,Prometheus定义了4中不同的指标类型(metric type):Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)。

4.1 Counter:只增不减的计数器

Counter是一个简单但有强大的工具,例如我们可以在应用程序中记录某些事件发生的次数,通过以时序的形式存储这些数据,我们可以轻松的了解该事件产生速率的变化。PromQL内置的聚合操作和函数可以用户对这些数据进行进一步的分析:

例如,通过rate()函数获取HTTP请求量的增长率:

rate(http_requests_total[5m]) 

4.3 Gauge:可增可减的仪表盘

与Counter不同,Gauge类型的指标侧重于反应系统的当前状态。因此这类指标的样本数据可增可减。常见指标如:node_memory_MemFree(主机当前空闲的内容大小)、node_memory_MemAvailable(可用内存大小)都是Gauge类型的监控指标。

通过Gauge指标,用户可以直接查看系统的当前状态:

node_memory_MemFree

对于Gauge类型的监控指标,通过PromQL内置函数delta()可以获取样本在一段时间返回内的变化情况。例如,计算CPU温度在两个小时内的差异:

delta(cpu_temp_celsius{host="zeus"}[2h]) 

还可以使用deriv()计算样本的线性回归模型,甚至是直接使用predict_linear()对数据的变化趋势进行预测。例如,预测系统磁盘空间在4个小时之后的剩余情况:

predict_linear(node_filesystem_free{job="node"}[1h], 4 * 3600)

4.4 使用Histogram和Summary分析数据分布情况

在大多数情况下人们都倾向于使用某些量化指标的平均值,例如CPU的平均使用率、页面的平均响应时间。这种方式的问题很明显,以系统API调用的平均响应时间为例:如果大多数API请求都维持在100ms的响应时间范围内,而个别请求的响应时间需要5s,那么就会导致某些WEB页面的响应时间落到中位数的情况,而这种现象被称为长尾问题。

为了区分是平均的慢还是长尾的慢,最简单的方式就是按照请求延迟的范围进行分组。例如,统计延迟在010ms之间的请求数有多少而1020ms之间的请求数又有多少。通过这种方式可以快速分析系统慢的原因。Histogram和Summary都是为了能够解决这样问题的存在,通过Histogram和Summary类型的监控指标,我们可以快速了解监控样本的分布情况。

例如,指标prometheus_tsdb_wal_fsync_duration_seconds的指标类型为Summary。 它记录了Prometheus Server中wal_fsync处理的处理时间,通过访问Prometheus Server的/metrics地址,可以获取到以下监控样本数据:

prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.5"} 0.012352463
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.9"} 0.014458005
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.99"} 0.017316173
prometheus_tsdb_wal_fsync_duration_seconds_sum 2.888716127000002
prometheus_tsdb_wal_fsync_duration_seconds_count 216

从上面的样本中可以得知当前Promtheus Server进行wal_fsync操作的总次数为216次,耗时2.888716127000002s。其中中位数(quantile=0.5)的耗时为0.012352463,9分位数(quantile=0.9)的耗时为0.014458005s。

Prometheus对于数据的存储方式就意味着,不同的标签就代表着不同的特征维度。用户可以通过这些特征维度对查询,过滤和聚合样本数据。

例如,通过node_load1,查询出当前时间序列数据库中所有名为node_load1的时间序列:

node_load1

如果找到满足某些特征维度的时间序列,则可以使用标签进行过滤:

node_load1{instance="localhost:9100"} 

通过以标签为核心的特征维度,用户可以对时间序列进行有效的查询和过滤,当然如果仅仅是这样,显然还不够强大,Prometheus提供的丰富的聚合操作以及内置函数,可以通过PromQL轻松回答以下问题:

  • 当前系统的CPU使用率
avg(irate(node_cpu{mode!="idle"}[2m])) without (cpu, mode)

  • CPU占用率前5位的主机有哪些
topk(5, avg(irate(node_cpu{mode!="idle"}[2m])) without (cpu, mode))

  • 预测在4小时候后,磁盘空间占用大致会是什么情况
predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600)

其中avg(),topk()等都是PromQL内置的聚合操作,irate(),predict_linear()是PromQL内置的函数,irate()函数可以计算一段时间返回内时间序列中所有样本的单位时间变化率。predict_linear函数内部则通过简单线性回归的方式预测数据的变化趋势。

以Grafana为例,在Grafana中可以通过将Promtheus作为数据源添加到系统中,后再使用PromQL进行数据可视化。在Grafana v5.1中提供了对Promtheus 4种监控类型的完整支持,可以通过Graph Panel,Singlestat Panel,Heatmap Panel对监控指标数据进行可视化。

  • 使用Graph Panel可视化主机CPU使用率变化情况:

 

  • 使用Sigle Panel显示当前状态:

 

  • 使用Heatmap Panel显示数据分布情况:

 

 Prometheus通过PromQL提供了强大的数据查询和处理能力。对于外部系统而言可以通过Prometheus提供的API接口,使用PromQL查询相关的样本数据,从而实现如数据可视化等自定义需求,PromQL是Prometheus对内,对外功能实现的主要接口。

 

关于Grafana与Promthues的使用案例详情可以参考:https://github.com/yunlzheng/prometheus-book/blob/master/grafana/README.md

0x05 告警处理中心:Alertmanager

告警在Prometheus的架构中被划分成两个独立的部分:告警产生和告警处理。

在Prometheus可以通过文件的形式定义告警规则,Promthues会周期性的计算告警规则中的PromQL表达式判断是否达到告警触发条件,如果满足,则在Prometheus内部产生一条告警。

告警规则文件,通过YAML格式进行定义:

groups:
- name: hostStatsAlert
rules:
- alert: hostCpuUsageAlert
expr: sum(avg without (cpu)(irate(node_cpu{mode!='idle'}[5m]))) by (instance) > 0.85
for: 1m
labels:
  severity: page
annotations:
  summary: "Instance {{ $labels.instance }} CPU usgae high"
  description: "{{ $labels.instance }} CPU usage above 85% (current value: {{ $value }})

这里定义当主机的CPU使用率大于85%时,产生告警。告警状态将在Promethues的UI中进行展示。

到目前为止Promethues通过周期性的校验告警规则文件,从而在内部触发告警。

而后续的告警处理则由Alertmanager进行统一处理。

Alertmanager作为一个独立的组件,负责接收并处理来自Prometheus Server(也可以是其它的客户端程序)的告警信息。Alertmanager可以对这些告警信息进行进一步的处理,比如消除重复的告警信息,对告警信息进行分组并且路由到正确的接受方,Alertmanager内置了对邮件,Slack等通知方式的支持,同时还支持与Webhook的通知集成,以支持更多的可能性,例如可以通过Webhook与钉钉或者企业微信进行集成。同时AlertManager还提供了静默和告警抑制机制来对告警通知行为进行优化。

 

关于Alertmanager的详细内容可以参考:https://github.com/yunlzheng/prometheus-book/blob/master/alert/README.md

Prometheus作为是一个开源的完整监控解决方案,其对传统监控系统的check-alert模型进行了彻底的颠覆,形成了基于中央化的规则计算、统一分析和告警的新模型。

0x06 使用Blackbox进行黑盒监控

在前面的部分中,我们主要介绍了Node Exporter的使用,对于这类Exporter而言,它们主要监控服务或者基础设施的内部使用状态,即白盒监控。通过对监控指标的观察能够预判可能出现的问题,从而对潜在的不确定因素进行优化。

而从完整的监控逻辑的角度,除了大量的应用白盒监控以外,还应该添加适当的黑盒监控。黑盒监控即以用户的身份测试服务的外部可见性,常见的黑盒监控包括HTTP探针、TCP探针等用于检测站点或者服务的可访问性,以及访问效率等。

黑盒监控相较于白盒监控最大的不同在于黑盒监控是以故障为导向当故障发生时,黑盒监控能快速发现故障,而白盒监控则侧重于主动发现或者预测潜在的问题。一个完善的监控目标是要能够从白盒的角度发现潜在问题,能够在黑盒的角度快速发现已经发生的问题。

这里类比敏捷中著名的敏捷测试金字塔,对于完整的监控而言,我们需要大量的白盒监控,用于监控服务的内部运行状态,从而可以支持有效的故障分析。 同时也需要部分的黑盒监控,用于检测主要服务是否发生故障。

Blackbox Exporter是Prometheus社区提供的官方黑盒监控解决方案,其允许用户通过:HTTP、HTTPS、DNS、TCP以及ICMP的方式对网络进行探测。用户可以直接使用go get命令获取Blackbox Exporter源码并生成本地可执行文件。

 Blackbox Exporter运行时,需要指定探针配置文件,例如blackbox.yml:

modules:
http_2xx:
prober: http
http:
  method: GET
http_post_2xx:
prober: http
http:
  method: POST

启动blackbox_exporter即可启动一个探针服务:

blackbox_exporter --config.file=/etc/prometheus/blackbox.yml

启动后,通过访问http://127.0.0.1:9115/probe?module=http_2xx&target=baidu.com可以获得blackbox对baidu.com站点探测的结果。

probe_http_duration_seconds{phase="connect"} 0.055551141 
probe_http_duration_seconds{phase="processing"} 0.049736019
probe_http_duration_seconds{phase="resolve"} 0.011633673
probe_http_duration_seconds{phase="tls"} 0
probe_http_duration_seconds{phase="transfer"} 3.8919e-05
# HELP probe_http_redirects The number of redirects
# TYPE probe_http_redirects gauge
probe_http_redirects 0
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
probe_http_ssl 0
# HELP probe_http_status_code Response HTTP status code
# TYPE probe_http_status_code gauge
probe_http_status_code 200
# HELP probe_http_version Returns the version of HTTP of the probe response
# TYPE probe_http_version gauge
probe_http_version 1.1
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
probe_ip_protocol 4
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
probe_success 1

在Prometheus中可以通过添加响应的监控采集任务,即可获取对相应站点的探测结构样本数据:

- job_name: 'blackbox'
metrics_path: /probe
params:
  module: [http_2xx]
static_configs:
  - targets:
    - http://prometheus.io    # Target to probe with http.
    - https://prometheus.io   # Target to probe with https.
    - http://example.com:8080 # Target to probe with http on port 8080.
relabel_configs:
  - source_labels: [__address__]
    target_label: __param_target
  - source_labels: [__param_target]
    target_label: instance
  - target_label: __address__
    replacement: 127.0.0.1:9115

0x07 规模化监控解决方案

到目前为止,我们了解了Prometheus的基础架构和主要工作机制,如下所示:

Prometheus周期性的从Target中获取监控数据并保存到本地的time-series中,并且通过PromQL对外暴露数据查询接口。 内部周期性的检查告警规则文件,产生告警并有Alertmanager对告警进行后续处理。

那么问题来了,这里Prometheus是单点,Alertmanager也是单点。 这样的结构能否支持大规模的监控量?

 对于Prometheus而言,要想完全理解其高可用部署模式,首先我们需要理解Prometheus的数据存储机制。

 

如上所示,Prometheus 2.x采用自定义的存储格式将样本数据保存在本地磁盘当中。按照两个小时为一个时间窗口,将两小时内产生的数据存储在一个块(Block)中,每一个块中包含该时间窗口内的所有样本数据(chunks),元数据文件(meta.json)以及索引文件(index)。

当前时间窗口内正在收集的样本数据,Prometheus则会直接将数据保存在内存当中。为了确保此期间如果Prometheus发生崩溃或者重启时能够恢复数据,Prometheus启动时会从写入日志(WAL)进行重播,从而恢复数据。此期间如果通过API删除时间序列,删除记录也会保存在单独的逻辑文件当中(tombstone)。

通过时间窗口的形式保存所有的样本数据,可以明显提高Prometheus的查询效率,当查询一段时间范围内的所有样本数据时,只需要简单的从落在该范围内的块中查询数据即可。而对于历史数据的删除,也变得非常简单,只要删除相应块所在的目录即可。

 对于单节点的Prometheus而言,这种基于本地文件系统的存储方式能够让其支持数以百万的监控指标,每秒处理数十万的数据点。为了保持自身管理和部署的简单性,Prometheus放弃了管理HA的复杂度。

因此首先,对于这种存储方式而言,我们需要明确的几点:

  1. Prometheus本身不适用于持久化存储长期的历史数据,默认情况下Prometheus只保留15天的数据。
  2. 本地存储也意味着Prometheus自身无法进行有效的弹性伸缩。


而当监控规模变得巨大的时候,对于单台Prometheus而言,其主要挑战包括以下几点:

  1. 服务的可用性,如何确保Prometheus不会发生单点故障;
  2. 监控规模变大的意味着,Prometheus的采集Job的数量也会变大(写)操作会变得非常消耗资源;
  3. 同时也意味着大量的数据存储的需求。

7.1 简单HA:服务可用性

由于Prometheus的Pull机制的设计,为了确保Prometheus服务的可用性,用户只需要部署多套Prometheus Server实例,并且采集相同的Exporter目标即可。

基本的HA模式只能确保Prometheus服务的可用性问题,但是不解决Prometheus Server之间的数据一致性问题以及持久化问题(数据丢失后无法恢复),也无法进行动态的扩展。因此这种部署方式适合监控规模不大,Promthues Server也不会频繁发生迁移的情况,并且只需要保存短周期监控数据的场景。

 7.2 基本HA + 远程存储

 在基本HA模式的基础上通过添加Remote Storage存储支持,将监控数据保存在第三方存储服务上。

 

当Prometheus在获取监控样本并保存到本地的同时,会将监控数据发送到Remote Storage Adaptor,由Adaptor完成对第三方存储的格式转换以及数据持久化。

当Prometheus查询数据的时候,也会从Remote Storage Adaptor获取数据,合并本地数据后进行数据查询。

在解决了Prometheus服务可用性的基础上,同时确保了数据的持久化,当Prometheus Server发生宕机或者数据丢失的情况下,可以快速的恢复。 同时Prometheus Server可能很好的进行迁移。因此,该方案适用于用户监控规模不大,但是希望能够将监控数据持久化,同时能够确保Prometheus Server的可迁移性的场景。

7.3 基本HA + 远程存储 + 联邦集群

 当单台Prometheus Server无法处理大量的采集任务时,用户可以考虑基于Prometheus联邦集群的方式将监控采集任务划分到不同的Prometheus实例当中即在任务级别功能分区。

 这种部署方式一般适用于两种场景:

场景一:单数据中心 + 大量的采集任务

这种场景下Prometheus的性能瓶颈主要在于大量的采集任务,因此用户需要利用Prometheus联邦集群的特性,将不同类型的采集任务划分到不同的Prometheus子服务中,从而实现功能分区。例如一个Prometheus Server负责采集基础设施相关的监控指标,另外一个Prometheus Server负责采集应用监控指标。再有上层Prometheus Server实现对数据的汇聚。

场景二:多数据中心

这种模式也适合与多数据中心的情况,当Prometheus Server无法直接与数据中心中的Exporter进行通讯时,在每一个数据中部署一个单独的Prometheus Server负责当前数据中心的采集任务是一个不错的方式。这样可以避免用户进行大量的网络配置,只需要确保主Prometheus Server实例能够与当前数据中心的Prometheus Server通讯即可。 中心Prometheus Server负责实现对多数据中心数据的聚合。

7.4 高可用方案选择

上面的部分,根据不同的场景演示了3种不同的高可用部署方案。当然对于Prometheus部署方案需要用户根据监控规模以及自身的需求进行动态调整,下表展示了Prometheus和高可用有关3个选项各自解决的问题,用户可以根据自己的需求灵活选择。

 

 对于Alertmanager而言,Alertmanager集群之间使用Gossip协议相互传递状态,因此对于Prometheus而言,只需要关联多个Alertmanager实例即可,关于Alertmanager集群的详细详细可以参考:

https://github.com/yunlzheng/prometheus-book/blob/master/ha/alertmanager-high-availability.md

0x08 服务发现与云原生:以Kubernetes为例

对于诸如Kubernetes这类容器或者云环境,对于Prometheus而言,需要解决的一个重要问题就是如何动态的发现部署在Kubernetes环境下的需要监控的所有目标。

对于Kubernetes而言,如上图所示,我们可以把当中所有的资源分为几类:

  1. 基础设施层(Node):集群节点,为整个集群和应用提供运行时资源
  2. 容器基础设施(Container):为应用提供运行时环境
  3. 用户应用(Pod):Pod中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能
  4. 内部服务负载均衡(Service):在集群内,通过Service在集群暴露应用功能,集群内应用和应用之间访问时提供内部的负载均衡。
  5. 外部访问入口(Ingress):通过Ingress提供集群外的访问入口,从而可以使外部客户端能够访问到部署在Kubernetes集群内的服务。


因此,在不考虑Kubernetes自身组件的情况下,如果要构建一个完整的监控体系,我们应该考虑,以下5个方面:

  1. 集群节点状态监控:从集群中各节点的kubelet服务获取节点的基本运行状态;
  2. 集群节点资源用量监控:通过Daemonset的形式在集群中各个节点部署Node Exporter采集节点的资源使用情况;
  3. 节点中运行的容器监控:通过各个节点中kubelet内置的cAdvisor中获取个节点中所有容器的运行状态和资源使用情况;
  4. 从黑盒监控的角度在集群中部署Blackbox Exporter探针服务,检测Service和Ingress的可用性;
  5. 如果在集群中部署的应用程序本身内置了对Prometheus的监控支持,那么我们还应该找到相应的Pod实例,并从该Pod实例中获取其内部运行状态的监控指标。

而对于Prometheus这一类基于Pull模式的监控系统,显然也无法继续使用的static_configs的方式静态的定义监控目标。而对于Prometheus而言其解决方案就是引入一个中间的代理人(服务注册中心),这个代理人掌握着当前所有监控目标的访问信息,Prometheus只需要向这个代理人询问有哪些监控目标控即可, 这种模式被称为服务发现。

 

Prometheus提供了对Kubernetes的完整支持,通过与Kubernetes的API进行交互,Prometheus可以自动的发现Kubernetes中所有的Node、Service、Pod、Endpoints以及Ingress资源的相关信息。

通过服务发现找到所有的监控目标后,并通过Prometheus的Relabling机制对这些资源进行过滤,metrics地址替换等操作,从而实现对各类资源的全自动化监控。

例如,通过以下流程任务配置,可以自动从集群节点的kubelet服务中内置的cAdvisor中获取容器的监控数据:

- job_name: 'kubernetes-cadvisor'
scheme: https

tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token

kubernetes_sd_configs:
- role: node

relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor

由或者是通过集群中部署的blackbox exporter对服务进行网络探测:

- job_name: 'kubernetes-services'
metrics_path: /probe

params:
module: [http_2xx]
kubernetes_sd_configs:
- role: service

relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
target_label: kubernetes_name

 0x09 参考

详细请参考原作者github书籍 https://github.com/yunlzheng/prometheus-book

原文地址:https://www.cnblogs.com/JetpropelledSnake/p/10314891.html