关于腾讯云:如何用Prometheus监控十万container的Kubernetes集群

4次阅读

共计 10175 个字符,预计需要花费 26 分钟才能阅读完成。

概述

不久前,咱们在文章《如何扩大单个 Prometheus 实现近万 Kubernetes 集群监控?》中具体介绍了 TKE 团队大规模 Kubernetes 联邦监控零碎 Kvass 的演进过程,其中介绍了针对规模较大的集群,咱们是如何通过批改 Prometheus 代码来实现横向扩缩容的。通过计划上的改良,Kvass 目前曾经反对以 Sidecar 的形式实现 Prometheus 集群化,而不是批改 Prometheus 代码。因为计划对社区有肯定价值,团队决定将我的项目开源进去,分享给社区。我的项目地址

本文首先将给出 Prometheus 的单机性能瓶颈,以及现有的社区集群化计划,随后将具体介绍开源版 Kvass 的设计思维,应用案例及压测后果。

另外,腾讯云容器团队在 Kvass 的设计思维上进一步优化,构建了反对多集群的高性能云原生监控服务,产品目前已正式公测,欢送读者试用。传送门: https://console.cloud.tencent…

后续章节咱们也将间接应用该产品来展现 Kvass 对大规模集群的监控能力。

Prometheus

Prometheus 依附其强劲的单机性能,灵便的 PromSQL,沉闷的社区生态,逐步成为云原生时代最外围的监控组件,被寰球各大产商用于监控他们的外围业务。

然而,面对大规模监控指标(数千万 series)时,因为原生 Prometheus 只有单机版本,不提供集群化性能,开发人员不得不通过一直减少机器的配置来满足 Prometheus 一直上涨的内存。

单机性能瓶颈

咱们对单机 Prometheus 进行的压测,用以探测单个 Prometheus 分片的正当负载,压测的指标有两个。

  • 确定 target 数目对 Prometheus 负载的关系
  • 确定 series 数目和 Prometheus 负载的关系

target 相关性

咱们放弃总 series 为 100 万不变,通过扭转 target 个数,察看 Prometheus 负载变动。

压测后果

target 数量 CPU (core) mem (GB)
100 0.17 4.6
500 0.19 4.2
1000 0.16 3.9
5000 0.3 4.6
  • 从表中咱们发现 target 数目的改变对 Prometheus 负载的影响并不是强相干的。在 target 数目增长 50 倍的状况下,CPU 耗费有小量增长,然而内存简直不变。

series 相关性

咱们放弃 target 数目不变,通过扭转总 series 数,察看 Prometheus 的负载变动。

压测后果

series 数量 (万) CPU (core) mem (GB) 查问 1000 series 15m 数据 (s)
100 0.191 3.15 0.2
300 0.939 20.14 1.6
500 2.026 30.57 1.5
  • 从表中,Prometheus 的负载受到 series 的影响较大,series 越多,资源耗费越大。
  • 当 series 数据超过 300 万时,Prometheus 内存增长较为显著,须要应用较大内存的机器来运行。

压测过程中,咱们应用了工具去生成预期数目的 series,工具生成的 series 每个 label 的长度及值的长度都较小,固定为 10 个字符左右。咱们的目标是察看绝对负载变动,理论生产中因为 label 长度不同,服务发现机制的耗费不同,雷同的 series 数目所耗费的负载会比压测中高不少。

现有集群化计划

针对单机 Prometheus 在大规模数据监控时的性能瓶颈问题,社区目前曾经存在一些分片化计划,次要包含以下几种。

hash_mod

Prometheus 官网反对通过 Relabel 机制,在配置文件中,对采集上来的数据进行 hash,通过在不同 Prometheus 实例的配置文件中指定不同的 moduleID 来进行分片化,而后通过联邦,Thanos 等形式将数据进行对立汇总,如下图所示,读者也能够间接参考【官网文档】。

配置文件宰割

还有一种办法是依据业务进行 job 层面的宰割,不同 Prometheus 应用齐全独立的采集配置,其中蕴含了不同的 job,。

上述计划存在的问题

无论是 hash_mod 的形式,还是配置文件宰割的形式,其本质都是将数据切分到多个采集配置中,由不同 Prometheus 进行采集。两者都存在以下几个毛病。

  • 对预监控数据要有所理解: 应用上述办法的前提是使用者必须对监控对象会上报的数据有所理解,例如必须晓得监控对象会上报某个用于 hash_mod 的 label,或者必须晓得不同 job 的整体规模,能力对 job 进行划分。
  • 实例负载不平衡: 尽管上述计划预期都是心愿将数据打散到不同 Prometheus 实例上,但实际上通过某些 label 的值进行 hash_mod 的,或者罗唆按 job 进行划分的形式并不能保障每个实例最终所采集的 series 数是平衡的,实例仍旧存在内存占用过高的危险。
  • 配置文件有侵入: 使用者必须对原配置文件进行革新,退出 Relabel 相干配置,或者将一份配置文件划分成多份,因为配置文件不再繁多,新增,批改配置难度大大增加。
  • 无奈动静扩缩容: 上述计划中的因为配置是依据理论监控指标的数据规模来非凡制订的,并没有一种对立的扩缩容计划,能够在数据规模增长时减少 Prometheus 个数。当然,用户如果针对本人业务理论状况编写扩缩容的工具的确是能够的,然而这种形式并不能在不同业务间复用。
  • 局部 API 不再失常: 上述计划将数据打散到了不同实例中,而后通过联邦或者 Thanos 进行汇总,失去全局监控数据,然而在不额定解决的状况下会导致局部 Prometheus 原生 API 无奈失去正确的值,最典型的是 /api/v1/targets,上述计划下无奈失去全局 targets 值。

Kvass 的原理

设计指标

针对上述问题,咱们心愿设计一种无侵入的集群化计划,它对使用者体现进去的,是一个与原生 Prometheus 配置文件统一,API 兼容,可扩缩容的虚构 Prometheus。具体而言,咱们有以下设计指标。

  • 无侵入,单配置文件: 咱们心愿使用者看到的,批改的都是一份原生的配置文件,不必加任何非凡的配置。
  • 无需感知监控对象 :咱们心愿使用者不再须要事后理解采集对象,不参加集群化的过程。
  • 实例负载尽可能平衡: 咱们心愿能依据监控指标的理论负载来划分采集工作,让实例尽可能平衡。
  • 动静扩缩容: 咱们心愿零碎可能依据采集对象规模的变动进行动静扩缩容,过程中数据一直点,不缺失。
  • 兼容外围 PrometheusAPI: 咱们心愿一些较为外围的 API,如上边提到的 /api/v1/target 接口是失常的。

架构

Kvass 由多个组件形成,下图给出了 Kvass 的架构图,咱们在架构图中应用了 Thanos,实际上 Kvass 并不强依赖于 Thanos,能够换成其余 TSDB。

  • Kvass sidecar: 用于接管 Coordinator 下发的采集工作,生成新的配置文件给 Prometheus,也服务保护 target 负载状况。
  • Kvass coordinator: 该组件是集群的核心控制器,负责服务发现,负载探测,targets 下发等。
  • Thanos 组件: 图中只应用了 Thanos sidecar 与 Thanos query,用于对分片的数据进行汇总,失去对立的数据视图。

Coordinator

Kvass coordinaor 首先会代替 Prometheus 对采集指标做服务发现,实时取得须要采集的 target 列表。

针对这些 target,Kvass coordinaor 会负责对其做负载探测,评估每个 target 的 series 数,一旦 target 负载被探测胜利,Kvass coordinaor 就会在下个计算周期将 target 调配给某个负载在阈值以下的分片。

Kvass coordinaor 还负责对分片集群做扩缩容。

服务发现

Kvass coordinaor 援用了原生 Prometheus 的服务发现代码,用于实现与 Prometheus 100% 兼容的服务发现能力,针对服务发现失去的待抓取 targets,Coordinaor 会对其利用配置文件中的 relabel_configs 进行解决,失去解决之后的 targets 及其 label 汇合。服务发现后失去的 target 被送往负载探测模块进行负载探测。

负载探测

负载探测模块从服务发现模块取得解决之后的 targets,联合配置文件中的抓取配置(如 proxy,证书等)对指标进行抓取,随后解析计算抓取后果,取得 target 的 series 规模。

负载探测模块并不存储任何抓取到的指标数据,只记录 target 的负载,负载探测只对 target 探测一次,不保护后续 target 的负载变动,长期运行的 target 的负载信息由 Sidecar 保护,咱们将在前面章节介绍。

target 调配与扩容

在 Prometheus 单机性能瓶颈那一节,咱们介绍过 Prometheus 的内存和 series 相干,确切来说,Prometheus 的内存和其 head series 间接相干。Prometheus 会将最近(默认为 2 小时)采集到的数据的 series 信息缓存在内存中,咱们如果能管制好每个分片内存中 head series 的数目,就能无效管制每个分片的内存使用量,而管制 head series 理论就是管制分片以后采集的 target 列表。

基于上边的思路,Kvass coordinaor 会周期性的对每个分片以后采集的 target 列表进行治理:调配新 target,删除有效 target。

在每个周期,Coordinaor 会首先从所有分片取得以后运行状态,其中包含分片以后内存中的 series 数目及以后正在抓取的 target 列表。随后针对从服务发现模块失去的全局 target 信息进行以下解决

  • 如果该 target 曾经被某个分片抓取,则持续调配给他,分片的 series 数不变。
  • 如果该 target 没有任何分片抓取,则从负载探测模块取得其 series(如果还未探测完则跳过,下个周期持续),从分片中挑一个目前内存中 series 加上该 target 的 series 后仍然比阈值低的,调配给他。
  • 如果以后所有分片没法包容所有待调配的 targets,则进行扩容,扩容数量与全局 series 总量成正比。

target 迁徙和缩容

在零碎运行过程中,target 有可能会被删除,如果某个分片的 target 被删除且超过 2 小时,则该分片中的 head series 就会升高,也就是呈现了局部闲暇,因为 target 调配到了不同分片,如果有大量 target 被删除,则会呈现很多分片的内存占用都很低的状况,这种状况下,零碎的资源利用率很低,咱们须要对系统进行缩容。

当呈现这种情时,Coordinaor 会对 target 进行迁徙,行将序号更大的分片(分片会从 0 进行编号)中的 target 转移到序号更低的分片中,最终让序号低的分片负载变高,让序号高的分片齐全闲暇进去。如果存储应用了 thanos,并会将数据存储到 cos 中,则闲暇分片在通过 2 小时候会删除(确保数据已被传到 cos 中)。

多正本

Kvass 的分片以后只反对以 StatefulSet 形式部署。

Coordinator 将通过 label selector 来取得所有分片 StatefulSet,每个 StatefulSet 被认为是一个正本,StatefulSet 中编号雷同的 Pod 会被认为是同一个分片组,雷同分片组的 Pod 将被调配雷同的 target 并预期有雷同的负载。

/api/v1/targets 接口

上文提到 Coordinator 依据配置文件做了服务发现,失去了 target 列表,所以 Coordinator 实际上能够失去 /api/v1/targets 接口所须要的返回后果汇合,然而因为 Coordinator 只做了服务发现,并不进行理论采集,所以 target 的采集状态(例如衰弱状态,上一次采集工夫等)都无奈间接得悉。

当 Coordinator 接管到 /api/v1/targets 申请时,他会基于服务发现失去的 target 汇合,联合向 Sidecar(如果 target 已调配)或向探测模块(target 还未调配)询问 target 采集状态,综合后将正确的 /api/v1/targets 后果返回。

Sidecar

上一节介绍了 Kvass coordinaor 的基本功能,要想零碎失常运行,还须要 Kvass sidecar 的配合,其核心思想是将配置文件中所有服务发现模式全副改成 static_configs 并间接将曾经 relabel 过的 target 信息写入配置中,来达到打消分片服务发现和 relabel 行为,只采集局部 target 的成果。

每个分片都会有一个 Kvass sidecar,其外围性能包含从 Kvass coordinator 承受本分片负责的 target 列表,生成新的配置文件给该分片的 Prometheus 应用。另外,Kvass sidecar 还会劫持抓取申请,保护 target 最新负载。Kvass sidecar 还作为 PrometheusAPI 的网关,修改局部申请后果。

配置文件生成

Coordinaor 通过服务发现,relabel 及负载探测后,会将 target 调配给某个分片,并将 target 信息下发给 Sidecar,包含

  • target 的地址,
  • target 预估的 series 值
  • target 的 hash 值
  • 解决完 relabel 之后的 label 汇合。

Sidecar 依据从 Coordinator 失去的 target 信息,联合原始配置文件,生成一个新的配置文件给 Prometheus 应用,这个新的配置文件做了如下改变。

  • 将所有服务发现机制改为 static_configs 模式,并间接写入 target 列表,每个 target 蕴含通过 relabel 之后的 label 值
  • 因为当初 target 曾经 relabel 过了,所以删除 job 配置中的 relabel_configs 项,然而仍旧保留 metrics_rebale_configs
  • 将 target 的 label 中的 scheme 字段全副替换成 http,并将原 schme 以申请参数的模式退出到 label 汇合中
  • 将 target 的 job_name 以申请参数的模式退出到 label 汇合中 * 注入 proxy_url 将所有抓取申请代理到 Sidecar

咱们来看一个例子,如果原来的配置是一个 kubelet 的采集配置

global:
  evaluation_interval: 30s
  scrape_interval: 15s
scrape_configs:
- job_name: kubelet
  honor_timestamps: true
  metrics_path: /metrics
  scheme: https
  kubernetes_sd_configs:
  - role: node
  bearer_token: xxx
  tls_config:
    insecure_skip_verify: true
  relabel_configs:
  - separator: ;
    regex: __meta_kubernetes_node_label_(.+)
    replacement: $1
    action: labelmap

通过注入将生成一个新的配置文件

global:
  evaluation_interval: 30s
  scrape_interval: 15s
scrape_configs:
- job_name: kubelet                                        
  honor_timestamps: true                                                                      
  metrics_path: /metrics                                   
  scheme: https  
  proxy_url: http://127.0.0.1:8008 # 所有抓取申请代理到 Sidecar
  static_configs:                                          
  - targets:                                               
    - 111.111.111.111:10250                                   
    labels:                                                
      __address__: 111.111.111.111:10250                      
      __metrics_path__: /metrics                           
      __param__hash: "15696628886240206341"                
      __param__jobName: kubelet                            
      __param__scheme: https  # 保留原始的 scheme                             
      __scheme__: http        # 设置新的 scheme,这将使得代理到 Sidecar 的抓取申请都是 http 申请
      # 以下是通过 relabel_configs 解决之后失去的 label 汇合
      beta_kubernetes_io_arch: amd64                       
      beta_kubernetes_io_instance_type: QCLOUD             
      beta_kubernetes_io_os: linux                         
      cloud_tencent_com_auto_scaling_group_id: asg-b4pwdxq5
      cloud_tencent_com_node_instance_id: ins-q0toknxf     
      failure_domain_beta_kubernetes_io_region: sh         
      failure_domain_beta_kubernetes_io_zone: "200003"     
      instance: 172.18.1.106                               
      job: kubelet                                         
      kubernetes_io_arch: amd64                            
      kubernetes_io_hostname: 172.18.1.106                 
      kubernetes_io_os: linux

上边新生成的配置文件是 Prometheus 真正应用的配置文件,Sidecar 通过 Coordinator 下发的 target 列表来生成配置,就能够让 Prometheus 有选择性得进行采集。

抓取劫持

在上边的配置生成中,咱们会将 proxy 注入到 job 的配置中,并且 target 的 label 中,scheme 会被设置成 http,所以 Prometheus 所有的抓取申请都会被代理到 Sidecar,之所以要这么做,是因为 Sidecar 须要保护每个 target 新的 series 规模,用于 Coordinator 查阅后作为 target 迁徙的参考。

从上边配置生成咱们能够看到,有以下几个额定的申请参数会被一并发送到 Sidecar

  • hash:target 的 hash 值,用于 Sidecar 辨认是哪个 target 的抓取申请,hash 值由 Coordinator 依据 target 的 label 汇合进行计算取得并传递给 Sidecar。
  • jobName:是哪个 job 下的抓取申请,用于 Sidecar 依据原配置文件中 job 的申请配置(如原 proxy_url,证书等)对抓取指标发动真正的申请。
  • scheme:这里的 scheme 是 target 通过 relabel 操作之后最终失去的协定值,尽管在 job 配置文件中曾经有 scheme 字段,但 Prometheus 配置文件仍旧反对通过 relabel 指定某个 target 的申请协定。在上述生成新配置过程中,咱们将实在的 scheme 保留到这个参数里,而后将 scheme 全副设置成 http。

有了上述几个参数,Sidecar 就能够对抓取指标发动正确的申请,并失去监控数据,在统计的 target 这次抓取的 series 规模后,Sidecar 会将监控数据拷贝一份给 Prometheus。

API 代理

因为 Sidecar 的存在,局部发往 Prometheus 的 API 申请须要被非凡解决,包含

  • /-/reload:因为 Prometheus 真正应用的配置文件由 Sidecar 生成,针对该接口,须要由 Sidecar 去解决并在解决胜利后调用 Prometheus 的 /-/reload 接口。
  • /api/v1/status/config:该接口须要由 Sidecar 解决并把原配置文件返回。
  • 其余接口间接发往 Prometheus。

全局数据视图

因为咱们将采集指标扩散到了不同分片中,导致每个分片的数据都只是全局数据的一部分,所以咱们须要应用额定的组件来将所有数据进行汇总并去重(多正本的状况下),失去全局数据视图。

以 thanos 为例

thanos 是一个十分好的计划,通过退出 thanos 组件,能够很不便得失去 kvass 集群的全局数据视图。当然咱们也能够通过退出 remote writer 配置来应用其余 TSDB 计划,例如 influxdb,M3 等等。

应用例子

这一节咱们通过一个部署例子,来直观感受一下 Kvass 的成果,相干 yaml 文件能够在这里找到 https://github.com/tkestack/k…
读者能够将我的项目 clone 到本地,并进入 examples。

git clone https://github.com/tkestack/kvass.git
cd kvass/examples

部署数据生成器

咱们提供了一个 metrics 数据生成器,能够指定生成肯定数量的 series,在本例子中,咱们将部署 6 个 metrics 生成器正本,每个会生成 10045 series (其中 45 series 为 golang 的 metrics)。

kubectl create -f  metrics.yaml

部署 kvass

当初咱们部署基于 Kvass 的 Prometheus 集群,用以采集这 6 个 metrics 生成器的指标。

首先咱们部署 rbac 相干配置

kubectl create -f kvass-rbac.yaml

接着部署一个 Prometheus config 文件,这个文件就是咱们的原始配置,咱们在这个配置文件中,应用 kubernetes_sd 来做服务发现

kubectl create -f config.yaml

配置如下

global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    cluster: custom
scrape_configs:
- job_name: 'metrics-test'
  kubernetes_sd_configs:
    - role: pod
  relabel_configs:
  - source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_name]
    regex: metrics
    action: keep
  - source_labels: [__meta_kubernetes_pod_ip]
    action: replace
    regex: (.*)
    replacement: ${1}:9091
    target_label: __address__
  - source_labels:
    - __meta_kubernetes_pod_name
    target_label: pod

当初咱们来部署 Kvass coordinator

kubectl create -f coordinator.yaml

咱们在 Coordinator 的启动参数中设置每个分片的最大 head series 数目不超过 30000

–shard.max-series=30000

咱们当初就能够部署带有 Kvass sidecar 的 Prometheus 了,这里咱们只部署单个正本

kubectl create -f prometheus-rep-0.yaml

部署 thanos-query

为了失去全局数据,咱们须要部署一个 thanos-query

kubectl create -f thanos-query.yaml

查看后果

根据上述计算,监控指标总计 6 个 target, 60270 series,依据咱们设置每个分片不能超过 30000 series,则预期须要 3 个分片。

咱们发现,Coordinator 胜利将 StatefulSet 的正本数改成了 3。

咱们看下单个分片内存中的 series 数目,发现只有 2 个 target 的量

咱们再通过 thanos-query 来查看全局数据,发现数据是残缺的(其中 metrics0 为指标生成器生成的指标名)

云原生监控

腾讯云容器团队在 Kvass 的设计思维上进一步优化,构建了高性能反对多集群云原生监控服务,产品目前已正式公测。

大集群监控

这一节咱们就间接应用云原生监控服务来监控一个规模较大的实在集群,测试一下 Kvass 监控大集群的能力。

集群规模

咱们关联的集群规模大抵如下

  • 1060 个节点
  • 64000+ Pod
  • 96000+ container

采集配置

咱们间接应用云原生监控服务在关联集群默认增加的采集配置,目前已蕴含了社区支流的监控指标:

  • kube-state-metrics
  • node-exporer
  • kubelet
  • cadvisor
  • kube-apiserver
  • kube-scheduler
  • kube-controler-manager

测试后果

  • 总计 3400+target, 2700+ 万 series
  • 总计扩容了 17 个分片
  • 每个分片 series 稳固在 200w 以下
  • 每个分片耗费内存在 6 -10G 左右

云原生监控所提供的默认 Grafana 面板也能失常拉取

targets 列表也能失常拉取

多集群监控

值得一提的是,云原生监控服务不仅反对监控单个大规模集群,还能够用同个实例监控多个集群,并反对采集和告警模板性能,可一键将采集告警模板下发至各地区各个集群,彻底辞别了每个集群反复增加配置的问题。

总结

本文从问题剖析,设计指标,原理分析,应用案例等方面具体介绍了一种开源 Prometheus 集群化技术,可在不批改 Prometheus 代码的前提下使其反对横向扩缩容,从而监控单机 Prometheus 无奈监控的大规模集群。

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

正文完
 0