本文嘗試以通俗的方式向讀者介紹K8s的Pod的自動(dòng)化橫向擴(kuò)縮容的領(lǐng)域模型。其實(shí)是以領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)的思考方式來學(xué)習(xí)一項(xiàng)技術(shù)。希望能對(duì)讀者幫助。
問題是什么
當(dāng)要理解一個(gè)解決方案時(shí),我們從問題域開始理解,會(huì)更容易。
比如存在一個(gè)場(chǎng)景:基于Pod的CPU使用率進(jìn)行自動(dòng)化擴(kuò)容。當(dāng)一個(gè)Pod的CPU使用率大于60%,并持續(xù)15秒時(shí),我們就希望Pod的數(shù)量從10個(gè)擴(kuò)到13個(gè)。
要實(shí)現(xiàn)這個(gè)場(chǎng)景,我們推斷K8s應(yīng)該存在一種機(jī)制方便我們實(shí)現(xiàn)這個(gè)場(chǎng)景。這種機(jī)制就是HPA(Horizontal Pod Autoscaler)。
換位思考一下,如果你是HPA機(jī)制的使用者,你會(huì)如何使用HPA呢?
你可能會(huì)配置如下:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
(如果看不懂,也沒有關(guān)系,你只需要知道,你可以通過代碼來定義HPA的行為)
作為用戶,你只需要通過YAML文件定義清楚你的期望就可以了。至于如何實(shí)現(xiàn),是由HPA機(jī)制的實(shí)現(xiàn)者實(shí)現(xiàn)的。
就好比司機(jī)開車過程中是不需要考慮動(dòng)力系統(tǒng)是由電機(jī)實(shí)現(xiàn)的,還是由柴油引擎實(shí)現(xiàn)的。這就是“接口是用戶的”的含義了。當(dāng)然,作為汽車的設(shè)計(jì)者,你就必須考慮動(dòng)力系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)。
同樣的,作為K8s的設(shè)計(jì)者,就必須考慮HPA機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)。
當(dāng)用戶通過kubectl apply -f hpa.yaml命令部署HPA到K8s中時(shí),我們的K8s該做什么呢?它需要考慮以下問題:
- 我該如何拿到用戶Pod的某一個(gè)指標(biāo)的值呢?
- 多久拿一次指標(biāo)呢?
- 當(dāng)這個(gè)指標(biāo)不是CPU,內(nèi)存等資源指標(biāo),而是應(yīng)用本身的自定義指標(biāo)呢?如果指標(biāo)數(shù)據(jù)甚至不在K8s內(nèi)部呢?
- Pod本來已經(jīng)是由控制器控制的了,我們是該控制控制器去完成工作,還是直接控制Pod去完成?
- 當(dāng)用戶需要根據(jù)多個(gè)指標(biāo)的值共同決定擴(kuò)容時(shí),我們?cè)撊绾螜?quán)衡其中的策略?
- 如果Pod中有多個(gè)容器,如何根據(jù)其中一個(gè)容器的指標(biāo)進(jìn)行擴(kuò)容?
- 以上說的都是擴(kuò)容,如何縮容呢?
- 縮容太快了,怎么辦?即如何保證縮容時(shí)的穩(wěn)定性?
筆者對(duì)以上相對(duì)口語的表述進(jìn)行抽象。當(dāng)我們作為K8s的HPA的設(shè)計(jì)者與實(shí)現(xiàn)者時(shí),我們需要考慮以下問題:
- 指標(biāo)來源問題;
- 指標(biāo)的數(shù)量問題:即不僅只支持針對(duì)一個(gè)指標(biāo)的擴(kuò)縮容;
- 指標(biāo)類型支持問題:資源指標(biāo)、自定義指標(biāo)、外部指標(biāo);
- Pod擴(kuò)縮的控制器實(shí)現(xiàn);
- 自定義Pod擴(kuò)縮行為:擴(kuò)容行為應(yīng)該可以由用戶自定義。
接下來我們分別看下K8s是如何解決以上問題的。
指標(biāo)來源與指標(biāo)類型
HPA控制器會(huì)從Metrics API中獲取指標(biāo)。而Metrics API根據(jù)不同的指標(biāo)類型去不同的Metrics API的實(shí)現(xiàn)中去獲取指標(biāo)。

Metrics API支持三類指標(biāo):
- 資源指標(biāo):CPU和內(nèi)存的使用率指標(biāo),由Metrics Server提供。Metrics Server需要單獨(dú)安裝;
- 自定義指標(biāo):比如應(yīng)用的連接數(shù)大小。最終由你的Custom Metrics API的實(shí)現(xiàn)者提供;
- 外部自定義指標(biāo):與K8s 對(duì)象無關(guān)的自定義指標(biāo)。
自定義指標(biāo)與外部自定義指標(biāo)的區(qū)別是該自定義指標(biāo)是否來自于與應(yīng)用同處于同一個(gè)K8s集群。
雖然定義是這樣,這個(gè)界線也可以被打破,如下圖:

Pod擴(kuò)縮的控制器實(shí)現(xiàn)及自定義Pod擴(kuò)縮行為
當(dāng)HPA拿到指標(biāo)后,在哪里,又該如何實(shí)現(xiàn)對(duì)Pod的數(shù)量的控制呢?
既然Pod已經(jīng)存在Deployment 及其 Replicate Controller了,沒有必要再重新設(shè)計(jì)一個(gè)新的控制器,在現(xiàn)有的控制器之上進(jìn)行操作即可。
這部分邏輯是HPA的核心邏輯。具體實(shí)現(xiàn)在kube-controller-manager。網(wǎng)絡(luò)上已經(jīng)有很多源碼分析。此處不再贅述。

小結(jié)
本文雖說的是K8s的HPA的機(jī)制的領(lǐng)域模型,但是,你發(fā)現(xiàn)這個(gè)領(lǐng)域模型也適用于非K8s的部署方式。
總的來說,關(guān)于HPA你只需要記住兩個(gè)問題:
- 指標(biāo)從何而來
- 如何根據(jù)指標(biāo)進(jìn)行擴(kuò)縮容
然后找到這兩個(gè)問題答案。當(dāng)我們想通這兩個(gè)問題后,即使不在K8s中實(shí)現(xiàn)HPA,我們也會(huì)有思路實(shí)現(xiàn)。