新一代云原生监控系统Prometheus--理解数据模型/指标/标签/PromQL/Exporter

1. Prometheus 简介

Promethues与Kubernetes有着十分相似的历程,均是源自Google内部多年的运维经验。Prometheus 于 2016 年 5 月加入 CNCF 基金会,成为继 Kubernetes 之后的第二个 CNCF 托管项目。Kubernetes和Promethues分别代表了云原生模式下容器编排以及监控的事实标准。

1.1 常用监控系统的不足

对于Nagios、Zabbix这类常用监控系统而言,其核心是采用了测试和告警(check&alert)的监控系统模型。 往往存在以下问题:

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

1.2 Prometheus的优势

相比于传统监控系统Prometheus具有以下优点:

  1. 监控服务的内部运行状态
    Pometheus鼓励用户监控服务的内部状态,基于Prometheus丰富的Client库,用户可以轻松的在应用程序中添加对Prometheus的支持,从而让用户可以获取服务和应用内部真正的运行状态。

  2. 易于管理
    Prometheus核心部分只有一个单独的二进制文件,不存在任何的第三方依赖(数据库,缓存等等)。唯一需要的就是本地磁盘,因此不会有潜在级联故障的风险。

  3. 强大的数据模型
    所有采集的监控数据均以指标(metric)的形式保存在内置的时间序列数据库当中(TSDB)。

  4. 强大的查询语言PromQL
    Prometheus内置了一个强大的数据查询语言PromQL。 通过PromQL可以实现对监控数据的查询、聚合。同时PromQL也被应用于数据可视化(如Grafana)以及告警当中。
    通过PromQL可以轻松回答类似于以下问题:在过去一段时间中95%应用延迟时间的分布范围?CPU占用率前5位的服务有哪些?

  5. 高效
    对于监控系统而言,大量的监控任务必然导致有大量的数据产生。而Prometheus可以高效地处理这些数据,对于单一Prometheus Server实例而言它可以处理:数以百万的监控指标/每秒处理数十万的数据点。

  6. 易于集成
    使用Prometheus可以快速搭建监控服务,并且可以非常方便地在应用程序中进行集成。目前支持: Java, JMX, Python, Go,Ruby, .Net, Node.js等等语言的客户端SDK。
    同时Prometheus还支持与其他的监控系统进行集成:Graphite, Statsd, Collected, Scollector, muini, Nagios等。
    Prometheus社区还提供了大量第三方实现的监控数据采集支持:JMX, CloudWatch, EC2, MySQL, PostgresSQL, Haskell, Bash, SNMP, Consul, Haproxy, Mesos, Bind, CouchDB, Django, Memcached, RabbitMQ, Redis, RethinkDB, Rsyslog等等。

  7. 可视化
    Prometheus Server中自带了一个Prometheus UI,通过这个UI可以方便地直接对数据进行查询,并且支持直接以图形化的形式展示数据。

2. 概念理解

2.1 数据模型

Prometheus通过指标名称(metrics name)以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而label则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤,聚合,统计从而产生新的计算后的一条时间序列。

指标
每一条时间序列由指标名称(Metrics Name)以及一组标签(键值对)唯一标识。其中指标的名称(metric name)可以反映被监控样本的含义(例如,http_requests_total — 表示当前系统接收到的 HTTP 请求总量)。

标签
通过使用标签,Prometheus 开启了强大的多维数据模型:对于相同的指标名称,通过不同标签列表的集合,会形成特定的度量维度实例(例如:所有包含度量名称为 /api/tracks 的 http 请求,打上 method=POST 的标签,就会形成具体的 http 请求)

样本
在时间序列中的每一个点称为一个样本(sample),样本由以下三部分组成:

  • 指标(metric):指标名称和描述当前样本特征的 labelsets;
  • 时间戳(timestamp):一个精确到毫秒的时间戳;
  • 样本值(value): 一个 folat64 的浮点型数据表示当前样本的值。

表示方式
例如,指标名称为 api_http_requests_total,标签为 method=“POST” 和 handler="/messages" 的时间序列可以表示为:

api_http_requests_total{method="POST", handler="/messages"}

2.2 指标类型

Prometheus 的客户端库中提供了四种核心的指标类型。但这些类型只是在客户端库(客户端可以根据不同的数据类型调用不同的 API 接口)和在线协议中,实际在 Prometheus server 中并不对指标类型进行区分,而是简单地把这些指标统一视为无类型的时间序列。

Counter(计数器)
Counter 类型代表一种样本数据单调递增的指标,即只增不减,除非监控系统发生了重置。例如,你可以使用 counter 类型的指标来表示服务的请求数、已完成的任务数、错误发生的次数等。

Gauge(仪表盘)
Gauge 类型代表一种样本数据可以任意变化的指标,即可增可减。Gauge 通常用于像温度或者内存使用率这种指标数据,也可以表示能随时增加或减少的“总数”,例如:当前并发请求的数量。

Histogram(直方图)
Histogram 在一段时间范围内对数据进行采样(通常是请求持续时间或响应大小等),并将其计入可配置的存储桶(bucket)中,后续可通过指定区间筛选样本,也可以统计样本总数,最后一般将数据展示为直方图。

Summary(摘要)
与 Histogram 类型类似,用于表示一段时间内的数据采样结果(通常是请求持续时间或响应大小等),但它直接存储了分位数(通过客户端计算,然后展示出来),而不是通过区间来计算。

2.3 PromQL

PromQL是Prometheus内置的数据查询语言,其提供对时间序列数据丰富的查询,聚合以及逻辑运算能力的支持。

例如,如果我们只需要查询所有http_requests_total时间序列中满足标签instance为localhost:9090的时间序列,则可以使用如下表达式:

http_requests_total{instance="localhost:9090"}

反之使用instance!="localhost:9090"则可以排除这些时间序列:

http_requests_total{instance!="localhost:9090"}

2.4 Exporter

广义上讲所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter。而Exporter的一个实例称为target,如下所示,Prometheus通过轮询的方式定期从这些target中获取样本数据:
prometheus exporter
Prometheus社区提供了丰富的Exporter实现,涵盖了从基础设施,中间件以及网络等各个方面的监控功能。

除了直接使用社区提供的Exporter程序以外,用户还可以基于Prometheus提供的Client Library创建自己的Exporter程序。

所有的Exporter程序都需要按照Prometheus的规范,返回监控的样本数据。以Node Exporter为例,当访问/metrics地址时会返回以下内容:

# 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

需要特别注意的是对于histogram和summary类型的样本。需要按照以下约定返回样本数据:

# A histogram, which has a pretty complex representation in the text format:
# HELP http_request_duration_seconds A histogram of the request duration.
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.05"} 24054
http_request_duration_seconds_bucket{le="0.1"} 33444
http_request_duration_seconds_bucket{le="0.2"} 100392
http_request_duration_seconds_bucket{le="+Inf"} 144320
http_request_duration_seconds_sum 53423
http_request_duration_seconds_count 144320

# Finally a summary, which has a complex representation, too:
# HELP rpc_duration_seconds A summary of the RPC duration in seconds.
# TYPE rpc_duration_seconds summary
rpc_duration_seconds{quantile="0.01"} 3102
rpc_duration_seconds{quantile="0.05"} 3272
rpc_duration_seconds{quantile="0.5"} 4773
rpc_duration_seconds_sum 1.7560473e+07
rpc_duration_seconds_count 2693

3. 通过Prometheus监控Kubernetes

3.1 Kubernetes应用管理模型

在这里插入图片描述
Pod
Pod是Kubernetes中的最小调度资源。Pod中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能。对于这组容器而言它们共享相同的网络和存储资源,因此它们之间可以直接通过本地网络(127.0.0.1)进行访问。当Pod被创建时,调度器(kube-schedule)会从集群中找到满足条件的节点运行它。

Controller
如果部署应用程序时,需要启动多个实例(副本),则需要使用到控制器(Controller)。用户可以在Controller定义Pod的调度规则、运行的副本数量以及升级策略等等信息,当某些Pod发生故障之后,Controller会尝试自动修复,直到Pod的运行状态满足Controller中定义的预期状态为止。Kubernetes中提供了多种Controller的实现,包括:Deployment(无状态应用)、StatefulSet(有状态应用)、Daemonset(守护模式)等,以支持不同类型应用的部署和调度模式。

通过Controller和Pod我们定义了应用程序是如何运行的,接下来需要解决如何使用这些部署在Kubernetes集群中的应用。Kubernetes将这一问题划分为两个问题域,第一,集群内的应用如何通信。第二,外部的用户如何访问部署在集群内的应用?

Service
对于第一个问题,在Kubernetes中通过定义Service(服务)来解决。Service在Kubernetes集群内扮演了服务发现和负载均衡的作用。在Kubernetes下部署的Pod实例都会包含一组描述自身信息的Lable,而创建Service,可以声明一个Selector(标签选择器)。Service通过Selector,找到匹配标签规则的Pod实例,并将对Service的请求转发到代理的Pod中。Service创建完成后,集群内的应用就可以通过使用Service的名称作为DNS域名进行相互访问。

Ingress
而对于第二个问题,Kubernetes中定义了单独的资源Ingress(入口)。Ingress是一个工作在7层的负载均衡器,其负责代理外部进入集群内的请求,并将流量转发到对应的服务中。

Namespace
最后,对于同一个Kubernetes集群其可能被多个组织使用,为了隔离这些不同组织创建的应用程序,Kubernetes定义了Namespace(命名空间)对资源进行隔离。

3.2 Kubernetes监控策略

Kubernetes作为开源的容器编排工具,为用户提供了一个可以统一调度,统一管理的云操作系统。其解决如用户应用程序如何运行的问题。而一旦在生产环境中大量基于Kubernetes部署和管理应用程序后,作为系统管理员,还需要充分了解应用程序以及Kubernetes集群服务运行质量如何,通过对应用以及集群运行状态数据的收集和分析,持续优化和改进,从而提供一个安全可靠的生产运行环境。

从物理结构上讲Kubernetes主要用于整合和管理底层的基础设施资源,对外提供应用容器的自动化部署和管理能力,这些基础设施可能是物理机、虚拟机、云主机等等。因此,基础资源的使用直接影响当前集群的容量和应用的状态。在这部分,我们需要关注集群中各个节点的主机负载,CPU使用率、内存使用率、存储空间以及网络吞吐等监控指标。

从自身架构上讲,kube-apiserver是Kubernetes提供所有服务的入口,无论是外部的客户端还是集群内部的组件都直接与kube-apiserver进行通讯。因此,kube-apiserver的并发和吞吐量直接决定了集群性能的好坏。

其次,对于外部用户而言,Kubernetes是否能够快速的完成pod的调度以及启动,是影响其使用体验的关键因素。而这个过程主要由kube-scheduler负责完成调度工作,而kubelet完成pod的创建和启动工作。因此在Kubernetes集群本身我们需要评价其自身的服务质量,主要关注在Kubernetes的API响应时间,以及Pod的启动时间等指标上。

Kubernetes的最终目标还是需要为业务服务,因此我们还需要能够监控应用容器的资源使用情况。对于内置了对Prometheus支持的应用程序,也要支持从这些应用程序中采集内部的监控指标。最后,结合黑盒监控模式,对集群中部署的服务进行探测,从而当应用发生故障后,能够快速处理和恢复。

综上所述,我们需要综合使用白盒监控和黑盒监控模式,建立从基础设施,Kubernetes核心组件,应用容器等全面的监控体系。

在白盒监控层面我们需要关注:

  • 基础设施层(Node):为整个集群和应用提供运行时资源,需要通过各节点的kubelet获取节点的基本状态,同时通过在节点上部署Node Exporter获取节点的资源使用情况;
  • 容器基础设施(Container):为应用提供运行时环境,Kubelet内置了对cAdvisor的支持,用户可以直接通过Kubelet组件获取给节点上容器相关监控指标;
  • 用户应用(Pod):Pod中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能。如果用户部署的应用程序内置了对Prometheus的支持,那么我们还应该采集这些Pod暴露的监控指标;
  • Kubernetes组件:获取并监控Kubernetes核心组件的运行状态,确保平台自身的稳定运行。

而在黑盒监控层面,则主要需要关注以下:

  • 内部服务负载均衡(Service):在集群内,通过Service在集群暴露应用功能,集群内应用和应用之间访问时提供内部的负载均衡。通过Blackbox Exporter探测Service的可用性,确保当Service不可用时能够快速得到告警通知;
  • 外部访问入口(Ingress):通过Ingress提供集群外的访问入口,从而可以使外部客户端能够访问到部署在Kubernetes集群内的服务。因此也需要通过Blackbox Exporter对Ingress的可用性进行探测,确保外部用户能够正常访问集群内的功能;

参考

Prometheus 中文文档
prometheus-book

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值