KServe + Fluid 加速大模型推理

背景

KServe 是 Kubernetes 上的標準模型推理平臺,專爲高度可擴展的場景而構建,支持現代 Serverless 推理工作負載,用於在任意框架上提供機器學習(ML)模型服務。它提供高性能、高度抽象的接口,以支持常見的 ML 框架(如Tensorflow、XGBoost、Scikit-Learn、PyTorch 和 ONNX)來解決生產模型服務場景。此外,KServe 封裝了自動縮放、網絡、健康檢查和服務配置的複雜性,支持GPU 自動縮放、歸零縮放和金絲雀發佈等。爲生產級別機器學習服務提供了一個簡單、可插拔且完整的支持,包括預測、預處理、後處理和可解釋性的能力。

人工智能生成內容(AIGC)和大型語言模型(LLM)在近一年內方興未艾,進一步提升了了大衆對 AI 的期望值。爲了能夠產生新的業務價值,越來越多的公司開始使用 KServe 來部署它們,主要原因是:

  1. 分佈式處理:大型語言模型(LLMs)的參數量龐大,需要極高的計算資源,而KServe平臺提供了分佈式處理能力,可以將計算任務分佈到多個節點上進行並行計算,從而加速計算過程。
  2. Serverless:KServe 平臺是無服務器算法的典型代表,可以在需求變化時自動進行擴縮容。這種特性使得部署大型語言模型變得更加靈活和高效,並能夠顯著提升模型的響應速度。
  3. 統一化部署:KServe 平臺爲用戶提供了一種更加簡便和統一的方式來部署和管理大型語言模型。這樣一來,用戶無需自行設置和配置算法環境,即可開始進行模型的訓練和預測工作。
  4. 監控和管理:KServe 平臺具備完備的監控和管理功能,用戶可以清晰地瞭解到模型的運行狀況和性能表現,並能夠及時調整參數和處理問題,從而保證模型的高效和可靠。

但是在生產實踐中,KServe 對於大型語言模型(LLMs)的支持依然有不小的挑戰。主要問題在於:

  1. 模型啓動時間長:大型語言模型(LLMs)的參數規模相當巨大,體積通常很大甚至達到幾百 GB,導致拉取到 GPU 顯存的耗時巨大,啓動時間非常慢。此外,KServe 通過存儲初始化器(Storage Initializer)從遠程存儲中拉取模型到本地,這也需要很長時間,對根據流量進行 KServe 無服務器自動擴縮容功能產生不利影響。
  2. 容器鏡像拉取時間長:大型語言模型(LLMs)的運行時環境依賴 GPU 基礎環境,相應的容器鏡像通常很大,這會導致拉取時間長,拖慢應用啓動速度。
  3. 模型更新效率低、複雜度高:大型語言模型(LLMs)由多個文件組成,模型更新時只需部分更新或添加部分文件,但 KServe 需要重啓容器和重新拉取模型,無法支持模型的熱升級,這帶來效率低和複雜度高的問題。

KServe 在 Kubecon 2023 就提到了 Fluid 有可能幫助解決其在彈性上遇到的問題。Fluid 是一個開源的 Kubernetes 原生的分佈式數據集編排和加速引擎,主要服務於雲原生場景下的數據密集型應用,例如大數據應用、AI 應用等。參見數據加速 Fluid 概述[1]

阿里雲容器服務團隊和 KServe,Fluid 社區的小夥伴一起探索在阿里雲 Serverless Kubernetes 平臺上簡單,方便,高性能,生產級別的支持大型語言模型(LLMs):

  1. 服務託管,產品支持:阿里雲服務網格(簡稱 ASM)對於 KServe 提供了原生支持,要知道 KServe 依賴於底層Istio的穩定性對於 KServe 來說非常重要,使用託管的服務網格後,高可用、免運維、內建安全最佳實踐;用戶可以更專注於大語言模型相關的工作。除此之外 KServe 和 Fluid 也可以一鍵安裝。
  2. 協同社區優化使用模式:在 KServe 最新版支持除了存儲初始化器(Storage Initializer)外,也支持標準的 PVC 模式,通過避免從遠程存儲中拉取模型到本地,減少存儲不足的風險和提升啓動速度;也可以支持模型熱升級。
  3. 通過彈性分佈式緩存加速模型加載流程:Fluid 與 KServe 相結合,通過數據預熱到分佈式緩存,縮短 Pod 啓動時間 80% 同時支持模型熱升級,無容器重啓。
  4. 以上能力完全通過運行阿里雲無服務器 Kubernetes 容器服務(ASK)上,在業務沒有運行按需彈性、按秒計費,同時基於請求量的 GPU 無服務器自動擴展,縮放至零。

一切就緒,我們一起開啓阿里雲 Kubernetes(ACK) 中 KServe 推理大模型之旅:

實踐步驟

前提條件

  • 已創建 ACK 集羣,集羣的 Kubernetes 版本 ≥1.18,具體操作,請參見創建 Kubernetes 託管版集羣[2]

本演示使用的 ACK 集羣包含 3 個 ecs.g7.xlarge 規格的 ecs 和 1 個 ecs.g7.2xlarge 規格的 ecs。您可以在創建時選擇添加 3 個 ecs.g7.xlarge 規格的 ecs,待集羣創建完成後新建一個節點池以增加一個 1 個 ecs.g7.2xlarge 規格的 ecs,關於創建節點池的具體操作請參考創建節點池[3]

  • 已創建 v1.17 及以上版本的 ASM 實例,並已將上述 ACK 集羣添加到該實例中。具體操作,請參見創建 ASM 實例[4]和添加集羣到 ASM 實例[5]

您可以使用上述配置來創建阿里雲服務網格 ASM 實例,其中:

  • 實例規格需要選擇企業版(以啓用數據面集羣 KubeAPI 訪問 Istio 資源能力)
  • Istio 版本需要選擇 v1.17 及以上
  • 網格的地域、專有網絡需要與創建的 Kubernetes 集羣保持一致,以保證網絡暢通
  • 可以視需求選擇是否勾選 “使用 EIP 暴露 API Server”,開啓後將爲內網 SLB 實例創建並綁定一個 EIP,您將可以從公網訪問 ASM 實例的 API Server,並操作 Istio CR
  • 可觀測性及網格審計部分依賴日誌服務和阿里雲 Prometheus 監控服務,若依賴服務尚未開通,在創建時您可以不勾選
  • 【重要】必須勾選啓用數據面集羣 KubeAPI 訪問 Istio 資源。
  • 集羣本地域名需要與您的 Kubernetes 集羣的本地域名保持一致。
  • ASM 實例已經開啓通過數據面集羣 KubeAPI 訪問 Istio 資源能力。具體操作,參考:通過數據面集羣 KubeAPI 訪問 Istio 資源[6]
  • 已爲集羣添加入口網關。本實例使用 ASM 入口網關作爲集羣網關,ASM 入口網關名稱爲默認的 ingressgateway,開放端口 80 和 443。具體操作,請參見創建入口網關服務[7]
  • 已在 ACK 或 ASK 集羣中部署 Knative Serving 組件,並開啓 Knative on ASM 功能。具體操作,參考:使用 Knative on ASM 部署 Serveless 應用[8]中的前提及步驟一。

步驟一:開啓 KServe on ASM 功能

  1. 登錄 ASM 控制檯[9],在左側導航欄,選擇服務網格 > 網格管理。
  2. 在網格管理頁面,單擊目標實例名稱,然後在左側導航欄,選擇生態集成中心 > KServe on ASM。
  3. 在 KServe on ASM 頁面,單擊啓用 KServe on ASM。

說明:KServe on ASM 功能依賴 cert-manager 組件的部署與使用。cert-manager 是一個證書生命週期管理系統,支持證書的申請、部署等功能。如果您沒有在集羣中安裝 cert-manager,您需要在 KServe on ASM 頁面開啓 在集羣中自動安裝 CertManager 組件,以自動爲您安裝 cert-manager;否則您需要關閉此項,再單擊啓用 KServe on ASM。

步驟二:安裝 ACK-Fluid 並開啓 AI 模型緩存加速

1. 爲您的 ACK 或 ASK 集羣部署 ack-fluid 組件,並保證 ack-fluid 組件的版本在 0.9.10 及以上。

說明:如果您的數據面集羣爲 ACK 集羣,您需要在 ACK 集羣中安裝雲原生AI套件並部署 ack-fluid 組件。參考:加速在線應用數據訪問[10]

如果您的數據面集羣爲 ASK 集羣,您需要在 ASK 集羣中部署 ack-fluid 組件。參考:加速 Job 應用數據訪問[11]

2. 準備AI模型並上傳至 OSS Bucket。

a. 準備訓練好的 AI 模型保存數據。本文以基於 pytorch 的開源 transformer 大語言模型 bloom 爲例,可以在 hugging face 社區中獲取模型數據:https://huggingface.co/bigscience/bloom-560m/tree/main

b. 將下載的模型數據文件上傳至 OSS Bucket,並記錄模型數據文件的保存位置。模型數據文件的保存位置格式爲 oss://{bucket}/{path}。例如,如果您創建了名爲 fluid-demo 的 bucket,並在 bucket 中的 models/bloom 目錄中上傳了所有的模型數據文件,則模型數據文件的保存位置爲 oss://fluid-demo/models/bloom

說明:您可以通過 OSS 提供的客戶端工具 ossutil 上傳數據。具體操作,請參見安裝 ossutil[12]

3. 創建部署 Fluid 及 AI 服務的命名空間,並配置 OSS 訪問權限。

a. 使用 kubectl 連接到數據面 ACK/ASK 集羣。具體操作,參考:通過 kubectl 連接 Kubernetes 集羣[13]

b. 使用 kubectl 創建命名空間,以部署 Fluid 及 KServe AI 服務。本文以 kserve-fluid-demo 命名空間爲例。

kubectl create ns kserve-fluid-demo

c. 使用 kubectl 爲命名空間添加 eci 標籤,以將命名空間中的 Pod 調度到虛擬節點上。

kubectl label namespace kserve-fluid-demo alibabacloud.com/eci=true

d. 使用以下內容,創建 oss-secret.yaml 文件。其中 fs.oss.accessKeyId 和 fs.oss.accessKeySecret 分別代表可以訪問 OSS 的 accessKeyId 和 accessKeySecret。

apiVersion: v1
kind: Secret
metadata:
  name: access-key
stringData:
  fs.oss.accessKeyId: xxx #替換爲可以訪問OSS的阿里雲accessKeyId
  fs.oss.accessKeySecret: xxx #替換爲可以訪問OSSd的阿里雲accessKeySecret

e. 執行以下命令,部署 Secret,配置 OSS 訪問祕鑰。

kubectl apply -f oss-secret.yaml -n kserve-fluid-demo

4. 在 Fluid 中聲明待訪問的 AI 模型數據。您需要提交一個 Dataset CR 和一個 Runtime CR。其中,Dataset CR 描述數據在外部存儲系統中的 URL 位置,JindoRuntime CR:描述緩存系統及其具體配置。

a. 使用以下內容,保存爲 oss-jindo.yaml 文件。

apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
  name: oss-data
spec:
  mounts:
  - mountPoint: "oss://{bucket}/{path}" # 需要替換爲模型數據文件的保存位置
    name: bloom-560m
    path: /bloom-560m
    options:
      fs.oss.endpoint: "{endpoint}"  # 需要替換爲實際的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: 50Gi
        high: "0.95"
        low: "0.7"
  fuse:
    args:
      - -ometrics_port=-1
  master:
    nodeSelector:
      node.kubernetes.io/instance-type: ecs.g7.xlarge
  worker:
    nodeSelector:
      node.kubernetes.io/instance-type: ecs.g7.xlarge

說明:您需要將 Dataset CR 中的 oss://{bucket}/{path} 替換爲上文中記錄的模型數據文件的保存位置。將 Dataset CR 中的 {endpoint}替換爲 OSS 的訪問域名。如何獲取不同地域 OSS 的訪問域名,參考:訪問域名和數據中心[14]

a. 執行以下命令,部署 Dataset 和 JindoRuntime CR。

kubectl create -f oss-jindo.yaml -n kserve-fluid-demo

b. 執行以下命令,查看 Dataset 和 JindoRuntime 的部署情況。

kubectl get jindoruntime,dataset -n kserve-fluid-demo

預期輸出:

NAME                                  MASTER PHASE   WORKER PHASE   FUSE PHASE   AGE
jindoruntime.data.fluid.io/oss-data   Ready          Ready          Ready        3m

NAME                             UFS TOTAL SIZE   CACHED   CACHE CAPACITY   CACHED PERCENTAGE   PHASE   AGE
dataset.data.fluid.io/oss-data   3.14GiB          0.00B    100.00GiB        0.0%                Bound   3m

由預期輸出中得到,Dataset 的 PHASE爲Bound,JindoRuntime 的 FUSE PHASE 爲 Ready,代表 Dataset 和 JindoRuntime 都部署成功。

5. 在 Fluid 中進行數據預熱,提升數據訪問性能。

a. 使用以下內容,保存爲 oss-dataload.yaml。

apiVersion: data.fluid.io/v1alpha1
kind: DataLoad
metadata:
  name: oss-dataload
spec:
  dataset:
    name: oss-data
    namespace: kserve-fluid-demo
  target:
    - path: /bloom-560m
      replicas: 2

b. 執行以下命令,部署 Dataload 以預熱數據。

kubectl create -f oss-dataload.yaml -n kserve-fluid-demo

c. 執行以下命令,查看數據預熱的進度。

kubectl get dataload -n kserve-fluid-demo

預期輸出:

NAME           DATASET    PHASE      AGE     DURATIONoss-dataload
oss-data   Complete   1m      45s

由預期輸出得到,數據預熱耗時約 45s。需要等待一段時間才能使得數據預熱完成。

步驟三:部署 AI 模型推理服務

1. 將以下內容保存爲 oss-fluid-isvc.yaml

apiVersion: "serving.kserve.io/v1beta1"
kind: "InferenceService"
metadata:
  name: "fluid-bloom"
spec:
  predictor:
    timeout: 600
    minReplicas: 0
    nodeSelector:
      node.kubernetes.io/instance-type: ecs.g7.2xlarge
    containers:
      - name: kserve-container
        image: cheyang/kserve-fluid:bloom-gpu
        resources:
          limits:
            cpu: "3"
            memory: 8Gi
          requests:
            cpu: "3"
            memory: 8Gi
        env:
          - name: STORAGE_URI
            value: "pvc://oss-data/bloom-560m"
          - name: MODEL_NAME
            value: "bloom"
            # 如果使用GPU則設置成True,否則設置爲False
          - name: GPU_ENABLED
            value: "False"

說明:本例中的 InferenceService 配置中在 image 字段使用了 cheyang/kserve-fluid:bloom-gpu 示例鏡像,該鏡像提供加載模型及推理服務的接口,您可以在 KServe 開源社區中找到此示例鏡像的代碼,並進行鏡像自定義:https://github.com/kserve/kserve/tree/master/docs/samples/fluid/docker

2. 執行以下命令,部署 InferenceService AI 模型推理服務。

kubectl create -f oss-fluid-isvc.yaml -n kserve-fluid-demo

3. 執行以下命令,查看 AI 模型推理服務的部署狀態。

kubectl get inferenceservice -n kserve-fluid-demo

預期輸出:

NAME          URL                                                
READY   PREV   LATEST   PREVROLLEDOUTREVISION   LATESTREADYREVISION           AGEfluid-bloom   http://fluid-bloom.kserve-fluid-demo.example.com   True           100                              fluid-bloom-predictor-00001   2d

由預期輸出可以看到 READY 字段爲 True,證明 AI 模型推理服務已經部署成功。

步驟四:訪問 AI 模型推理服務

1. 獲取 ASM 入口網關地址

a. 登錄 ASM 控制檯,在左側導航欄,選擇服務網格 > 網格管理。

b. 在網格管理頁面,單擊目標實例名稱,然後在左側導航欄,選擇 ASM 網關 > 入口網關。

c. 在入口網關頁面找到名爲 ingressgateway 的 ASM 入口網關,在服務地址區域,查看並獲取 ASM 網關服務地址。

2. 訪問示例 AI 模型推理服務

執行以下命令,訪問示例 AI 模型推理服務 bloom,將其中的 ASM 網關服務地址替換爲上文中獲取的 ASM 入口網關地址。

curl -v -H "Content-Type: application/json" -H "Host: fluid-bloom.kserve-fluid-demo.example.com" "http://{ASM網關服務地址}:80/v1/models/bloom:predict" -d '{"prompt": "It was a dark and stormy night", "result_length": 50}'

預期輸出:

*   Trying xxx.xx.xx.xx :80...
* Connected to xxx.xx.xx.xx  (xxx.xx.xx.xx ) port 80 (#0)
> POST /v1/models/bloom:predict HTTP/1.1
> Host: fluid-bloom-predictor.kserve-fluid-demo.example.com
> User-Agent: curl/7.84.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 65
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-length: 227
< content-type: application/json
< date: Thu, 20 Apr 2023 09:49:00 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 1142
< 
{
  "result": "It was a dark and stormy night, and the wind was blowing in the\ndirection of the west. The wind was blowing in the direction of the\nwest, and the wind was blowing in the direction of the west. The\nwind was"
}
* Connection #0 to host xxx.xx.xx.xx left intact

從預期輸出中看到,AI 模型推理服務成功對示例輸入進行了續寫並返回推理結果。

性能基準測試

我們的性能基準測試將比較 KServe 使用自身存儲初始化器(OSS Storage Initializer)和 Fluid 的推理服務的擴容時間,測試不同規格模型情況下的擴容時間,即衡量服務從 0 擴展到 1 所需的時間。

我們所選的測試機型爲:

  • Fluid 機型:ecs.g7.xlarge
  • 推理機型:ecs.g7.2xlarge

使用的 Fluid Runtime 爲:

  • JindoFS

其他前提:

  • OSS 的數據桶和 ACK 集羣在同一個區域
  • 數據預熱提前完成
  • ACK 集羣節點上已經緩存了容器鏡像

性能測試命令:

# Total time includes: pod initialization and running + download model (storage initializer) + load model + inference + network
curl --connect-timeout 3600 --max-time 3600 -o /dev/null -s -w 'Total: %{time_total}s\n' -H "Content-Type: application/json" -H "Host: ${SERVICE_HOSTNAME}" "http://${INGRESS_HOST}:${INGRESS_PORT}/v1/models/bloom:predict" -d '{"prompt": "It was a dark and stormy night", "result_length": 50}'
# Total time:
Model Name Model Size (Snapshot) Machine Type KServe + Storage Initializer KServe + Fluid
bigscience/bloom-560m[15] 3.14GB ecs.g7.2xlarge(cpu: 8, memory: 32G) total: 58.031551s(download:33.866s, load: 5.016s) total: 8.488353s(load: 2.349s)(2 workers)
bigscience/bloom-7b1[16] 26.35GB ecs.g7.4xlarge(cpu: 16, memory: 64G) total: 329.019987s(download: 228.440s, load: 71.964s) total: 27.800123s(load: 12.084s)(3 workers)

Total:無服務情況下的推理響應時間(從 0 開始擴容),包括容器調度,啓動,模型下載,模型加載到顯存,模型推理和網絡延遲時間。

我們可以觀察到 Fluid 在大語言模型(LLM)的場景下,

  1. 大幅提升 KServe 的冷啓動速度,模型越大啓動時間優化越明顯
  2. 不但大幅度節省模型下載到雲盤(Storage Initializer初始化)的時間,另外也可以通過增加緩存 worker 帶寬的方式突破雲盤的帶寬限制(本例子中從雲盤讀取模型到內存的耗時也可以節省一半甚至三分之二)

這樣恰恰可以大幅提升 KServe 在容器場景下的彈性擴縮容能力。

總結和展望

通過現有的雲原生 AI 框架支持大模型這種新物種還需要不斷地改善和優化,但是道阻且長,行則將至。阿里雲容器服務團隊願意和社區的小夥伴一起探索如何能夠用更低的成本支持更好的 LLM 推理場景,提供標準開放的方案,產品化的能力。我們後續會提供通過計算彈性擴縮容的規律觸發數據緩存的彈性擴縮容來控制成本,以及大模型的熱更新方法。

相關鏈接:

[1] 數據加速 Fluid 概述

https://help.aliyun.com/document_detail/208335.html

[2] 創建 Kubernetes 託管版集羣

https://help.aliyun.com/document_detail/95108.html?spm=a2c4g.118970.0.0.1c6953c8tAGxmn

[3] 創建節點池

https://help.aliyun.com/document_detail/160490.html?spm=a2c4g.476586.0.0.d23b4180G64qLH

[4] 創建 ASM 實例

https://help.aliyun.com/document_detail/147793.htm#task-2370657

[5] 添加集羣到 ASM 實例

https://help.aliyun.com/document_detail/148231.htm#task-2372122

[6] 通過數據面集羣 KubeAPI 訪問 Istio 資源

https://help.aliyun.com/document_detail/431215.html

[7] 創建入口網關服務

https://help.aliyun.com/document_detail/149546.htm#task-2372970

[8] 使用 Knative on ASM 部署 Serveless 應用

https://help.aliyun.com/document_detail/611862.html

[9] ASM 控制檯

https://account.aliyun.com/login/login.htm?oauth_callback=https%3A%2F%2Fservicemesh.console.aliyun.com%2F&lang=zh

[10] 加速在線應用數據訪問

https://help.aliyun.com/document_detail/440265.html

[11] 加速 Job 應用數據訪問

https://help.aliyun.com/document_detail/456858.html

[12] 安裝 ossutil

https://help.aliyun.com/document_detail/120075.htm#concept-303829

[13] 通過 kubectl 連接 Kubernetes 集羣

https://help.aliyun.com/document_detail/86378.html

[14] 訪問域名和數據中心

https://help.aliyun.com/document_detail/31837.html

[15] bigscience/bloom-560m

https://huggingface.co/bigscience/bloom-560m

[16] bigscience/bloom-7b1

https://huggingface.co/bigscience/bloom-7b1

作者:黃馳琳、露營、車漾

點擊立即免費試用雲產品 開啓雲上實踐之旅!

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章