1. 程式人生 > 其它 >Kubernetes基本入門-元資料資源(四)

Kubernetes基本入門-元資料資源(四)

元資料型資源

HPA

HPA全稱HorizontalPodAutoscaler,Pod水平自動擴縮,可以根據CPU利用率自動擴縮RC、Deployment、RS或StatefulSet中的Pod數量,目的是自動擴縮工作負載以滿足需求。
水平擴縮意味著對增加的負載的響應是部署更多的Pod。 與"垂直(Vertical)"擴縮不同,對於Kubernetes,垂直擴縮意味著將更多資源(例如:記憶體或 CPU)分配給已經為工作負載執行的Pod。如果負載減少,並且Pod的數量高於配置的最小值,HPA會指示工作負載資源(Deployment、StatefulSet或其他類似資源)縮減。水平Pod自動擴縮不適用於無法擴縮的物件(例如:DaemonSet)

  1. 如何工作

HorizontalPodAutoscaler被實現為Kubernetes API資源和控制器。HPA的工作示意圖如下所示:

HPA控制Deployment及其RS的規模,Kubernetes將水平Pod自動擴縮實現為一個間歇執行的控制迴路,它不是一個連續的過程。間隔由kube-controller-manager的--horizontal-pod-autoscaler-sync-period引數設定(預設間隔為15秒)。
每個時間段內,控制器管理器根據每個HPA定義指定的指標查詢資源利用率。控制器管理器找到由scaleTargetRef定義的目標資源,然後根據目標資源的.spec.selector標籤選擇Pod,並從資源指標API(針對每個Pod的資源指標)或自定義指標獲取指標API(適用於所有其他指標)。

  • 對於按Pod統計的資源指標,如CPU,控制器從資源指標API中獲取每個HPA指定的Pod的度量值,如果設定了目標使用率,控制器獲取每個Pod中的容器資源使用情況,並計算資源使用率。如果設定了target值,將直接使用原始資料,不再計算百分比。控制器根據平均的資源使用率或原始值計算出擴縮的比例,進而計算出目標副本數。如果Pod某些容器不支援資源採集,那麼控制器將不會使用該Pod的CPU使用率。
  • 如果Pod使用自定義指示,控制器機制與資源指標類似,區別在於自定義指標只使用原始值,而不是使用率。
  • 如果Pod使用物件指標和外部指標,每個指標描述一個物件資訊,這個指標將直接根據目標設定值相比較,生成一個擴縮比例。在autoscaling/v2beta2版本API中,這個指標也可以根據Pod數量平分後計算。

HPA的常見用途是將其配置為從聚合API(metrics.k8s.io、custom.metrics.k8s.io 或 external.metrics.k8s.io)獲取指標。metrics.k8s.io API通常由名為Metrics Server的外掛提供,需要單獨啟動。

  1. 實現細節

從最基本的角度來看,Pod水平自動擴縮控制器根據當前指標和期望指標來計算擴縮比例。

說明:期望副本數 = ceil[當前副本數 * (當前指標 / 期望指標)]

例如,如果當前指標值為200m,而期望值為100m,則副本數將加倍, 因為200.0 / 100.0 == 2.0如果當前值為 50m,則副本數將減半,因為50.0 / 100.0 == 0.5。如果比率足夠接近1.0(在全域性可配置的容差範圍內,預設為 0.1), 則控制平面會跳過擴縮操作。

在檢查容差並決定最終值之前,控制平面還會考慮是否缺少任何指標,以及有多少Pod已就緒。所有設定了刪除時間戳的Pod(帶有刪除時間戳的物件正在關閉/移除的過程中)都會被忽略,所有失敗的Pod都會被丟棄。

如果某個Pod缺失度量值,將會被擱置,只在最終確定擴縮數量時再考慮。如果HPA指定的是targetAverageValue或targetAverageUtilization,那麼它會將指定Pod度量值的平均值當做currentMetricValue。當使用CPU指標來擴縮時,任何還未就緒(還在初始化,或者可能是不健康的)狀態的Pod或最近的指標度量值採集於就緒狀態前的Pod,該Pod也會被擱置。在排除掉被擱置的Pod後,擴縮比例就會根據currentMetricValue/desiredMetricValue計算出來。

由於技術限制,HPA控制器在確定是否保留某些CPU指標時無法準確確定Pod首次就緒的時間(預設值為30秒,該值使用--horizontal-pod-autoscaler-initial-readiness-delay標誌配置),如果Pod未準備好並在其啟動後的一個可配置的短時間視窗內轉換為未準備好,它會認為Pod尚未準備好。 一旦Pod準備就緒,如果發生在自啟動後較長的可配置的時間內(預設5分鐘,該值由-horizontal-pod-autoscaler-cpu-initialization-period標誌配置),它就會認為任何向準備就緒的轉換都是第一個。

如果缺失某些度量值,控制平面會更保守地重新計算平均值,在需要縮小時假設這些Pod消耗目標值的100%, 需要放大時假設這些Pod消耗了0%目標值,這可以在一定程度上抑制擴縮的幅度。此外,如果存在任何尚未就緒的Pod,工作負載會在不考慮遺漏指標或尚未就緒的Pod的情況下進行擴縮, 控制器保守地假設尚未就緒的Pod消耗了期望指標的0%,從而進一步降低了擴縮的幅度。

考慮到尚未準備好的Pod和缺失的指標後,控制器會重新計算使用率。如果新的比率與擴縮方向相反,或者在容差範圍內,則控制器不會執行任何擴縮操作。在其他情況下,新比率用於決定對Pod數量的任何更改。平均利用率的原始值是通過HPA狀態體現的,而不考慮尚未準備好的Pod或缺少的指標,即使使用新的使用率也是如此。

如果建立HPA時指定了多個指標,那麼會按照每個指標分別計算擴縮副本數,取最大值進行擴縮。如果任何一個指標無法順利地計算出擴縮副本數(比如,通過API獲取指標時出錯),並且可獲取的指標建議縮容,那麼本次擴縮會被跳過。如果一個或多個指標給出的desiredReplicas值大於當前值,HPA仍然能實現擴容。

在HPA控制器執行擴縮操作之前,會記錄擴縮建議資訊。控制器會在操作時間視窗中考慮所有的建議資訊,並從中選擇得分最高的建議。這個值可通過kube-controller-manager服務的啟動引數--horizontal-pod-autoscaler-downscale-stabilization進行配置,預設值為5分鐘。這個配置可以讓系統更為平滑地進行縮容操作,從而消除短時間內指標值快速波動產生的影響。

更多內容參考:

如下為HPA的官方使用示例:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  # HPA的伸縮物件描述,HPA會動態修改該物件的pod數量
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  # HPA的最小pod數量和最大pod數量
  minReplicas: 1
  maxReplicas: 10
  # 監控的指標陣列,支援多種型別的指標共存
  metrics:
  # Object型別的指標
  - type: Object
    object:
      metric:
        # 指標名稱
        name: requests-per-second
      # 監控指標的物件描述,指標資料來源於該物件
      describedObject:
        apiVersion: networking.k8s.io/v1beta1
        kind: Ingress
        name: main-route
      # Value型別的目標值,Object型別的指標只支援Value和AverageValue型別的目標值
      target:
        type: Value
        value: 10k
  # Resource型別的指標
  - type: Resource
    resource:
      name: cpu
      # Utilization型別的目標值,Resource型別的指標只支援Utilization和AverageValue型別的目標值
      target:
        type: Utilization
        averageUtilization: 50
  # Pods型別的指標
  - type: Pods
    pods:
      metric:
        name: packets-per-second
      # AverageValue型別的目標值,Pods指標型別下只支援AverageValue型別的目標值
      target:
        type: AverageValue
        averageValue: 1k
  # External型別的指標
  - type: External
    external:
      metric:
        name: queue_messages_ready
        # 該欄位與第三方的指標標籤相關聯,(此處官方文件有問題,正確的寫法如下)
        selector:
          matchLabels:
            env: "stage"
            app: "myapp"
      # External指標型別下只支援Value和AverageValue型別的目標值
      target:
        type: AverageValue
        averageValue: 30

PodTemplate

負載資源的控制器通常使用Pod模板(Pod Template) 來建立Pod並管理它們。Pod模板是包含在工作負載物件中的規範,用來建立Pod。這類負載資源包括Deployment、Job和DaemonSets等。工作負載的控制器會使用負載物件中的PodTemplate來生成實際的Pod。PodTemplate是用來執行應用時指定的負載資源的目標狀態的一部分。
下面的示例是一個簡單的Job的清單,其中的template指示啟動一個容器。該Pod中的容器會列印一條訊息之後暫停。

apiVersion: batch/v1
kind: Job
metadata:
  name: hello
spec:
  template:
    # 這裡是 Pod 模版
    spec:
      containers:
      - name: hello
        image: busybox
        command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
      restartPolicy: OnFailure
    # 以上為 Pod 模版

修改Pod模版或者切換到新的Pod模版都不會對已經存在的Pod起作用。Pod不會直接收到模版的更新。相反,新的Pod會被創建出來,與更改後的Pod模版匹配。
例如,Deployment控制器針對每個Deployment物件確保執行中的Pod與當前的Pod模版匹配。如果模版被更新,則Deployment必須刪除現有的Pod,基於更新後的模版建立新的Pod。每個工作負載資源都實現了自己的規則,用來處理對Pod模版的更新。
在節點上,kubelet並不直接監測或管理與Pod模版相關的細節或模版的更新,這些細節都被抽象出來。這種抽象和關注點分離簡化了整個系統的語義,並且使得使用者可以在不改變現有程式碼的前提下就能擴充套件叢集的行為。

LimitRange

LimitRange從字面意義上指的是對範圍進行限制,實際上是對CPU和記憶體資源使用範圍的限制。如果在一個設定有默LimitRange控制的名稱空間建立容器,且該容器沒有宣告自己的記憶體限制時,會被指定預設記憶體限制。
下面給出一個限制範圍物件的配置檔案,該配置聲明瞭預設的記憶體請求和預設的記憶體限制:

apiVersion: v1
kind: LimitRange
metadata:
  name: mem-limit-range
spec:
  limits:
  - default:
      memory: 512Mi
    defaultRequest:
      memory: 256Mi
    type: Container

選擇一個名稱空間(default-mem-example)建立限制範圍:

kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults.yaml --namespace=default-mem-example

如果在default-mem-example名稱空間建立容器,並且該容器沒有宣告自己的記憶體請求和限制值,它將被指定預設的記憶體請求256M和預設的記憶體限制512M。
下面是具有一個容器的Pod的配置檔案,容器未指定記憶體請求和限制。

apiVersion: v1
kind: Pod
metadata:
  name: default-mem-demo
spec:
  containers:
  - name: default-mem-demo-ctr
    image: nginx

建立Pod

kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults-pod.yaml --namespace=default-mem-example

檢視Pod詳情:輸出內容顯示該Pod的容器有256M的記憶體請求和512M的記憶體限制。這些都是LimitRange設定的預設值。

kubectl get pod default-mem-demo --output=yaml --namespace=default-mem-example

# 輸出結果
containers:
- image: nginx
  imagePullPolicy: Always
  name: default-mem-demo-ctr
  resources:
    limits:
      memory: 512Mi
    requests:
      memory: 256Mi

更多內容檢視:LimitRange