【Knative系列】理解 Knative Serving擴(kuò)縮容系統(tǒng)的設(shè)計

本文主要講解 Knative Serving擴(kuò)縮容系統(tǒng)的設(shè)計原理及實現(xiàn)細(xì)節(jié),主要從以下三個方面進(jìn)行講解:

  • Knative Serving 擴(kuò)縮容系統(tǒng)的組件;
  • 涉及的API;
  • 擴(kuò)縮容和冷啟動時的 控制流和數(shù)據(jù)流的一些細(xì)節(jié);

組件

Knative Serving 是 Knative 系統(tǒng)的核心,而理解 Knative Serving 系統(tǒng)內(nèi)的組件能更容易了理解 Knative Serving 系統(tǒng)的實現(xiàn):
了解其中的控制流和數(shù)據(jù)流的走向,了解其在擴(kuò)縮容過程中的作用。因篇幅有限,這里只對組件進(jìn)行簡要描述,后續(xù)會針對每個組件進(jìn)行詳細(xì)的單獨講解。

1. queue-proxy

queue-proxy 是 一個伴隨著用戶容器運(yùn)行的 Sidecar 容器,跟用戶容器運(yùn)行在同一個 Pod 中。每個請求到達(dá)業(yè)務(wù)容器之前都會經(jīng)過 queue-proxy 容器,
這也是它問什么叫 proxy 的原因。

queue-proxy 的主要作用是統(tǒng)計和限制到達(dá)業(yè)務(wù)容器的請求并發(fā)量,當(dāng)對一個 Revision 設(shè)置了并發(fā)量之后(比如設(shè)置了5),queue-proxy 會確保不會同時有超過5個請求打到業(yè)務(wù)容器。當(dāng)有超過5個請求到來時,queue-proxy會先把請求暫存在自己的隊列 queue 里,(這也是為什么名字里有個 queue的緣故)。queue-proxy 同時會統(tǒng)計進(jìn)來的請求量,同時會通過指定端口提供平均并發(fā)量和 rps(每秒請求量)的查詢。

2. Autoscaler

Autoscaler 是 Knative Serving 系統(tǒng)中一個重要的 pod,它由三部分組成:

  • PodAutoscaler reconciler
  • Collector
  • Decider

PodAutoscaler reconciler 會監(jiān)測 PodAutoscaler(KPA)的變更,然后交由 CollectorDecider 處理

Collector 主要負(fù)責(zé)從應(yīng)用的 queue-proxy 那里收集指標(biāo), Collector 會收集每個實例的指標(biāo),然后匯總得到整個系統(tǒng)的指標(biāo)。為了實現(xiàn)擴(kuò)縮容,會搜集所有應(yīng)用實例的樣本,并將收集到的樣本反映到整個集群。

Decider 得到指標(biāo)之后,來決定多少個Pod 被擴(kuò)容出來。簡單的計算公式如下:

want = concurrencyInSystem/targetConcurrencyPerInstance

另外,擴(kuò)縮容的量也會受到 Revision 中最大最小實例數(shù)的限制。同時 Autoscaler 還會計算當(dāng)前系統(tǒng)中剩余多少突發(fā)請求容量(可擴(kuò)縮容多少實例)進(jìn)來決定 請求是否走 Activator 轉(zhuǎn)發(fā)。

3. Activator

Activator 是整個系統(tǒng)中所用應(yīng)用共享的一個組件,是可以擴(kuò)縮容的,主要目的是緩存請求并給 Autoscaler主動上報請求指標(biāo)

Activator 主要作用在從零啟動和縮容到零的過程,能根據(jù)請求量來對請求進(jìn)行負(fù)載均衡。當(dāng) revision 縮容到零之后,請求先經(jīng)過 Activator 而不是直接到 revision。 當(dāng)請求到達(dá)時,Activator 會緩存這這些請求,同時攜帶請求指標(biāo)(請求并發(fā)數(shù))去觸發(fā) Autoscaler擴(kuò)容實例,當(dāng)實例 ready后,Activator 才會將請求從緩存中取出來轉(zhuǎn)發(fā)出去。同時為了避免后端的實例過載,Activator 還會充當(dāng)一個負(fù)載均衡器的作用,根據(jù)請求量決定轉(zhuǎn)發(fā)到哪個實例(通過將請求分發(fā)到后端所有的Pod上,而不是他們超過設(shè)置的負(fù)載并發(fā)量)。 Knative Serving 會根據(jù)不同的情況來決定是否讓請求經(jīng)過 Activator,當(dāng)一個應(yīng)用系統(tǒng)中有足夠多的pod實例時,Activator 將不再擔(dān)任代理轉(zhuǎn)發(fā)角色,請求會直接打到 revision 來降低網(wǎng)絡(luò)性能開銷。

queue-proxy 不同,Activator 是通過 websocket 主動上報指標(biāo)給 Autoscaler,這種設(shè)計當(dāng)然是為了應(yīng)用實例盡可能快的冷啟動。queue-proxy 是被動的拉?。?code>Autoscaler去 queue-proxy指定端口拉取指標(biāo)。

API

PodAutoscaler (PA,KPA)

API: podautoscalers.autoscaling.internal.knative.dev

PodAutoscaler 是對擴(kuò)縮容的一個抽象,簡寫是 KPA 或 PA ,每個 revision
會對應(yīng)生成一個 PodAutoscaler。
可通過下面的指令查看

kubectl get kpa -n xxx

ServerlessServices (SKS)

API: serverlessservices.networking.internal.knative.dev

ServerlessServicesKPA 產(chǎn)生的,一個 KPA 生成一個 SKS,SKS 是對 k8s service 之上的一個抽象,
主要是用來控制數(shù)據(jù)流是直接流向服務(wù) revision(實例數(shù)不為零) 還是經(jīng)過 Activator(實例數(shù)為0)。

對于每個 revision,會對應(yīng)生成兩個k8s service ,一個public service,一個 private service.

private service 是標(biāo)準(zhǔn)的 k8s service,通過label selector 來篩選對應(yīng)的deploy 產(chǎn)生的pod,即 svc 對應(yīng)的 endpoints 由 k8s 自動管控。

public service 是不受 k8s 管控的,它沒有 label selector,不會像 private service 一樣 自動生成 endpoints。public service 對應(yīng)的 endpoints
由 Knative SKS reconciler 來控制。

SKS 有兩種模式:proxyserve

  • serve 模式下 public service 后端 endpoints 跟 private service一樣, 所有流量都會直接指向 revision 對應(yīng)的 pod。
  • proxy 模式下 public service 后端 endpoints 指向的是 系統(tǒng)中 Activator 對應(yīng)的 pod,所有流量都會流經(jīng) Activator

數(shù)據(jù)流

下面看幾種情況下的數(shù)據(jù)流向,加深對Knative 擴(kuò)縮容系統(tǒng)機(jī)制的理解。

1. 穩(wěn)定狀態(tài)下的擴(kuò)縮容

scale-up-down.png

穩(wěn)定狀態(tài)下的工作流程如下:

  1. 請求通過 ingress 路由到 public service ,此時 public service 對應(yīng)的 endpoints 是 revision 對應(yīng)的 pod
  2. Autoscaler 會定期通過 queue-proxy 獲取 revision 活躍實例的指標(biāo),并不斷調(diào)整 revision 實例。
    請求打到系統(tǒng)時, Autoscaler 會根據(jù)當(dāng)前最新的請求指標(biāo)確定擴(kuò)縮容比例。
  3. SKS 模式是 serve, 它會監(jiān)控 private service 的狀態(tài),保持 public service 的 endpoints 與 private service 一致 。

2. 縮容到零

scale-to-0.png

縮容到零過程的工作流程如下:

  1. AutoScaler 通過 queue-proxy 獲取 revision 實例的請求指標(biāo)
  2. 一旦系統(tǒng)中某個 revision 不再接收到請求(此時 Activatorqueue-proxy 收到的請求數(shù)都為 0)
  3. AutoScaler 會通過 Decider 確定出當(dāng)前所需的實例數(shù)為 0,通過 PodAutoscaler 修改 revision 對應(yīng) Deployment 的 實例數(shù)
  4. 在系統(tǒng)刪掉 revision 最后一個 Pod 之前,會先將 Activator 加到 數(shù)據(jù)流路徑中(請求先到 Activator)。Autoscaler 觸發(fā) SKS 變?yōu)?proxy 模式,此時 SKSpublic service 后端的endpoints 變?yōu)?Activator 的IP,所有的流量都直接導(dǎo)到 Activator
  5. 此時,如果在冷卻窗口時間內(nèi)依然沒有流量進(jìn)來,那么最后一個 Pod 才會真正縮容到零。

3. 冷啟動(從零開始擴(kuò)容)

scale-from-0.png

冷啟動過程的工作流程如下:

當(dāng) revision 縮容到零之后,此時如果有請求進(jìn)來,則系統(tǒng)需要擴(kuò)容。因為 SKSproxy 模式,流量會直接請求到 Activator 。Activator 會統(tǒng)計請求量并將 指標(biāo)主動上報到 Autoscaler, 同時 Activator 會緩存請求,并 watch SKSprivate service, 直到 private service 對應(yīng)的endpoints產(chǎn)生。

Autoscaler 收到 Activator 發(fā)送的指標(biāo)后,會立即啟動擴(kuò)容的邏輯。這個過程的得出的結(jié)論是至少一個Pod要被創(chuàng)造出來,AutoScaler 會修改 revision 對應(yīng) Deployment 的副本數(shù)為為N(N>0),AutoScaler 同時會將 SKS 的狀態(tài)置為 serve 模式,流量會直接到導(dǎo)到 revision 對應(yīng)的 pod上。

Activator 最終會監(jiān)測到 private service 對應(yīng)的endpoints的產(chǎn)生,并對 endpoints 進(jìn)行健康檢查。健康檢查通過后,Activator 會將之前緩存的請求轉(zhuǎn)發(fā)到
健康的實例上。

最終 revison 完成了冷啟動(從零擴(kuò)容)。

本文作者: zhaojizhuang
本文鏈接https://chumper.cn/2020/09/30/knative-autoscalling/
版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/) 許可協(xié)議。轉(zhuǎn)載請注明出處!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容