使用Kubernetes 1.15版本,經過API(/metrics)查詢Kubernetes監控指標時,在某些指標的 HELP
信息中,能夠看到諸如 「[ALPHA]」 、「[STABLE]」 、「(Deprecated)」等字樣,用來標明監控指標的穩定性,以便於用戶跟據自身需求來放心的使用這些指標來監控集羣。golang
一個典型的指標以下所示:編程
# HELP rest_client_request_latency_seconds [ALPHA] (Deprecated) Request latency in seconds. Broken down by verb and URL. # TYPE rest_client_request_latency_seconds histogram rest_client_request_latency_seconds_bucket{url="https://[::1]:6443/%7Bprefix%7D",verb="GET",le="0.001"} 36 rest_client_request_latency_seconds_bucket{url="https://[::1]:6443/%7Bprefix%7D",verb="GET",le="0.002"} 148 rest_client_request_latency_seconds_bucket{url="https://[::1]:6443/%7Bprefix%7D",verb="GET",le="0.004"} 166 rest_client_request_latency_seconds_bucket{url="https://[::1]:6443/%7Bprefix%7D",verb="GET",le="0.008"} 172
與其餘API的標識同樣,ALPHA
意味着該監控指標還處理於實驗階段,可能隨時會改變,並且不保證會通知用戶,用戶須要謹慎使用。Deprecated
意味着該監控指標已被棄用,在未來的版本中會被刪除,用戶須要儘快中止使用或使用替代的監控指標。api
本文編寫時間爲1.16版本發佈前夕,既有的監控指標還未所有遷移到該框架中,因此只有部分監控指標會有穩定性標識。app
本文但願從監控指標穩定性框架的開發背景講起,接着介紹該框架的實現原理,以幫助開發者更詳細的瞭解和使用這個特性。框架
不少集羣監控系統都使用Kubernetes提供的監控指標來監控集羣運行情況,然而Kubernetes提供的指標沒有任何穩定性的保證,也就是說Kubernetes隨時有可能修改這些指標,用戶升級新的Kubernetes版本後,有可能原有的監控指標已被修改或直接刪除,這給用戶帶來了困擾,這種用戶的困擾引發了社區關注。學習
爲了解決這個問題,社區進行了普遍的討論,總結下來有這兩種主流的思路:測試
/metrics/v1beta1
、/metrics/v1
等;這兩種思路都有相應的優缺點:this
最後,結合這兩個思路的優缺點,社區使用了一個更具創新性的方案,也就是本文要介紹的穩定性框架,該框架在實現層面相對使用版本標記
更簡單,在工程層面比使用文檔標記
更易於管理。url
與每一個公司成立時都須要一個願景或口號同樣,監控指標穩定性框架也有本身的願景:設計
兩個願景,一個是幫助Kubernetes開發人員定義本身的監控指標,一個是如何向用戶呈現穩定性保證。
同時,如下內容不在框架的考慮範圍:
事實上,本框架不考慮的這些內容也很重要,會在社區其餘事項中去作,只是本框架不負責這些內容。
咱們或許都據說過Prometheus已成爲Kubernetes監控的事實標準,這體如今Kubernetes的不少組件(kube-scheduler、kubelet、kube-controller-manager和kube-apiserver等)都使用Prometheus客戶端來生成Prometheus格式的監控指標。
使用Prometheus,對於每一個監控指標通常會先初始化一個實例,再添加到全局的註冊表中,最後當用戶使用API訪問時,http handler 負責把這些監控指標導出。
初始化實例:
var authenticatedUserCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "authenticated_user_requests", Help: "Counter of authenticated requests broken out by username.", }, []string{"username"}, )
添加到註冊表:
prometheus.MustRegister(authenticatedUserCounter)
http handler 使用的也是 Prometheus提供的handler:
// Install adds the DefaultMetrics handler func (m DefaultMetrics) Install(c *mux.PathRecorderMux) { register() c.Handle("/metrics", prometheus.Handler()) }
由上能夠看到,原有的監控標標嚴重依賴Prometheus的特性,而新的框架設計將會對監控指標的定義、初始化、註冊過程進行封裝,即各組件再也不直接使用Prometheus,而是使用新的框架,儘管新的框架仍是使用Prometheus來實現,但提供了更多個性化的設計。
在監控指標定義環節,新框架提供了新的指標參數結構體,以便於增長穩定性標識。
好比,曾經使用Prometheus定義一個計數器時會使用prometheus.CounterOpts
結構體,以下所示:
var someMetricDefinition = prometheus.CounterOpts{ Name: "some_metric", Help: "some description", }
新框架則提供了一個通過擴展的參數結構體kubemetrics.CounterOpts
,新增長了StabilityLevel
和DeprecatedVersion
等字段用於表示穩定性和棄用標示。
表示一個監控指標被廢棄,能夠以下定義:
var deprecatedMetricDefinition = kubemetrics.CounterOpts{ Name: "some_deprecated_metric", Help: "some description", StabilityLevel: kubemetrics.STABLE, // 自定義字段,穩定性標識 DeprecatedVersion: "1.15", // 自定義字段,棄用標識 }
表示一個ALPHA監控指標,能夠以下定義:
var alphaMetricDefinition = kubemetrics.CounterOpts{ Name: "some_alpha_metric", Help: "some description", StabilityLevel: kubemetrics.ALPHA, DeprecatedVersion: "1.15", // 可選字段,標明將在哪一個版本棄用 }
與Prometheus一致,新框架對4種監控指標分別作了擴展:
本節暫不對每種監控指標展開介紹,仍是聚焦在闡述新框架的實現思路上。
曾經,使用Prometheus來初始化監控指標(獲取監控指標實例),將使用一系列的prometheus.NewXXX()
方法,以下所示:
var someCounterVecMetric = prometheus.NewCounterVec( someMetricDefinition, // 指標定義 []string{"some-label", "other-label"}, // 指標的label }
一方面,因爲新的框架擴展了指標定義結構體,沒法繼續使用prometheus.NewXXX()
方法,另外一方面新框架也但願能在指標初始化時擴展自定義行爲(好比處理定義環節加入的字段),因此新框架中也提供了相似的一系列方法。
使用新框架的方法來初始化實例示例以下:
var deprecatedMetric = kubemetrics.NewCounterVec( deprecatedMetricDefinition, // 擴展的指標定義 []string{"some-label", "other-label"}, }
一樣與Prometheus保持一致,新框架也提供了全部的初始化方法:
一樣,本節暫不對每種初始化方法展開介紹,這部份內容留到後面的章節中。
曾經,使用Prometheus來註冊一個監控指標實例時,其實是註冊到一個全局的註冊表,以下所示:
prometheus.MustRegister(someCounterVecMetric)
新框架中對註冊也進行了封裝,以便增長自定義的行爲,好比廢棄版本檢查,註冊邏輯僞代碼以下:
import version "k8s.io/apimachinery/pkg/version" type Registry struct { promregistry *prometheus.Registry KubeVersion version.Info } func (r *Registry) MustRegister(metric kubemetrics.Metric) { if metricutils.compare(metric.DeprecatedVersion).isLessThan(r.KubeVersion) { // 若是廢棄版本比當前版本低,檢查廢棄規則,不知足則再也不註冊 // check if binary has deprecated metrics enabled otherwise // no-op registration return } else if metricutils.compare(metric.DeprecatedVersion).isEqual(r.KubeVersion) { // 若是廢棄版本與當前版本一致,則把棄用信息增長到指標的 HELP 信息中並記錄 warning 日誌 // append deprecated text to description // emit warning in logs // continue to actual registration } // 若是是 ALPHA 監控指標,增長相應的標識到 HELP 信息中 r.promregistry.MustRegister(metric.realMetric) // 最後仍是使用Prometheus來完成註冊 }
使用新框架註冊,以下所示:
kubemetrics.MustRegister(deprecatedMetric) kubemetrics.MustRegister(alphaMetric)
由上綜述,能夠看到在編程層面,既有的監控指標能夠方便的遷移到新框架,若是監控指標沒有個性化的需求,那麼其行爲與原Prometheus徹底一致,若是有個性化的需求,經過簡單的配置就可完成,具體的實現細節所有由新框架負責。
當前版本(kubernetes 1.15 & 1.16)提供兩個級別的穩定性,用來闡述每一個監控指標的穩定性:
須要額外說起的時,在當前的設計中並無考慮 Beta 級別,新框架做者表示未來有須要時再添加,添加也會很是簡單。
Alpha 級別的監控指標,基本上不提供任何穩定性的保證,它們能夠隨時被修改,並且新框架引入後,既有的監控指標都將標記爲這個級別。
Stable 級別的監控指示,基本上能夠保證「再也不修改」,除非未來被廢棄。這裏所說的「再也不修改」指如下三個內容不會修改:
針對Stable級別的監控指標,lable列表不會改變,但lable 值是能夠改變的。好比,某個指標用於記錄鑑權的次數,使用"result"做爲lable進行區分,lable 值原來是"success"和"failure",是容許增長新的lable 值的,好比增長一個"error"(不是簡單的鑑權失敗,而是出現某種異常)。
好比,你以前獲得的指標將會由:
authentication_attempts{result="success"} 1345 authentication_attempts{result="failure"} 100
變成:
authentication_attempts{result="success"} 1345 authentication_attempts{result="failure"} 100 authentication_attempts{result="error"} 1 // 增長新的lable 值
通常來說,這種變化對用戶的衝擊不會很大。
針對Stable級別的監控指標,刪除或增長 lable 是不容許的,若是必需要這麼作,須要先把當前的指標廢棄,再提供一個新的監控指標。
對於用戶來說,新框架還提供了一個由用戶顯式的屏蔽某些監控指標的能力,默認狀況下,全部的監控指標都會被註冊並最終經過API提供給用戶,但使用新框架後,用戶能夠經過相應組件的啓動參數顯式的關掉某些監控指標,好比:
--disable-metrics=somebrokenmetric,anothermetric
把一個監控指標標記爲 Stable 意味着對廣大用戶作出了一個承諾,這跟 API 是一致的。因此將某個監控指標標記爲 Stable 或者 廢棄某個監控指標時,須要很是謹慎的 review。
然而,跟據Kubernetes社區的組織劃分,各個組件分別有不一樣的 group (準確叫法是SIG)來負責相應的組件開發,各group的 reviewer 可能並不徹底瞭解新框架所引入的這個理念,因此各group頗有可能未來破壞以前作出的穩定性承諾。而每一個相關監控指標的修改都由負責監控的group來review,代價會很是大,而變得不可取。
針對這個問題,kubernetes社區又提供了讓人眼前一亮的方法,即引入新的一致性測試。 即,生成一份現有的穩定性列表,並存放到某個由監控組管理的目錄中,增長新的CI工做流收集最新的穩定性監控指標,兩者對比,若是不一致,CI 會失敗並拒絕合入,除非顯式的修改穩定性列表。CI能夠保證當顯式的修改穩定性列表時,必須通過監控組的批准。
每一個Stable的監控指標,在決定要將其廢棄後,能夠在監控指標定義處顯式的指定將要棄用的版本(DeprecatedVersion
)。某個指標標記爲廢棄後不會立刻被刪除,須要留給用戶一個適配的窗口,在接下來的某些版本中才會真正被刪除。
被廢棄的監控指標都會經歷以下階段(每一個階段表明一個kubernetes minor版本):
Stable metric -> Deprecated metric -> Hidden metric -> Deletion
好比,某個監控指標在1.16版本進入 Stable 階段,將在 1.17版本棄用,那麼在各版本其狀態以下:
好比,某個監控指標將在1.17版本廢棄,那麼1.17版本(或更早的版本)開發時能夠這樣設置:
var someCounter = kubemetrics.CounterOpts{ Name: "some_counter", Help: "this counts things", StabilityLevel: kubemetrics.STABLE, DeprecatedVersion: "1.17", // this metric is deprecated when the Kubernetes version == 1.17 }
使用1.17以前的版本,監控指標信息以下:
# HELP some_counter this counts things # TYPE some_counter counter some_counter 0
那麼用戶在使用1.17版本時,將會看到相應的指標信息中出現棄用信息:
# HELP some_counter (Deprecated from 1.17) this counts things # TYPE some_counter counter some_counter 0
此外,當監控指標被標記爲廢棄後,雖然能正常使用,可是在相應的組件日誌中能夠看到告警日誌。
當監控指標被棄用的下一個版本,即DeprecatedVersion
== current_kubernetes_version - 1時,該監控指標默認會被隱藏:即不會自動註冊。
被隱藏的指標能夠經過相應組件的啓動參數(--enable-hidden-metrics=really_deprecated_metric)來顯式的啓用。
若是用戶忘記在上個版本中作好適配,仍然能夠在本版本中繼續使用,這無疑給用戶延長了適配窗口。
另外,須要特別說起的幾點是:
新的監控指標框架是社區衆多專家智慧的結晶,從其設計理念上能夠看出Kubernetes社區對用戶承諾的重視,能夠看出對軟件工程的深層次的思考,值得學習。