全部產品
Search
文件中心

Container Service for Kubernetes:Auto ScalingFAQ

更新時間:Jul 30, 2024

本文介紹Container ServiceACKAuto Scaling的常見問題及解決辦法。

類型

問題

節點伸縮常見問題

工作負載伸縮常見問題

基於阿里雲組件指標的容器水平伸縮常見問題

節點自動調整常見問題

如何升級cluster-autoscaler組件至最新版本?

對於已開啟叢集自動Auto Scaling的叢集,可通過以下方式升級cluster-autoscaler組件

  1. 登入Container Service管理主控台,在左側導覽列選擇叢集

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇節點管理 > 節點池

  3. 單擊節點伸縮右側的編輯,然後在面板下方單擊確定,即可升級cluster-autoscaler至最新版本。

cluster-autoscaler組件可類比判斷的資源有哪些?

cluster-autoscaler組件已經支援以下資源的類比和判斷:

cpu
memory
sigma/eni
ephemeral-storage
aliyun.com/gpu-mem (僅共用GPU)
nvidia.com/gpu

如果需要其他資源類型,請參見開啟彈性的節點池如何配置自訂資源?

cluster-autoscaler組件是否支援自訂資源?

cluster-autoscaler組件目前僅支援Kubernetes標準對象,暫時不支援Kubernetes自訂資源。

如何指定節點不被cluster-autoscaler組件縮容?

為目標節點配置Node Annotation "cluster-autoscaler.kubernetes.io/scale-down-disabled": "true",使其不被cluster-autoscaler縮容。添加Annotation的命令樣本如下。

kubectl annotate node <nodename> cluster-autoscaler.kubernetes.io/scale-down-disabled=true

如何延遲cluster-autoscaler組件對不可調度Pod的擴容反應時間?

可以通過cluster-autoscaler.kubernetes.io/pod-scale-up-delayAnnotation為每個Pod設定延遲擴容時間。如果K8s沒有在該延遲結束時調度它們,那麼CA可能會考慮對它們進行擴充。Annotation樣本如下:"cluster-autoscaler.kubernetes.io/pod-scale-up-delay": "600s"

為什麼節點自動調整組件無法彈出節點?

請檢查是否存在如下幾種情境:

  • 配置伸縮組的執行個體類型無法滿足Pod的資源申請(Request)。ECS執行個體規格給出的資源大小是執行個體的售賣規格,實際運行時請考慮以下資源預留。

  • 對可用性區域有約束的Pod,無法觸發配置了多可用性區域的節點池擴容。

  • 是否完整按照步驟執行了授權操作。授權操作是叢集維度,需要每個叢集操作一次。關於授權,請參見啟用節點自動調整

  • 開啟自動調整的節點池中出現如下異常情況。

    • 執行個體未加入到叢集且逾時。

    • 節點未ready且逾時。

    為保證後續擴縮準確性,彈性組件以阻尼方式處理異常情況,在處理完異常情況節點前,不進行擴縮容。

為什麼節點自動調整組件無法縮容節點?

請檢查是否存在如下幾種情境:

  • 節點Pod的資源申請(Request)閾值高於設定的縮容閾值。

  • 節點上運行kube-system命名空間的Pod。

  • 節點上的Pod包含強制的調度策略,導致其他節點無法運行此Pod。

  • 節點上的Pod擁有PodDisruptionBudget,且到達了PodDisruptionBudget的最小值。

您可以在開源社區得到更多關於節點自動調整組件的常見問題與解答。

多個伸縮組在Auto Scaling的時候是如何被選擇的?

在Pod處在無法調度時,會觸發Auto Scaling組件的類比調度邏輯,會根據伸縮組配置的標籤和汙點以及執行個體規格等資訊進行判斷。當配置的伸縮組可以類比調度Pod的時候,就會被選擇進行節點彈出。當同時有多個伸縮組滿足類比調度條件的時候,預設採用的是最少浪費原則,即根據類比彈出後節點上剩餘的資源最小為原則進行抉擇。

什麼類型的Pod可以阻止cluster-autoscaler組件移除節點?

當Pod不是由原生Kubernetes Controller建立的Pod(例如非Deployment、ReplicaSet、Job、StatefulSet等對象建立的Pod),或者當節點上的Pod不能被安全地終止或遷移時,cluster-autoscaler組件可能會阻止移除這個節點。詳細資料,請參見什麼類型的Pod可以阻止CA移除節點?

cluster-autoscaler組件使用了哪些調度策略來判斷不可調度Pod能否調度到開啟自動調整節點池?

使用的調度策略如下所示。

  • PodFitsResources

  • GeneralPredicates

  • PodToleratesNodeTaints

  • MaxGCEPDVolumeCount

  • NoDiskConflict

  • CheckNodeCondition

  • CheckNodeDiskPressure

  • CheckNodeMemoryPressure

  • CheckNodePIDPressure

  • CheckVolumeBinding

  • MaxAzureDiskVolumeCount

  • MaxEBSVolumeCount

  • ready

  • NoVolumeZoneConflict

開啟彈性的節點池如何配置自訂資源?

通過為開啟彈性的節點池配置如下固定首碼的ECS標籤(Tag),可以讓彈性組件識別到已開啟彈性的節點池中可供給的自訂資源,或者識別到指定的某些資源的精確值。

k8s.io/cluster-autoscaler/node-template/resource/{資源名}:{資源大小}

樣本:

k8s.io/cluster-autoscaler/node-template/resource/hugepages-1Gi:2Gi

為什麼Pod無法調度到節點自動調整組件彈出節點?

受底層資源佔用計算精度約束,自動調整組件估算的節點可調度資源可能大於實際節點的可調度資源。關於底層資源佔用計算精度約束的更多資訊,請參見購買執行個體後查看記憶體大小,為什麼和購買時的執行個體規格定義不一致?。當Pod資源申請佔用較大時(建議超過節點資源70%時),需要使用者使用彈性前Pod確認是否可調度到同執行個體規格的節點。

彈性組件在判斷節點的資源是否滿足時,僅考慮Pending Pods和Daemonset Pods的資源,如果節點上有非Daemonset的Static Pods,請您預先為此類Pod預留資源。

如何通過Pod Annotation影響cluster-autoscaler組件的節點縮容?

您可以指定Pod阻止或不阻止節點被cluster-autoscaler組件縮容。

  • 阻止節點被縮容:為Pod添加Annotation "cluster-autoscaler.kubernetes.io/safe-to-evict": "false"

  • 不阻止節點被縮容:為Pod添加Annotation "cluster-autoscaler.kubernetes.io/safe-to-evict": "true"

哪些操作會觸發cluster-autoscaler組件自動更新?

為保證cluster-autoscaler組件配置的即時性、版本與叢集的相容性,以下操作會觸發cluster-autoscaler組件自動更新:

  • 更新自動調整配置

  • 建立、刪除、更新開啟彈性節點池

  • 成功升級叢集

如何啟用或禁用特定DaemonSet的驅逐?

cluster-autoscaler組件會根據是否開啟 Daemonset Pod 排水配置決定是否驅逐DaemonSet Pods,這些配置是叢集維度,對叢集中的DaemonSet Pods通用。更多資訊,請參見步驟一:開啟節點自動調整。如果想要對某個DaemonSet Pod指定是否需要被驅逐,可以對這個DaemonSet Pod添加Annotation"cluster-autoscaler.kubernetes.io/enable-ds-eviction":"true"

類似的,DaemonSet Pod的Annotation中如果有"cluster-autoscaler.kubernetes.io/enable-ds-eviction":"false",則會顯示禁止Cluster Autoscaler驅逐這個DaemonSet Pod。

說明
  • 如果未開啟DaemonSet Pod排水,此Annotation僅對非空節點的DaemonSet Pods有效。如果想開啟空節點DaemonSet Pods,需要先開啟DaemonSet Pod排水。

  • 此Annotation需要在DaemonSet Pod上指定,而不是DaemonSet對象本身。

  • 此Annotation對不屬於任何DaemonSet的Pod沒有影響。

  • 預設情況下,Cluster Autoscaler對DaemonSet Pod的驅逐是非阻塞模式的,即不等待DaemonSet Pod驅逐完成後,就會執行後續流程。如需要Cluster Autoscaler等待指定DaemonSet Pod驅逐完成後再執行後續縮容流程,除以上啟用配置外,請為相應Pod添加Annotation"cluster-autoscaler.kubernetes.io/wait-until-evicted":"true"

如果一個伸縮組內配置了多資源類型的執行個體規格,Auto Scaling時如何計算這個伸縮組的資源呢?

對於配置了多個執行個體規格的伸縮組,Auto Scaling組件以資源維度在各個執行個體規格中取最小值,作為資源計算的基準。

例如,如果一個伸縮組內配置了兩種執行個體規格,一個是CPU 4核記憶體32 GB,另一個是CPU 8核記憶體16 GB。Auto Scaling組件認為這個伸縮組能保證的擴容出的CPU是4核記憶體16 GB的執行個體資源。因此如果狀態為pending的Pod的requests資源超出4核或者16 GB,則不會進行擴容。

如果您配置了多執行個體規格但需要考慮資源預留,請參見為什麼節點自動調整組件無法彈出節點?

容器水平伸縮(HPA)常見問題

HPA的監控資料current欄位為何顯示為unknown

當HPA的監控資料的current欄位顯示為unknown時,表示kube-controller-manager無法訪問監控資料來源擷取對應的監控資料,HPA擴縮容時會失敗。

Name:                                                  kubernetes-tutorial-deployment
Namespace:                                             default
Labels:                                                <none>
Annotations:                                           <none>
CreationTimestamp:                                     Mon, 10 Jun 2019 11:46:48  0530
Reference:                                             Deployment/kubernetes-tutorial-deployment
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  <unknown> / 2%
Min replicas:                                          1
Max replicas:                                          4
Deployment pods:                                       1 current / 0 desired
Conditions:
  Type           Status  Reason                   Message
  ----           ------  ------                   -------
  AbleToScale    True    SucceededGetScale        the HPA controller was able to get the target's current scale
  ScalingActive  False   FailedGetResourceMetric  the HPA was unable to compute the replica count: unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server is currently unable to handle the request (get pods.metrics.k8s.io)
Events:
  Type     Reason                   Age                      From                       Message
  ----     ------                   ----                     ----                       -------
  Warning  FailedGetResourceMetric  3m3s (x1009 over 4h18m)  horizontal-pod-autoscaler  unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server is currently unable to handle the request (get pods.metrics.k8s.io)

原因如下:

  • 原因一:Resource Metrics資料來源無法使用。請先執行命令kubectl top pod檢查是否返回資料。如果所有的Pod都無資料,請執行kubectl get apiservice檢查當前提供Resource Metrics的資料來源的情況。返回的樣本資料如下。

    展開查看返回的樣本資料

    NAME                                   SERVICE                      AVAILABLE   AGE
    v1.                                    Local                        True        29h
    v1.admissionregistration.k8s.io        Local                        True        29h
    v1.apiextensions.k8s.io                Local                        True        29h
    v1.apps                                Local                        True        29h
    v1.authentication.k8s.io               Local                        True        29h
    v1.authorization.k8s.io                Local                        True        29h
    v1.autoscaling                         Local                        True        29h
    v1.batch                               Local                        True        29h
    v1.coordination.k8s.io                 Local                        True        29h
    v1.monitoring.coreos.com               Local                        True        29h
    v1.networking.k8s.io                   Local                        True        29h
    v1.rbac.authorization.k8s.io           Local                        True        29h
    v1.scheduling.k8s.io                   Local                        True        29h
    v1.storage.k8s.io                      Local                        True        29h
    v1alpha1.argoproj.io                   Local                        True        29h
    v1alpha1.fedlearner.k8s.io             Local                        True        5h11m
    v1beta1.admissionregistration.k8s.io   Local                        True        29h
    v1beta1.alicloud.com                   Local                        True        29h
    v1beta1.apiextensions.k8s.io           Local                        True        29h
    v1beta1.apps                           Local                        True        29h
    v1beta1.authentication.k8s.io          Local                        True        29h
    v1beta1.authorization.k8s.io           Local                        True        29h
    v1beta1.batch                          Local                        True        29h
    v1beta1.certificates.k8s.io            Local                        True        29h
    v1beta1.coordination.k8s.io            Local                        True        29h
    v1beta1.events.k8s.io                  Local                        True        29h
    v1beta1.extensions                     Local                        True        29h
    ...
    [v1beta1.metrics.k8s.io                 kube-system/metrics-server   True        29h]
    ...
    v1beta1.networking.k8s.io              Local                        True        29h
    v1beta1.node.k8s.io                    Local                        True        29h
    v1beta1.policy                         Local                        True        29h
    v1beta1.rbac.authorization.k8s.io      Local                        True        29h
    v1beta1.scheduling.k8s.io              Local                        True        29h
    v1beta1.storage.k8s.io                 Local                        True        29h
    v1beta2.apps                           Local                        True        29h
    v2beta1.autoscaling                    Local                        True        29h
    v2beta2.autoscaling                    Local                        True        29h

    如果v1beta1.metrics.k8s.io所對應的API Service不是kube-system/metrics-server,檢查是否由於安裝Prometheus Operator覆蓋導致。如果是覆蓋導致的問題,可以通過部署以下的YAML模板進行恢複。

    apiVersion: apiregistration.k8s.io/v1beta1
    kind: APIService
    metadata:
      name: v1beta1.metrics.k8s.io
    spec:
      service:
        name: metrics-server
        namespace: kube-system
      group: metrics.k8s.io
      version: v1beta1
      insecureSkipTLSVerify: true
      groupPriorityMinimum: 100
      versionPriority: 100

    如果非上述問題,請確認已在叢集的營運管理>組件管理頁面安裝了metrics-server組件。更多資訊,請參見metrics-server

  • 原因二:滾動發布或擴容時無法擷取資料。

    預設metrics-server的採集周期是1 min。剛擴容或更新完成後,metrics-server會有一段時間無法擷取監控資料。請於擴容或更新後2 min左右進行查看。

  • 原因三:未配置request欄位。

    HPA預設是通過實際的利用率/request作為利用率的數值,因此可以檢查Pod的resource欄位中是否包含request欄位。

  • 原因四:指標名填寫錯誤。請檢查指標名(包括大小寫)是否正確。例如,如果將HPA支援的cpu指標誤寫為CPU,監控資料current欄位會顯示為unknown

HPA擴縮容失敗,指標擷取異常怎麼辦?

HPA擴縮容失敗可能是因為指標擷取異常,HPA的監控資料current欄位將顯示為unknown。此時,HPA將無法擷取用於決策擴縮容的指標,也就無法調整Pod數量。請參見HPA的監控資料current欄位為何顯示為unknown?排查問題原因,並採取對應的解決措施。

為何HPA在滾動發布時出現擴容多餘Pod的現象?

社區Controller Manager在滾動發布時,對於沒有監控資料的Pod,進行監控資料的補零操作,從而有一定的機率出現擴容出多餘的Pod現象(多彈現象)。您可以通過以下配置防止多彈。

  • 叢集維度配置。

    您可以通過升級ACK提供的最新版metrics-server,並在metrics-server的啟動參數上開啟開關防止多彈。

    這是全域開關,設定後對叢集內所有相關負載生效。

    # 在metrics-server的啟動參數中加入以下選項。
    --enable-hpa-rolling-update-skipped=true  
  • 工作負載維度配置。如果只想對指定的工作負載開啟防止多彈,您可以使用以下兩種方法防止多彈。

    • 方法一:通過在指定工作負載的模板中添加以下Annotation,可以在滾動發布時臨時暫停HPA的判斷生效。

      ##工作負載的spec.template.metadata.annotations加入Annotation,滾動發布時臨時暫停HPA的判斷生效。
      HPARollingUpdateSkipped: "true"

      展開查看範例程式碼詳情

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-deployment-basic
        labels:
          app: nginx
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: nginx
          template:
              metadata:
                labels:
                  app: nginx
                annotations:
                  HPARollingUpdateSkipped: "true"  # 跳過滾動發布時的HPA的效果。
              spec:
                containers:
                - name: nginx
                  image: nginx:1.7.9
                  ports:
                  - containerPort: 80

    • 方法二:通過在指定工作負載的模板中添加以下Annotation,可以在應用發布開始階段跳過設定的預熱時間段。

      ##工作負載的spec.template.metadata.annotations加入Annotation,在應用發布開始階段跳過設定的預熱的時間段。
      HPAScaleUpDelay: 3m # 3m僅為樣本,具體時間段請按需設定

      展開查看範例程式碼詳情

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-deployment-basic
        labels:
          app: nginx
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: nginx
          template:
              metadata:
                labels:
                  app: nginx
                annotations:
                  HPAScaleUpDelay: 3m  # m代表分鐘,表示HPA在Pod建立3分鐘後開始生效,可選單位為[s(秒),m(分)]。
              spec:
                containers:
                - name: nginx
                  image: nginx:1.7.9
                  ports:
                  - containerPort: 80

HPA到達閾值為何不進行擴縮容?

HPA的擴縮容的觸發條件不僅是CPU使用率或記憶體使用量率超過閾值與低於閾值,需要額外考慮的是如果擴容或者縮容後,是否會再次觸發縮容或者擴容,減少震蕩的情境。

例如當您的擴容閾值設定為80%,如果有兩個Pod的CPU目前使用率都是70%,這種情況下就不會縮容。因為縮容後可能單個Pod的CPU使用率高於80%,就會觸發擴容,這樣就會來回擴縮容出現震蕩。

HPA採集周期如何配置?

對版本號碼大於v0.2.1-b46d98c-aliyun的metric-server,在metric-server的啟動參數中設定--metric-resolution,例如--metric-resolution=15s即可。

CronHPA是否相容HPA?

CronHPA可以相容HPA。阿里雲Container ServiceACK將CronHPA中的scaleTargetRef設定為HPA對象,然後通過HPA對象來尋找真實的scaleTargetRef,從而讓CronHPA感知HPA的目前狀態。CronHPA不會直接調整Deployment的副本數目,而是通過HPA來操作Deployment,這樣可以避免HPA和CronHPA的衝突問題。關於CronHPA相容HPA的更多資訊,請參見實現CronHPA與HPA的協同

如何解決HPA啟動時CPU或記憶體飆高造成擴容出多餘Pod的多彈現象?

對於Java等需要預熱的語言與架構而言,在容器剛啟動的時候,有可能會出現分鐘層級的CPU、記憶體飆高,可能會造成HPA的誤觸發。您可以通過將ACK提供的metrics-server組件升級至0.3.9.6版本以上,並在Pod的Annotation上增加開關防止誤觸發,解決此問題。關於如何升級metrics-server組件,請參見升級叢集至v1.12版本前升級metrics-server組件

增加開關防止誤觸發部署樣本YAML如下。

展開查看樣本YAML詳情

## 以Deployment為例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-basic
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        HPAScaleUpDelay: 3m # m代表分鐘,表示HPA在Pod建立3分鐘後開始生效,可選單位為[s(秒),m(分)]。
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9 # Replace it with your exactly <image_name:tags>.
        ports:
        - containerPort: 80 

為什麼HPA審計日誌數值未達閾值但擴縮了?

問題原因

Pod水平自動擴縮控制器根據當前指標和期望指標來計算擴縮比例,期望副本數 = ceil(當前副本數 × (當前指標 / 期望指標))。

從這個公式可以看出,期望副本數的準確度是由當前副本數、當前指標和期望指標的準確度來保證的。以HPA中應用廣泛的資源指標為例,HPA擷取當前副本數時,是先擷取scaleTargetRef所定義的對象的scale子資源(subResources),然後將scale的status的Selector的值轉化為labelselector,以此作為條件去匹配擷取Pod。如果某個時刻,用這個條件擷取到的Pod並不完全屬於scaleTargetRef中定義的對象,那以此計算出的期望副本數就很可能不符合預期(比如即時指標低於閾值卻擴容了)。

常見可能導致匹配Pod數目不準確的原因:

  • 滾動發布。

  • 給其他不屬於scaleTargetRef中對象的Pod打標了相同Label。執行如下命令,可判斷是否有其他Pod。

    kubectl get pods -n {命名空間名字} -l {scale子資源的status.Selector的值}

解決方案

HPA縮容時,能夠決定Pod縮容的順序嗎?

不能。HPA可以根據定義的指標自動增加或減少Pod的數量,但並不能決定哪些Pod應該首先被終止。Pod終止的順序、優雅退出時間等特性均由管理Pod的Controller決定。

HPA使用率指標單位的含義是什嗎?

使用率指標通常為無單位的整數值或以m為單位的整數值,換算比例為1000m=1。例如,當tcp_connection_counts為70000m時,等同於70。

基於阿里雲組件指標的容器水平伸縮常見問題

如果執行kubectl get hpa後發現target一欄為unknow怎麼辦?

請按照以下操作解決。

  1. 執行kubectl describe hpa <hpa_name>,確認HPA失效的原因。

    • 如果Conditions欄位提示AbleToScaleFalse,請確認Deployment是否正常部署。

    • 如果Conditions欄位提示ScalingActiveFalse,請繼續下一步。

  2. 執行kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/"。如果返回為Error from server (NotFound): the server could not find the requested resource,請確認alibaba-cloud-metrics-adapter的啟動狀態。

    如果確認alibaba-cloud-metrics-adapter狀態正常,請確認HPA指標是否是Ingress相關指標。如果是Ingress相關指標,您需要提前部署Log Service組件。更多資訊,請參見Nginx Ingress訪問日誌分析與監控

  3. 確認HPA指標填寫正確。sls.ingress.route的值格式為<namespace>-<svc>-<port>

    • namespace為Ingress所在的命名空間。

    • svc是Ingress對應的Service名稱。

    • port是Ingress對應Service的連接埠名稱。

如何尋找HPA支援的指標名稱?

請參見阿里雲HPA指標,以下列舉為常用指標。

指標名稱

描述

附加參數

sls_ingress_qps

指定的IngressRoute每秒查詢率

sls.ingress.route

sls_alb_ingress_qps

ALB資料的IngressRoute每秒查詢率

sls.ingress.route

sls_ingress_latency_avg

所有請求的延遲

sls.ingress.route

sls_ingress_latency_p50

50%請求的延遲

sls.ingress.route

sls_ingress_latency_p95

95%請求的延遲

sls.ingress.route

sls_ingress_latency_p99

99%請求的延遲

sls.ingress.route

sls_ingress_latency_p9999

99.99%請求的延遲

sls.ingress.route

sls_ingress_inflow

Ingress的流入頻寬

sls.ingress.route

當使用者自訂了Nginx Ingress日誌格式,如何進行適配操作?

基於阿里雲組件指標的容器水平伸縮介紹了使用SLS Ingress指標進行容器水平伸縮,需要您開啟並正確配置叢集中Nginx Ingress日誌接入阿里雲Log Service。

  • 在建立叢集時,Log Service是預設開啟的。當您保持預設值不變,叢集建立成功後,您可以在阿里雲Log ServiceSLS控制台查看Nginx Ingress的訪問日誌分析報表和監控Nginx Ingress即時狀態。

  • 在建立叢集時,若您手動關閉了Log Service,叢集建立完成後,如果想要使用SLS Ingress指標進行容器水平伸縮,您需要重新開啟或配置Log Service。詳細資料,請參見Nginx Ingress訪問日誌分析與監控

  • 當您需要自訂Nginx Ingress日誌格式時,由於叢集中初次開啟Log Service部署AliyunLogConfig的CRD只針對ACK預設Ingress Controller中的日誌格式生效,若您修改過Ingress Controller的訪問日誌格式,請修改CRD配置中的Regex提取processor_regex部分。具體操作,請參見通過DaemonSet-CRD方式採集容器日誌