本文基于Knative 0.7.0版本代碼故响,解讀KPA的工作原理傀广。
PA reconcile
創(chuàng)建PA時(shí),PA controller會(huì)開始reconcile過程彩届。
這里KPA可以通過annotationautoscaling.knative.dev/class=kpa.autoscaling.knative.dev
或者hpa.autoscaling.knative.dev
來指定背后是kpa還是hpa伪冰。如果是hpa,那么reconcile過程則是直接創(chuàng)建一個(gè)簡(jiǎn)單的kubernetes hpa樟蠕,目前僅支持resource類型的CPU贮聂,和Object類型的concurrency,即服務(wù)的同步處理請(qǐng)求數(shù)寨辩,同樣通過annotation指定autoscaling.knative.dev/metric=cpu
或者concurrency
.
后面假設(shè)是kpa模式吓懈。
reconcile過程分為兩步:同步各類資源和反饋desiredReplicas。
同步各類資源
reconcile的過程開始靡狞,會(huì)分別去reconcile以下幾個(gè)資源骄瓣,如果不存在,則會(huì)去創(chuàng)建:
metricService耍攘,他就是kubernetes的service,背后暴露了Pod上metrics sidecar的訪問方式畔勤,其創(chuàng)建是通過deployment的selector選擇pod蕾各,并暴露9090
和9091
端口,target port則分別是port name=queue-metrics
和port name=user-metrics
的端口配置
serverlessService庆揪,就是knative的自己的service資源
decider式曲,也是knative自己的資源,他保存了針對(duì)當(dāng)前服務(wù)autoScaling的一些配置信息,他是內(nèi)存態(tài)的吝羞,并沒有在etcd落盤兰伤。并且desiredReplicas也是通過他的status反饋回來的。reconcile在創(chuàng)建decider的時(shí)候會(huì)去MultiScaler上注冊(cè)它钧排,以啟動(dòng)autoScaler敦腔,后面會(huì)講到。
metric恨溜,knative的crd符衔,為metricCollector記錄了metricService的信息,以及stable和panic窗口的大小糟袁。reconciler在創(chuàng)建metric時(shí)判族,會(huì)去MetricCollector上注冊(cè),以開始收集metric项戴,后面會(huì)講到形帮。
stableWindow
大小通過pa上的annotation"autoscaling.knative.dev/window"指定,如"60s"周叮。否則就會(huì)使用全局的配置辩撑。
panicWindow
大小通過<panic-window-percentage> * stable-window / 100 得到,可以通過PA上的annotation"autoscaling.knative.dev/panicWindowPercentage"指定则吟,如“50.0”即50%槐臀,不能大于100.0或小于1.0,否則被設(shè)為0氓仲。如果沒提供水慨,也是0,即disable panic window敬扛。
反饋DesiredReplicas
最后會(huì)從decider.status里拿到目前的desiredScale晰洒,然后去嘗試更新對(duì)用deployment的replicas,當(dāng)然啥箭,這里的更新過程會(huì)考慮desiredScale是否合法谍珊,比如是否在最大最小的replicas范圍內(nèi)。
各組件工作原理
MultiScaler
顧名思義急侥,MultiScaler會(huì)維護(hù)一個(gè)scaler的集合砌滞。
每次根據(jù)一個(gè)decider創(chuàng)建一個(gè)scaler后,multiScaler都會(huì)為它單獨(dú)起一個(gè)goroutine坏怪。這個(gè)goroutine會(huì)定時(shí)去計(jì)算desiredScale贝润,并把它更新到decider的statue上÷料“定時(shí)”是通過decider上的spec.tickInterval字段給出打掘,此值是從configMap的全局配置中得到华畏,默認(rèn)是2秒。
這個(gè)計(jì)算desiredScale的過程是調(diào)用uniScaler接口的Scale方法尊蚁。
UniScaler
在uniScale的Scale實(shí)現(xiàn)方法中亡笑,它會(huì)通過MetricClient分別拿到stableWindow和panicWindow聚合出的所有pod的總concurrency值observedStableConcurrency, observedPanicConcurrency。而這里的stableWindow和panicWindow則是通過metric資源拿到横朋。
之后會(huì)根據(jù)拿到的concurrency值判斷當(dāng)前是stable mode還是panic mode仑乌。如果observedPanicConcurrency / readyPodsCount >= panicThreshold則進(jìn)入panic mode。panicThreshold通過target * panicThresholdPercentage得到叶撒。target有三個(gè)來源绝骚,具體參考代碼。panicThresholdPercentage通過PA的annotation"autoscaling.knative.dev/panicThresholdPercentage"得到祠够,最小值110.0压汪,比這小的話則被設(shè)為0。如果進(jìn)入panic mode則replicas只增不減古瓤。
MetricClient (MetricCollector)
reconcile每次創(chuàng)建Metric資源的時(shí)候止剖,都會(huì)去MetricCollector上注冊(cè)metric,以開始收集對(duì)應(yīng)服務(wù)的metric落君。在注冊(cè)時(shí)會(huì)為每個(gè)metric創(chuàng)建一個(gè)對(duì)應(yīng)collection穿香,以及啟動(dòng)一個(gè)goroutine。collection是與某個(gè)服務(wù)對(duì)應(yīng)的metric集合的實(shí)體绎速,而goroutine則會(huì)定時(shí)(hardcode 1秒)通過ServiceScraper去訪問metricService拿取metric皮获。而訪問metric的url正是從Metric.spec.ScrapeTarget生成的,這里ScrapeTarget的值就是metricService.name纹冤。(url格式:http://<svc-name>.<ns-name>:9090/metrics)洒宝。collection在scrape metric時(shí),會(huì)計(jì)算一個(gè)取樣量萌京,比如pod數(shù)小于或等于3雁歌,則取樣量為3,否則為pod總數(shù)的一個(gè)比例值知残。根據(jù)取樣量n靠瞎,會(huì)n次訪問上面說的url,經(jīng)由metric service(普通的k8s service)從隨機(jī)的pod的sidecar中拿到當(dāng)前的concurrency總量并取平均求妹,得到當(dāng)前的pod平均concurrency乏盐,作為當(dāng)前時(shí)間的指標(biāo)轰异。
Stable mode & Panic mode
stable mode窗口為60秒存哲,默認(rèn)計(jì)算頻率為2秒记焊,autoScaler會(huì)聚合60秒內(nèi)的concurrency數(shù)據(jù)來計(jì)算每個(gè)pod的平均concurrency愉老,并調(diào)整deployment的replicas。(此處pod的數(shù)量來自于metrics server任内,而不是deployment的replicas退疫,因?yàn)閙etrics server才是準(zhǔn)確的)
同時(shí)参歹,autoScaler也會(huì)去聚合一個(gè)panic window時(shí)間內(nèi)的指標(biāo)(默認(rèn)6秒)强挫,如果panic window內(nèi)岔霸,pod平均concurrency就達(dá)或超過了panic閾值(默認(rèn)為目標(biāo)concurrency的2倍),則進(jìn)入panic mode
panic mode時(shí)俯渤,autoScaler也是每2秒就計(jì)算一次呆细,并調(diào)整deployment的replicas,但是他只增加八匠,不減少絮爷。當(dāng)最后一次增加pod事件發(fā)生后,經(jīng)過stable-window秒(默認(rèn)stable-window是60秒)梨树,則自動(dòng)恢復(fù)stable mode坑夯。
全局配置
autoScaling相關(guān)的配置可以通過PA的annotation指定,如果沒有則會(huì)使用configMap提供的默認(rèn)配置抡四。
參考:https://github.com/knative/serving/blob/v0.7.0/pkg/autoscaler/config.go#L56