(一)ACK prometheus-operator 之架构梳理

本文涉及的产品
可观测可视化 Grafana 版,10个用户账号 1个月
可观测监控 Prometheus 版,每月50GB免费额度
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 本文以troubleshooting的思维为切入点,深入梳理prometheus-operator架构原理,技术上跟阿里云arms_prometheus是相通的,便于在问题场景中快速定位。

前提条件

本文环境基于阿里云ACK专有集群1.22以及ACK应用市场的ack-prometheus-operator  chart 12.0.0。


概念区分

Prometheus-Operator vs Prometheus vs Kube-Prometheus

这是三个不同的开源项目,概念上不要混淆,简单看下三者关联:

Prometheus:用于监控k8s集群,收集容器集群的监控指标,可以作为三方展示平台比如grafana的数据源。

Prometheus Operator可用于管理Prometheus,operator本身并不做监控,可以看成是prometheus的自动化运维工具, 类似是一个翻译器,用于将便捷的配置翻译成标准prometheus配置文件。

Kube-Prometheus : 目前k8s集群监控的主流项目,主要使用Prometheus做集群监控,使用Prometheus Operator做监控的运维管理,也就是以上二者的结合。

ACK应用市场的ACK-Prometheus-Operator 新版本是集成了kube-prometheus的。本文基于ACK-Prometheus-Operator chart 12.0.0,也就是kube-prometheus展开解析。

ACK-Prometheus-Operator 架构

一句话总结,ACK-Prometheus-Operator Kube-Prometheus主要包含Prometheus-operator控制器、prometheus server监控系统、各种exporter做指标采集组件和prometheus alert报警系统。本系列不涉及alert组件。


本文重点章节:

最后一节,《Prometheus-Operator 配置更新流程》, 分别介绍了:

标准prometheus配置解读

Operator CRD配置之间的匹配关系

Prometheus如何reload新配置

配置更新生效流程

Prometheus-Operator 架构

分别梳理prometheus以及prometheus-operator两部分。

  • prometheus官网给出的架构图如下:


Prometheus  本身就是一个k8s 监控系统,负责实现对监控数据的获取,存储以及查询。Prometheus server 的基本原理是通过 HTTP/HTTPS 周期性抓取被监控目标的 metrics(指标)数据,任意组件只要提供对应的 HTTP/HTTPS 接口并且符合 Prometheus 定义的数据格式,就可以接入 Prometheus 监控。在监控领域,有PUSH/PULL两种概念,prom-operator 这种由prom server 调用被监控对象(targets)获取监控数据的方式被称为 Pull(拉) 。

ACK-prometheus便是采用pull方式 (此处对比的是pushgateway,ACK-prometheus-operator 组件没有单独部署pushgateway做指标的“push”)。其次,Prometheus Server 需要对采集到的监控数据进行存储,Prometheus Server 本身就是一个时序数据库,将采集到的监控数据按照时间序列的方式存储在本地磁盘当中。


Prometheus-Operator官网给出的架构图。

可以直观的看出Prometheus-Operator负责部署和管理prometheus server.


Operator 是 Kubernetes 的一种自定义资源的控制器,就像KCM组件内置资源控制器如deployment  controller 管理deployment一样,Prometheus-Operator会管理控制prometheus相关资源,可以参考CNCFOperator 白皮书

Prometheus-Operator根据相关CRD(servicemonitor等)配置及时更新prometheus server的监控对象(targets)使其可以按照实际配置预期运行,可以将Prometheus-Operator看成一个代码化的自动化的简化prometheus 部署维护操作的高级运维人员。


Prometheus-Operator既然是一种k8s controller,则具备 k8s controller的通用性架构。通用k8s控制器内部可以分informer -worker queue -control loop三部分,不在本文做赘述,只是了解下prometheus-operator 也是基于这种架构不断的watch apiserver中相关crd的变更去推动prometheus 的配置更新。

图来自 《https://kingjcy.github.io/post/cloud/paas/base/kubernetes/k8s-controller/


ACK-Prometheus-Operator 部署

ACK-Prometheus-Operator 集成 kube-prometheus架构中的组件详细介绍请各自参考超链接中的官网,不做赘述。ACK应用市场基于helm chart 部署后,主要部署了以下几个组件:


在ACK-prometheus-operator 架构中,各个组件对应形式如下:

部署组件

映射在ACK中的资源

类型

怎么部署到ack集群的

Prometheus Operator

ack-prometheus-operator-operator

Deployment

helm部署

Prometheus server

prometheus-ack-prometheus-operator-prometheus

statefulset

prometheus-operator 根据helm部署的CRD prometheus 部署 statefulset

Alertmanager

alertmanager-ack-prometheus-operator-alertmanager

statefulset

prometheus-operator 根据helm部署的CRD alertmanagers 部署statefulset

Prometheus node-exporter

ack-prometheus-operator-prometheus-node-exporter

DaemonSet

helm部署

Grafana

ack-prometheus-operator-grafana

Deployment

helm部署

kube-state-metrics

ack-prometheus-operator-kube-state-metrics

Deployment

helm部署


Prometheus-Operator CRD资源

Prometheus-Operator 是本文的重点,以deployment的形式存在,其中包含了所有CRD的schema定义、模型,以及各CRD的处理逻辑。它负责部署并管理相关CRD资源,定期循环watch apiserver, 将相关的CRD更新/配置更新及时应用到运行中的prometheus系统中。

这些CRD都是一些方便使用人员配置的项目,以k8s用户熟悉的方式(label、selectors)定义prometheus的scrap job, 支持多种label比较方式: In, NotIn, Exists, DoesNotExists 。

k8s用户更新CRD后,最终会被operator翻译成prometheus标准的配置文件,prometheus.yml完成自动更新和生效,无需重启prometheus实例。

每一个CRD的标准格式不赘述,在配置环节会有具体示例。以下CRD可以通过kubectl get xx 获取具体信息。

CRD 名称

作用

Prometheus

最核心的一个CRD, 控制prometheus server的statefulset状态。

该CRD用于部署、管理prometheus stateful实例,以及配置该prometheus实例与ServiceMonitor(通过serviceMonitorNamespaceSelector标签)、Altermanager(通过alertmanagers标签)、PromtheusRule(通过ruleSelector标签)之间的关联。   一个Prometheus crd 资源创建后,promtheus-operator会自动创建一个prometheus stateful实例。

ServiceMonitor

纯配置,Operator告诉prometheus server , 要监控的 targets是基于k8s service动态发现。 Operator基于servicemonitor的配置生成promtheus的标准配置文件promtheus.yml。

注意的是,ServiceMonitor中的endpoint被转换为prometheus.yml中的kubernetes_sd_configs标签,即服务发现仍然是通过prometheus的原生能力完成的,ServiceMonitor或prometheus-operator并不具备服务发现能力,仅仅是配置转换与应用能力。

PodMonitor

纯配置,类似于ServiceMonitor,只不过要监控的 targets是基于k8s pod label 动态发现,是针对pod级别的scrap job。

Alertmanager

用于部署和管理promtheus的Altermanager实例.一个Altermanager资源定义会对应于一个stateful实例,prometheus-opertaor会根据Alertmanager中指定replicas、image、RBAC等信息将promtheus的altermanager pod部署,prometheus实例会自动与该Alertmanager相关联,共同完成监控->告警的链路。

PrometheusRule

用于生成promtheus的告警规则文件.纯配置项。promtheus-operator会将该资源转换为prometheus的rule文件,挂在于prometheus实例的文件系统中:

alertmanagerconfigs

Alertmanager配置, 默认无配置。

probes

默认无配置。

thanosrulers

控制Thanos deployment, 默认无配置。


各个CRD以及operator之间的关系:



图来自《https://v1-0.choerodon.io/zh/blog/prometheus-operator-introduce/



Prometheus-Operator 配置更新流程


Prometheus Server 可以通过静态配置static_configs管理监控目标,也可以配合使用 Service/Pod Discovery 的方式(sd_config)动态管理监控目标,并从这些监控目标中获取数据。

Prometheus-operator 通过定期循环watch apiserver,获取到CRD资源(比如servicemonitor)的创建或者更新,将配置更新及时应用到运行中的prometheus pod中转换成标准promethesu配置文件供prom server使用。

标准prometheus配置解读

标准配置文件参考网上现成的分析就行,随手找了一个:https://developer.aliyun.com/article/830280


标准配置官方解析: https://prometheus.io/docs/prometheus/latest/configuration/configuration/示例


不过我们使用ack-prometheus-operator,其实是想尽量避免手写这种及其不易读容器出错的的配置,所以会利用operator CRD去做配置。


Operator CRD配置之间的匹配关系

使用CRD做prometheus配置,“匹配”是一个很重要的细节,详细匹配关系如图,任何地方匹配失败会导致转化成的标配prometheus文件无法识别到targets。




配置间的匹配总结就是:

ServiceMonitor注意事项:

  • ServiceMonitor的label  需要跟prometheus中定义的serviceMonitorSelector一致
  • ServiceMonitor的endpoints中port时对应k8s service资源中的portname, 不是port number.
  • ServiceMonitor的selector.matchLabels需要匹配k8s service中的label
  • ServiceMonitor资源创建在prometheus的namespace下,使用namespaceSelector匹配要监控的k8s svc的ns.
  • servicemonitor若匹配多个svc,会发生数据重复


PodMonitor注意事项:

  • PodMonitor的label  需要跟prometheus中定义的podMonitorSelector一致
  • PodMonitor的spec.podMetricsEndpoints.port 需要写pod中定义的port name,不能写port number。
  • PodMonitor的selector.matchLabels需要匹配k8s pod 中的label
  • PodMonitor资源创建在prometheus的namespace下,使用namespaceSelector匹配要监控的k8s pod的ns.



Prometheus如何reload新配置

简单讲就是重启进程或者调用HTTP /-/reload 接口:

A configuration reload is triggered by sending a SIGHUP to the Prometheus process or sending a HTTP POST request to the /-/reload endpoint (when the --web.enable-lifecycle flag is enabled). This will also reload any configured rule files.


Prometheus stateful pod 包含config-reloader  和 prometheus两个container。其中,config-reloader 用于定期调用reload接口去刷新配置。有几个时间间隔值需要了解下,新配置部署后需要等待的生效时间,参考官网。 可以看到,默认每3分钟reload一次新配置。

const (
 defaultWatchInterval = 3 * time.Minute // 3 minutes was the value previously hardcoded in github.com/thanos-io/thanos/pkg/reloader.
 defaultDelayInterval = 1 * time.Second // 1 second seems a reasonable amount of time for the kubelet to update the secrets/configmaps.
 defaultRetryInterval = 5 * time.Second // 5 seconds was the value previously hardcoded in github.com/thanos-io/thanos/pkg/reloader.
#
 watchInterval := app.Flag("watch-interval", "how often the reloader re-reads the configuration file and directories; when set to 0, the program runs only once and exits").Default(defaultWatchInterval.String()).Duration()
 delayInterval := app.Flag("delay-interval", "how long the reloader waits before reloading after it has detected a change").Default(defaultDelayInterval.String()).Duration()
 retryInterval := app.Flag("retry-interval", "how long the reloader waits before retrying in case the endpoint returned an error").Default(defaultRetryInterval.String()).Duration()
 watchedDir := app.Flag("watched-dir", "directory to watch non-recursively").Strings()


那如果测试期间不想等3分钟呢?除了重启,可以手动触发reload 么?(其实没必要)

先说结论:手动模拟方式:curl -X POST http://localhost:9090/-/reload   (localhost可以换成prom pod ip)


扩展:

pod中的多容器,为何netstat可以看到全部容器进程监听,ps 看不到?思考一下, 不在此处赘述。

config-reloader container: 自己的监听是8080,9090不是自己container的监听。

prometheus container,自己的监听是9090.


看下yaml定义进一步理解两个容器如何合作:


config-reloader容器启动参数可以看出,他会定期发出这个reload接口调用,由于9090是prometheus server container中的进程监听,其实是prometheus server响应的这个接口。 config-reload 进程负责的是定期call 9090端口的reload接口.



默认 prom server命令行开启了  --web.enable-lifecycle ,因此可以使用reload/quit 接口 (不开启这个参数则无法使用这俩接口)。prometheus container收到reload 接口调用后,便会reload  启动参数里定义的--config.file。



但是prometheus server container relaod的是固定文件--config.file,这个文件是如何获取/发现最新的配置内容呢?看下文。


配置更新生效流程

  • 1. helm或者kubectl更新servicemonitor、podmonitor或者prometheus CRD 中的配置(包含addtionalscrapeconfig)
  • 2. Prometheus-operator watch apiserver获取到以上CRD 中的更新
  • 3. Prometheus-operator 将捕捉到的更新都翻译成prometheus标准配置格式prometheus.yaml
  • 4. Prometheus-operator 打包prometheus.yaml 到secret “prometheus-ack-prometheus-operator-prometheus ” 中,存储为secret.data字段: prometheus.yaml.gz,
  • 5. 以上secret的data是被mount 给prometheus pod 的config-reloader  container中的。
  • 6. 由config-reloader 解压gz文件后读取出标准 prometheus.yml文件,通过empty-dir共享给prometheus container 。
  • 7. Prometheus 进程读取参数 --config.file 指定的文件路径,就是通过emptydir的共享文件,即config-reloader输出的config yaml文件。
  • 8. Prometheus server 根据配置中的relabel等信息,动态/静态发现要监控的targets, 对targets发起http/https请求抓取metrics数据。
  • 9. 抓取metrics数据存储后提供给UI做query查询,或者提供给grafana等做展示。

看下第六步config-reloader中的处理:


从secret中查看标准prom config配置:

kubectl get secret prometheus-ack-prometheus-operator-prometheus   -n monitoring -ojson|jq -r '.data["prometheus.yaml.gz"]' |base64 -d| gunzip

看下prometheus pod yaml中关于secret mount的定义:

containers:
#prometheus 启动参数读取emptydir实现的共享文件,即config-reloader输出的config yaml文件
          name: prometheus
        - args:
            - '--config.file=/etc/prometheus/config_out/prometheus.env.yaml'
          volumeMounts:
            - mountPath: /etc/prometheus/config_out
              name: config-out
#config-reloader 读取secret中的配置内容并gunzip为标准prom config yaml格式输出到config_out,config_out通过emptydir实现共享。
    name: config-reloader
        - args:
            - '--config-file=/etc/prometheus/config/prometheus.yaml.gz'
            - >-
              --config-envsubst-file=/etc/prometheus/config_out/prometheus.env.yaml
          volumeMounts:
            - mountPath: /etc/prometheus/config
              name: config
            - mountPath: /etc/prometheus/config_out
              name: config-out
#volumes
  volumes:
        - name: config
          secret:
            defaultMode: 420
            secretName: prometheus-ack-prometheus-operator-prometheus
        - emptyDir: {}
          name: config-out
        - name: config
          secret:
            defaultMode: 420
            secretName: prometheus-ack-prometheus-operator-prometheus



参考:

https://yuque.antfin.com/xingyu.cxy/gz5g1e/uzs2k8

https://zhuanlan.zhihu.com/p/342823695

https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/operator/what-is-prometheus-operator

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
23天前
|
存储 Kubernetes 负载均衡
Kubernetes设计架构
Kubernetes 是一个开源的容器编排平台,用于自动化应用的部署、扩展和管理。其设计架构高度可扩展且灵活,能管理大规模分布式系统。核心组件包括集群(含主节点和工作节点)、API 服务器、etcd、控制器管理器、调度器、Pod、服务、命名空间、配置管理、持久化存储、网络模型及扩展性支持。这些组件共同实现了应用的高效运行与管理。
48 7
|
22天前
|
Prometheus Kubernetes 监控
Prometheus 与 Kubernetes 的集成
【8月更文第29天】随着容器化应用的普及,Kubernetes 成为了管理这些应用的首选平台。为了有效地监控 Kubernetes 集群及其上的应用,Prometheus 提供了一个强大的监控解决方案。本文将详细介绍如何在 Kubernetes 集群中部署和配置 Prometheus,以便对容器化应用进行有效的监控。
36 1
|
22天前
|
Prometheus 监控 Kubernetes
Prometheus 在微服务架构中的应用
【8月更文第29天】随着微服务架构的普及,监控和跟踪各个服务的状态变得尤为重要。Prometheus 是一个开源的监控系统和时间序列数据库,非常适合用于微服务架构中的监控。本文将详细介绍 Prometheus 如何支持微服务架构下的监控需求,包括服务发现、服务间的监控指标收集以及如何配置 Prometheus 来适应这些需求。
51 0
|
22天前
|
Kubernetes API 调度
Kubernetes 架构解析:理解其核心组件
【8月更文第29天】Kubernetes(简称 K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。它提供了一个可移植、可扩展的环境来运行分布式系统。本文将深入探讨 Kubernetes 的架构设计,包括其核心组件如何协同工作以实现这些功能。
48 0
|
7天前
|
Kubernetes Docker 微服务
构建高效的微服务架构:基于Docker和Kubernetes的最佳实践
在现代软件开发中,微服务架构因其灵活性和可扩展性而受到广泛青睐。本文探讨了如何利用Docker和Kubernetes来构建高效的微服务架构。我们将深入分析Docker容器的优势、Kubernetes的编排能力,以及它们如何结合实现高可用性、自动扩展和持续部署。通过具体的最佳实践和实际案例,读者将能够理解如何优化微服务的管理和部署过程,从而提高开发效率和系统稳定性。
|
1月前
|
Kubernetes Serverless API
Kubernetes 的架构问题之利用不可变性来最小化对API Server的访问如何解决
Kubernetes 的架构问题之利用不可变性来最小化对API Server的访问如何解决
68 7
|
1月前
|
弹性计算 Kubernetes 安全
Kubernetes 的架构问题之在Serverless Container中保障应用的安全防护如何解决
Kubernetes 的架构问题之在Serverless Container中保障应用的安全防护如何解决
144 8
|
1月前
|
弹性计算 Kubernetes Serverless
Kubernetes 的架构问题之ACK/ASK支持ECI的Serverless Container如何解决
Kubernetes 的架构问题之ACK/ASK支持ECI的Serverless Container如何解决
76 7
|
1月前
|
弹性计算 Kubernetes Serverless
Kubernetes 的架构问题之Serverless Container中不支持特权模式的问题如何解决
Kubernetes 的架构问题之Serverless Container中不支持特权模式的问题如何解决
68 6
|
1月前
|
Kubernetes 安全 Serverless
Kubernetes 的架构问题之Serverless Container中提供对外服务如何解决
Kubernetes 的架构问题之Serverless Container中提供对外服务如何解决
62 5