共計(jì) 9193 個(gè)字符,預(yù)計(jì)需要花費(fèi) 23 分鐘才能閱讀完成。
本篇內(nèi)容介紹了“監(jiān)控自定義指標(biāo)的 HPA 怎么部署”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓丸趣 TV 小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
HPA 簡(jiǎn)介
HPA(Horizontal Pod Autoscaler)是 kubernetes(以下簡(jiǎn)稱 k8s)的一種資源對(duì)象,能夠根據(jù)某些指標(biāo)對(duì)在 statefulSet、replicaController、replicaSet 等集合中的 pod 數(shù)量進(jìn)行動(dòng)態(tài)伸縮,使運(yùn)行在上面的服務(wù)對(duì)指標(biāo)的變化有一定的自適應(yīng)能力。
HPA 目前支持四種類型的指標(biāo),分別是 Resource、Object、External、Pods。其中在穩(wěn)定版本 autoscaling/v1 中只支持對(duì) CPU 指標(biāo)的動(dòng)態(tài)伸縮,在測(cè)試版本 autoscaling/v2beta2 中支持 memory 和自定義指標(biāo)的動(dòng)態(tài)伸縮,并以 annotation 的方式工作在 autoscaling/v1 版本中。HPA 在 k8s 中的結(jié)構(gòu)
首先可以看一下 HPA 在 k8s 中的結(jié)構(gòu),這里找了一個(gè) k8s 官方給出的 HPA 例子,我在關(guān)鍵字段上給出一些注釋方便理解。
- type: Pods
pods:
metric:
name: packets-per-second
# AverageValue 類型的目標(biāo)值,Pods 指標(biāo)類型下只支持 AverageValue 類型的目標(biāo)值
target:
type: AverageValue
averageValue: 1k
# External 類型的指標(biāo)
- type: External
external:
metric:
name: queue_messages_ready
# 該字段與第三方的指標(biāo)標(biāo)簽相關(guān)聯(lián),(此處官方文檔有問題,正確的寫法如下) selector:
matchLabels:
env: stage
app: myapp
# External 指標(biāo)類型下只支持 Value 和 AverageValue 類型的目標(biāo)值
target:
type: AverageValue
averageValue: 30
autoscaling/v1 版本將 metrics 字段放在了 annotation 中進(jìn)行處理。
target 共有 3 種類型:Utilization、Value、AverageValue。Utilization 表示平均使用率;Value 表示裸值;AverageValue 表示平均值。
metrics 中的 type 字段有四種類型的值:Object、Pods、Resource、External。
Resource 指的是當(dāng)前伸縮對(duì)象下的 pod 的 cpu 和 memory 指標(biāo),只支持 Utilization 和 AverageValue 類型的目標(biāo)值。
Object 指的是指定 k8s 內(nèi)部對(duì)象的指標(biāo),數(shù)據(jù)需要第三方 adapter 提供,只支持 Value 和 AverageValue 類型的目標(biāo)值。
Pods 指的是伸縮對(duì)象(statefulSet、replicaController、replicaSet)底下的 Pods 的指標(biāo),數(shù)據(jù)需要第三方的 adapter 提供,并且只允許 AverageValue 類型的目標(biāo)值。
External 指的是 k8s 外部的指標(biāo),數(shù)據(jù)同樣需要第三方的 adapter 提供,只支持 Value 和 AverageValue 類型的目標(biāo)值。
HPA 動(dòng)態(tài)伸縮的原理
HPA 在 k8s 中也由一個(gè) controller 控制,controller 會(huì)間隔循環(huán) HPA,檢查每個(gè) HPA 中監(jiān)控的指標(biāo)是否觸發(fā)伸縮條件,默認(rèn)的間隔時(shí)間為 15s。一旦觸發(fā)伸縮條件,controller 會(huì)向 k8s 發(fā)送請(qǐng)求,修改伸縮對(duì)象(statefulSet、replicaController、replicaSet)子對(duì)象 scale 中控制 pod 數(shù)量的字段。k8s 響應(yīng)請(qǐng)求,修改 scale 結(jié)構(gòu)體,然后會(huì)刷新一次伸縮對(duì)象的 pod 數(shù)量。伸縮對(duì)象被修改后,自然會(huì)通過 list/watch 機(jī)制增加或減少 pod 數(shù)量,達(dá)到動(dòng)態(tài)伸縮的目的。
HPA 伸縮過程敘述
HPA 的伸縮主要流程如下:
1. 判斷當(dāng)前 pod 數(shù)量是否在 HPA 設(shè)定的 pod 數(shù)量區(qū)間中,如果不在,過小返回最小值,過大返回最大值,結(jié)束伸縮。
2. 判斷指標(biāo)的類型,并向 api server 發(fā)送對(duì)應(yīng)的請(qǐng)求,拿到設(shè)定的監(jiān)控指標(biāo)。一般來說指標(biāo)會(huì)根據(jù)預(yù)先設(shè)定的指標(biāo)從以下三個(gè) aggregated APIs 中獲取:metrics.k8s.io、custom.metrics.k8s.io、 external.metrics.k8s.io。其中 metrics.k8s.io 一般由 k8s 自帶的 metrics-server 來提供,主要是 cpu,memory 使用率指標(biāo),另外兩種需要第三方的 adapter 來提供。custom.metrics.k8s.io 提供自定義指標(biāo)數(shù)據(jù),一般跟 k8s 集群有關(guān),比如跟特定的 pod 相關(guān)。external.metrics.k8s.io 同樣提供自定義指標(biāo)數(shù)據(jù),但一般跟 k8s 集群無關(guān)。許多知名的第三方監(jiān)控平臺(tái)提供了 adapter 實(shí)現(xiàn)了上述 api(如 prometheus),可以將監(jiān)控和 adapter 一同部署在 k8s 集群中提供服務(wù),甚至能夠替換原來的 metrics-server 來提供上述三類 api 指標(biāo),達(dá)到深度定制監(jiān)控?cái)?shù)據(jù)的目的。
3. 根據(jù)獲得的指標(biāo),應(yīng)用相應(yīng)的算法算出一個(gè)伸縮系數(shù),并乘以目前 pod 數(shù)量獲得期望 pod 數(shù)量。系數(shù)是指標(biāo)的期望值與目前值的比值,如果大于 1 表示擴(kuò)容,小于 1 表示縮容。指標(biāo)數(shù)值有平均值(AverageValue)、平均使用率(Utilization)、裸值(Value)三種類型,每種類型的數(shù)值都有對(duì)應(yīng)的算法。以下幾點(diǎn)值得注意:如果系數(shù)有小數(shù)點(diǎn),統(tǒng)一進(jìn)一;系數(shù)如果未達(dá)到某個(gè)容忍值,HPA 認(rèn)為變化太小,會(huì)忽略這次變化,容忍值默認(rèn)為 0.1。
HPA 擴(kuò)容算法是一個(gè)非常保守的算法。如果出現(xiàn)獲取不到指標(biāo)的情況,擴(kuò)容時(shí)算最小值,縮容時(shí)算最大值;如果需要計(jì)算平均值,出現(xiàn) pod 沒準(zhǔn)備好的情況,平均數(shù)的分母不計(jì)入該 pod。
一個(gè) HPA 支持多個(gè)指標(biāo)的監(jiān)控,HPA 會(huì)循環(huán)獲取所有的指標(biāo),并計(jì)算期望的 pod 數(shù)量,并從期望結(jié)果中獲得最大的 pod 數(shù)量作為最終的伸縮的 pod 數(shù)量。一個(gè)伸縮對(duì)象在 k8s 中允許對(duì)應(yīng)多個(gè) HPA,但是只是 k8s 不會(huì)報(bào)錯(cuò)而已,事實(shí)上 HPA 彼此不知道自己監(jiān)控的是同一個(gè)伸縮對(duì)象,在這個(gè)伸縮對(duì)象中的 pod 會(huì)被多個(gè) HPA 無意義地來回修改 pod 數(shù)量,給系統(tǒng)增加消耗,如果想要指定多個(gè)監(jiān)控指標(biāo),可以如上述所說,在一個(gè) HPA 中添加多個(gè)監(jiān)控指標(biāo)。
4. 檢查最終的 pod 數(shù)量是否在 HPA 設(shè)定的 pod 數(shù)量范圍的區(qū)間,如果超過最大值或不足最小值都會(huì)修改為最大值或最小值。然后向 k8s 發(fā)出請(qǐng)求,修改伸縮對(duì)象的子對(duì)象 scale 的 pod 數(shù)量,結(jié)束一個(gè) HPA 的檢查,獲取下一個(gè) HPA,完成一個(gè)伸縮流程。
HPA 的應(yīng)用場(chǎng)景
HPA 的特性結(jié)合第三方的監(jiān)控應(yīng)用,使得部署在 HPA 伸縮對(duì)象(statefulSet、replicaController、replicaSet)上的服務(wù)有了非常靈活的自適應(yīng)能力,能夠在一定限度內(nèi)復(fù)制多個(gè)副本來應(yīng)對(duì)某個(gè)指標(biāo)的急劇飆升,也可以在某個(gè)指標(biāo)較小的情況下刪除副本來讓出計(jì)算資源給其他更需要資源的應(yīng)用使用,維持整個(gè)系統(tǒng)的穩(wěn)定。非常適合于一些流量波動(dòng)大,機(jī)器資源吃緊,服務(wù)數(shù)量多的業(yè)務(wù)場(chǎng)景,如:電商服務(wù)、搶票服務(wù)、金融服務(wù)等。
k8s-prometheus-adapter
前文說到,許多監(jiān)控系統(tǒng)通過 adapter 實(shí)現(xiàn)了接口,給 HPA 提供指標(biāo)數(shù)據(jù)。在這里我們具體介紹一下 prometheus 監(jiān)控系統(tǒng)的 adapter。
prometheus 是一個(gè)知名開源監(jiān)控系統(tǒng),具有數(shù)據(jù)維度多,存儲(chǔ)高效,使用便捷等特點(diǎn)。用戶可以通過豐富的表達(dá)式和內(nèi)置函數(shù),定制自己所需要的監(jiān)控?cái)?shù)據(jù)。
prometheus-adapter 在 prometheus 和 api-server 中起到了適配者的作用。prometheus-adapter 接受從 HPA 中發(fā)來,通過 apiserver aggregator 中轉(zhuǎn)的指標(biāo)查詢請(qǐng)求,然后根據(jù)內(nèi)容發(fā)送相應(yīng)的請(qǐng)求給 prometheus 拿到指標(biāo)數(shù)據(jù),經(jīng)過處理后返回給 HPA 使用。prometheus 可以同時(shí)實(shí)現(xiàn) metrics.k8s.io、custom.metrics.k8s.io、 external.metrics.k8s.io 三種 api 接口,代替 k8s 自己的 matrics-server,提供指標(biāo)數(shù)據(jù)服務(wù)。
prometheus-adapter 部署能否成功的關(guān)鍵在于配置文件是否正確。配置文件中可以設(shè)定需要的指標(biāo)以及對(duì)指標(biāo)的處理方式,以下是一份簡(jiǎn)單的配置文件,加上注釋以稍做解釋。
# 指標(biāo)規(guī)則,可以多個(gè)規(guī)則共存,上一個(gè)規(guī)則的結(jié)果會(huì)傳給下一個(gè)規(guī)則
rules:
# 計(jì)算指標(biāo)數(shù)據(jù)的表達(dá)式
- metricsQuery: sum(rate( .Series { .LabelMatchers}[5m])) by (.GroupBy)
# 指標(biāo)重命名,支持正則表達(dá)式。這里表示刪除指標(biāo)名字中的 _seconds_total
name:
as:
matches: (.*)_seconds_total$
# 指標(biāo)與 k8s 資源通過標(biāo)簽關(guān)聯(lián),這里將指標(biāo)通過標(biāo)簽與 k8s 的 namspace 和 pod 相互關(guān)聯(lián)
resources:
overrides:
namespace:
resource: namespace
pod:
resource: pod
# 過濾指標(biāo)條件
seriesFilters: []
# 指標(biāo)查詢表達(dá)式,可以根據(jù)標(biāo)簽等條件,篩選特定的指標(biāo)
seriesQuery: {namespace!= ,pod!=}
metricsQuery 字段會(huì)在 k8s 請(qǐng)求時(shí)執(zhí)行,其中,“”“”是 go 的模板語法,Series 表示指標(biāo)名稱,LabelMatchers 表示指標(biāo)與 k8s 對(duì)象名稱匹配的標(biāo)簽鍵值對(duì),GroupBy 表示指標(biāo)數(shù)值歸并的標(biāo)簽名。
不太好理解,這里截取官方文檔中的一個(gè)例子來進(jìn)行說明,看了就應(yīng)該明白了:
For instance, suppose we had a series http_requests_total (exposed ashttp_requests_per_second in the API) with labels service, pod,ingress, namespace, and verb. The first four correspond to Kubernetes resources. Then, if someone requested the metric pods/http_request_per_second for the pods pod1 and pod2 in the somens namespace, we’d have:
- Series: http_requests_total
- LabelMatchers: pod=~\ pod1|pod2 ,namespace= somens
- GroupBy: pod
resources 字段是 k8s 資源對(duì)象與指標(biāo)關(guān)聯(lián)的重要字段,本質(zhì)上是根據(jù)指標(biāo)的標(biāo)簽值與 k8s 資源對(duì)象名稱進(jìn)行匹配,resources 字段告訴系統(tǒng),應(yīng)該用指標(biāo)的哪個(gè)標(biāo)簽的標(biāo)簽值來匹配 k8s 資源對(duì)象名稱。有兩個(gè)方法關(guān)聯(lián)資源,一種是通過 overrides,將特定的標(biāo)簽與 k8s 資源對(duì)象綁定起來,當(dāng) k8s 請(qǐng)求指標(biāo)的時(shí)候,會(huì)將資源對(duì)象名稱與這個(gè)特定的標(biāo)簽值進(jìn)行比較,來分辨指標(biāo)具體是哪個(gè)對(duì)象的;另一種是 template,通過 go 語言模板語法將 k8s 資源對(duì)象名轉(zhuǎn)化成標(biāo)簽名,進(jìn)行匹配。
第二種方法,不太好理解,同樣截取官方文檔中的一個(gè)例子來進(jìn)行說明:
# any label `kube_ group _ resource ` becomes group . resource in Kubernetes
resources:
template: kube_ .Group _ .Resource
部署一個(gè)監(jiān)控自定義指標(biāo)的 HPA
1. 部署 prometheus 應(yīng)用,使其正常工作。可以使用官方的 helm 包快捷部署,之后的應(yīng)用也基本以 helm 包的方式部署,不再贅述。
2. 部署需要伸縮的應(yīng)用。這里我選擇了一個(gè)簡(jiǎn)單的 nginx 服務(wù),部署為 deployment 作為伸縮對(duì)象。
3. 在應(yīng)用的命名空間下,部署提供自定義指標(biāo)的應(yīng)用。這里我選擇了官方的 prometheus-node-exporter,并以 nodeport 的方式暴露數(shù)據(jù)端口,作為自定義指標(biāo)數(shù)據(jù)的來源。這個(gè)應(yīng)用會(huì)以 daemonSet 的方式運(yùn)行在 k8s 集群的每個(gè) node 上,并對(duì)外開放在自己 node 上獲取到的指標(biāo)。
在 prometheus 的界面上已經(jīng)可以看到 node-exporter 暴露出來的指標(biāo)了
4. 部署 prometheus-adapter 應(yīng)用。在 helm 包的 values 中修改其配置文件,配置文件如下
resources:
template: .Resource
seriesFilters: []
seriesQuery: {namespace!= ,pod!=}
- metricsQuery: sum(rate( .Series { .LabelMatchers}[5m])) by (.GroupBy)
name:
as:
matches: (.*)_total$
resources:
template: .Resource
seriesFilters:
- isNot: (.*)_seconds_total$
seriesQuery: {namespace!= ,pod!=}
- metricsQuery: sum(.Series { .LabelMatchers}) by (.GroupBy)
name:
as:
matches: (.*)$
resources:
template: .Resource
seriesFilters:
- isNot: (.*)_total$
seriesQuery: {namespace!= ,pod!=}
上述配置文件將 secondstotal 和_total 結(jié)尾的指標(biāo)用 prometheus 的內(nèi)置函數(shù)進(jìn)行了速率計(jì)算,并去掉對(duì)應(yīng)的后綴作為指標(biāo)名稱。
我們?cè)?k8s 中利用 kubectl 查看指標(biāo)是否能夠獲得到指標(biāo)
kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/
你會(huì)看到所有的你能夠獲得的指標(biāo)名稱,但是名字和數(shù)據(jù)已經(jīng)和原來的指標(biāo)有所不同了,因?yàn)槲覀冊(cè)?adapter 的配置文件中做了一定程度的修改。
然后我們獲取一下 node_cpu 這個(gè)指標(biāo),看看是否能夠正確地顯示出來
kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-nginx/pods/*/node_cpu | jq
這個(gè)命令能夠顯示 my-nginx 這個(gè) namspace 下的所有 pod 的 node_cpu 指標(biāo)的數(shù)據(jù),結(jié)果如下
{
kind : MetricValueList ,
apiVersion : custom.metrics.k8s.io/v1beta1 ,
metadata : {
selfLink : /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-nginx/pods/%2A/node_cpu
},
items : [
{
describedObject : {
kind : Pod ,
namespace : my-nginx ,
name : prometheus-node-exporter-b25zl ,
apiVersion : /v1
},
metricName : node_cpu ,
timestamp : 2019-10-29T03:33:47Z ,
value : 3822m
}
]
}
ok,到這里,說明所有的組件工作正常,hpa 能夠順利地得到這個(gè)指標(biāo)。需要注意的是 HPA 和監(jiān)控對(duì)象,伸縮對(duì)象一定要部署在同一個(gè)命名空間下,不然會(huì)獲取不到相應(yīng)的指標(biāo)。
5. 部署 hpa,其 yaml 文件如下
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: hpa-asdfvs
namespace: my-nginx
spec:
scaleTargetRef:
apiVersion: apps/v1beta1
kind: Deployment
name: my-nginx
minReplicas: 1
maxReplicas: 10
metrics:
- type: Object
object:
metric:
name: node_cpu
describedObject:
apiVersion: v1
kind: Pod
name: prometheus-node-exporter-b25zl
target:
type: Value
value: 9805m
我們將根據(jù) prometheus-node-exporter 這個(gè) pod 的 node_cpu 這個(gè)指標(biāo)來動(dòng)態(tài)伸縮我們的 nginx 應(yīng)用。
我們來獲取一下這個(gè) hpa
kubectl get horizontalPodAutoscaler -n my-nginx hpa-asdfvs -oyaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
annotations:
autoscaling.alpha.kubernetes.io/conditions: [{ type : AbleToScale , status : True , lastTransitionTime : 2019-10-29T02:54:50Z , reason : ReadyForNewScale , message : recommended
size matches current size },{ type : ScalingActive , status : True , lastTransitionTime : 2019-10-29T03:05:24Z , reason : ValidMetricFound , message : the
HPA was able to successfully calculate a replica count from Pod metric node_cpu },{ type : ScalingLimited , status : False , lastTransitionTime : 2019-10-29T02:54:50Z , reason : DesiredWithinRange , message : the
desired count is within the acceptable range }]
autoscaling.alpha.kubernetes.io/current-metrics: [{type : Object , object :{ target :{ kind : Pod , name : prometheus-node-exporter-b25zl , apiVersion : v1}, metricName : node_cpu , currentValue : 3822m }}]
autoscaling.alpha.kubernetes.io/metrics: [{type : Object , object :{ target :{ kind : Pod , name : prometheus-node-exporter-b25zl , apiVersion : v1}, metricName : node_cpu , targetValue : 9805m }}]
kubectl.kubernetes.io/last-applied-configuration: |
{apiVersion : autoscaling/v2beta2 , kind : HorizontalPodAutoscaler , metadata :{ annotations :{}, name : hpa-asdfvs , namespace : my-nginx }, spec :{maxReplicas :10, metrics :[{ object :{ describedObject :{ apiVersion : v1 , kind : Pod , name : prometheus-node-exporter-b25zl}, metric :{name : node_cpu}, target :{type : Value , value : 9805m}}, type : Object }], minReplicas :1, scaleTargetRef :{apiVersion : apps/v1beta1 , kind : Deployment , name : my-nginx}}}
creationTimestamp: 2019-10-29T02:54:45Z
name: hpa-asdfvs
namespace: my-nginx
resourceVersion: 164701
selfLink: /apis/autoscaling/v1/namespaces/my-nginx/horizontalpodautoscalers/hpa-asdfvs
uid: 76fa6a19-f9f7-11e9-8930-0242c5ccd054
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1beta1
kind: Deployment
name: my-nginx
status:
currentReplicas: 1
desiredReplicas: 1
lastScaleTime: 2019-10-29T03:06:10Z
可以看到 hpa 以 annotation 的方式在 v1 版本工作,并將 matrics 字段寫入了 annotation 中。在 annotation 的 condition 字段中,我們清楚地看到 HPA 已經(jīng)獲取到了這個(gè)指標(biāo)。之后我們可以嘗試降低 target 值來讓 pod 擴(kuò)展,或者增加 target 值來使 pod 縮減。
“監(jiān)控自定義指標(biāo)的 HPA 怎么部署”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注丸趣 TV 網(wǎng)站,丸趣 TV 小編將為大家輸出更多高質(zhì)量的實(shí)用文章!