前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Prometheus 云原生kubernetes服务发现原理图解

Prometheus 云原生kubernetes服务发现原理图解

作者头像
Reactor2020
发布2023-03-22 19:13:58
1.5K0
发布2023-03-22 19:13:58
举报
文章被收录于专栏:【云原生 • Prometheus】

云原生kubernetes服务发现原理图解

概述

上节分析了Prometheus服务发现核心流程(如下图),Discoverer基于不同协议发现采集点,通过channel通知到updater协程,然后更新到discoveryManager结构体trargets字段中,最终由sender协程将discoveryManagertargets字段数据发送给scrape采集模块。

Discoverer定义的接口类型,不同的服务发现协议基于该接口进行实现:

代码语言:javascript
复制
type Discoverer interface {
 // Run hands a channel to the discovery provider (Consul, DNS, etc.) through which
 // it can send updated target groups. It must return when the context is canceled.
 // It should not close the update channel on returning.
 Run(ctx context.Context, up chan<- []*targetgroup.Group)
}

k8s协议配置

Prometheus本身就是作为云原生监控出现的,所以对云原生服务发现支持具有天然优势。kubernetes_sd_configs 服务发现协议核心原理就是利用API Server提供的Rest接口获取到云原生集群中的PODServiceNodeEndpointsEndpointsliceIngress等对象的元数据,并基于这些信息生成Prometheus采集点,并且可以随着云原生集群状态变更进行动态实时刷新。

kubernetes云原生集群的PODServiceNodeIngress等对象元数据信息都被存储到etcd数据库中,并通过API Server组件暴露的Rest接口方式提供访问或操作这些对象数据信息。 ❞

kubernetes_sd_configs配置示例:」

代码语言:javascript
复制
  - job_name: kubernetes-pod
    kubernetes_sd_configs:
    - role: pod
      namespaces:
        names:
        - 'test01'
      api_server: https://apiserver.simon:6443
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token 
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

配置说明:

  • api_server指定API Server地址,出于安全考虑,这些接口是带有安全认证的,bearer_token_fileca_file则指定访问API Server使用到的认证信息;
  • role指定基于云原生集群中哪种对象类型做服务发现,支持PODServiceNodeEndpointsEndpointsliceIngress六种类型;
  • namespaces指定作用于哪个云原生命名空间下的对象,不配置则对所有的云原生命名空间生效;

「为什么没有配置api server信息也可以正常进行服务发现?」

很多时候我们并不需要配置api server相关信息也可以进行服务发现,如我们将上面示例简化如下写法:

代码语言:javascript
复制
  - job_name: kubernetes-pod
    kubernetes_sd_configs:
    - role: pod
      namespaces:
        names:
        - 'test01'

一般Prometheus部署在监控云原生集群上,从 Pod 使用 Kubernetes API 官方客户端库(client-go)提供了更为简便的方法:rest.InClusterConfig()API Server地址是从POD的环境变量KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT构建出来, token 以及 ca 信息从POD固定的文件中获取,因此这种场景下kubernetes_sd_configsapi_serverca_file是不需要配置的。

client-gokubernetes官方提供的go语言的客户端库,go应用使用该库可以访问kubernetesAPI Server,这样我们就能通过编程来对kubernetes资源进行增删改查操作。 ❞

Informer机制

从之前分析的服务发现协议接口设计得知,了解k8s服务发现协议入口在discovery/kubernetes.goRun方法:

Run方法中switch罗列出不同role的处理逻辑,刚好和配置示例中role支持的六种云原生对象类型对应,只是基于不同的对象进行服务发现,基本原理都是一致的。

云原生服务发现基本原理是访问API Server获取到云原生集群资源对象,PrometheusAPI Server进行交互这里使用到的是client-go官方客户端里的Informer核心工具包。Informer底层使用ListWatch机制,在Informer首次启动时,会调用List API获取所有最新版本的资源对象,缓存在内存中,然后再通过Watch API来监听这些对象的变化,去维护这份缓存,降低API Server的负载。除了ListWatchInformer还可以注册自定义事件处理逻辑,之后如果监听到事件变化就会调用对应的用户自定义事件处理逻辑,这样就实现了用户业务逻辑扩展。

Informer机制工作流程如下图:

Informer机制本身比较复杂,这里先暂时不太具体说明,只需要理解Prometheus使用Informer机制获取和监听云原生资源对象,即上图中只有「绿色框部分是自定义业务逻辑」,其它都是client-go框架informer工具包提供的功能。

这其中的关键就是注册自定义AddFuncDeleteFuncUpdateFunc三种事件处理器,分别对应增、删、改操作,当触发对应操作后,事件处理器就会被回调感知到。比如云原生集群新增一个POD资源对象,则会触发AddFunc处理器,该处理器并不做复杂的业务处理,只是将该对象的key放入到Workqueue队列中,然后Process Item组件作为消费端,不停从Workqueue中提取数据获取到新增PODkey,然后交由Handle Object组件,该组件通过Indexer组件提供的GetByKey()查询到该新增POD的所有元数据信息,然后基于该POD元数据就可以构建采集点信息,这样就实现kubernetes服务发现。

「为什么需要Workqueue队列?」

Resource Event Handlers组件注册自定义事件处理器,获取到事件时只是把对象key放入到Workerqueue中这种简单操作,而没有直接调用Handle Object进行事件处理,这里主要是避免阻塞影响整个informer框架运行。如果Handle Object比较耗时放到Resource Event Handlers组件中直接处理,可能就会影响到④⑤功能,所以这里引入Workqueue类似于MQ功能实现解耦。

源码分析

熟悉了上面Informer机制,下面以role=POD为例结合Prometheus源码梳理下上面流程。

1、创建和API Server交互底层使用的ListWatch工具;

2、基于ListWatch创建Informer

3、注册资源事件,分别对应资源创建、资源删除和资源更新事件处理;

❝这里的 podAddCountpodDeleteCountpodUpdateCount分别对应下面三个指标序列,指标含义也比较明显: prometheus_sd_kubernetes_events_total(role="pod", event="add") prometheus_sd_kubernetes_events_total(role="pod", event="delete") prometheus_sd_kubernetes_events_total(role="pod", event="update") role标识资源类型,包括:"endpointslice", "endpoints", "node", "pod", "service", "ingress"五种类型; event标识事件类型,包括:"add", "delete", "update"三种类型。 ❞

4、事件处理,AddFuncDeleteFuncUpdateFunc注册的事件处理逻辑一样,处理逻辑也比较简单:就是获取资源对象key,并将其写入到Workqueue中;

❝对于POD资源,这里的key就是:namespace/pod_name格式,比如key=test01/nginx-deployment-5ffc5bf56c-n2pl8。 ❞

5、给Workqueue注册一个无限循环处理逻辑,就能持续从Workqueue中取出key进行处理;

❝针对Pod里的每个Container上的每个port,都会生成一个对应采集点target,其中__address__就是PodIP+port组合。 ❞

6、最后启动Informer,让整个流程运转起来;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Reactor2020 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 云原生kubernetes服务发现原理图解
    • 概述
      • k8s协议配置
        • Informer机制
          • 源码分析
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档