当前视点!【prometheus】-08 图解云原生服务发现机制
Prometheus服务发现机制之Kubernetes
概述
分析过云原生监控接入方案,下面开始看下云原生服务发现机制。Prometheus本身就是作为云原生监控出现的,所以对云原生服务发现支持具有天然优势。Kubernetes服务发现协议允许使用Kubernetes Rest API检索出Prometheus需要监控的targets,并且跟着集群状态进行同步变更。
(相关资料图)
kubernetes_sd_configs表示基于Kubernetes进行服务发现,服务发现目标类型使用role表示,比如:role=service,表示针对Kubernetes中的service资源对象,进行具体的服务发现操作。kubernetes_sd_configs支持的role包括:node、service、pod、endpoints、ingress。
原理
基于Kubernetes进行服务发现,主要针对Kubernetes中的service、pod、node等资源对象进行服务发现,Prometheus使用client-go对role中指定的资源对象进行监听。一般Prometheus部署在Kubernetes集群中的话,Prometheus可以直接利用指定的Service Account对Kubernetes API进行访问。若Prometheus在Kubernetes集群之外,则kubernetes_sd_configs还需指定监控集群的API Server的URL以及相关的认证信息,从而能够创建对应集群的Client。
“client-go是kubernetes官方提供的go语言的客户端库,go应用使用该库可以访问kubernetes的API Server,这样我们就能通过编程来对kubernetes资源进行增删改查操作。
配置示例:
- job_name: kubernetes-pod metrics_path: /metrics kubernetes_sd_configs: - role: pod namespaces: names: - "test01" api_server: https://apiserver.simon:6443 bearer_token_file: d:/token.k8s tls_config: insecure_skip_verify: true bearer_token_file: d:/token.k8s tls_config: insecure_skip_verify: true协议分析
Kubernetes服务发现大致原理如下图:
1、通过clientset访问API Server,根据role配置获取不同的集群资源对象;
2、通过List & Watch机制,注册监听事件:
p.informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(o interface{}) { podAddCount.Inc() p.enqueue(o) }, DeleteFunc: func(o interface{}) { podDeleteCount.Inc() p.enqueue(o) }, UpdateFunc: func(_, o interface{}) { podUpdateCount.Inc() p.enqueue(o) },})通过informer.AddEventHandler函数可以为集群资源添加资源事件回调方法,支持3种资源事件回调方法:AddFunc、DeleteFunc、UpdateFunc,分别对应新增资源、修改资源和删除资源时事件触发。
3、资源变更注册回调方法中,将目标资源对象转成key放入到队列queue中,如下pod资源:
func (p *Pod) enqueue(obj interface{}) { //obj是pod资源对象,通过DeletionHandlingMetaNamespaceKeyFunc将其转换成key //比如key=test01/nginx-deployment-5ffc5bf56c-n2pl8,即namespace/pod_name格式 key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) if err != nil { return } p.queue.Add(key)}4、后台goroutines无限循环执行process逻辑,process逻辑中就是不停从queue中提取数据进行处理,比如pod.go对应逻辑如下:
func (p *Pod) process(ctx context.Context, ch chan<- []*targetgroup.Group) bool { keyObj, quit := p.queue.Get() if quit { return false } defer p.queue.Done(keyObj) key := keyObj.(string) //与 MetaNamespaceKeyFunc() 功能相反的是 SplitMetaNamespaceKey() 函数,它将传入的 Key 分解,返回对象所在的命名空间和对象名称。 namespace, name, err := cache.SplitMetaNamespaceKey(key) if err != nil { return true } //根据key获取资源对象obj o, exists, err := p.store.GetByKey(key) if err != nil { return true } if !exists { //pod被删除时,exists=false // 然后发送targets为空的tg,即移除 send(ctx, ch, &targetgroup.Group{Source: podSourceFromNamespaceAndName(namespace, name)}) return true } pod, err := convertToPod(o) if err != nil { level.Error(p.logger).Log("msg", "converting to Pod object failed", "err", err) return true } //p.buildPod(pod):将资源对象信息转成target groups send(ctx, ch, p.buildPod(pod)) return true}大致逻辑:
a、根据从queue中提取的key,使用p.store.GetByKey(key)获取对应的资源对象,比如pod、service等对象;
b、如果对象不存在,则表示资源对象被删除,则创建一个targets集合为空的target groups,这样Scrape Manager就会移除targets;
c、使用buildXXX(obj)将资源对象解析成target groups,如buildNode()、buildPod()等;
d、最后使用send()方法将解析的target groups通过通道channel传递出去,最终传递给Scrape Manager,这样target groups中targets将被Prometheus抓取监控数据。
pod资源的target groups结构如下示例,每个pod对象都会被解析成target groups,其中包含targets集合、labels标签集合:
Discovery创建
1、假如我们定义如下抓取作业:
- job_name: kubernetes-nodes-cadvisor metrics_path: /metrics scheme: https kubernetes_sd_configs: - role: node api_server: https://apiserver.simon:6443 bearer_token_file: d:/token.k8s tls_config: insecure_skip_verify: true bearer_token_file: d:/token.k8s tls_config: insecure_skip_verify: true relabel_configs: # 将标签(.*)作为新标签名,原有值不变 - action: labelmap regex: __meta_kubernetes_node_label_(.*) # 修改NodeIP:10250为APIServerIP:6443 - action: replace regex: (.*) source_labels: ["__address__"] target_label: __address__ replacement: 192.168.52.151:6443 - action: replace source_labels: [__meta_kubernetes_node_name] target_label: __metrics_path__ regex: (.*) replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor 会被解析成kubernetes.SDConfig如下:
kubernetes.SDConfig定义如下:
type SDConfig struct { APIServer config.URL `yaml:"api_server,omitempty"` Role Role `yaml:"role"` HTTPClientConfig config.HTTPClientConfig `yaml:",inline"` NamespaceDiscovery NamespaceDiscovery `yaml:"namespaces,omitempty"` Selectors []SelectorConfig `yaml:"selectors,omitempty"`}2、Discovery创建
//创建Clientset,可看成操作Kubernetes API的客户端c, err := kubernetes.NewForConfig(kcfg) if err != nil { return nil, err }return &Discovery{ client: c, logger: l, role: conf.Role, namespaceDiscovery: &conf.NamespaceDiscovery, discoverers: make([]discovery.Discoverer, 0), selectors: mapSelector(conf.Selectors),}, nil3、Discovery创建完成,最后会调用Discovery.Run()启动服务发现:
func (d *Discovery) Run(ctx context.Context, ch chan<- []*targetgroup.Group) { d.Lock() namespaces := d.getNamespaces() switch d.role { case RoleEndpointSlice: role=endpointslice逻辑 case RoleEndpoint: role=endpoints逻辑 case RolePod: role=pod逻辑 case RoleService: role=service逻辑 case RoleIngress: role=ingress逻辑 case RoleNode: role=node逻辑 default: level.Error(d.logger).Log("msg", "unknown Kubernetes discovery kind", "role", d.role) } var wg sync.WaitGroup for _, dd := range d.discoverers { wg.Add(1) go func(d discovery.Discoverer) { defer wg.Done() d.Run(ctx, ch) }(dd) } d.Unlock() wg.Wait() <-ctx.Done()}4、注册集群资源对象监听事件回调逻辑:
for _, namespace := range namespaces { p := d.client.CoreV1().Pods(namespace) plw := &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { options.FieldSelector = d.selectors.pod.field options.LabelSelector = d.selectors.pod.label return p.List(ctx, options) }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { options.FieldSelector = d.selectors.pod.field options.LabelSelector = d.selectors.pod.label return p.Watch(ctx, options) }, } pod := NewPod( log.With(d.logger, "role", "pod"), cache.NewSharedInformer(plw, &apiv1.Pod{}, resyncPeriod), ) d.discoverers = append(d.discoverers, pod) go pod.informer.Run(ctx.Done())}
都市游、微度假等成主流 主要景区中秋迎客383.3万人次同比增长24%
记者昨天从市文旅局了解到,中秋节假期,全市199家重点旅游景区(地区)累计游客接待总量383 3万人次,同比增长24%;累计营业总收入27107 1万
2022-09-21
郑州管城区、二七区今天开展核酸检测,最全采样点看这里
今天(5月18日)郑州市管城区7:00—17:00二七区9:00—16:00开展核酸检测管城回族区新冠肺炎疫情防控指挥部办公室关于在全区范围开展新冠病
2022-05-19郑州发布99号通告:调整封控管控区域
郑州市新冠肺炎疫情防控指挥部办公室关于调整封控管控区域的通告(2022年99号)根据疫情形势变化,经郑州市疫情防控指挥部研究,自5月18日
2022-05-195月17日河南新增本土确诊病例3例、本土无症状感染者8例
5月17日0—24时,全省新增本土确诊病例3例(郑州市3例),含1例无症状感染者转确诊病例(在郑州市),新增本土无症状感染者8例(郑州市6例
2022-05-19
【行走郑州·读懂最早中国】锁定“云游麦田里的博物馆”直播,探寻最早中国
黄河孕育华夏,麦穗延续苍生,文物折射历史,历史照亮未来。看直播 抽门票为全面展示郑州城市魅力,深入塑造行走郑州·读懂最早中国品牌体
2022-05-19郑州约谈百果园郑州地区负责人
今日记者获悉,针对近期成都、武汉相继曝出百果园销售腐败变质水果切盘的负面新闻,为全面加强能力作风建设,严格落实国家食品安全示范城市
2022-05-19
全力备汛!郑州94支队伍10313人集结到位
记者从近日召开的郑州市2022年城市防汛工作会议上了解到,郑州市组建了94支共10313人的防汛应急抢险队伍。目前,这些队伍正在全力备汛。据
2022-05-19
【行走河南·读懂中国】河南四大文旅集团入榜全国文旅集团品牌影响力百强
2022年5月16日,迈点研究院发布《2022年4月中国文旅业发展报告》,河南省的四个知名文旅集团,银基文旅集团、建业文旅、洛阳文旅集团、河南
2022-05-19
图集|来自郑州五月的浪漫,闯入莫奈的花园
遇见郑州五月的浪漫,走进这片虞美人和矢车菊的花海,彷佛置身于莫奈的花园。色彩缤纷的花儿在微风中摇曳生姿,好似步入童话般的世界。
2022-05-19郑州市普通中专采用网上报名 志愿填报时间为5月22日〜25日
5月17日上午,《2022年郑州市普通中等专业学校招生工作意见》发布,今年,郑州市普通中专采用网上报名。普通中专志愿填报时间为5月22日至25
2022-05-19X 关闭
X 关闭
