<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          優(yōu)化 Kubernetes 橫向擴(kuò)縮容 HPA

          共 4364字,需瀏覽 9分鐘

           ·

          2021-06-03 23:10

          圖片來(lái)源: instagram.com/febin_raj

          Pod水平自動(dòng)擴(kuò)縮(Horizontal Pod Autoscaler, 簡(jiǎn)稱HPA)可以基于 CPU/MEM 利用率自動(dòng)擴(kuò)縮Deployment、StatefulSet 中的 Pod 數(shù)量,同時(shí)也可以基于其他應(yīng)程序提供的自定義度量指標(biāo)來(lái)執(zhí)行自動(dòng)擴(kuò)縮。默認(rèn)HPA可以滿足一些簡(jiǎn)單場(chǎng)景,對(duì)于生產(chǎn)環(huán)境并不一定適合,本文主要分析HPA的不足與優(yōu)化方式。

          HPA Resource類型不足

          默認(rèn)HPA提供了Resource類型,通過(guò)CPU/MEM使用率指標(biāo)(由metrics-server提供原始指標(biāo))來(lái)擴(kuò)縮應(yīng)用。

          使用率計(jì)算方式

          在Resource類型中,使用率計(jì)算是通過(guò)request而不是limit,源碼如下:

          // 獲取Pod resource request
          func calculatePodRequests(pods []*v1.Pod, resource v1.ResourceName) (map[string]int64, error) {
           requests := make(map[string]int64, len(pods))
           for _, pod := range pods {
            podSum := int64(0)
            for _, container := range pod.Spec.Containers {
             if containerRequest, ok := container.Resources.Requests[resource]; ok {
              podSum += containerRequest.MilliValue()
             } else {
              return nil, fmt.Errorf("missing request for %s", resource)
             }
            }
            requests[pod.Name] = podSum
           }
           return requests, nil
          }
          // 計(jì)算使用率
          func GetResourceUtilizationRatio(metrics PodMetricsInfo, requests map[string]int64, targetUtilization int32) (utilizationRatio float64, currentUtilization int32, rawAverageValue int64, err error) {
           metricsTotal := int64(0)
           requestsTotal := int64(0)
           numEntries := 0

           for podName, metric := range metrics {
            request, hasRequest := requests[podName]
            if !hasRequest {
             // we check for missing requests elsewhere, so assuming missing requests == extraneous metrics
             continue
            }

            metricsTotal += metric.Value
            requestsTotal += request
            numEntries++
           }


           currentUtilization = int32((metricsTotal * 100) / requestsTotal)

           return float64(currentUtilization) / float64(targetUtilization), currentUtilization, metricsTotal / int64(numEntries), nil
          }

          通常在Paas平臺(tái)中會(huì)對(duì)資源進(jìn)行超配,limit即用戶請(qǐng)求資源,request即實(shí)際分配資源,如果按照request來(lái)計(jì)算使用率(會(huì)超過(guò)100%)是不符合預(yù)期的。相關(guān)issue見(jiàn)72811,目前還存在爭(zhēng)論??梢孕薷脑创a,或者使用自定義指標(biāo)來(lái)代替。

          多容器Pod使用率問(wèn)題

          默認(rèn)提供的Resource類型的HPA,通過(guò)上述方式計(jì)算資源使用率,核心方式如下:

          metricsTotal = sum(pod.container.metricValue)
          requestsTotal = sum(pod.container.Request)
          currentUtilization = int32((metricsTotal * 100) / requestsTotal)

          計(jì)算出所有container的資源使用量再比總的申請(qǐng)量,對(duì)于單容器Pod這沒(méi)影響。但對(duì)于多容器Pod,比如Pod包含多個(gè)容器con1、con2(request都為1cpu),con1使用率10%,con2使用率100%,HPA目標(biāo)使用率60%,按照目前方式得到使用率為55%不會(huì)進(jìn)行擴(kuò)容,但實(shí)際con2已經(jīng)達(dá)到資源瓶頸,勢(shì)必會(huì)影響服務(wù)質(zhì)量。當(dāng)前系統(tǒng)中,多容器Pod通常都是1個(gè)主容器與多個(gè)sidecar,依賴主容器的指標(biāo)更合適點(diǎn)。

          好在1.20版本中已經(jīng)支持了ContainerResource可以配置基于某個(gè)容器的資源使用率來(lái)進(jìn)行擴(kuò)縮,如果是之前的版本建議使用自定義指標(biāo)替換。

          性能問(wèn)題

          單線程架構(gòu)

          默認(rèn)的hpa-controller是單個(gè)Goroutine執(zhí)行的,隨著集群規(guī)模的增多,勢(shì)必會(huì)成為性能瓶頸,目前默認(rèn)hpa資源同步周期會(huì)15s,假設(shè)每個(gè)metric請(qǐng)求延時(shí)為100ms,當(dāng)前架構(gòu)只能支持150個(gè)HPA資源(保證在15s內(nèi)同步一次)

          func (a *HorizontalController) Run(stopCh <-chan struct{}) {
            // ...
           // start a single worker (we may wish to start more in the future)
           go wait.Until(a.worker, time.Second, stopCh)

           <-stopCh
          }

          可以通過(guò)調(diào)整worker數(shù)量來(lái)橫向擴(kuò)展,已提交PR。

          調(diào)用鏈路

          hpa controller中一次hpa資源同步,需要調(diào)用多次apiserver接口,主要鏈路如下

          1. 通過(guò)scaleForResourceMappings得到scale資源
          2. 調(diào)用computeReplicasForMetrics獲取metrics value
          3. 調(diào)用Scales().Update更新計(jì)算出的副本數(shù)

          尤其在獲取metrics value時(shí),需要先調(diào)用apiserver,apiserver調(diào)用metrics-server/custom-metrics-server,當(dāng)集群內(nèi)存在大量hpa時(shí)可能會(huì)對(duì)apiserver性能產(chǎn)生一定影響。

          其他

          對(duì)于自定義指標(biāo)用戶需要實(shí)現(xiàn)custom.metrics.k8s.ioexternal.metrics.k8s.io,目前已經(jīng)有部分開(kāi)源實(shí)現(xiàn)見(jiàn)custom-metrics-api。

          另外,hpa核心的擴(kuò)縮算法根據(jù)當(dāng)前指標(biāo)和期望指標(biāo)來(lái)計(jì)算擴(kuò)縮比例,并不適合所有場(chǎng)景,只使用線性增長(zhǎng)的指標(biāo)。

          期望副本數(shù) = ceil[當(dāng)前副本數(shù) * (當(dāng)前指標(biāo) / 期望指標(biāo))]

          watermarkpodautoscaler提供了更靈活的擴(kuò)縮算法,比如平均值、水位線等,可以作為參考。

          總結(jié)

          Kubernetes提供原生的HPA只能滿足一部分場(chǎng)景,如果要上生產(chǎn)環(huán)境,必須對(duì)其做一些優(yōu)化,本文總結(jié)了當(dāng)前HPA存在的不足,例如在性能、使用率計(jì)算方面,并提供了解決思路。

          ?

          本文鏈接: https://qingwave.github.io/k8s-hpa-enchance/

          ?


          瀏覽 114
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  首页 - 大香蕉 | 18禁成人在线网站 | 少妇一区二区三区 | 色一色撸一撸 | 成人欧美一区二区三区男男 |