Fluid 助力阿里雲 Serverless 容器極致提速

作者:東伝

背景

數據對於當今互聯網業務的重要性不言而喻,它幾乎滲透到了當今這個世界的每一個角落。但單有數據是不夠的,真正讓數據產生價值的,是針對各業務場景運行的對大量數據的密集分析與計算,如機器學習、大數據分析、OLAP 聚合分析等等。近些年,隨着數據規模的增大,這些對於資源有着更高要求的數據密集應用自然地導向了以彈性資源著稱的雲服務。

在這種數據密集應用上雲的趨勢下,Serverless 似乎並不是這個趨勢的明顯受益者。儘管幾乎所有人都對這種計算資源無限擴容、彈性敏捷交付、低運維成本的架構不吝讚美之詞,但由於它將計算存儲分離的架構推向了一個更純粹的極端,具有強數據依賴的數據密集應用想要高效運行於 Serverless 環境變得極其困難。

舉例來說,如果我們想將 AI 推理服務應用部署在 Serverless 架構下,每個服務應用啓動前必須將存放在外部存儲系統的 AI 模型首先拉取到本地內存中。考慮到近年來 AI 大模型已經成爲業界主流,讓我們假設這個 AI 模型的大小爲 30GB,並且存儲於 OSS 對象存儲服務中,如果需要同時啓動 100 個這樣的 AI 推理服務應用,那麼總共的數據讀取量就是 3000GB。OSS 存儲默認的數據訪問限速是 10Gbps,這就意味着 100 個應用都需要等待 2400 秒(3000GB * 8 / 10Gbps) 纔可以真正開始對外提供服務。如果每個服務我們創建一個 ecs.gn7i-c32g1.16xlarge 的實例(按每小時單價折算每秒 0.008 元),這意味着光在等待數據上就已經花掉了 1920 元(0.008 元/秒 * 2400 秒 * 100) 。總結來說,我們大量的費用沒有花在產生價值的計算上,這顯然不是我們想要的。(*實際價格以阿里雲官網顯示爲準)

那麼,有沒有什麼方法可以優化上述過程?這就引入了本文的主角:Fluid。Fluid 是一個 Kubernetes 原生的分佈式數據集編排和加速引擎。Fluid 誕生的初衷即是爲應用的數據訪問延時問題提供雲原生的解決方案。對於困擾着 Serverless 數據密集應用的上述相關問題,Fluid 在保證用戶簡單易用的使用體驗前提下,給出了一套 Serverless 環境新的數據訪問架構方案,幫助用戶提升數據訪問效率。

1.png

本文將 step by step 地介紹 Fluid 的運行示例,幫助大家瞭解如何在阿里雲 ASK(Alibaba Serverless Kubernetes)環境中使用 Fluid,展示如何藉助 Fluid 實現 zero to zero 的(從零資源使用開始到全部資源釋放結束)規模化數據密集型任務執行模式,並取得降本提速的效果。

Fluid on ASK 運行示例

Fluid 數據編排加速 Serverless Kubernetes 功能尚處於公測階段,可點擊閱讀原文申請體驗席位。

Fluid 部署

在運行以下示例前,首先需要搭建一個 ASK 集羣,並配置好連接該集羣的 Kubeconfig。相關步驟可參考文末文檔《如何創建 ASK 集羣》 。在使用 Fluid 的各項功能前,需要將 Fluid 的各控制面組件部署到 ASK 集羣中。這個部署過程可以通過阿里雲容器服務-Kubernetes 控制檯輕鬆完成。

如下圖所示:

2.png

  1. 選擇 ASK 集羣面板右側的“應用-Helm”子面板
  2. 點擊"創建"按鈕
  3. 在 Chart 市場中搜索 ack-fluid 即可找到 Fluid 對應的 Helm Chart,填寫“應用名”(例:ack-fluid)。
  4. 點擊“下一步”後,選擇使用默認的 fluid-system 作爲部署的命名空間
  5. 接着無需對 Chart Values 進行任何修改,直接點擊“確定”,即可將 Fluid 部署到 ASK 集羣中。

在配置完 ASK 集羣對應的 Kubeconfig 信息後,輸入以下命令:

$ kubectl get pod -n fluid-system

可以觀察到 Fluid 的幾個組件已經正常運行起來:

NAME                                  READY   STATUS    RESTARTS   AGE
dataset-controller-d99998f79-dgkmh    1/1     Running   0          2m48s
fluid-webhook-55c6d9d497-dmrzb        1/1     Running   0          2m49s

其中:

  • Dataset Controller:負責維護各個 Fluid 所引入的 Dataset CRs 的完整生命週期。
  • Fluid Webhook: 負責對用戶需要訪問數據的應用 Pod 進行自動化變換(Mutation),無感知地幫助用戶實現 Serverless 場景的數據訪問功能。

除了上述描述的兩個組件外,Fluid 的控制面仍然包含了一些與各類緩存系統(例如:JindoFS、JuiceFS、Alluxio 等)緊密關聯的控制器組件,這些組件在初始部署狀態下不會創建,僅當用戶指定需要使用某種緩存系統時,與其相關聯的緩存系統控制器組件 Pod 纔會按需擴容,從而在按量付費的 ASK 環境中儘可能地幫助用戶節省成本。

數據緩存部署

Fluid 世界中的一切都以 Dataset 這一自定義資源爲中心:無論是對外部存儲中已有數據的抽象管理還是應用 Pod 的數據訪問,用戶都需要和 Dataset 資源進行交互。每當用戶創建一個 Dataset CR 並指定了它的緩存系統後端,Fluid 就會自動地將數據緩存部署到 Kubernetes 集羣中。

在下面的實踐過程中,我們以阿里雲 OSS 對象存儲作爲外部存儲系統爲例,模擬一個完整的 “緩存部署-數據訪問-資源回收”的標準數據使用過程。

  • 數據文件準備

首先,準備一個待訪問的文件。例如,這裏我們使用 dd 命令快速創建一個大小約爲 30G 的文件:

$ cd $(mktemp -d)

$ dd if=/dev/zero of=./largefile-30G bs=10M count=3072

3072+0 records in
3072+0 records out
32212254720 bytes (32 GB) copied, 108.189 s, 298 MB/s

$ ls -lh ./largefile-30G 
-rw-r--r-- 1 root root 30G Sep  7 21:11 ./largefile-30G

接着,把上述創建的待訪問文件上傳到 OSS Bucket 中,這裏以一個位於 Beijing Region 的名爲 fluid-demo 的 OSS Bucket 爲例。

$ ossutil cp -i <access_key_id> -k <access_key_secret> -e oss-cn-beijing-internal.aliyuncs.com ./largefile-30G oss://fluid-demo/
  • 創建 Fluid Dataset 和 Runtime 資源

數據準備和上傳後,即可在 Fluid 中聲明上述待訪問的數據。具體而言,我們需要提交一個 Dataset CR 和一個 Runtime CR。Dataset CR 中描述數據在外部存儲系統中的 URL 位置,Runtime CR 描述緩存系統及系統具體配置。

首先,把訪問 OSS Bucket 所需的身份憑證信息存儲於 Secret 中:

$ kubectl create secret generic oss-access-key \
  --from-literal=fs.oss.accessKeyId=<access_key_id> \
  --from-literal=fs.oss.accessKeySecret=<access_key_secret>

接着,定義 Dataset CR 和 Runtime CR。這裏我們選擇 JindoFS 作爲緩存系統後端,Fluid Runtime 資源爲 JindoRuntime:

apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
  name: demo-dataset
spec:
  mounts: 
    - mountPoint: oss://fluid-demo # OSS Bucket URL
      name: demo
      path: /
      options:
        fs.oss.endpoint: oss-cn-beijing-internal.aliyuncs.com # OSS Bucket內網訪問端點
      encryptOptions:
        - name: fs.oss.accessKeyId
          valueFrom:
            secretKeyRef:
              name: oss-access-key
              key: fs.oss.accessKeyId
        - name: fs.oss.accessKeySecret
          valueFrom:
            secretKeyRef:
              name: oss-access-key
              key: fs.oss.accessKeySecret
---
apiVersion: data.fluid.io/v1alpha1
kind: JindoRuntime
metadata:
  name: demo-dataset
spec:
  # 緩存Worker節點數量
  replicas: 5
  podMetadata:
    annotations:
      # 選擇JindoFS Pod使用的實例規格
      k8s.aliyun.com/eci-use-specs: ecs.d1ne.6xlarge
      # 啓用實例鏡像緩存,加速Pod啓動過程
      k8s.aliyun.com/eci-image-cache: "true"
  tieredstore:
    levels:
      # 以40GiB的內存作爲每個緩存Worker節點的緩存介質
      - mediumtype: MEM
        volumeType: emptyDir
        path: /dev/shm
        quota: 40Gi
        high: "0.99"
        low: "0.99"

創建上述 Dataset CR 和 JindoRuntime CR 到 ASK 集羣:

$ kubectl create -f dataset.yaml
  • 查看 Dataset 部署狀態

Dataset CR 和 JindoRuntime CR 創建後,約 1 到 2 分鐘後,Dataset 將部署完成,屆時可以查看到與緩存系統以及後端存儲系統中數據的相關信息。

$ kubectl get dataset demo-dataset 
NAME           UFS TOTAL SIZE   CACHED   CACHE CAPACITY   CACHED PERCENTAGE   PHASE   AGE
demo-dataset   30.00GiB         0.00B    200.00GiB        0.0%                Bound   2m9s

例如,上方示例展示了 Fluid Dataset 的相關信息

  • OSS 中數據集總大小(UFS TOTAL SIZE) :30.00GiB
  • 當前緩存量(CACHED):0.00B
  • 緩存系統容量(CACHE CAPACITY):200.00GiB
  • 數據集緩存百分比(CACHED PERCENTAGE): 0.0%
  • Dataset 狀態(PHASE):Bound,表示已成功部署。

數據緩存預熱

Fluid 實現的 Kubernetes 集羣內數據訪問加速不是什麼 Magic Trick:其本質是通過數據分流(Data Offloading) 來降低中心存儲的訪問壓力:Fluid 會把需要訪問的數據緩存到與應用 Pod 更近的分佈式緩存系統(例如:JindoFS、JuiceFS、Alluxio 等)中,於是,與緩存系統位於同一 VPC 網絡的應用 Pod,就能夠以遠比直接訪問中心存儲帶寬更高的 VPC 內網帶寬進行數據訪問。進一步地,由於對接的是分佈式緩存系統,所以當單個緩存系統 Worker 節點提供帶寬不足時,可將分佈式緩存系統擴容,從而實現數據訪問帶寬的彈性伸縮,匹配 Serverless 場景下的計算資源彈性。

因此,爲了通過數據分流實現高帶寬數據訪問,在應用 Pod 進行數據訪問前執行數據緩存預熱是一個“磨刀不誤砍柴工”的必要操作。

  • 創建 DataLoad CR

在 Fluid 中執行數據緩存預熱只需創建如下的 DataLoad CR:

apiVersion: data.fluid.io/v1alpha1
kind: DataLoad
metadata:
  name: demo-dataset-warmup
spec:
  # 指定需要預熱的Dataset
  dataset:
    name: demo-dataset
    namespace: default
  loadMetadata: true
  target:
    - path: / # 指定預熱的數據子路徑,“/”表示預熱整個數據集
      replicas: 5 # 預熱後數據在緩存系統中的副本數量
$ kubectl create -f dataload.yaml
  • 查看預熱後 Dataset 狀態

查看 DataLoad CR 狀態,直至其 PHASE 變爲 Complete 狀態:

$ kubectl get dataload demo-dataset-warmup
NAME                  DATASET        PHASE      AGE     DURATION
demo-dataset-warmup   demo-dataset   Complete   2m38s   2m20s

通過 Duration 可以查看數據預熱耗費的時間,上述示例中預熱耗時爲 2m20s

在數據緩存預熱完成後,Dataset 上相關的緩存狀態也會隨即更新:

$ kubectl get dataset demo-dataset     
NAME           UFS TOTAL SIZE   CACHED      CACHE CAPACITY   CACHED PERCENTAGE   PHASE   AGE
demo-dataset   30.00GiB         150.00GiB   200.00GiB        100.0%              Bound   8m27s

可以看到,數據預熱完成後,整個數據集都已經被緩存在了分佈式緩存系統中,緩存比例 100.0%,由於預熱時指定了預熱的緩存副本數量爲 5,預熱後緩存佔用總量爲數據集大小的 5 倍。

注:增加緩存副本數量有助於減輕數據訪問時對分佈式緩存 Worker 節點的單點訪問性能瓶頸。

數據訪問

緊接着,嘗試創建應用 Pod 來訪問 OSS 中的數據。我們將會一次性拉起 100 個應用 Pod,讓這些 Pod 同時訪問 OSS 中的數據文件。這樣的數據讀取模式在 AI 推理服務彈性擴容、自動駕駛仿真等具體場景中都十分常見。

  • 創建數據訪問應用

例如:下面是一個 Argo Workflow 應用示例:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: parallelism-fluid-
spec:
  entrypoint: parallelism-fluid
  # Argo Workflow Task最大併發數,即同時啓動100個Pod
  parallelism: 100
  podSpecPatch: '{"terminationGracePeriodSeconds": 0}'
  podMetadata:
    labels:
      # 添加如下label打開Fluid對Serverless場景的數據訪問支持
      alibabacloud.com/fluid-sidecar-target: eci
    annotations:
      # 啓用實例鏡像緩存,加速Pod啓動過程
      k8s.aliyun.com/eci-image-cache: "true"
      # 選擇Argo Workflow Pod使用的實例規格
      k8s.aliyun.com/eci-use-specs: ecs.g6e.4xlarge
  templates:
  - name: parallelism-fluid
    steps:
    - - name: domd5sum
        template: md5sum
        withSequence:
          start: "1"
          end: "100"
  - name: md5sum
    container:
      imagePullPolicy: IfNotPresent
      image: alpine:latest
      # 每個pod計算待讀取文件的md5sum
      command: ["/bin/sh", "-c", "md5sum /data/largefile-30G"]
      volumeMounts:
      - name: data-vol
        mountPath: /data
    volumes:
    - name: data-vol
      persistentVolumeClaim:
        claimName: demo-dataset # claimName須與Fluid Dataset名字一致
$ argo submit workflow.yaml
  • 查看數據訪問應用狀態

上述示例的 Argo Workflow 將會一次性拉起 100 個 Pod 進行並行數據訪問。待上述 100 個 Pod 全部完成後,可以看到如下結果:

$ argo list
NAME                      STATUS      AGE   DURATION   PRIORITY
parallelism-fluid-x677t   Succeeded   8m    5m         0

查看任務的具體信息:

$ argo get parallelism-fluid-x677t                                                                                                                               
Name:                parallelism-fluid-x677t                                                                                                                      
Namespace:           default                                                                                                                                      
ServiceAccount:      unset (will run with the default ServiceAccount)                                                                                             
Status:              Succeeded                                                                                                                                    
Conditions:                                                                                                                                                       
 PodRunning          False
 Completed           True
Created:             Wed Sep 07 21:25:30 +0800 (7 minutes ago)
Started:             Wed Sep 07 21:25:30 +0800 (7 minutes ago)
Finished:            Wed Sep 07 21:31:28 +0800 (1 minute ago)
Duration:            5 minutes 58 seconds
Progress:            100/100
ResourcesDuration:   8h10m22s*(1 alibabacloud.com/vfuse),24h15m6s*(1 cpu),24h15m6s*(100Mi memory)

STEP                        TEMPLATE           PODNAME                             DURATION  MESSAGE
 ✔ parallelism-fluid-x677t  parallelism-fluid                                                   
 └─┬─✔ domd5sum(0:1)        md5sum             parallelism-fluid-x677t-2855796525  5m          
   ├─✔ domd5sum(1:2)        md5sum             parallelism-fluid-x677t-1226856655  5m          
   ├─✔ domd5sum(2:3)        md5sum             parallelism-fluid-x677t-2858910973  5m          
   ├─✔ domd5sum(3:4)        md5sum             parallelism-fluid-x677t-2609269875  4m          
   ├─✔ domd5sum(4:5)        md5sum             parallelism-fluid-x677t-616770109   5m          
   ├─✔ domd5sum(5:6)        md5sum             parallelism-fluid-x677t-3071900311  5m          
   ├─✔ domd5sum(6:7)        md5sum             parallelism-fluid-x677t-3841084237  5m          
   ├─✔ domd5sum(7:8)        md5sum             parallelism-fluid-x677t-120540963   5m          
   ├─✔ domd5sum(8:9)        md5sum             parallelism-fluid-x677t-1353329645  5m          
   ├─✔ domd5sum(9:10)       md5sum             parallelism-fluid-x677t-2391364586  5m          
   ├─✔ domd5sum(10:11)      md5sum             parallelism-fluid-x677t-4083824607  5m          
   ├─✔ domd5sum(11:12)      md5sum             parallelism-fluid-x677t-258640575   5m          
   ├─✔ domd5sum(12:13)      md5sum             parallelism-fluid-x677t-3913466863  5m          
   ├─✔ domd5sum(13:14)      md5sum             parallelism-fluid-x677t-1949266799  5m          
   ├─✔ domd5sum(14:15)      md5sum             parallelism-fluid-x677t-214569823   5m          
   ├─✔ domd5sum(15:16)      md5sum             parallelism-fluid-x677t-684353087   5m

可以看到,整個任務的運行時長爲 5m58s。

資源回收

  • 數據緩存資源回收

用戶可以在不再需要數據緩存時,將緩存從 ASK 集羣中回收以節省集羣資源並降低成本。Fluid 中對於緩存系統的回收僅需要將關聯的 Fluid Dataset 刪除,例如:

$ kubectl delete dataset demo-dataset

執行上述刪除命令後等待一段時間(Fluid 將會進行一些清理工作),緩存系統的相關 Pod 都會被回收。

  • Fluid 控制面組件回收

在緩存系統相關 Pod 回收後,用戶同樣可以試情況回收控制面組件佔用的資源。執行下面的腳本,縮容控制面組件。

$ kubectl get deployments.apps -n fluid-system | awk 'NR>1 {print $1}' | xargs kubectl scale deployments -n fluid-system --replicas=0

當再次需要使用 Fluid 時,執行下面的擴容命令,創建新的控制面組件 Pod 即可:

$ kubectl scale -n fluid-system deployment dataset-controller --replicas=1

$ kubectl scale -n fluid-system deployment fluid-webhook --replicas=1

方案效果

多次運行上述示例,並調整緩存系統 Worker 的數量(5 個或 10 個)或選擇直接訪問 OSS 對象存儲,我們得到了如下效果數據:

效果 1:可彈性伸縮的數據訪問帶寬

3.png

圖 1 緩存/存儲系統提供的有效數據訪問帶寬對比

根據數據訪問應用的整體耗時、訪問的數據文件大小以及數據訪問的 Pod 數量,我們可以計算出圖 1 中的“有效數據訪問帶寬*”性能表現。從圖 1 來看,相比於 OSS 存儲系統提供的默認帶寬(10Gbps),F luid 的數據分流機制可以爲 Serverless 應用提供更大的有效訪問帶寬,並且該帶寬可通過增加緩存 Worker 節點數量彈性提升。

*有效數據訪問帶寬 = Serverless 數據訪問 Pod 數量 x 每 Pod 訪問的數據量 / 數據訪問應用整體耗時

效果 2:因數據訪問加速而降低的費用成本

4.png

圖 2 直接訪問 OSS vs. Fluid 成本對比

上述示例中我們使用如下的 ECI 實例規格:

  • Argo Workflow 任務 Pod:ecs.g6e.4xlarge (每秒單價 0.0012 元)
  • 緩存系統 Pod:ecs.d1ne.6xlarge (每秒單價 0.0056 元)

由此可計算得到“圖 2 直接訪問 OSS vs. Fluid 成本對比”。觀察圖 2 不難發現,通過 Fluid 訪問 OSS 中的數據能夠將成本削減爲原來的約六分之一到八分之一。另外,在同樣使用 Fluid 訪問數據的前提下,使用更多的緩存 Worker 節點可以節省更多成本。這背後的主要原因是 Fluid 提供了更大的數據訪問帶寬,從而使得數據訪問性能提升,縮短了應用花在數據讀取上的時間(見圖 3),從而使得購買的 Serverless 彈性算力真正做到物盡其用。

5.png

圖 3 Argo Workflow 任務耗時對比

總結

本文展示了一個在 ASK 環境中運行 Fluid 的完整數據訪問示例,希望能夠幫助大家瞭解 Fluid 的使用體驗、運行效果以及 Serverless 和數據密集型應用結合的更多可行性。具體而言,我們看到:

  • 用戶使用 Fluid 訪問數據是簡單易用的:用戶只需要把原來訪問 OSS 的 PVC 修改爲 Fluid Dataset 對應的 PVC。
  • Fluid 能夠提供可彈性伸縮的數據訪問帶寬,幫助規模化的數據訪問應用提升數據讀取效率。
  • 由於數據讀取效率的提升,Fluid 能夠幫助規模化的數據訪問應用大幅降低費用成本。

參考鏈接

[1] 如何創建 ASK 集羣:

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

[2] ACK 雲原生 AI 套件詳情:

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

[3] Fluid 項目 github 地址:

https://github.com/fluid-cloudnative/fluid

點擊此處,申請 ACK 雲原生 AI 套件免費體驗席位!

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