雲知聲: 基於 JuiceFS 的超算平臺儲存實踐

2022-12-22 15:01:13

雲知聲從一家專注於語音及語言處理的技術公司,現在技術棧已經發展到具備影象、自然語言處理、訊號等全棧式的 AI 能力,是國內頭部人工智慧獨角獸企業。公司擁抱雲端計算,在智慧醫療、智慧酒店、智慧教育等方面都有相應的解決方案。

Atlas 是雲知聲的底層基礎技術平臺,支撐著雲知聲所有模型的迭代:

第一層是業務層,主要是公司的業務如語音處理、影象處理、自然語言處理等。

第二層是控制中心,從資料生產、資料接入到模型釋出都可以一站式完成。

第三層是核心的計算層,主要支援深度學習,以及資料預處理。

最底層是基礎架構層,主要是由 GPU 叢集、CPU 叢集以及分散式儲存構成,所有的機器都是用 100Gbps 的 InfiniBand 高速網互聯。

儲存場景與需求

雲知聲初期的建設目標就是要建成一站式的 AI 平臺,包含 AI 模型的生產,資料預處理,模型開發,模型訓練以及最後模型的上線。

如上圖所示,每個步驟都需要跟資料互動,其中資料預處理和模型訓練需要比較大的 IO

• 資料預處理,主要是語音處理會提取語音特徵,會把語音特徵轉成 numpy 格式的檔案;影象處理的過程中,會對影象做預處理,做訓練資料的格式轉換;
• 模型開發,主要是演演算法工程師做程式碼的編輯,模型演演算法的偵錯;
• 模型訓練,途中會需要做多輪資料讀取,以及模型會輸出到相應的儲存上,這個步驟所需要的 IO 非常大;在模型上線的時候,服務會去讀取儲存系統中的模型檔案。總結一下我們對儲存的需求:

  1. 能夠對接整個模型開發的的全鏈路,在幾個比較核心的功能塊中都要能夠支援;
  2. 支援 CPU、GPU 的資料讀取的任務;
  3. 我們的場景主要是語音、文字和影象資料,這些場景的特點是檔案大小都比較小,所以要支援小檔案場景下的高效能處理。
  4. 我們的業務場景主要是讀多入寫少,模型訓練的時候大部分是在讀取資料,基本不會寫入資料。
    基於以上這些需求點,我們需要一套高效能可靠的分散式儲存系統。

雲知聲儲存建設歷程

早期的時候,我們的 GPU 只有十幾臺左右,當時使用 NFS 做了一個小規模的叢集。同時在 2016 年引入了 CephFS 的測試環境,當時那個版本的 CephFS 在小檔案場景下效能不太好,所以就沒有把 CephFS 帶入到生產環境。

後來我們繼續做了調研,發現 Lustre 在 HPC 領域是最為常用的高效能檔案系統。測試表明 Lustre 在規模化的構建以及效能方面表現都不錯,於是從2017 年到 2022 年,我們全部是用 Lustre 來承載所有的資料業務。

但是隨著使用的 GPU 越來越多,現在有 5.7 億億次/秒左右的浮點處理能力,底層儲存的 IO 已經跟不上上層計算能力。於是,我們開始探索新的儲存,為後續的儲存擴容做升級,同時在使用 Lustre 的過程中也遇到了一些問題。

第一:運維方式,Lustre 主要是基於核心的,直接嵌在核心,有時候定位問題會涉及到機器的重啟之類的操作;

第二:技術棧,因為我們的雲平臺的開發主要是以 golang 為主,所以比較偏向於使用與開發語言比較契合的儲存。Lustre 使用的是 C 語言,在客製化優化方面需要有較多人力精力。

第三:資料的可靠性,Lustre 主要依賴硬體可靠性(比如 RAID 技術),軟體層面主要是實現後設資料節點和物件跟資料節點的 HA 方案。相比這些,我們還是更希望使用三副本或者是糾刪碼這類更可靠的軟體方案。

第四:多級快取的功能的需求,在 2021 年的時候,我們用了 Fluid + Alluxio 來作為 Lustre 的分散式加速,Alluxio 能夠較好的為我們的叢集做計算提速,減輕底層儲存的壓力。但是我們一直在探索希望直接從儲存系統來進行使用者端快取,這樣操作對使用者來說能夠更加透明一點。

在 2021 年的時候 JuiceFS 剛開源時,我們就對它的特性做了調研。

第一,產品特性:JuiceFS 支援 POSIX 介面,能夠以 HostPath 的方式去掛載,這種方式跟我們在使用 NAS 的方式是一模一樣的,使用者在使用時基本不用做任何改變;JuiceFS 後設資料以及物件儲存,都有比較多的可選方案,像Redis、 TiKV在AI領域是比較合適的。底層 Ceph、MinIO 還有一些公有云的物件儲存使用者都可以自行選擇。

第二,上層排程:JuiceFS 除了支援 HostPath,同時也是支援CSI 驅動方式,能夠以更加雲原生的方式讓使用者去接入相應的儲存。

第三,業務框架適配:POSIX 介面適配深度學習框架。第四,運維:後設資料引擎以及物件儲存,業界方案都比較成熟,選擇也比較多,而且 JuiceFS 有後設資料自動備份以及回收站功能。JuiceFS 與業務比較契合,因此我們進行了 POC 測試。

測試環境如上圖所示,結果發現 Lustre 跟 JuiceFS 來相比,由於JuiceFS 直接用到了核心頁快取,相比 Lustre 直接存取機械盤,效能有很大提升(如下圖所示,越小越好)。

經過了 POC 測試,我們決定把JuiceFS 帶入生產環境。目前整個Atlas 的叢集所有 GPU 的計算節點,以及所有的開發偵錯節點,都安裝了 JuiceFS 使用者端。

JuiceFS 直接對接redis 叢集和ceph,計算節點大部分用的 HostPath 方式接入。同時 Atlas 叢集也部署了 JuiceFS CSI Driver,使用者可以以雲原生的方式接入。

JuiceFS 在 Atlas 的使用方式

為了保證資料的安全性,超算平臺上的每個組歸屬於不同的目錄,每個目錄下是各自組內或者部門內的成員,不同組之間的目錄是不可見的

目錄的許可權是基於 Linux 的許可權管控機制。使用者在 Atlas 叢集提交訓練任務的時候,叢集的任務提交工具會自動讀取系統上使用者的 UID 與 GID 資訊,然後將其注入使用者提交的任務 Pod 的 SecurityContext 欄位,則 Atlas 叢集上執行的容器 Pod 內所有容器的程序執行的 UID 與儲存系統上的資訊一致,保證許可權不越界。

節點存取 JuiceFS,實現了多級快取:

  • 第一級:快取就是記憶體的頁快取。

  • 第二級:所有的計算節點的多塊 SSD,提供二級的加速能力。

  • 第三級:使用 Ceph。如果 3 塊 1t 的 SSD 還是不能支撐使用者的資料,那它會從 Ceph 讀取。

2021 年初的時候,雲知聲和 JuiceFS 團隊一起把 JuiceFSRuntime 整合到 Fluid 上面。因為以裸機的方式去用快取,我們發現使用者對快取的可見性比較不好,快取的清理全部是系統自動做的,使用者的可控性沒那麼高,所以才會把 JuiceFS 整合到 Fluid 。

Fluid 會啟動 JuiceFS 相關的元件,包括 FUSE 和 Worker Pod。其中 FUSE Pod 提供了 JuiceFS 使用者端的快取能力,Worker Pod 則實現了對快取生命週期的管理,Atlas 平臺的 AI 離線訓練任務通過與 FUSE Pod 使用者端互動,進行 AI 訓練資料的讀取。

通過 Fluid 提供的快取排程能力以及資料集的可觀測性,平臺的使用者可以通過親和排程將快取部署在特定的計算節點上,同時使用者能夠直觀的看到快取的使用情況(例如快取資料集的大小、快取的百分比、快取的容量等)。

JuiceFS 的建設實踐

目前 Atlas 不能存取公網,是在專用的隔離網內,因此我們全部都是私有化部署。

我們生產環境的後設資料引擎採用 Redis,2020 年的時候,TiKV 對接到 JuiceFS 還不是很成熟,我們計劃首先用 Redis 來做過渡,物件儲存的是用 Ceph。Redis 節點的系統磁碟做了 RAID1,同時 Redis 持久化的資料會定期同步到另一臺備份節點上。Redis 的資料持久化我們採用 AOF + RDB 的方案,每秒進行一次資料持久化。

物件儲存採用自建的 Ceph 叢集,Ceph 叢集採用 Cephadm 進行部署,目前生產環境用的是 Octopus 版本。我們當時借鑑了很多業界的方案,對記憶體在記憶體層面做了一些優化,以及在軟體層面也做了相應的調優,主要如下:

伺服器層面(參考)
• 42 Cores 256GB 2418T HDD
• 系統磁碟: 2
960G SAS SSD
• BlueStore
• 關閉 NUMA
• 升級 kernel: 5.4.146 開啟 io_uring
• Kernel pid max,修改 /proc/sys/kernel/pid_max

Ceph 設定方面
• Ceph RADOS:直接呼叫 librados 介面,不走 S3 協定
• Bucket shard
• 關閉 pg 的自動調整功能
• OSD 紀錄檔儲存(採用 bluestore,建議裸容量配比—— block : block.db : block.wal = 100:1:1,後兩者建議採用 SSD 或 NVMe SSD)
• 3 副本

重點提下,要把 Ceph 叢集的核心升到比較新的版本,然後開啟 io_uring 功能,這樣效能會有比較大的提升。在軟體方面我們是直接呼叫了rados 的介面,就不走 S3 協定了,效率會稍微高一點,所有的節點用 100G 的 InfiniBand 高速網路去做互聯。

雲知聲環境中 JuiceFS 對接的物件儲存是 Ceph RADOS,JuiceFS 採用 librados 與 Ceph 進行互動,因此需要重新編譯 JuiceFS 使用者端,建議 librados 的版本要跟 Ceph 的對應,這點要注意一下。如果用 CSI Driver 的時候,在 PV/PVC 的建立,會讀取 /etc/ceph/ceph.conf 也要注意版本的支援。

完善的監控體系

現在整個鏈路比較長了,底層有後設資料引擎叢集、Ceph 物件儲存叢集,還有上層的使用者端以及業務,每層都要有相應的監控方案。

使用者端節點,我們主要是做紀錄檔的收集,需要注意的是各個掛載點 JuiceFS 使用者端紀錄檔要做匯聚,error 告警,避免紀錄檔將系統磁碟打爆或者節點無法寫。

各個 JuiceFS 使用者端也要有相應的監控手段,比如檢視各掛載點的 .stat 檔案和紀錄檔觀察指標是否正常,然後看看 Redis 跟 Ceph 叢集的 IO 與紀錄檔,要保證整個鏈路都是可控的,這樣定位問題就比較方便。

上圖是 Ceph 的監控圖,因為我們的使用者端節點用的是 SSD 的快取,現在資料基本不會讀取到 Ceph,大部分是快取在讀取,所以 Ceph 的流量不大。

上圖是 JuiceFS 監控上擷取的資料,可以看到節點的基本百分百至百分之九十幾都能夠命中,快取命中率還是比較高的,大部分資料還是在走快取的。

參與 JuiceFS 社群建設

雲知聲在使用 JuiceFS 社群版的過程中,一直積极參與社群建設。在 2021 年和 JuiceData 團隊合作開發了上文中提到的 Fluid JuiceFS Runtime。近期, 我們發現社群版基於目錄的配額還沒有開發,於是在前幾個月我們開發了一個版本,對目錄的檔案數跟檔案大小做了限制, PR 目前已經提交,現在也正在跟 JuiceFS 社群一起進行合併的工作。

JuiceFS 在 Atlas 的使用場景與收益

JuiceFS 使用者端多級快取目前主要應用在我們的文字識別、語音降噪以及語音識別場景。由於 AI 模型訓練的資料讀取特點是讀多寫少,我們充分利用 JuiceFS 使用者端的快取帶來 IO 讀取的加速收益。

收益一:加速 AI模型訓練

1)語音降噪測試

降噪場景模型的測試中使用的是散檔案,每個資料都是 wav 格式,小於 100k 的語音小檔案,在降噪場景我們測試了資料 dataload 階段的 I/O 資料,JuiceFS 使用者端節點的記憶體快取為 512G,在 500h 規模的資料下、以 40 的 batch size 進行測試。

從測試結果來看,單從資料讀取效率上,在 wav 小檔案方面,JuiceFS 為 6.45 it/s,而 Lustre 為 5.15 it/s,效能提升 25%。JuiceFS 有效加速了我們端到端的模型訓練,整體縮短了模型的產出時間。

2)文字識別場景

在文字識別場景中,模型為 CRNN backbone 為 MobileNet v2 ,測試環境如下:

生成了一個 LMDB 的巨量資料檔案,這時候 IO 對頻寬的要求比較高,而不是對小檔案的效能要求。200G 記憶體快取是能支撐整個資料的,所以我們沒有走底層的儲存,而是直接從使用者端讀取,整體效能也有比較大的提升。

在這個測試中,主要做了 JuiceFS 跟 Lustre 的速度對比,從實驗的結果來看從 Lustre 讀每個 batch 耗時 1.5s,從 JuiceFS 讀每個 batch 耗時為 1.1s,提升36%。從模型收斂的時間來看,從 Lustre 的 96 小時下降到 JuiceFS 的 86 小時,使用 JuiceFS 能夠將 CRNN 模型的產出時間縮短 10 小時。

模型偵錯與資料處理

做程式碼偵錯時,多個使用者會同時在一臺偵錯機上去執行模型測試,以及程式碼的遍歷,當時統計了大部分使用者是會使用一些遠端的 IDE,連線到偵錯節點,然後構建自己的虛擬環境,會把大量的安裝包提前安裝在Lustre上。

大部分都是幾十k 或者幾百k 的小檔案,要把這些包匯入在我們記憶體上。之前使用 Lustre 時,因為使用者太多了所以需求吞吐較高,同時對小檔案效能要求比較高,發現效果不是很好,在 import 包時會比較卡,導致程式碼偵錯的時候比較慢,整體效率比較低。

後來使用了JuiceFS 使用者端的快取,在第一次編譯時也比較慢,但第二次的編譯時因為資料已經全部落在快取上,速度和效率就比較高了,程式碼跳轉也就比較快,程式碼提示 import 也比較快。使用者測試後大概有 2~4 倍的速度提升。

結語

從 Lustre 到JuiceFS

從 2017 年到 2021 的時候,我們用 Lustre 也是比較穩定的,叢集儲存量少於 50% 的時候,軟體的穩定性都是比較高的。

Lustre 作為老牌 HPC 領域的儲存系統,為許多全球最大的超算系統提供動力,具有多年的生產環境經驗。其具有符合 POSIX 標準、支援各種高效能低時延的網路,允許 RDMA 存取的優點,適用於傳統 HPC 領域的高效能運算,跟深度學習的介面是契合的,所有的業務都是不需要做程式碼修改。但是也有一些缺點:

第一,Lustre 無法支援雲原生 CSI Driver。

第二,Lustre 對運維人員的要求比較高,因為全部是以 C 語言寫的,有時候出一些 Bug 無法快速解決,整體社群的開放性和活躍度不是很高。

JuiceFS 有這樣一些特點:

第一,JuiceFS 是一款雲原生領域的分散式儲存系統產品,提供了 CSI Driver 以及 Fluid 等方式使用能夠更好地與 Kubernetes 進行結合。

第二,JuiceFS 的部署方案比較靈活,後設資料引擎可選性高,物件儲存如果使用者網路允許,其實對接到公有云的物件儲存會更好。

第三,在儲存擴容運維方面較為簡單。完全相容 POSIX 標準使得深度學習的應用可以無縫遷移,但是由於後端物件儲存的特點,使得 JuiceFS 在隨機寫方面會有較高的延遲。

第四,JuiceFS 支援本地快取、核心頁快取,實現了冷熱資料的分層和加速。這一點是我們比較看重的,在我們的業務場景是比較合適的,但是在隨機寫的時候就不太合適。社群版本目前分散式快取的功能也還不提供。

後續規劃

• 後設資料引擎升級,TiKV 適合在 1 億以上檔案數量(最多可以支撐到百億級檔案),對效能以及資料安全都有較高要求的場景,目前我們已經完成了 TiKV 的內部測試也在積極跟進社群的進展,後續要將後設資料引擎遷移到 TiKV。
• 目錄配額優化,目前已經把基礎版本的功能合入到了JuiceFS 社群版本,也跟 JuiceFS 社群進行了討論,在一些場景上有些效能還需要優化。
• 希望去做一些 Nonroot 的功能,現在所有的節點都是 root 許可權能存取所有的資料,許可權太大我們希望只在特定節點去開放 root 的許可權。
• 最後也會去看看社群這邊的話是否有 QoS 的方案,比如基於 UID 或者 GID 的限速。