全部產品
Search
文件中心

Container Service for Kubernetes:基於GPU指標實現Auto Scaling

更新時間:Jun 19, 2024

Kubernetes提供了Custom Metrics機制,該機制可以對接阿里雲Prometheus監控來採集GPU指標。本文介紹如何部署阿里雲Prometheus監控,並結合樣本說明如何通過阿里雲Prometheus監控觀測GPU指標,實現容器的Auto Scaling。

前提條件

您已建立GPU叢集或已建立專有GPU叢集

功能介紹

在高效能運算領域,例如深度學習模型訓練、推理等情境,通常需要使用GPU來做計算加速。為了節省成本,您可以根據GPU指標(利用率、顯存)來進行Auto Scaling。

Kubernetes預設提供CPU和記憶體作為HPAAuto Scaling的指標。如果有更複雜的情境需求,例如基於GPU指標進行自動擴縮容,您可以通過Prometheus Adapter適配Prometheus採集到的GPU指標,再利用Custom Metrics API來對HPA的指標進行擴充,從而根據GPU利用率、顯存等指標進行Auto Scaling。GPUAuto Scaling原理如下圖所示:

hpa

步驟一:部署阿里雲Prometheus和Metrics Adapter

  1. 步驟一:開啟阿里雲Prometheus監控

    說明

    如果您在建立叢集時,已選中安裝Prometheus,則不需要重複安裝。

  2. 安裝並配置ack-alibaba-cloud-metrics-adapter。

    一、擷取HTTP API地址

    1. 登入ARMS控制台

    2. 在左側導覽列選擇Prometheus監控 > 執行個體列表,進入可觀測監控 Prometheus 版的執行個體列表頁面。

    3. 在頁面頂部選擇Container ServiceK8s叢集所在的地區,然後選擇執行個體類型Prometheus for Container Service的目標執行個體名稱,進入對應執行個體頁面。

    4. 在左側導覽列單擊設定,複製HTTP API地址下的內網地址。

    二、配置Prometheus Url

    1. 登入Container Service管理主控台,在左側導覽列選擇市場 > 應用市場

    2. 應用市場頁面單擊應用目錄頁簽,搜尋並單擊ack-alibaba-cloud-metrics-adapter

    3. ack-alibaba-cloud-metrics-adapter頁面,單擊一鍵部署

    4. 基本資料設定精靈中,選擇叢集和命名空間,然後單擊下一步

    5. 參數配置設定精靈中,選擇Chart版本,在參數配置中將上述擷取的HTTP API地址設定為Prometheus的url值,然後單擊確定

步驟二:配置GPU指標Adapter Rules

一、查詢GPU指標

查詢GPU相關指標。詳細資料,請參見監控指標說明

二、配置Adapter Rules

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

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇應用 > Helm

  3. 在Helm列表的操作列,單擊ack-alibaba-cloud-metrics-adapter對應的更新。在custom欄位下添加如下rules

    展開查看詳細rules資訊

    - metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NodeName:
            resource: node
      seriesQuery: DCGM_FI_DEV_GPU_UTIL{} # GPU使用率
    - metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          NodeName:
            resource: node
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_SM_UTIL{} # 容器GPU使用率。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NodeName:
            resource: node
      seriesQuery: DCGM_FI_DEV_FB_USED{} # 顯存使用量。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          NodeName:
            resource: node
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_MEM_USED{} # 容器顯存使用量。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>) / sum(DCGM_CUSTOM_CONTAINER_MEM_ALLOCATED{}) by (<<.GroupBy>>)
      name:
        as: ${1}_GPU_MEM_USED_RATIO
        matches: ^(.*)_MEM_USED
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_MEM_USED{NamespaceName!="",PodName!=""}  # 容器GPU顯存使用率。

    添加後效果如下。

    1690252651140-f693f03a-0f9e-4a6a-8772-b7abe9b2912a.png

    執行以下命令時,存在HPA可以識別的輸出條目DCGM_FI_DEV_GPU_UTILDCGM_CUSTOM_PROCESS_SM_UTILDCGM_FI_DEV_FB_USEDDCGM_CUSTOM_PROCESS_MEM_USED指標,則說明配置成功生效。下面以DCGM_CUSTOM_PROCESS_SM_UTIL為例進行說明,實際以輸出為準。

    展開查看輸出樣本

    kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1"
    {
    	[
        ...
    		{
          "name": "nodes/DCGM_CUSTOM_PROCESS_SM_UTIL",
          "singularName": "",
          "namespaced": false,
          "kind": "MetricValueList",
          "verbs": [
            "get"
          ]
        },
        ...
        {
          "name": "pods/DCGM_CUSTOM_PROCESS_SM_UTIL",
          "singularName": "",
          "namespaced": true,
          "kind": "MetricValueList",
          "verbs": [
            "get"
          ]
        },
        ...
        {
          "name": "namespaces/DCGM_CUSTOM_PROCESS_SM_UTIL",
          "singularName": "",
          "namespaced": false,
          "kind": "MetricValueList",
          "verbs": [
            "get"
          ]
        }
        ...
        {
          "name": "DCGM_CUSTOM_PROCESS_GPU_MEM_USED_RATIO",
          "singularName": "",
          "namespaced": false,
          "kind": "MetricValueList",
          "verbs": [
            "get"
          ]
        }
        ...
    	]
    }

步驟三:基於GPU指標實現Auto Scaling

本樣本通過在GPU上部署一個模型推理服務,然後對其進行壓測,根據GPU利用率測試Auto Scaling。

一、部署推理服務

  1. 執行以下命令部署推理服務。

    展開查看命令詳情

    cat <<EOF | kubectl create -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: bert-intent-detection
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: bert-intent-detection
      template:
        metadata:
          labels:
            app: bert-intent-detection
        spec:
          containers:
          - name: bert-container
            image: registry.cn-hangzhou.aliyuncs.com/ai-samples/bert-intent-detection:1.0.1
            ports:
            - containerPort: 80
            resources:
              limits:
                nvidia.com/gpu: 1
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: bert-intent-detection-svc
      labels:
        app: bert-intent-detection
    spec:
      selector:
        app: bert-intent-detection
      ports:
      - protocol: TCP
        name: http
        port: 80
        targetPort: 80
      type: LoadBalancer
    EOF
  2. 查看Pod和Service狀態。

    • 執行以下命令查看Pod狀態。

      kubectl get pods -o wide

      預期輸出:

      NAME                                    READY   STATUS    RESTARTS   AGE     IP           NODE                        NOMINATED NODE   READINESS GATES
      bert-intent-detection-7b486f6bf-f****   1/1     Running   0          3m24s   10.15.1.17   cn-beijing.192.168.94.107   <none>           <none>

      預期輸出表明,當前只有一個Pod部署在192.168.94.107這個GPU節點上。

    • 執行以下命令查看Service狀態。

      kubectl get svc bert-intent-detection-svc

      預期輸出:

      NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
      bert-intent-detection-svc   LoadBalancer   172.16.186.159   47.95.XX.XX   80:30118/TCP   5m1s

      預期輸出中顯示服務名稱,表示服務部署成功。

  3. 通過SSH登入GPU節點192.168.94.107後,執行以下命令查看GPU使用方式。

    nvidia-smi

    預期輸出:

    Wed Feb 16 11:48:07 2022
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 450.102.04   Driver Version: 450.102.04   CUDA Version: 11.0     |
    |-------------------------------+----------------------+----------------------+
    | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
    |                               |                      |               MIG M. |
    |===============================+======================+======================|
    |   0  Tesla V100-SXM2...  On   | 00000000:00:07.0 Off |                    0 |
    | N/A   32C    P0    55W / 300W |  15345MiB / 16160MiB |      0%      Default |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |    0   N/A  N/A   2305118      C   python                          15343MiB |
    +-----------------------------------------------------------------------------+

    預期輸出表明,推理服務進程已運行在GPU上。由於尚未發起請求,當前GPU利用率為0。

  4. 執行以下命令調用推理服務,驗證部署是否成功。

    curl -v  "http://47.95.XX.XX/predict?query=Music"

    預期輸出:

    *   Trying 47.95.XX.XX...
    * TCP_NODELAY set
    * Connected to 47.95.XX.XX (47.95.XX.XX) port 80 (#0)
    > GET /predict?query=Music HTTP/1.1
    > Host: 47.95.XX.XX
    > User-Agent: curl/7.64.1
    > Accept: */*
    >
    * HTTP 1.0, assume close after body
    < HTTP/1.0 200 OK
    < Content-Type: text/html; charset=utf-8
    < Content-Length: 9
    < Server: Werkzeug/1.0.1 Python/3.6.9
    < Date: Wed, 16 Feb 2022 03:52:11 GMT
    <
    * Closing connection 0
    PlayMusic # 意圖識別結果。

    預期輸出中,HTTP請求返回狀態代碼200並返回意圖識別結果,表明推理服務部署成功。

二、配置HPA

本文以GPU利用率為例進行說明,當Pod的GPU利用率大於20%時,觸發擴容。HPA目前支援的指標如下。

指標名稱

說明

單位

DCGM_FI_DEV_GPU_UTIL

  • GPU卡的利用率。

  • 該指標僅在獨佔GPU調度時有效。

    重要

    在共用GPU的情況下,同一張GPU卡被分配給多個Pod,而NVIDIA目前僅提供卡層級的利用率,並未提供應用層級的利用率,所以在Pod中執行nvidia-smi看到的利用率為整張卡的利用率。

%

DCGM_FI_DEV_FB_USED

  • GPU卡顯存使用量。

  • 該指標僅在獨佔GPU調度時有效。

MiB

DCGM_CUSTOM_PROCESS_SM_UTIL

容器的GPU利用率。

%

DCGM_CUSTOM_PROCESS_MEM_USED

容器的GPU顯存使用量。

MiB

DCGM_CUSTOM_PROCESS_GPU_MEM_USED_RATIO

容器的GPU顯存利用率。

容器的GPU顯存利用率=當前Pod容器GPU實際顯存使用量(Used) / 當前Pod容器GPU分配的顯存使用量(Allocated)

%

  1. 執行以下命令部署HPA。

    叢集版本≥1.23

    cat <<EOF | kubectl create -f -
    apiVersion: autoscaling/v2  # 使用autoscaling/v2版本的HPA配置。
    kind: HorizontalPodAutoscaler
    metadata:
      name: gpu-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: bert-intent-detection
      minReplicas: 1
      maxReplicas: 10
      metrics:
      - type: Pods
        pods:
          metric:
            name: DCGM_CUSTOM_PROCESS_SM_UTIL
          target:
            type: Utilization
            averageValue: 20 # 當容器的GPU利用率超過20%,觸發擴容。
    EOF

    叢集版本<1.23

    cat <<EOF | kubectl create -f -
    apiVersion: autoscaling/v2beta1  # 使用autoscaling/v2beta1版本的HPA配置。
    kind: HorizontalPodAutoscaler
    metadata:
      name: gpu-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: bert-intent-detection
      minReplicas: 1
      maxReplicas: 10
      metrics:
      - type: Pods
        pods:
          metricName: DCGM_CUSTOM_PROCESS_SM_UTIL # Pod的GPU利用率。
          targetAverageValue: 20 # 當容器的GPU利用率超過20%,觸發擴容。
    EOF
  2. 執行以下命令查看HPA狀態。

    kubectl get hpa

    預期輸出:

    NAME      REFERENCE                          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    gpu-hpa   Deployment/bert-intent-detection   0/20      1         10        1          74s

    預期輸出表明,TARGETS0/20,即當前GPU利用率為0,當GPU利用率超過20%時觸發彈性擴容。

三、測試推理服務Auto Scaling

測試擴容效果

  1. 執行以下命令進行壓測。

    hey -n 10000 -c 200 "http://47.95.XX.XX/predict?query=music"
    說明

    HPA彈性擴容的期望副本數的計算公式:期望副本數 = ceil[當前副本數 * (當前指標 / 期望指標)]。例如,當前副本數為1,當前指標為23,期望指標為20,由計算公式得到期望副本數為2。

  2. 壓測過程中,觀察HPA和Pod的狀態。

    1. 執行以下命令查看HPA的狀態。

      kubectl get hpa

      預期輸出:

      NAME      REFERENCE                          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
      gpu-hpa   Deployment/bert-intent-detection   23/20     1         10        2          7m56s

      預期輸出表明,TARGETS值為23/20,當前GPU利用率超過20%時,觸發Auto Scaling,此時叢集開始擴容。

    2. 執行以下命令查看Pod的狀態。

      kubectl get pods

      預期輸出:

      NAME                                    READY   STATUS    RESTARTS   AGE
      bert-intent-detection-7b486f6bf-f****   1/1     Running   0          44m
      bert-intent-detection-7b486f6bf-m****   1/1     Running   0          14s

      預期輸出表明,當前有2個Pod。由上述計算公式得到Pod總數應為2,公式計算值與實際輸出一致。

    HPA和Pod的預期輸出,Pod擴容成功。

測試縮容效果

當壓測停止,GPU利用率降低且低於20%後,系統開始進行彈性縮容。

  1. 執行以下命令查看HPA的狀態。

    kubectl get hpa

    預期輸出:

    NAME      REFERENCE                          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    gpu-hpa   Deployment/bert-intent-detection   0/20      1         10        1          15m

    預期輸出表明,TARGETS0/20 ,即當前GPU利用率為0,大約5分鐘後,系統開始進行彈性縮容。

  2. 執行以下命令查看Pod的狀態。

    kubectl get pods

    預期輸出:

    NAME                                    READY   STATUS    RESTARTS   AGE
    bert-intent-detection-7b486f6bf-f****   1/1     Running   0          52m

    預期輸出表明,當前Pod個數為1,即縮容成功。

常見問題

如何判斷是否使用了GPU卡?

您可以通過GPU監控頁簽,觀察GPU卡的使用率波動狀況,以此判斷GPU卡是否被使用。如果使用率上升,表明使用了GPU卡。如果使用率不變,表明未使用GPU卡。詳細方法為:

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

  2. 叢集列表頁面中,單擊目的地組群名稱,然後在左側導覽列中,選擇營運管理 > Prometheus監控

  3. Prometheus監控頁面,單擊GPU監控頁簽,然後觀察GPU卡的使用率波動狀況。