全部產品
Search
文件中心

Container Service for Kubernetes:AI模型推理服務在Knative中最佳配置實踐

更新時間:Nov 02, 2024

Knative和AI結合提供了快速部署、高彈性和低成本的技術優勢,適用於需要頻繁調整計算資源的AI應用情境,例如模型推理等。您可以通過Knative Pod部署AI模型推理任務,配置自動擴縮容、靈活分配GPU資源等功能,提高AI推理服務能力和GPU資源使用率。

加速模型部署

為了保證Knative Serving部署的AI模型推理服務實現快速的伸縮能力,應避免將AI模型打包到容器鏡像中。當AI模型和容器鏡像打包在一起時,容器的大小會顯著地增大,從而減緩容器的部署速度。此外,當AI模型被打包在容器內時,AI模型的版本將與容器鏡像版本綁定,增加了版本控制的複雜性。

為避免上述問題,推薦您將AI模型的資料載入到Object Storage Service、Apsara File Storage NAS等外部介質中,並通過PVC掛載到Knative服務Pod中。同時,可使用分布式資料集編排和加速引擎Fluid來加速對AI模型的讀取和載入過程(參見JindoFS加速OSS檔案訪問EFC加速NAS或CPFS檔案訪問等相關文檔),實現大模型的秒級載入。

前提條件

步驟一:定義資料集

當您將AI模型存放在Object Storage Service時,可以使用Dataset來聲明OSS上的資料集,並使用JindoRuntime執行緩衝任務。

展開查看樣本YAML

apiVersion: v1
kind: Secret
metadata:
  name: access-key
stringData:
  fs.oss.accessKeyId: your_ak_id   # 請替換為訪問OSS所用的access key ID。
  fs.oss.accessKeySecret: your_ak_skrt   # 請替換為訪問OSS所用的access key secret。
---
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
  name: oss-data
spec:
  mounts:
  - mountPoint: "oss://{Bucket}/{path-to-model}" # 請替換為模型所在的OSS Bucket以及儲存路徑。
    name: xxx
    path: "{path-to-model}" # 根據程式載入模型的路徑,替換該處的模型儲存路徑。
    options:
      fs.oss.endpoint: "oss-cn-beijing.aliyuncs.com"  # 請替換為實際的OSS endpoint地址。
    encryptOptions:
      - name: fs.oss.accessKeyId
        valueFrom:
          secretKeyRef:
            name: access-key
            key: fs.oss.accessKeyId
      - name: fs.oss.accessKeySecret
        valueFrom:
          secretKeyRef:
            name: access-key
            key: fs.oss.accessKeySecret
  accessModes:
    - ReadOnlyMany
---
apiVersion: data.fluid.io/v1alpha1
kind: JindoRuntime
metadata:
  name: oss-data
spec:
  replicas: 2
  tieredstore:
    levels:
      - mediumtype: SSD
        volumeType: emptyDir
        path: /mnt/ssd0/cache
        quota: 100Gi
        high: "0.95"
        low: "0.7"
  fuse:
    properties:
      fs.jindofsx.data.cache.enable: "true"
    args:
      - -okernel_cache
      - -oro
      - -oattr_timeout=7200
      - -oentry_timeout=7200
      - -ometrics_port=9089
    cleanPolicy: OnDemand

步驟二:掛載PVC實現加速效果

聲明Dataset和JindoRuntime後,系統會自動建立同名PVC,將PVC掛載到Knative服務中即可實現加速效果。

展開查看樣本YAML

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: sd-backend
spec:
  template:
    spec:
      containers:
        - image: <YOUR-IMAGE>   # 請將<YOUR-IMAGE>替換為您的鏡像名稱。
          name: image-name
          ports:
            - containerPort: xxx
              protocol: TCP
          volumeMounts:
            - mountPath: /data/models  # 根據程式載入模型的路徑,替換moutPath。
              name: data-volume
      volumes:
        - name: data-volume
          persistentVolumeClaim:
            claimName: oss-data   # 掛載和Dataset同名的PVC。

步驟三:通過鏡像緩衝實現秒級載入

除AI模型本身之外,也需要考慮容器鏡像大小對Knative服務的影響。運行AI模型的服務容器往往需要打包CUDA、pytorch-gpu等一系列依賴,導致其容器鏡像大小顯著增加。當使用ECI Pod部署Knative AI模型推理服務時,建議使用ImageCache來加速鏡像的拉取過程,ImageCache能夠為ECI Pod提供鏡像緩衝功能,通過提前緩衝鏡像來顯著加速鏡像拉取時間、實現秒級鏡像拉取,參見使用ImageCache加速建立ECI Pod

apiVersion: eci.alibabacloud.com/v1
kind: ImageCache
metadata:
  name: imagecache-ai-model
  annotations:
    k8s.aliyun.com/eci-image-cache: "true" # 開啟鏡像緩衝複用。
spec:
  images:
  - <YOUR-IMAGE>
  imageCacheSize:
    25 # 鏡像緩衝大小,單位GiB。
  retentionDays:
    7 # 鏡像緩衝保留時間。

優雅關閉容器

為了確保進行中的請求不會突然終止,容器應在收到SIGTERM訊號時啟動正常關閉。

  • 收到SIGTERM訊號後,如果應用程式使用HTTP探測,則設定容器為非就緒狀態,防止將新的請求轉寄給正在關閉的容器。

  • 在關閉過程中,Knative的queue-proxy可能仍在將請求轉寄到容器。建議將timeoutSeconds參數應該設定為最長預期處理請求回應時間的1.2倍左右,以確保所有請求可以在容器終止之前完成。例如,如果最長的請求回應時間需要10秒,建議將timeoutSeconds參數設定為12秒。

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: helloworld-go
      namespace: default
    spec:
      template:
        spec:
          timeoutSeconds: 12

並發參數配置

通過正確配置並發參數,您可以顯著提升Knative服務的效能和響應速度。這些設定可以協助您的應用程式更有效地處理高並發請求負載,從而提高整體的服務品質和使用者體驗。

  • 並發硬限制:硬限制是強制上限。如果並發達到硬限制,多餘的請求將被緩衝,並且必須等待,直到有足夠的可用資源來執行請求。

  • 並發軟式節流:軟式節流是有針對性的限制,而不是嚴格的約束。在類似請求突然爆發的情況下,可能會超過該值。

  • 目標使用率:相較於直接修改target,調整目標使用率autoscaling.knative.dev/target-utilization-percentage提供了更直觀的並發層級管理方式。將此配置接近 100% 可以實現最高效的並發處理。

更多詳細說明及執行個體,請參見並發數配置介紹

自動彈性擴縮容

在對自動彈性進行調整之前,首先需定義最佳化目標,例如減少延遲、最大限度地降低成本或適應尖峰流量模式。然後測量Pod在預期情境下啟動所需的時間。例如,部署單個Pod可能與同時部署多個Pod具有不同的方差和平均啟動時間。這些指標為自動彈性配置提供了基準。

更多參數資訊及配置說明,請參見基於流量請求數實現服務自動擴縮容

擴縮容模式

自動彈性有兩種模式,穩定模式(Stable Mode)和恐慌模式(Panic Mode),每種模式都有單獨的視窗。穩定模式用於一般操作,而恐慌模式預設情況下具有更短的視窗,用於在流量突發時快速擴容Pod。

穩定強制回應視窗

通常為了保持穩定的擴縮容行為,穩定視窗應該比平均Pod啟動時間長,推薦設定為平均時間的2倍。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/window: "40s"

恐慌強制回應視窗

恐慌視窗是穩定視窗的百分比。其主要功能是管理突然的、意外的流量高峰。

重要

此配置容易導致過度擴容,尤其當Pod啟動時間較長時。請謹慎配置。

  • 如果穩定視窗設定為30秒,恐慌視窗配置為10%,則系統將使用3秒的資料來判斷是否進入恐慌縮放模式。如果Pod通常需要30秒才能啟動,則系統可能會在新Pod仍在上線時繼續擴容,從而可能導致過度擴容Pod。

  • 在調整其他參數並確保縮允許存取為穩定之前,避免對恐慌視窗進行微調,尤其是當考慮到恐慌視窗的值短於或等同於Pod啟動時間的情形。若穩定視窗為平均Pod啟動時間的兩倍,可以考慮將恐慌視窗值設定為50%,以此作為平衡正常和高峰流量模式的起點。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/panic-window-percentage: "20.0"

恐慌模式閾值是傳入流量與服務容量的比率。根據流量的尖峰和可接受的延遲水平來調整此值。初始值為200%或更高,直到縮允許存取為穩定。服務運行一段時間之後,可以考慮進一步調整。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/panic-threshold-percentage: "150.0"

彈性速率

為了更好地響應流量模式,可以通過調整擴容和縮容速率來控制系統的彈性。預設配置通常能夠滿足大部分需求,但在特定情境下可能需要進行相應的調整。在調整速率之前需要觀察當前情況,並優先在測試環境中變更和驗證,以評估其影響。如果遇到擴縮容問題,請檢查與擴容和縮容速率相關的參數,如穩定視窗和恐慌視窗等。

擴容速率

除非遇到特定問題,否則擴容速率通常不需要修改。例如,如果同時對多個Pod進行擴容,可能由於需等待資源的分配,導致啟動時間延長,則需要調整擴容速率。如果觀察到頻繁擴縮,可能還需要考慮調整其他相關參數,如穩定視窗或者恐慌視窗大小,以最佳化伸縮行為。

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  max-scale-up-rate: "500.0"

縮容速率

縮容速率最初應設定為平均Pod啟動時間或更長。預設值通常足以滿足大多數使用方式,但如果重點在於最佳化成本,可以考慮調高速率,以便在流量高峰後更快地縮容。

縮容率是一個乘數,例如,值N/2將允許系統在彈性周期結束時將Pod數量縮減至當前數量的一半。對於Pod數量較少的服務,較低的縮容率有助於保持Pod數量更加平滑,避免頻繁地伸縮造成的波動,從而提高系統穩定性。

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  max-scale-down-rate: "4.0"

延遲縮容

可以通過指定延遲縮容的時間視窗,避免新請求進入時頻繁擴縮容,導致響應延遲的問題。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/scale-down-delay: "2m" // 表示延遲 2 分鐘縮容

擴縮容邊界

這些參數與業務的規模和可用資源高度相關。

下限

autoscaling.knative.dev/min-scale控制每個修訂版應具有的最小副本數。Knative將保持不少於此數量的副本。對於那些使用率不高但需要保持始終可用的服務,將該值設定為1可以確保至少有一個副本始終運行。對於可能會有大量突發流量的服務,應將此值設定高於1以提高應對能力。如果希望服務能夠在無流量時縮減到零副本,可將該值設定為0。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/min-scale: "0"

上限

autoscaling.knative.dev/max-scale不應超過可用資源。使用此參數主要限制最大資源成本。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/max-scale: "3"

初始擴容數

配置初始規模,建議配置為現有Pod數量的1.2倍左右,以便新版本可以充分處理現有流量。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/initial-scale: "3"

共用GPU調度

結合ACK共用GPU調度能力,Knative模型服務可以充分利用cGPU顯存隔離能力,高效利用GPU裝置資源。

在Knative使用共用GPU只需要在Knative Service中limits設定aliyun.com/gpu-mem參數即可,樣本如下。

展開查看樣本YAML

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    spec:
      containerConcurrency: 1
      containers:
      - image: registry-vpc.cn-hangzhou.aliyuncs.com/demo-test/test:helloworld-go
        name: user-container
        ports:
        - containerPort: 6666
          name: http1
          protocol: TCP
        resources:
          limits:
            aliyun.com/gpu-mem: "3"

探針配置

您可以通過配置存活探針(Liveness Probe)和就緒探針(Readiness Probe)監測Knative服務的健康和可用性。相較於 Kubernetes 的探針策略,Knative 採用更頻繁的積極探測,以最大限度減少冷啟動時間,加速 Pod 啟動到啟動並執行過程。

  • Liveness Probe:存活探針用於監視容器的健康情況。如果容器處於失敗狀態或在容器運行中服務未成功啟動,存活探針將重新啟動容器。

  • Readiness Probe:配置就緒探針可以有效管理應用的自動擴縮容過程,確保只有準備好的執行個體可以接收流量,從而提升系統的可靠性和響應效率。

    • 在載入所有組件並且容器完全準備好之前,TCP探針不會啟動監聽連接埠。

    • 在端點能夠處理請求之前,HTTP探測不應將服務標記為就緒。

    • 調整探測間隔periodSeconds時,請保持較短的間隔。理想情況下,該時間應小於預設值10秒。

更多詳細說明及最佳實務,請參見在Knative中配置連接埠探測

按需自動縮容至零以節約資源

Knative的突出功能之一是能夠在服務不使用時將Pod縮容至零。

對於需要管理多個模型的使用者,推薦為每個獨立的模型建立單獨的Knative服務,以避免在一個服務內部整合複雜的商務邏輯。

  • 藉助Knative的縮容到零的功能,可以做到長時間未被訪問的模型不會產生資源成本。

  • 當用戶端第一次訪問模型服務時,Knative能夠實現從零狀態開始的自動擴容。

更多詳細說明及最佳實務,請參見配置保留執行個體

基於多版本設定合理的灰階節奏

Knative優勢之一是可以確保不間斷的服務可用性,特別是在推出新版本時。當部署新代碼或對服務變更時Knative會保持舊版本運行,直到新版本準備就緒。

可以通過流量百分比閾值進行配置。流量百分比是一個關鍵參數,它決定Knative何時應將流量從舊版本切換到新版本。該百分比可以低至10%,也可以高達100%,取決於具體需求。對於不需要舊服務的非生產環境,可以將流量百分比設定為100%。當新版本準備就緒時,會立即關閉舊版本。

在Pod可用性有限的情況下進行大規模操作時,需要控制舊版本的縮容速度。如果某個服務在500個Pod上運行,而只有300個額外的Pod可用,那麼設定過大的流量百分比可能會導致服務部分不可用。

更多詳細說明及最佳實務,請參見基於流量灰階發布服務

ECS和ECI資源混用

如果希望常態情況下使用ECS資源,突發流量時使用ECI,那麼可以結合ResourcePolicy來實現。在常態下通過ECS資源承載流量,而在遇到突增的流量時,額外擴容的資源會使用ECI進行承載。

  • 在擴容過程中,Knative Pod會優先利用ECS資源進行擴充。當Pod數量超過預設的最大值,或ECS資源不足時,則會轉而使用ECI來建立新的Pod。

  • 縮容時,會根據調度節點的逆序,優先縮容在ECI上的Pod。

更多詳細說明及最佳實務,請參見在Knative中同時使用ECS和ECI資源