k8s 監控(三)prometheus-adapter

本文屬於 k8s 監控系列,其他文章爲:node

  1. k8s 監控(一)安裝 Prometheus
  2. k8s 監控(二)監控集羣組件和 pod
  3. k8s 監控(四)監控宿主機

原本按計劃這篇文章應該講 grafana 和 alertmanager 的,可是因爲它們部署起來太簡單沒有啥寫的動力。最近由於研究了 Prometheus adapter,因此想將本身的研究所得寫下來,也許下一篇會寫 grafana 和 alertmanager。。python

ok,讓咱們直接進入正文。git

kubernetes apiserver 提供了兩種 api 用於監控指標相關的操做:github

kubernetes apiserver 用於將 kubernetes 的功能經過 restapi 的方式暴露出去,給其餘組件使用,可是它提供的都是核心相關功能。有些功能有用,可是非核心,apiserver 又得提供這樣的功能咋辦?正則表達式

考慮到這樣的狀況,kubernetes apiserver 提供對應的 api,可是對於達到這個 api 的請求,它並不處理,而是轉發到一個擴展 apiserver 上。有意思的是,這個擴展 apiserver 只要遵循規範,任何人均可以開發。json

使用者在使用擴展 apiserver 時,只須要將其註冊到 kube-aggregator(kubernetes apiserver 的功能),aggregator 就會將對於這個 api 的請求轉發到這個擴展 apiserver 上。固然 kubernetes apiserver 和擴展 apiserver 之間的交互會涉及到很是多的細節,這裏就很少提。api

resource metrics API 和 custom metrics API 就是這樣的例子,kubernetes apiserver 提供了這兩個 api,可是具體的實現它就無論了。markdown

而這篇文章的目的就是經過 Prometheus adapter 實現它們。app

api group 和 api version

在實現這兩個 api 以前,咱們先來聊聊 api 組和 api 版本。ide

所謂的 api group 就是你執行 kubectl api-versions 出現的值,這些值由 api group 和 api version 構成。

# kubectl api-versions
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
...
複製代碼

內容太多,這裏只列出了 5 個。第一個 admissionregistration.k8s.io/v1beta1 中,admissionregistration.k8s.io 是 api group,v1beta1 表示它的版本。

若是 api group 爲空表示核心 api,kubernetes 的資源都是由 api group 提供的。那麼如何知道哪些資源是由哪些 api group 提供的呢?

執行 kubectl api-resources 就可以知道了:

# kubectl api-resources
NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bindings                                                                      true         Binding
componentstatuses                 cs                                          false        ComponentStatus
configmaps                        cm                                          true         ConfigMap
endpoints                         ep                                          true         Endpoints
events                            ev                                          true         Event
limitranges                       limits                                      true         LimitRange
namespaces                        ns                                          false        Namespace
nodes                             no                                          false        Node
...
複製代碼

內容不少,這裏只列出一部分。輸出結果爲 5 列,NAME 列就是資源名,它的功能由 APIGROUP 列的 api group 提供。SHORTNAMES 列就是這些資源的縮寫了,縮寫在使用 kubectl 時很是好用。

上面列出的全部結果中,APIGROUP 都爲空,表示這些資源都是核心 api 提供的。當你看到某些 role 或者 clusterRole 中 apiGroup 的值爲 "" 時,就應該知道它要訪問的資源都是核心 api 提供的。

對於咱們要實現的兩個 api:

  • resource metrics API 的 api group 是 metrics.k8s.io,版本爲 v1beta1
  • custom metrics API 的 api group 是 custom.metrics.k8s.io,版本爲 v1beta1

它們的 api group 和 api version 會在後面註冊時用到。

custom metrics API

先說這個 custom metrics API,resource metrics API 放在後面。你若是說你只須要 resource metrics API,那你也得看這個,由於這兩個 api 都由 Prometheus adapter 來實現。

custom metrics API 徹底就是給 HPA v2 準備的,由於 v1 只能使用 CPU 做爲 pod 橫向擴展的指標,很明顯沒法知足使用者的須要。

custom metrics API 的實現有多個,咱們之因此選擇 Prometheus adapter,是由於咱們已經安裝了 Prometheus。而經過 Prometheus adapter,只要存在於 Prometheus 中的指標,均可以拿來作 HPA 的條件,這樣就能知足全部的使用場景了。

kubernetes 1.14 中 apiserver 已經開啓了 Aggregation layer,所以咱們只須要安裝 Prometheus adapter 就行。

咱們會使用 deployment 部署 Prometheus adapter,固然會爲啓動它的 serviceAccount 綁定各類角色。由於它自己就是一個 apiserver,所以它會監聽一個端口,對外提供 http 服務。

咱們還須要爲它建立一個 service,kubernetes apiserver 轉發請求時,會將請求發送到 service 上,經由 service 到達後面的 Prometheus adapter。

本文全部的 yml 文件均保存在 GitHub,這裏就不一一列出了。Prometheus adapter 相關的文件都在 adapter 目錄下,custom metrics API 用到的文件有:

prometheus-adapter-apiServiceCustomMetrics.yml
prometheus-adapter-apiServiceMetrics.yml
prometheus-adapter-clusterRoleAggregatedMetricsReader.yml
prometheus-adapter-clusterRoleBindingDelegator.yml
prometheus-adapter-clusterRoleBinding.yml
prometheus-adapter-clusterRole.yml
prometheus-adapter-configMap.yml
prometheus-adapter-deployment.yml
prometheus-adapter-roleBindingAuthReader.yml
prometheus-adapter-serviceAccount.yml
prometheus-adapter-service.yml
複製代碼

其中:

  • apiServiceCustomMetrics:用來提供註冊 api,api 組爲 custom.metrics.k8s.io,版本爲 v1beta1
  • apiServiceMetrics:用來提供註冊 api,api 組爲 metrics.k8s.io,版本爲 v1beta1。這是給 resource metrics 使用的;
  • roleBindingAuthReader:讓擴展 apiserver 能夠去讀取 configMap 來驗證 kubernetes apiserver 的身份,這個不用細究;
  • clusterRoleAggregatedMetricsReader:對 metrics.k8s.iocustom.metrics.k8s.io 下面的任意資源具備任意權限;
  • clusterRoleBindingDelegator:綁定權限,讓 Prometheus adapter 有權限提交 SubjectAccessReview 請求到 kubernetes apiserver;
  • clusterRole:Prometheus adapter 須要訪問集羣內的資源;
  • configMap:Prometheus adapter 的配置文件,這是重點之一;
  • service:kubernetes apiserver 先將請求發送到這個 service,再由它轉發到後面的 Prometheus adapter pod。

部署和測試

不少人在使用的時候會使用 kubernetes CA 簽署一個證書以後用這個證書來爲 Prometheus adapter 提供 https。其實不須要如此,Prometheus adapter 啓動的時候,若是你沒有給它提供證書,它會生成一個自簽署的證書來提供 https。

至於這個證書是否受信任並不重要,由於 prometheus-adapter-apiServiceCustomMetrics.yml 文件中存在 insecureSkipTLSVerify: true 這個選項。

clone 並部署:

git clone https://github.com/maxadd/k8s-prometheus
kubectl apply -f k8s-prometheus/adapter
複製代碼

經過下面直接訪問 api 的方式來測試部署是否 ok(你可能須要略等一下子):

kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | python -mjson.tool
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/monitoring/pods/*/fs_usage_bytes" | python -mjson.tool
複製代碼

第一條命令會輸出很是多的值,都是能夠用做 HPA 的指標。若是你沒有,那麼部署存在問題,緣由後面會講。

第二條命令會輸出 monitoring 名稱空間下全部 pod 的 fs_usage_bytes 指標的值,若是你沒有,那麼部署一樣存在問題。

由於我前面安裝 Prometheus 的文章中對 Prometheus 中的一些指標和標籤作了一些修改,所以若是你直接使用官方的配置,那麼確定會出問題的。配置相關的內容下面會提到。

另外,Prometheus adapter 啓動參數中的 -v 至關於 debug 級別,值越大,輸出的日誌就越詳細,最高貌似爲 10?可是好像這個日誌沒啥做用。。

配置文件

Prometheus adapter 的配置文件格式以下所示(因爲過長,因此截取了一部分)。它分爲兩個部分,第一個是 rules,用於 custom metrics;另外一個是 resourceRules,用於 metrics。若是你只用 Prometheus adapter 作 HPA,那麼 resourceRules 就能夠省略,反之亦然。

咱們從 rules 規則講起,這個規則下面有不少的查詢語句,這些查詢語句的做用就是儘量多的獲取指標,從而讓這些指標均可以用於 HPA。

也就是說經過 Prometheus adapter,你能夠將 Prometheus 中的任何一個指標都用於 HPA,可是前提是你得經過查詢語句將它拿到(包括指標名稱和其對應的值)。也就是說,若是你只須要使用一個指標作 HPA,那麼你徹底就能夠只寫一條查詢,而不像下面使用了好多個查詢。

rules:
 - seriesQuery: '{__name__=~"^container_.*",container_name!="POD",namespace!="",pod!=""}'
 seriesFilters: []
 resources:
 overrides:
 namespace:
 resource: namespace
 pod: # 官方示例中的這個值爲 pod_name,因爲我以前將 pod_name 改成了 pod,因此這裏也爲 pod
 resource: pods
 name:
 matches: ^container_(.*)_seconds_total$
 as: ""
 metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>,container_name!="POD"}[1m])) by (<<.GroupBy>>)
---
resourceRules:
 cpu:
 containerQuery: sum(rate(container_cpu_usage_seconds_total{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)
 nodeQuery: sum(rate(container_cpu_usage_seconds_total{<<.LabelMatchers>>, id='/'}[1m])) by (<<.GroupBy>>)
 resources:
 overrides:
 instance:
 resource: nodes
 namespace:
 resource: namespace
 pod:
 resource: pods
 containerLabel: container_name
複製代碼

接下來咱們會對其關鍵字進行解釋:

  • seriesQuery:查詢 Prometheus 的語句,經過這個查詢語句查詢到的全部指標均可以用於 HPA;
  • seriesFilters:查詢到的指標可能會存在不須要的,能夠經過它過濾掉。過濾器有兩種方式:
    • is: <regex>:只獲取正則表達式匹配到的指標名稱;
    • isNot: <regex>
  • resources:經過 seriesQuery 查詢到的只是指標,我若是要查詢某個 pod 的指標,確定要將它的名稱和所在的名稱空間做爲指標的標籤進行查詢,resources 就是將指標的標籤和 k8s 的資源類型關聯起來,最經常使用的就是 pod 和 namespace。有兩種添加標籤的方式,一種是 overrides,另外一種是 template
    • overrides:它會將指標中的標籤和 k8s 資源關聯起來。上面示例中就是將指標中的 pod 和 namespace 標籤和 k8s 中的 pods(pod 和 pods 都行,這就跟你 kubectl get pod/pods 同樣)和 namespace 關聯起來,由於 pod 和 namespace 都屬於核心 api 組,因此不須要指定 api 組。等你查詢某個 pod 的指標時,它會自動將 pod 的名稱和名稱空間做爲標籤加入到查詢條件中;
      • microservice: {group: "apps", resource: "deployment"} 這麼寫表示將指標中 microservice 這個標籤和 apps 這 api 組中 deployment 資源關聯起來;
    • template:經過 go 模板的形式。
      • template: "kube_<<.Group>>_<<.Resource>>" 這麼寫表示,假如 <<.Group>> 爲 apps,<<.Resource>> 爲 deployment,那麼它就是將指標中 kube_apps_deployment 標籤和 deployment 資源關聯起來;
  • name:用來給指標重命名的。之因此要給指標重命名是由於有些指標是隻增的,好比以 total 結尾的指標。這些指標拿來作 HPA 是沒有意義的,咱們通常計算它的速率,以速率做爲值,那麼此時的名稱就不能以 total 結尾了,因此要進行更名。
    • matches:經過正則表達式來匹配指標名,能夠進行分組;
    • as:默認值爲 $1,也就是第一個分組。as 爲空就是使用默認值的意思。
  • metricsQuery:這就是查詢 Prometheus 了,前面的 seriesQuery 查詢是得到 HPA 指標。當咱們要查某個指標的值時就要經過它指定的查詢語句進行了。能夠看到查詢語句使用了速率和分組,這就是解決上面提到的只增指標的問題,它還用到了模板。
    • Series:指標名稱;
    • LabelMatchers:附加的標籤,目前只有 pod 和 namespace 兩種,所以咱們要在以前使用 resources 進行關聯;
    • GroupBy:就是 pod 名稱,一樣須要使用 resources 進行關聯。

前面訪問 /apis/custom.metrics.k8s.io/v1beta1/ 出現的全部指標都是這些規則中 seriesQuery 查詢到的,固然名稱可能和 Prometheus 中不徹底同樣,由於這裏使用了 name 進行了重命名。

其實不少指標拿來作 HPA 是沒有必要的,好比說 Prometheus 自身的指標以及 k8s 組件指標等,可是 Prometheus adapter 確定但願將全部的指標都暴露出來,讓你想使用啥就使用啥,因此它的 seriesQuery 纔會這麼多。

訪問 /apis/custom.metrics.k8s.io/v1beta1/namespaces/monitoring/pods/*/fs_usage_bytes 則是經過 metricsQuery 進行查詢,從而獲取每一個 pod 的指標值。

部署有問題的多半就是配置文件中的關聯沒有作好,只有理解了這個配置文件的意思才能保證部署沒有問題。

剩下的 resourceRules 規則則是用於 resource metrics,只有 cpu 和 memory 兩個屬性,而這兩個屬性又分爲 node 和 pod,很容易看懂。當執行 kubectl top pods/nodes 時就會執行這兩條查詢語句。

關於 custom metrics 就到此爲止了,HPA 的內容這裏就不涉及了。

resource metrics API

resource metrics API 官方的說法是給 k8s 核心組件提供監控指標的,可是它只提供了 pod 和 node 的 CPU 和內存指標,功能實在有限。

官方給出它能夠作如下工做:

  • HPA:CPU 指標能夠拿來作 HPA。v1 版本的 HPA 也許依賴這個,如今已經無所謂了;
  • pod 調度:官方的意思是這是個擴展的功能,由於如今的 pod 調度根本沒有考慮到 node 的使用狀況;
  • 集羣聯邦:一樣是資源使用,可是如今沒有使用;
  • dashboard:出圖,沒用過 dashboard,也不知道是否是有效果;
  • kubectl top:這算是最實用的功能吧。

因此總結下來,resource metrics API 的最大做用就是居然是讓你可使用 kubectl top 命令?固然我們先無論它是否有用,咱們目的之一就是部署一個擴展 apiserver 來實現它,接下來就是選一個擴展 apiserver。

不少人會使用 metrics server 提供 resource metrics API,而後使用 Prometheus adapter 提供 custom metrics API。可是其實 Prometheus adapter 徹底能夠支持這兩種 api,所以咱們徹底不須要 metrics server,只部署一個 Prometheus adapter 就行。

前面咱們其實已經部署好了,只須要驗證就行。

# kubectl -n monitoring top pods
NAME                                  CPU(cores)   MEMORY(bytes)
alertmanager-c8d754fbc-2slzr          1m           15Mi
grafana-74bf6c49f6-lf7vw              7m           50Mi
kube-state-metrics-856448748c-xtdxl   0m           24Mi
prometheus-adapter-548c9b9c4c-mr9zq   0m           39Mi
複製代碼

可是執行 kubectl top node 會出現問題,由於我將 id='/' 的指標都刪掉了,若是不想將這些指標恢復,能夠看我下一篇收集宿主機指標的文章。

這篇文章就到這了,感謝閱讀,謝謝!