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

語言: CN / TW / HK

作者:東伝

背景

資料對於當今網際網路業務的重要性不言而喻,它幾乎滲透到了當今這個世界的每一個角落。但單有資料是不夠的,真正讓資料產生價值的,是針對各業務場景執行的對大量資料的密集分析與計算,如機器學習、大資料分析、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 套件免費體驗席位!