天天看點

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

【prometheus】-07 Kubernetes雲原生監控之kube-state-metrics叢集資源監控

2021-09-06

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

【prometheus】-06 Kubernetes雲原生監控之cAdvisor容器資源監控

2021-09-01

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

【prometheus】-05 Kubernetes雲原生監控之節點性能監控

2021-08-30

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

【prometheus】-04 輕松搞定Prometheus Eureka服務發現

2021-08-25

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

【prometheus】-03 輕松搞定Prometheus檔案服務發現

2021-08-23

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

【prometheus】-02 一張圖徹底搞懂Prometheus服務發現機制

2021-08-18

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

【prometheus】- 01 雲原生時代的監控系統入門

2021-08-16

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

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

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

原理

基于

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

服務發現大緻原理如下圖:

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之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

标簽集合:

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

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

如下:

【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

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),
}, nil
           

3、

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())
}
           
【prometheus】-08 圖解雲原生服務發現機制Prometheus服務發現機制之Kubernetes

繼續閱讀