VPA 的三個元件#

VPA 主要由三個元件組成,分別負責「觀察」、「重啟」與「注入」三件事:

  • Recommender
    • 觀察 Pod 的資源使用情形並計算預估值。
    • 參考歷史指標,給出建議的 requests/limits
  • Updater
    • 把需要更新的 Pod 驅逐(因為 Request/Limit 變更必須重啟容器)。
    • updatePolicy.updateMode: Auto 時,只要 Recommender 給出新建議就會觸發 Updater 行動。
  • Admission Controller
    • 在 Updater 把 Pod 驅逐、Deployment 準備重新建立時,透過 Webhook 介入。
    • 在新的 Pod 啟動前,把更新後的 requests/limits 注入進去。

三個元件互相搭配,才能把「重新計算建議 → 重啟 Pod → 套用新的資源設定」這條路走通。

安裝 VPA#

由於 Kubernetes 內建 API 只支援 HPA,使用 VPA 或 Cluster Autoscaler 等需要以 Custom Resource 的形式另外安裝。

下載官方 autoscaler repo 並進入 VPA 目錄:

git clone git@github.com:kubernetes/autoscaler.git
cd ./autoscaler/vertical-pod-autoscaler

執行安裝腳本:

./hack/vpa-up.sh

安裝過程中會建立 CRD、RBAC、ServiceAccount,以及 vpa-recommendervpa-updatervpa-admission-controller 三個 Deployment。

在 macOS 上,安裝過程可能因為系統內建的 LibreSSL 不支援 -addext 參數而失敗,看到類似 unknown option -addext 的錯誤訊息。這時要先把剛剛裝的部分卸下來,再升級 OpenSSL/LibreSSL。

先卸載:

./hack/vpa-down.sh

安裝較新的 LibreSSL,並把新版本放到 PATH 前面:

brew install libressl
echo 'export PATH="/opt/homebrew/opt/libressl/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

再次執行安裝:

./hack/vpa-up.sh

確認三個 VPA 元件都跑起來:

kubectl get pods -n kube-system | grep vpa
vpa-admission-controller-667dd5b58-jsftm   1/1     Running   0   84s
vpa-recommender-5f48d76d7-g7x6m            1/1     Running   0   85s
vpa-updater-6fc5699544-wrvhb               1/1     Running   0   85s

確認 CRD 已註冊:

kubectl api-resources | grep vpa
verticalpodautoscalercheckpoints   vpacheckpoint   autoscaling.k8s.io/v1   true   VerticalPodAutoscalerCheckpoint
verticalpodautoscalers             vpa             autoscaling.k8s.io/v1   true   VerticalPodAutoscaler

實戰練習#

測試用 Deployment#

這個範例的容器會週期性大量耗用 CPU,方便我們觀察 VPA 的推薦值:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hamster
  namespace: default
spec:
  selector:
    matchLabels:
      app: hamster
  replicas: 1
  template:
    metadata:
      labels:
        app: hamster
    spec:
      containers:
        - name: hamster
          image: k8s.gcr.io/ubuntu-slim:0.1
          resources:
            requests:
              cpu: 100m
              memory: 50Mi
            limits:
              cpu: 2000m
              memory: 2Gi
          command: ["/bin/sh"]
          args:
            - "-c"
            - "while true; do timeout 0.2s yes >/dev/null; sleep 0.5s; done"

對應的 VPA 設定#

# vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: hamster-vpa
  namespace: default
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: hamster
  updatePolicy:
    updateMode: "Off"
  resourcePolicy:
    containerPolicies:
      - containerName: "*"
        minAllowed:
          cpu: 100m
          memory: 50Mi
        maxAllowed:
          cpu: 1
          memory: 500Mi
        controlledResources: ["cpu", "memory"]

幾個重要欄位:

  • spec.updatePolicy.updateMode
    • Off:VPA 只給推薦值,不會自動修改任何設定。
    • Initial:只在 Pod 建立時套用推薦值,後續不會再自動調整。
    • Auto:完全交給 Recommender,自動套用推薦值。
    • Recreate:類似 Auto,但每次都以 recreate 方式重啟 Pod(使用情境較少)。
  • spec.resourcePolicy.containerPolicies
    • containerName:套用範圍,* 代表 Pod 內所有容器。
    • minAllowed / maxAllowed:可調整的下限與上限。
    • controlledResources:要監控的資源指標,目前可選 cpu 與 memory。

部署:

kubectl apply -f ./deployment.yaml -f ./vpa.yaml

查看推薦結果#

kubectl get vpa
NAME          MODE   CPU    MEM       PROVIDED   AGE
hamster-vpa   Auto   379m   262144k   True       2m58s

進一步看推薦細節:

kubectl describe vpa hamster-vpa

擷取重點輸出:

Status:
  Conditions:
    Last Transition Time: 2022-08-28T10:03:36Z
    Status: True
    Type: RecommendationProvided
  Recommendation:
    Container Recommendations:
      Container Name: hamster
      Lower Bound:
        Cpu: 204m
        Memory: 262144k
      Target:
        Cpu: 379m
        Memory: 262144k
      Uncapped Target:
        Cpu: 379m
        Memory: 262144k
      Upper Bound:
        Cpu: 1
        Memory: 500Mi

Status.Recommendation 中幾個值的意義:

  • Lower Bound:當 Pod 的 Request 小於此值時,VPA 會把 Pod 刪除並重建。
  • Upper Bound:當 Pod 的 Request 大於此值時,VPA 會把 Pod 刪除並重建。
  • Target:在 minAllowedmaxAllowed 範圍內的最終推薦值,用來讓容器以最佳狀態執行。
  • Uncapped Target:完全不受 minAllowed / maxAllowed 約束時的推薦值。

移除 VPA 模組#

./hack/vpa-down.sh

小結#

各種 Autoscaler 能幫我們省下不少不必要的資源浪費,HPA 與 VPA 也可以結合使用。但要特別注意:使用「非外部指標」的 HPA 會跟 VPA 的 Auto 模式互相打架,造成不可預期的結果。實務上比較穩妥的做法是 HPA 搭配 VPA 的 Off 模式——讓 VPA 只負責提供推薦值,作為人工調整 Request/Limit 時的參考。

原文出處#

  • GitHub:https://github.com/MikeHsu0618/2022-ithelp/tree/main/Day27
  • iThome:https://ithelp.ithome.com.tw/articles/10299462