【原創】Ingress-Nginx-Controller的Metrics監控原始碼改造簡析

wsjhk發表於2021-07-03

一、背景

  目前我們的生產環境一層Nginx已經容器化部署,但是監控並不完善,我們期望其具有Ingress-Nginx-Controller元件上報監控的資料。這樣可以建立請求全鏈路的監控大盤。有利於監控檢視關鍵鏈路的狀態資訊,並快速定位問題。因此需要研究Ingress-Nginx-Controller元件的監控機制原理,看是否可以移植到一層nginx上實現metrics監控資料的採集。

 

二、分析

  首先,目前常用的Ingress-Nginx-Controller有兩個。一個是K8S官方開源的Ingress-Nginx-Controller,另一個是nginx官方開源的Ingress-Nginx-Controller。我們使用的是K8S官方的版本。

  這兩個Controller大致的區別如下:

  1)K8S官方的Controller也是採用Go語言開發的,整合了Lua實現的OpenResty;而Nginx官方的Ccontroller是整合了Nginx;

  2)兩者對Nginx的配置不同,並且使用的nginx.conf配置模板也是不一樣的,Nginx官方的採用兩個模板檔案以include的方式配置upstream;K8S官方版本採用Lua動態配置upstream,所以不需要reload。

  所以,在pod頻繁變更的場景下,採用K8S官方版本不需要reload,影響會更小。 

  接下來,我們來看K8S官方的Ingress-Nginx-Controller是如何實現Metrics監控資料採集上報的。

  根據Ingress-Nginx-Controlleroller內部架構圖:

 

 

  可以知道,Ingress-Nginx-Controller的內部組成部分和通訊機制。這裡我們針對Nginx Metrics部分展開分析。於是,我們分析一下Ingress-Nginx-Controller的原始碼,找到其Metrics的入口。

  在ingress-nginx/cmd/nginx/main.go檔案中,我們找到了Metrics的入口,如下:

 

 

  可以看到,當我們訪問/metrics路徑去獲取監控資料時,程式會返回metrics.NewCollector()中採集的資料。繼續分析metrics.NewCollector的邏輯。在ingress-nginx/internal/ingress/metrics/main.go檔案中,我們可以看到:

 

   這就是metrics真實資料來源的採集入口,我們可以看到一共包含了四部分的資料:NGINXStatus,NGINXProcess,SocketCollector和IngressController。下面,我們看下這四部分資料具體是什麼?

 

1)NGINXStatus

 

   其中nginx.StatusPath就是/nginx_status

 

 

  由此可知,NGINXStatus的資料就是通過/nginx_status有nginx的status模板採集的資料。 

 

2)NGINXProcess

 

   而NGINXProcess的資料則是通過process_exporter的方式在/proc中採集nginx相關的資料。

 

3)SocketCollector

 

   而NGINXSocket部分的資料則是監聽/tmp/prometheus-nginx.socket這個socket檔案來收集的資料。那麼這個檔案的資料來源是哪裡呢?我們grep一下這個檔案,發現nginx的lua指令碼中有一個monitor.lua檔案,就是這個檔案採集到nginx的資料後寫進去的。

 

   由此可知,NGINXSocket的資料是通過monitor.lua採集的。

 

4)IngressController

 

   而NGINXController部分的資料則controller對nginx操作狀態資訊的統計,然後直接上報的。

  經過以上的分析,我們知道。ingress-nginx-controller的metrics監控包含了四部分資料:NGINXStatus,NGINXProcess,SocketCollector和IngressController。

  其中NGINXStatus和SocketCollector都是在nginx中實現,通過nginx自身的status模板和monitor.lua實現,並通過http或者socket的方式暴露。NGINXProcess和IngressController則是有ingress-controller本身實現。

 

三、一層Nginx實現類似ingress-nginx-controller的metrics監控

  由上面的分析我們可以知道,要使得普通的nginx例項具備Ingress-Nginx-Controller的metrics監控能力,需要將NGINXStatus,NGINXProcess,SocketCollector和IngressController四部分的資料採集能力移植到nginx例項上。

1)NGINXStatus不需要移植,nginx開啟status模組,以/nginx_status暴露即可;
2)SocketCollector移植簡單,將monitor.lua指令碼拷貝到nginx中,簡單配置跑起來即可;該部分是SocketCollector監聽在/tmp/prometheus-nginx.socket檔案,由monitor.lua採集資料後寫入。
3)NGINXProcess和IngressController移植較複雜,需要深入分析其原始碼,從ingress-nginx-controller中剝離出來後單獨執行。其中IngressController部分的資料丟棄。

   最後,通過抽離移植NGINXStatus,NGINXProcess,SocketCollector三部分監控內容。(程式碼見:https://github.com/wsjhk/nginx-custom-metrics.git)部署到一層nginx中需要做如下變更:

  1)抽離出來的程式碼編譯為ngxcustom-metrics二進位制可執行檔案,打包到nginx的映象中,隨容器啟動一起啟動。

  2)nginx的配置中需要新增Lua相關程式碼的部署,具體配置參考原始碼。

  3)Prometheus配置採集一層nginx的metrics監控資訊。驗證監控資料。

      (一層Nginx的容器化實現參考:https://mp.weixin.qq.com/s/q_kTlflDMg6MGyNOq6sVjQ)

        3.1)deployment中新增annotation:

 

 3.2)新增job_name採集:

- job_name: 'slb-nginx-pods'
  honor_labels: false
  kubernetes_sd_configs:
  - role: pod
    namespaces:
      names:
      - slb-nginx
  tls_config:
    insecure_skip_verify: true
  relabel_configs:
  - target_label: dc
    replacement: huadong1
  - target_label: cloud
    replacement: aliyun
  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    target_label: namespace
  - source_labels: [__meta_kubernetes_pod_name]
    action: replace
    target_label: pod
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
    action: keep
    regex: true
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
    action: replace
    target_label: __metrics_path__
    regex: (.+)
  - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_ngx_mr_port]
    action: replace
    regex: ([^:]+)(?::\d+)?;(\d+)
    replacement: $1:$2
    target_label: __address__
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme]
    action: replace
    target_label: __scheme__
    regex: (.+)

  

    採集到的資料樣例如下:

 

  至此,完成了Nginx監控Metrics的改造。

 

相關文章