主流K8S集群监控方案

4,483 阅读16分钟

Prometheus

什么是Prometheus


Prometheus是一套开源的监控系统、报警、时间序列的集合,最初由SoundCloud开发,后来随着越来越多公司的使用,于是便独立成开源项目。自此以后,许多公司和组织都采用了Prometheus作为监控告警工具。

image.png

从架构图中可以看出,Prometheus数据采集的方式比较特别,exporters作为Prometheus的数据采集员,将在特定服务器上采集需要的指标,然后通过特定的端口将其暴露供Prometheus采集。

数据采集

Prometheus Server

Prometheus Server负责实现对监控数据的获取,存储以及查询。

  • Prometheus Server可以通过静态配置管理监控目标,也可以配合使用Service Discovery的方式动态管理监控目标,并从这些监控目标中获取数据。
  • Prometheus Server需要对采集到的监控数据进行存储,Prometheus Server本身就是一个时序数据库,将采集到的监控数据按照时间序列的方式存储在本地磁盘当中。
  • Prometheus Server对外提供了自定义的PromQL语言,实现对数据的查询以及分析。
  • Prometheus Server内置的Express Browser UI,通过这个UI可以直接通过PromQL实现数据的查询以及可视化。
  • Prometheus Server的联邦集群能力可以使其从其他的Prometheus Server实例中获取数据,因此在大规模监控的情况下,可以通过联邦集群以及功能分区的方式对Prometheus Server进行扩展。

什么是exporter

广义上讲所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter。而Exporter的一个实例称为target,如下所示,Prometheus通过轮询的方式定期从这些target中获取样本数据:

exporter.png

Prometheus 已经成为云原生应用监控行业的标准,在很多流行的监控系统中都已经实现了 Prometheus的监控接口,例如 etcd、Kubernetes、CoreDNS等,它们可以直接被Prometheus监控,但大多数监控对象都没办法直接提供监控接口,主要原因有:

  • 很多系统在Prometheus诞生前的很多年就已发布,例如MySQL、Redis等;
  • 本身不支持 HTTP 接口,例如对于硬件性能指标,操作系统并没有原生的HTTP接口可以获取;
  • 考虑到安全性、稳定性及代码耦合等因素的影响,软件作者并不愿意将监控代码加入现有代码中。
  • 这些都导致无法通过一个规范解决所有监控问题。在此背景之下,Exporter 应运而生。Exporter 是一个采集监控数据并通过 Prometheus 监控规范对外提供数据的组件。除了官方实现的Exporter如Node ExporterJMX ExporterMySQLserver Exporter,还有很多第三方实现如Redis ExporterRabbitMQ Exporter等。

Exporter 主要通过被监控对象提供的监控相关的接口获取监控数据,主要有如下几种方式:

  • HTTP/HTTPS方式。例如 RabbitMQ exporter通过 RabbitMQ的 HTTPS接口获取监控数据。
  • TCP方式。例如Redis exporter通过Redis提供的系统监控相关命令获取监控指标,MySQL server exporter通过MySQL开放的监控相关的表获取监控指标。
  • 本地文件方式。例如Node exporter通过读取proc文件系统下的文件,计算得出整个操作系统的状态。

Prometheus 在面对众多繁杂的监控对象时并没有采用逐一适配的方式,而是制定了一套独特的监控数据规范,符合这套规范的监控数据都可以被Prometheus统一采集、分析和展现。所有的Exporter程序都需要按照Prometheus的规范,返回监控的样本数据。以JMX Exporter为例,当访问/metrics地址时会返回以下内容:

# TYPE jvm_classes_loaded_total counter
jvm_classes_loaded_total 3142.0
# HELP jvm_classes_unloaded_total The total number of classes that have been unloaded since the JVM has started execution
# TYPE jvm_classes_unloaded_total counter
jvm_classes_unloaded_total 0.0

数据格式

data_format.png

什么是Promql

PromQL (Prometheus Query Language) 是 Prometheus 自己开发的数据查询 DSL 语言,语言表现力非常丰富,内置函数很多,在日常数据可视化以及rule 告警中都会使用到它。

样例:

node_filesystem_size_bytes{machinetype="physicalmachine",fstype=~"ext4|xfs",mountpoint="/"}-0
(1-(node_filesystem_free_bytes{fstype=~"ext4|xfs",mountpoint="/",machinetype="physicalmachine"} / node_filesystem_size_bytes{fstype=~"ext4|xfs",mountpoint="/",machinetype="physicalmachine"})) * 100
sum (((1-(node_filesystem_free_bytes{fstype=~"ext4|xfs",mountpoint="/",machinetype="physicalmachine",} / node_filesystem_size_bytes{fstype=~"ext4|xfs",mountpoint="/",machinetype="physicalmachine"})) * 100)) by (instance)

topk(10,sum (((1-(node_filesystem_free_bytes{fstype=~"ext4|xfs",mountpoint="/",machinetype="physicalmachine",} / node_filesystem_size_bytes{fstype=~"ext4|xfs",mountpoint="/",machinetype="physicalmachine"})) * 100)) by (instance))

数据存储

prometheus-storage.png

高可用方案介绍

单台的 Prometheus 存在单点故障的风险,随着监控规模的扩大,Prometheus 产生的数据量也会非常大,性能和存储都会面临问题。毋庸置疑,我们需要一套高可用方案。

Prometheus联邦

当单个 Promthues 实例 无法处理大量的采集任务时,这个时候我们就可以使用基于 Prometheus 联邦集群的方式来将监控任务划分到不同的 Prometheus 实例中去。

federation.png 我们可以将不同类型的采集任务划分到不同的 Prometheus 实例中去执行,进行功能分片,比如一个 Prometheus 负责采集节点的指标数据,另外一个 Prometheus 负责采集应用业务相关的监控指标数据,最后在上层通过一个 Prometheus 对数据进行汇总。

具体的采集任务如何去进行分区也没有固定的标准,需要结合实际的业务进行考虑,除了上面的方式之外,还有一种情况就是单个的采集数据量就非常非常大,比如我们要采集上万个节点的监控指标数据,这种情况即使我们已经进行了分区,但是对于单个 Prometheus 来说压力也是非常大的,这个时候我们就需要按照任务的不同实例进行划分,我们通过 Prometheus 的 relabel 功能,通过 hash 取模的方式可以确保当前 Prometheus 只采集当前任务的一部分实例的监控指标。

# 省略其他配置......
relabel_configs:
- source_labels: [__address__]
  modulus: 4   # 将节点分片成 4 个组
  target_label: __tmp_hash
  action: hashmod
- source_labels: [__tmp_hash]
  regex: ^1$  # 只抓第2个组中节点的数据(序号0为第1个组)
  action: keep

Thanos

Thanos 是一个基于 Prometheus 实现的监控方案,其主要设计目的是解决原生 Prometheus 上的痛点,并且做进一步的提升,主要的特性有:全局查询,高可用,动态拓展,长期存储。下图是 Thanos 官方的架构图:

thanos.png

Thanos 主要由如下几个特定功能的组件组成:

  • 边车组件(Sidecar):连接 Prometheus,并把 Prometheus 暴露给查询网关(Querier/Query),以供实时查询,并且可以上传 Prometheus 数据给对象存储例如s3,以供长期保存
  • 查询网关(Querier/Query):实现了 Prometheus API,与汇集底层组件(如边车组件 Sidecar,或是存储网关 Store Gateway)的数据
  • 存储网关(Store Gateway):将云存储中的数据内容暴露出来
  • 压缩器(Compactor):将云存储中的数据进行压缩和下采样
  • 接收器(Receiver):从 Prometheus 的 remote-write WAL(Prometheus 远程预写式日志)获取数据,暴露出去或者上传到云存储
  • 规则组件(Ruler):针对监控数据进行评估和报警
  • Bucket:主要用于展示对象存储中历史数据的存储情况,查看每个指标源中数据块的压缩级别,解析度,存储时段和时间长度等信息。

工作流程

Thanos 是同时支持 Prometheus 读和写的远程存储方案,首先我们先看下指标写入的整个流程:

  • 首先 Prometheus 从所采集服务的 metrics 接口抓取指标数据,同时根据自身所配置的 recording rules 定期对抓取到的指标数据进行评估,将结果以 TSDB 格式分块存储到本地,每个数据块的存储时长为2小时,且默认禁用了压缩功能。

  • 然后 sidecar 嗅探到 Prometheus 的数据存储目录生成了新的只读数据块时,会将该数据块上传到对象存储桶中做为长期历史数据保存,在上传时会将数据块中的 meta.json 进行修改添加 thanos 相关的字段,如 external_labels

chunk_format.png

storage.png

  • rule 根据所配置的 recording rules 定期地向 query 发起查询获取评估所需的指标值,并将结果以 TSDB格式分块存储到本地。每个数据块的存储时长为2小时,且默认禁用了压缩功能,每个数据块的 meta.json 也附带了 thanos 拓展的 external_lables 字段。当本地生成了新的只读数据块时,其自身会将该数据块上传到远端对象存储桶中做为长期历史数据保存。

  • compact 定期将对象存储中地数据块进行压缩和降准采样,进行压缩时数据块中的 truck 会进行合并,对应的 meta.json 中的 level 也会一同增长,每次压缩累加1,初始值为1。在进行降准采样时会创建新的数据块,根据采样步长从原有的数据块中抽取值存储到新的数据块中,在 meta.json 中记录 resolution 为采样步长。 compact.png

读取指标的流程为:

  • 首先客户端通过 query APIquery 发起查询, query 将请求转换成 StoreAPI 发送到其他的 querysidecarrulestore 上。

  • sidecar 接收到来自于 query 发起的查询请求后将其转换成 query API 请求,发送给其绑定的 Prometheus,由Prometheus 从本地读取数据并响应,返回短期的本地采集和评估数据。 thanos-query.jpg

  • rule 接收到来自于 query 发起的查询请求后直接从本地读取数据并响应,返回短期的本地评估数据。

rule.jpg

  • store 接收到来自于 query 发起的查询请求后首先从对象存储桶中遍历数据块的 meta.json,根据其中记录的时间范围和标签先进行一次过滤。接下来从对象存储桶中读取数据块的 indexchunks 进行查询,部分查询频率较高的 index 会被缓存下来,下次查询使用到时可以直接读取。最终返回长期的历史采集和评估指标。

对于发送报警的流程如下所示:

  • Prometheus 根据自身配置的 alerting 规则定期地对自身采集的指标进行评估,当告警条件满足的情况下发起告警到 Alertmanager 上。

  • rule 根据自身配置的 alerting 规则定期的向 query 发起查询请求获取评估所需的指标,当告警条件满足的情况下发起告警到 Alertmanager 上。

  • Alertmanager 接收到来自于 Prometheus 和 rule 的告警消息后进行分组合并后发出告警通知。

VictoriaMetrics

VictoriaMetrics是一个快速、经济、可扩展的监控解决方案和时间序列数据库。它可以用作Prometheus的长期远程存储。 对于每秒摄取率低于一百万数据点的情况,官方建议使用单节点版本而不是集群版本。单节点版本可以根据CPU内核、RAM和可用存储空间的数量完美地扩展。与集群版本相比,单节点版本更容易配置和操作,所以在坚持使用集群版本之前要三思。

主要特性

  • 单节点版本也支持所有功能
  • 性能和容量水平扩展
  • 支持时间序列数据的多个独立名称空间(也称为多租户)
  • 支持多副本

架构

VictoriaMetrics集群版主要包括如下服务:

  • vmstorage - 存储数据
  • vminsert - 接受远程写入数据的请求,使用一致性hash将发送的数据分布到可用的vmstorage节点上
  • vmselect - 从 vmstorage 节点获取并聚合所需数据,返回给查询数据的客户端

每个服务可以独立扩展,并且可以在最合适的硬件上运行。vmstorage多副本彼此独立,不互相连接,不分享数据。这增强了集群可用性,简化了集群维护和集群扩展。 victoriametrics.png

多租户

VictoriaMetrics 集群模式支持多租户(namespace),租户以accountIDaccountID:projectID作为唯一标识。

  • 在将第一个数据点写入给定租户时,将自动创建租户。
  • 所有租户的数据均匀分布在可用的vmstorage节点上。这保证了当不同租户拥有不同的数据量和不同的查询负载时,vmstorage节点之间的负载是均匀的。
  • VictoriaMetrics不支持在一个请求中查询多租户的数据。

集群部署

最小集群必须包含以下节点:

  • a single vmstorage node with -retentionPeriod and -storageDataPath flags
  • a single vminsert node with -storageNode=<vmstorage_host>:8400
  • a single vmselect node with -storageNode=<vmstorage_host>:8401

为了高可用的目标推荐每个服务至少运行两个节点,类似于nginx这样的http负载均衡器必须放在vminsert和vmselect节点的前面:

  • requests starting with /insert must be routed to port 8480 on vminsert nodes.
  • requests starting with /select must be routed to port 8481 on vmselect nodes.

如果运行在k8s环境中,可以通过deployment和service配合部署实现负载均衡

VictoriaMetrics 自身监控

所有的集群组件都通/metrics接口提供多样的Prometheus格式数据,下面是这些服务监控接口默认监听的端口:

  • vminsert - 8480
  • vmselect - 8481
  • vmstorage - 8482

VictoriaMetrics Tools

vmagent

vmagent 是一个小型但强大的代理,它帮助您从各种来源收集指标,并将它们存储在victoria ametrics或任何其他支持remote_write协议的兼容prometheus存储系统中。同时兼容Prometheus discovery模块,可以完全替代Prometheus,用作数据采集功能。实现采集组件无状态。

vmagent.png

部署方法
/path/to/vmagent -promscrape.config=/path/to/prometheus.yml -remoteWrite.url=https://victoria-metrics-host:8428/api/v1/write
热更新配置文件
# 发送信号
kill -SIGHUP `pidof vmagent`
# 调用接口
curl -X POST http://vmagent:8429/-/reload

同时也提供定期刷新配置的选项-promscrape.configCheckInterval

复制以及高可用

vmagent通过配置多个-remoteWrite实现将数据推送到不同的storage集群,此外通过配置-remoteWrite.tmpDataPath,当storage组件不可用时vmagent会将采集到的数据存储到指定路径,等待storage可用时再次推送未发送的数据避免数据丢失。

vmalert

用于执行告警判断或数据聚合的组件,实现与Prometheus 告警部分相同的功能

特性

  • 与VictoriaMetrics TDSB集成
  • 支持VictoriaMetrics MetricsQL和表达式校验
  • 兼容Prometheus警告规则格式
  • 可以与Alertmanager集成
  • 告警状态持久化到时序数据库中,可以保障重启不丢失状态,相关介绍请点击
  • 轻量级,没有额外依赖

启动方法:

./bin/vmalert -rule=alert.rules \
    -datasource.url=http://localhost:8428 \  # PromQL compatible datasource
    -notifier.url=http://localhost:9093 \    # AlertManager URL
    -notifier.url=http://127.0.0.1:9093 \    # AlertManager replica URL
    -remoteWrite.url=http://localhost:8428 \ # remote write compatible storage to persist rules and alerts state
    -remoteRead.url=http://localhost:8428 \  # PromQL compatible datasource to restore alerts state from
    -external.label=cluster=east-1 \         # External label to be applied for each rule
    -external.label=replica=a                # Multiple external labels may be set
vmbackup

vmbackup从即时快照创建victoriametrics数据备份。

支持一下几种备份存储系统:

  • GCS. Example: gcs://<bucket>/<path/to/backup>
  • S3. Example: s3://<bucket>/<path/to/backup>
  • 任意兼容s3接口的存储,例如 MinIO, Ceph or Swift. 点击查看更多详情。
  • 本地文件系统. Example: fs://</absolute/path/to/backup>

vmbackup支持增量备份和全量备份。如果目标路径已经包含来自前一个备份的数据,则自动创建增量备份。如果目标路径已包含先前备份的数据,则会自动创建增量备份。 可以使用-origin指向同一远程存储上已经存在的备份来加快完整备份的速度。 在这种情况下,vmbackup会在服务器端复制现有备份和新备份之间的共享数据。 这样可以节省时间和数据传输成本。

备份过程可以随时中断。使用相同的参数重新启动vmbackup时,它将自动从中断点恢复。

备份的数据可以使用vmrestore组件恢复

vmrestore

vmrestore 使用vmbackup创建的备份数据中恢复数据,恢复进程可以在任何时候中断。当使用相同的参数重新启动vmrestore时,它会自动从中断点恢复。

使用方法:

数据恢复过程中 VictoriaMetrics服务必须停止

vmrestore -src=fs:///path/to/local/backup/dir -storageDataPath=<local/path/to/restore>
  • fs:///path/to/local/backup/dir 是备份数据的存放目录
  • <local/path/to/restore>这个是数据恢复生成的数据的存放目录,需要与VictoriaMetric启动参数-storageDataPath相同
vmbackupmanager

此服务可自动执行常规备份过程。 它支持以下备份间隔:每小时,每天,每周和每月。 可以同时配置多个备份间隔。 比如,备份管理器每小时创建一次每小时备份,而每天创建一次每日备份,等等。备份管理器必须具有对存储数据的读取访问权限,因此最佳实践是将其安装在与存储设备相同的计算机上(或作为sidecar)。 备份服务每小时进行一次备份,并将其放置到最新文件夹中,然后将数据复制到代表备份间隔(每小时,每天,每周和每月)的文件夹中。

以下是运行时所需要的常用参数:

  • -eula -设置为true 意味着拥有备份数据的权利。
  • -storageDataPath - VictoriaMetrics数据存放的目录
  • -snapshot.createURL - 需要备份数据时调用VictoriaMetrics 创建快照的接口.比如http://victoriametrics:8428/snapshot/create
  • -dst - 备份数据的存放地 s3、gcs、本地文件系统
  • -credsFilePath - 存放s3或gcs认证凭证的目录

备份策略通过以下参数:

  • -disableHourly - disable hourly run. Default false
  • -disableDaily - disable daily run. Default false
  • -disableWeekly - disable weekly run. Default false
  • -disableMonthly - disable monthly run. Default false

默认情况下,所有级别的备份都是开启的。backupmanager会在 -dst指定的目录下创建下面这些目录:

  • /latest/ - contains the latest backup
  • /hourly/ - contains hourly backups. Each backup is named as YYYY-MM-DD:HH
  • /daily/ - contains daily backups. Each backup is named as YYYY-MM-DD
  • /weekly/ - contains weekly backups. Each backup is named as YYYY-WW
  • /monthly/ - contains monthly backups. Each backup is named as YYYY-MM

backupmanager 每次运行都会创建全量备份,这意味着这意味着可以使用vmrestore从任何特定的备份中完全恢复系统。backupmanager 运行中默认使用增量更新,仅备份最近备份数据之后发生改变的数据。

以下两个参数适用于性能调整:

  • -maxBytesPerSecond - 如果使用网络存储,可以控制最大上传带宽。避免完全占用网络出口带宽。
  • -concurrency - 并行的worker数量。

备份数据保留策略:

  • -keepLastHourly - keep the last N hourly backups. Disabled by default

  • -keepLastDaily - keep the last N daily backups. Disabled by default

  • -keepLastWeekly - keep the last N weekly backups. Disabled by default

  • -keepLastMonthly - keep the last N monthly backups. Disabled by default