自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用Golang編寫(xiě)自定義Prometheus Metrics

網(wǎng)絡(luò) 通信技術(shù)
為什么想到要用golang來(lái)編寫(xiě)metrics呢?這主要是我們的一個(gè)客戶那里,k8s網(wǎng)絡(luò)使用了ovs,并且做了bond,即bond0和bond1,每個(gè)bond下面2張網(wǎng)卡。

本文轉(zhuǎn)載自微信公眾號(hào)「運(yùn)維開(kāi)發(fā)故事」,作者xiyangxixia。轉(zhuǎn)載本文請(qǐng)聯(lián)系運(yùn)維開(kāi)發(fā)故事公眾號(hào)。

一、前言

為什么想到要用golang來(lái)編寫(xiě)metrics呢?這主要是我們的一個(gè)客戶那里,k8s網(wǎng)絡(luò)使用了ovs,并且做了bond,即bond0和bond1,每個(gè)bond下面2張網(wǎng)卡。在上了生產(chǎn)后,讓我每天都要檢查一下網(wǎng)卡是否正常,因?yàn)橹熬陀芯W(wǎng)卡DOWN了。而我呢,比較懶,不想手動(dòng)去檢查。想著通過(guò)prometheus最終展示到grafana,我就在grafana上看看有沒(méi)有處于異常的網(wǎng)卡就好了。其次呢,我最近剛好在學(xué)習(xí)go,也想練練手;同時(shí)也問(wèn)了一下研發(fā)同學(xué),說(shuō)很簡(jiǎn)單,叫我試試,遇到困難時(shí)也愿意幫助我。所以,我就打算試試了。

二、環(huán)境

組件 版本 備注
k8s v1.14  
ovs v2.9.5  
go 1.14.1  

三、目標(biāo)

目標(biāo)就是要通過(guò)prometheus去拉取我的ovs bond的網(wǎng)卡狀態(tài)指標(biāo),那么這里我需要編寫(xiě)一個(gè)go程序去獲取我主機(jī)的ovs bond信息,并最終以metrics方式暴露供prometheus來(lái)拉取,在grafana上展示。示例如下:

  1. # 現(xiàn)獲取當(dāng)前bond信息 
  2. [root@test~]$ ovs-appctl  bond/show |grep '^slave' |grep -v grep  |awk '{print $2""$3}' 
  3. a1-b1:enabled 
  4. a2-b2:enabled 
  5. a3-b3:enabled 
  6. a4-b4:disabled 
  7. # 最終組件暴露的數(shù)據(jù)如下 5代表獲取bond信息的命令執(zhí)行執(zhí)行失敗了,0-4表示有幾張?zhí)幱赿isabled狀態(tài)的網(wǎng)卡 
  8. curl http://$IP:$PORT/metrics  
  9. ovs_bond_status{component="ovs"} 5 
  10. ovs_bond_status{component="ovs","a1b1"="enabled","a2b2"="disabled","a3b3"="enabled",a4b4="disabled“} 2 

四、構(gòu)想

由于要通過(guò)prometheus來(lái)抓取指標(biāo),所以bond 信息肯定要以metrics格式進(jìn)行暴露。metrics格式可以參考prometheus官網(wǎng)。

bond有兩個(gè),每個(gè)下面有兩張網(wǎng)卡,每張網(wǎng)卡的狀態(tài)只有enabled和disabled,因此用數(shù)字0-4來(lái)告訴用戶有幾張網(wǎng)卡disabled了,用數(shù)字5來(lái)表示命令執(zhí)行有問(wèn)題或沒(méi)有bond,需要人工介入。可以通過(guò)命令去獲取bond信息,因此還是采取命令方式去獲取。

要對(duì)執(zhí)行命令獲取的輸出結(jié)果進(jìn)行處理并放到metrics中去。注:metrics的label不能有【-】。

shell命令返回的bond正確信息用map去接收,key為網(wǎng)卡名,value為網(wǎng)卡狀態(tài)

可以參考client_golang/prometheus

五、實(shí)踐

先執(zhí)行shell命令去獲取bond信息

  1. # 現(xiàn)獲取當(dāng)前bond信息 
  2. [root@test~]$ ovs-appctl  bond/show |grep '^slave' |grep -v grep  |awk '{print $2""$3}' 
  3. a1-b1:enabled 
  4. a2-b2:enabled 
  5. a3-b3:enabled 
  6. a4-b4:disabled 

要針對(duì)shell的輸出結(jié)果進(jìn)行處理

  1. # 執(zhí)行shell命令,并對(duì)輸出進(jìn)行處理,記錄相關(guān)日志 
  2. // return map  
  3. // 一種是執(zhí)行命令錯(cuò)誤,一種是執(zhí)行命令成功,但是返回null 
  4. func getBondStatus() (m map[string]string) { 
  5.  result, err := exec.Command("bash""-c""ovs-appctl bond/show | grep '^slave' | grep -v grep | awk '{print $2\"\"$3}'").Output() 
  6.  if err != nil { 
  7.   log.Error("result: ", string(result)) 
  8.   log.Error("command failed: ", err.Error()) 
  9.   m = make(map[string]string) 
  10.   m["msg"] = "failure" 
  11.   return m 
  12.  } else if len(result) == 0 { 
  13.   log.Error("command exec failed, result is null"
  14.   m = make(map[string]string) 
  15.   m["msg"] = "return null" 
  16.   return m 
  17.  } 
  18. // 對(duì)結(jié)果進(jìn)行進(jìn)行處理,先去除兩邊空格 
  19.  ret := strings.TrimSpace(string(result)) 
  20.     // 通過(guò)換行符切割 
  21.  tt := strings.Split(ret, "\n"
  22.  //tt := []string{"a1-b1:enabled","a2-b2:disabled"
  23.     //如果key帶有【-】,則需要去掉 
  24.  var nMap = make(map[string]string) 
  25.  for i := 0; i < len(tt); i++ { 
  26.   // if key contains "-" 
  27.   if strings.Contains(tt[i], "-") == true { 
  28.    nKey := strings.Split(strings.Split(tt[i], ":")[0], "-"
  29.    nMap[strings.Join(nKey, "")] = (strings.Split(tt[i], ":"))[1] 
  30.   } else { 
  31.    nMap[(strings.Split(tt[i], ":"))[0]] = (strings.Split(tt[i], ":"))[1] 
  32.   } 
  33.  } 
  34.  return nMap 

定義metrics指標(biāo)

  1. // define a struct 
  2. type ovsCollector struct { 
  3.     // 可以定義多個(gè) 
  4.  ovsMetric *prometheus.Desc 
  5.  
  6. func (collector *ovsCollector) Describe(ch chan<- *prometheus.Desc) { 
  7.  ch <- collector.ovsMetric 
  8.  
  9. // 網(wǎng)卡名 
  10. var vLable = []string{} 
  11. // 網(wǎng)卡狀態(tài) 
  12. var vValue = []string{} 
  13. // 固定label,表明是ovs 
  14. var constLabel = prometheus.Labels{"component""ovs"
  15.  
  16. // define metric 
  17. func newOvsCollector() *ovsCollector { 
  18.  var rm = make(map[string]string) 
  19.  rm = getBondStatus() 
  20.  if _, ok := rm["msg"]; ok { 
  21.   log.Error("command execute failed:", rm["msg"]) 
  22.  } else { 
  23.         //只獲取網(wǎng)卡名 
  24.   for k, _ := range rm { 
  25.    // get the net 
  26.    vLable = append(vLable, k) 
  27.   } 
  28.  } 
  29.     // metric 
  30.  return &ovsCollector{ 
  31.   ovsMetric: prometheus.NewDesc("ovs_bond_status"
  32.    "Show ovs bond status", vLable, 
  33.    constLabel), 
  34.  } 

指標(biāo)對(duì)應(yīng)值

  1. // 命令執(zhí)行正確則將對(duì)應(yīng)的網(wǎng)卡、網(wǎng)卡狀態(tài)以及處于異常的網(wǎng)卡數(shù)量注入到到metrics中去 
  2. func (collector *ovsCollector) Collect(ch chan<- prometheus.Metric) { 
  3.  var metricValue float64 
  4.  var rm = make(map[string]string) 
  5.  rm = getBondStatus() 
  6.  if _, ok := rm["msg"]; ok { 
  7.   log.Error("command exec failed"
  8.   metricValue = 5 
  9.   ch <- prometheus.MustNewConstMetric(collector.ovsMetric, prometheus.CounterValue, metricValue) 
  10.  } else { 
  11.   vValue = vValue[0:0] 
  12.         //只取value 
  13.   for _, v := range rm { 
  14.    // get the net 
  15.    vValue = append(vValue, v) 
  16.             // 針對(duì)disabled計(jì)數(shù) 
  17.    if v == "disabled" { 
  18.     metricValue++ 
  19.    } 
  20.   } 
  21.   ch <- prometheus.MustNewConstMetric(collector.ovsMetric, prometheus.CounterValue, metricValue, vValue...) 
  22.  } 

程序入口

  1. func main() { 
  2.  ovs := newOvsCollector() 
  3.  prometheus.MustRegister(ovs) 
  4.  
  5.  http.Handle("/metrics", promhttp.Handler()) 
  6.  
  7.  log.Info("begin to server on port 8080"
  8.  // listen on port 8080 
  9.  log.Fatal(http.ListenAndServe(":8080", nil)) 

完整代碼

  1. package main 
  2.  
  3. import ( 
  4.  "github.com/prometheus/client_golang/prometheus" 
  5.  "github.com/prometheus/client_golang/prometheus/promhttp" 
  6.  log "github.com/sirupsen/logrus" 
  7.  "net/http" 
  8.  "os/exec" 
  9.  "strings" 
  10.  
  11. // define a struct   from prometheus's struct  named Desc 
  12. type ovsCollector struct { 
  13.  ovsMetric *prometheus.Desc 
  14.  
  15. func (collector *ovsCollector) Describe(ch chan<- *prometheus.Desc) { 
  16.  ch <- collector.ovsMetric 
  17.  
  18. var vLable = []string{} 
  19. var vValue = []string{} 
  20. var constLabel = prometheus.Labels{"component""ovs"
  21.  
  22. //  get the value of the metric from a function who would execute a command and return a float64 value 
  23. func (collector *ovsCollector) Collect(ch chan<- prometheus.Metric) { 
  24.  var metricValue float64 
  25.  var rm = make(map[string]string) 
  26.  rm = getBondStatus() 
  27.  if _, ok := rm["msg"]; ok { 
  28.   log.Error("command exec failed"
  29.   metricValue = 5 
  30.   ch <- prometheus.MustNewConstMetric(collector.ovsMetric, prometheus.CounterValue, metricValue) 
  31.  } else { 
  32.   vValue = vValue[0:0] 
  33.   for _, v := range rm { 
  34.    // get the net 
  35.    vValue = append(vValue, v) 
  36.    if v == "disabled" { 
  37.     metricValue++ 
  38.    } 
  39.   } 
  40.  
  41.  
  42.   ch <- prometheus.MustNewConstMetric(collector.ovsMetric, prometheus.CounterValue, metricValue, vValue...) 
  43.  } 
  44.  
  45. // define metric's name、help 
  46. func newOvsCollector() *ovsCollector { 
  47.  var rm = make(map[string]string) 
  48.  rm = getBondStatus() 
  49.  if _, ok := rm["msg"]; ok { 
  50.   log.Error("command execute failed:", rm["msg"]) 
  51.  } else { 
  52.   for k, _ := range rm { 
  53.    // get the net 
  54.    vLable = append(vLable, k) 
  55.   } 
  56.  } 
  57.  return &ovsCollector{ 
  58.   ovsMetric: prometheus.NewDesc("ovs_bond_status"
  59.    "Show ovs bond status", vLable, 
  60.    constLabel), 
  61.  } 
  62.  
  63. func getBondStatus() (m map[string]string) { 
  64.  result, err := exec.Command("bash""-c""ovs-appctl bond/show | grep '^slave' | grep -v grep | awk '{print $2\"\"$3}'").Output() 
  65.  if err != nil { 
  66.   log.Error("result: ", string(result)) 
  67.   log.Error("command failed: ", err.Error()) 
  68.   m = make(map[string]string) 
  69.   m["msg"] = "failure" 
  70.   return m 
  71.  } else if len(result) == 0 { 
  72.   log.Error("command exec failed, result is null"
  73.   m = make(map[string]string) 
  74.   m["msg"] = "return null" 
  75.   return m 
  76.  } 
  77.  ret := strings.TrimSpace(string(result)) 
  78.  tt := strings.Split(ret, "\n"
  79.  var nMap = make(map[string]string) 
  80.  for i := 0; i < len(tt); i++ { 
  81.   // if key contains "-" 
  82.   if strings.Contains(tt[i], "-") == true { 
  83.    nKey := strings.Split(strings.Split(tt[i], ":")[0], "-"
  84.    nMap[strings.Join(nKey, "")] = (strings.Split(tt[i], ":"))[1] 
  85.   } else { 
  86.    nMap[(strings.Split(tt[i], ":"))[0]] = (strings.Split(tt[i], ":"))[1] 
  87.   } 
  88.  } 
  89.  return nMap 
  90.  
  91. func main() { 
  92.  ovs := newOvsCollector() 
  93.  prometheus.MustRegister(ovs) 
  94.  
  95.  http.Handle("/metrics", promhttp.Handler()) 
  96.  
  97.  log.Info("begin to server on port 8080"
  98.  // listen on port 8080 
  99.  log.Fatal(http.ListenAndServe(":8080", nil)) 

六、部署

因?yàn)樽罱K要部署到k8s環(huán)境中, 先構(gòu)建鏡像,參考如下Dockerfile

  1. FROM golang:1.14.1 AS builder 
  2. WORKDIR /go/src 
  3. COPY ./ . 
  4. RUN go build -o ovs_check main.go 
  5.  
  6. # runtime 
  7. FROM centos:7.7 
  8. COPY --from=builder /go/src/ovs_check /xiyangxixia/ovs_check 
  9. ENTRYPOINT ["/xiyangxixia/ovs_check"

我這里部署使用的yaml如下所示:

  1. --- 
  2. apiVersion: apps/v1 
  3. kind: DaemonSet 
  4. metadata: 
  5.   name: ovs-agent 
  6.   namespace: kube-system 
  7. spec: 
  8.   minReadySeconds: 5 
  9.   selector: 
  10.     matchLabels: 
  11.       name: ovs-agent 
  12.   template: 
  13.     metadata: 
  14.       annotations: 
  15.       # 這里三個(gè)都要加上,告訴promethue抓取路徑 
  16.         prometheus.io/scrape: "true" 
  17.         prometheus.io/port: "8080" 
  18.         prometheus.io/path: "/metrics" 
  19.       labels: 
  20.         name: ovs-agent 
  21.     spec: 
  22.       containers: 
  23.       - name: ovs-agent 
  24.         image: ovs_bond:v1 
  25.         imagePullPolicy: IfNotPresent 
  26.         resources: 
  27.             limits: 
  28.               cpu: 100m 
  29.               memory: 200Mi 
  30.             requests: 
  31.               cpu: 100m 
  32.               memory: 200Mi 
  33.         securityContext: 
  34.           privileged: true 
  35.           procMount: Default 
  36.         volumeMounts: 
  37.         - mountPath: /lib/modules 
  38.           name: lib-modules 
  39.           readOnly: true 
  40.         - mountPath: /var/run/openvswitch 
  41.           name: ovs-run 
  42.         - mountPath: /usr/bin/ovs-appctl 
  43.           name: ovs-bin 
  44.           subPath: ovs-appctl 
  45.       serviceAccountName: xiyangxixia 
  46.       hostPID: true 
  47.       hostIPC: true 
  48.       volumes: 
  49.       - hostPath: 
  50.           path: /lib/modules 
  51.           type: "" 
  52.         name: lib-modules 
  53.       - hostPath: 
  54.           path: /var/run/openvswitch 
  55.           type: "" 
  56.         name: ovs-run 
  57.       - hostPath: 
  58.           path: /usr/bin/ 
  59.           type: "" 
  60.         name: ovs-bin 
  61.   updateStrategy: 
  62.     type: RollingUpdate 

七、測(cè)試

  1. [root@test ~]$ kubectl get po -n kube-system -o wide  |grep ovs 
  2. ovs-agent-h8zc6    1/1     Running     0    2d14h   10.211.55.41   master-1   <none>           <none> 
  3. [root@test ~]$ curl 10.211.55.41:8080/metrics |grep ovs_bond 
  4. # HELP ovs_bond_status Show ovs bond status 
  5. # TYPE ovs_bond_status counter 
  6. ovs_bond_status{component="ovs",a1b1="enabled",a2b2="enabled",a3b3="enabled",a4b4="enabled"} 0 

八、總結(jié)

 

以上就是這篇文章的所有了,原諒我學(xué)藝不精只能粗糙的介紹一下。感謝一直以來(lái)關(guān)注公眾號(hào)的朋友們!

 

責(zé)任編輯:武曉燕 來(lái)源: 運(yùn)維開(kāi)發(fā)故事
相關(guān)推薦

2020-12-14 10:26:48

Prometheus 監(jiān)控Services

2023-03-26 08:41:37

2021-03-26 20:37:14

Prometheus監(jiān)控指標(biāo)

2009-06-25 14:53:35

自定義UI組件JSF框架

2023-12-29 08:01:52

自定義指標(biāo)模板

2009-08-03 13:34:06

自定義C#控件

2023-10-31 09:10:39

2023-07-28 09:26:43

GolangZap

2015-02-12 15:33:43

微信SDK

2019-12-25 11:47:27

LinuxFVWM

2022-01-14 09:17:13

PythonAPISIX插件

2010-10-25 16:05:07

oracle自定義函數(shù)

2009-06-23 11:35:44

JSF的Naviati

2015-02-12 15:38:26

微信SDK

2009-06-22 15:07:45

原則和技巧JSF自定義復(fù)合組件

2016-12-26 15:25:59

Android自定義View

2015-06-10 10:54:24

自定義路PHP

2021-12-24 15:46:23

鴻蒙HarmonyOS應(yīng)用

2009-02-10 12:55:39

自定義控件AJAX.NET

2022-09-13 15:44:52

VSLook插件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)