NAVER 是一家多元化的互聯(lián)網(wǎng)公司政勃,擁有韓國最大的搜索引擎并在人工智能丈氓、自動駕駛等高科技領(lǐng)域積極投入桨嫁。
在搭建 AI 平臺時(shí)贰军,NAVER 評估了公有云平臺的存儲產(chǎn)品玻蝌、Alluxio 以及高性能專用存儲產(chǎn)品等多種選項(xiàng)后,最終決定采用 JuiceFS词疼。通過使用JuiceFS俯树,NAVER 成功地將內(nèi)部存儲資源升級為高性能、適應(yīng) AI 工作負(fù)載的存儲解決方案贰盗。
AiSuite 是 NAVER 開發(fā)者所使用的人工智能平臺许饿,它支持 NAVER 的各種服務(wù)的開發(fā)和運(yùn)維。
AiSuite 提供基于 Kubernetes 的容器環(huán)境舵盈,用于高效管理成本高昂的 GPU 資源陋率。它支持 Kubeflow球化,不僅便于 AI 模型的開發(fā),還能整合模型訓(xùn)練和部署服務(wù)的完整 AI 工作流程瓦糟。此外筒愚,AiSuite 還支持使用集成了公司內(nèi)部數(shù)據(jù)平臺 Kubeflow 工作流組件。
在建設(shè) AI 平臺時(shí)菩浙,最大的挑戰(zhàn)就是提供適合 AI 工作負(fù)載的存儲巢掺。隨著大型語言模型(LLM)的普及,為了生成優(yōu)質(zhì)的 AI 模型劲蜻,所需數(shù)據(jù)的規(guī)模越來越大陆淀,且分布式學(xué)習(xí)需要多個節(jié)點(diǎn)能夠同時(shí)訪問數(shù)據(jù)。此外先嬉,還應(yīng)能夠輕松應(yīng)用像 Llama 2倔约、MPT 等迅速出現(xiàn)的各種大型語言模型開源項(xiàng)目。
適用于 AI 平臺的存儲需求如下:
必須能夠處理大規(guī)模數(shù)據(jù)坝初;
為了進(jìn)行重復(fù)的訓(xùn)練浸剩,高性能是必須的;
必須能作為 Kubernetes 持久卷(persistent volume)使用鳄袍,即支持 Kubernetes CSI Driver绢要;
為了確保能夠直接使用各種開源軟件和庫而無需進(jìn)行任何修改,存儲系統(tǒng)應(yīng)具備 POSIX 兼容性拗小;
對于分布式學(xué)習(xí)和大規(guī)模服務(wù)重罪,必須支持多個進(jìn)程同時(shí)訪問(參考 ReadWriteMany, ReadOnlyMany);
必須確保數(shù)據(jù)的一致性哀九;
運(yùn)維工作應(yīng)當(dāng)盡可能小剿配。
尋找能夠滿足所有這些要求的存儲解決方案并非易事。云平臺如 AWS EFS 和 Google Filestore 等服務(wù)與這些要求相似阅束。但是呼胚,這些服務(wù)與 AWS S3 或 Google Cloud Storage 等對象存儲服務(wù)相比,它們的成本要高得多(標(biāo)準(zhǔn)費(fèi)率下 EFS和 AWS S3 有10倍的差異)息裸。此外蝇更,由于 AiSuite 是在 NAVER 內(nèi)部部署的,因此無法使用 AWS呼盆、GCP 等外部云存儲服務(wù)年扩。我們也可以引入一些專用的存儲解決方案,如 DDN EXAScaler访圃,但這會帶來高昂的成本厨幻。本文將介紹為解決這些問題所進(jìn)行的探討以及引入新存儲解決方案的經(jīng)驗(yàn)。
01 存儲方案選型
我們曾考慮引入像 GlusterFS、CephFS 這樣的開源解決方案况脆,但由此會帶來比較大的運(yùn)維負(fù)擔(dān)平绩。
我們希望能夠使用 NAVER 內(nèi)部現(xiàn)有資源可支持的存儲解決方案。 NAVER 內(nèi)部現(xiàn)有的存儲方案情況如下:
NAVER 的 C3 HDFS(Hadoop 分布式文件系統(tǒng))可以處理大規(guī)模數(shù)據(jù)漠另。但是捏雌,由于 HDFS 不支持 Kubernetes CSI Driver,因此無法將其用作 Kubernetes 的持久卷笆搓;
NAVER 的對象存儲 nubes 也可以處理大規(guī)模數(shù)據(jù)性湿,并支持 CLI、REST满败、S3肤频、POSIX 等多種接口。但是算墨,由于對象存儲的特性宵荒,它并不完全支持 POSIX API。此外净嘀,由于不支持 Kubernetes -- CSI Driver报咳,因此也不能將其用作 Kubernetes 的持久卷;
Ceph RBD 不支持 ReadWriteMany, ReadOnlyMany挖藏,因此無法在多個 Pod 中同時(shí)訪問暑刃;
NFS 可以簡單設(shè)置,但存在擴(kuò)展性和高可用性(HA)的問題膜眠;
Local Path 將數(shù)據(jù)存儲在 Kubernetes 節(jié)點(diǎn)的磁盤上岩臣。盡管訪問速度快,但不支持多用戶同時(shí)訪問宵膨。此外架谎,由于存儲的數(shù)據(jù)位于各個節(jié)點(diǎn)上,因此需要進(jìn)行特定的調(diào)度或在應(yīng)用程序級別實(shí)現(xiàn)相關(guān)功能辟躏。
初步方案:引入 Alluxio
為了在 AiSuite 中快速且輕松地使用在 Hadoop 集群中處理并存儲在 HDFS 上的數(shù)據(jù)谷扣,我們引入了 Alluxio。但 Alluxio 在我們的場景中存在以下問題:
不完全的 POSIX 兼容性
雖然可以將 Alluxio 用作 Kubernetes 持久卷鸿脓,但它不支持某些 POSIX API抑钟,例如符號鏈接、截?cái)嘁翱蕖allocate、追加幻件、xattr 等拨黔。例如,在掛載 Alluxio 的路徑 /data 后绰沥,追加操作將失敗篱蝇,如下所示:
$ cd /data/
$ echo "appended" >> myfile.txt
bash: echo: write error: File exists
許多 AI 開源軟件和庫默認(rèn)實(shí)現(xiàn)為假設(shè)數(shù)據(jù)位于本地文件系統(tǒng)上贺待。如果不支持某些 POSIX API,可能無法正常工作零截。因此麸塞,在使用 Alluxio 的情況下,有時(shí)需要將數(shù)據(jù)復(fù)制到 ephemeral storage 后再使用涧衙。這樣做會導(dǎo)致 AI 開發(fā)變得不便和低效哪工。
數(shù)據(jù)不一致
Alluxio 更類似于現(xiàn)有存儲系統(tǒng)上的一個緩存層,并非一個獨(dú)立的存儲解決方案弧哎。當(dāng)?shù)讓哟鎯Σ捎?HDFS 時(shí)雁比,直接對 HDFS 進(jìn)行更改而沒有經(jīng)過 Alluxio,可能會引起 Alluxio 與HDFS 數(shù)據(jù)的不同步撤嫩。
在 Alluxio 中偎捎,可以設(shè)置與原始存儲數(shù)據(jù)同步的時(shí)間間隔。更多詳細(xì)信息序攘,請參考 UFS Metadata Sync茴她。但是,如果同步過于頻繁程奠,會對原始存儲產(chǎn)生過多的元數(shù)據(jù)請求败京。AiSuite 運(yùn)行了一個以 HDFS 作為原始存儲的 Alluxio 實(shí)例,以便與基于 Hadoop 的數(shù)據(jù)平臺進(jìn)行交互梦染。但是赡麦,頻繁同步導(dǎo)致管理 HDFS 元數(shù)據(jù)的 NameNode 負(fù)載增加。
運(yùn)維壓力
Alluxio 需要運(yùn)行一個由 master 和 worker 服務(wù)器組成的單獨(dú)集群帕识,這也帶來了一定的運(yùn)維壓力泛粹。不僅如此,由于 AiSuite 的所有用戶都共享這個系統(tǒng)肮疗,一旦出現(xiàn)問題晶姊,可能會影響到所有用戶。
為什么選擇使用 JuiceFS
JuiceFS 是一種分布式文件系統(tǒng)伪货,采用“數(shù)據(jù)”與“元數(shù)據(jù)”分離存儲的架構(gòu)们衙,文件數(shù)據(jù)本身會被切分保存在對象存儲(例如 Amazon S3),而元數(shù)據(jù)則可以保存在 Redis碱呼、MySQL蒙挑、TiKV、SQLite 等多種數(shù)據(jù)庫中愚臀,這使得企業(yè)能夠利用現(xiàn)有存儲和數(shù)據(jù)庫忆蚀。
接下來,我會詳細(xì)介紹 JuiceFS,并解釋為什么選擇應(yīng)用 JuiceFS馋袜。
配置
元數(shù)據(jù)引擎(Metadata Engine):負(fù)責(zé)管理文件的元數(shù)據(jù)(文件名男旗、大小等)⌒辣睿可以使用多種數(shù)據(jù)庫察皇,如 Redis、TiKV泽台、MySQL/MariaDB什荣、PostgreSQL 等(文檔:如何設(shè)置元數(shù)據(jù))。
數(shù)據(jù)存儲(Data Storage):實(shí)際存儲數(shù)據(jù)的地方师痕±6茫可以使用多種存儲,包括 S3胰坟、OpenStack Swift因篇、Ceph、MinIO笔横、HDFS 等(文檔:如何設(shè)置對象存儲)竞滓;客戶端(Client):與元數(shù)據(jù)引擎、數(shù)據(jù)存儲進(jìn)行交互吹缔,執(zhí)行文件 I/O 操作商佑。支持多種接口笤昨,適用于不同的環(huán)境候齿;JuiceFS 的元數(shù)據(jù)和數(shù)據(jù)存儲能夠使用現(xiàn)有存儲和數(shù)據(jù)庫,并且可適配 Kubernetes 環(huán)境舌涨。例如晚碾,只要準(zhǔn)備好了 S3 對象存儲和 Redis抓半,就可以通過 JuiceFS 創(chuàng)建一個高性能且功能豐富的存儲解決方案。這也是 JuiceFS 吸引我們的原因格嘁。使用 NAVER 內(nèi)部支持的存儲和數(shù)據(jù)庫笛求,可以方便地搭建存儲系統(tǒng)。
特性
JuiceFS 支持并發(fā)訪問糕簿,同時(shí)支持 POSIX 和 Kubernetes 環(huán)境探入。滿足前面提到的用于 AI 平臺的存儲要求,具體特性如下:
- POSIX 兼容:可像本地文件系統(tǒng)一樣使用懂诗;
- HDFS 兼容:支持 HDFS API蜂嗽,可用于 Spark、Hive等數(shù)據(jù)處理框架响禽;
- S3 兼容:通過啟用 S3 網(wǎng)關(guān)徒爹,可以使用 S3 兼容接口進(jìn)行訪問荚醒;
- 云原生:支持 CSI Driver芋类,可用于 Kubernetes 持久卷隆嗅;
- 分布式:可在多個服務(wù)器上同時(shí)共享;
- 強(qiáng)一致性:提交的更改立即在所有服務(wù)器上生效侯繁;
- 出色性能:詳細(xì)信息請參閱性能基準(zhǔn)測試胖喳;
- 數(shù)據(jù)安全:支持數(shù)據(jù)加密;
- 文件鎖定:支持 BSD 鎖(flock)和 POSIX 鎖(fcntl)贮竟;
- 數(shù)據(jù)壓縮:支持 LZ4, Zstandard丽焊,可節(jié)省存儲空間。
存儲原理
JuiceFS 引入了以下概念來處理文件咕别,目的是為了彌補(bǔ)分布式存儲在物理上的分散性和對象存儲中對象難以修改的缺點(diǎn)技健。
Chunk:每個文件被劃分為 64MB 大小的 Chunk 進(jìn)行管理。大文件可以根據(jù)偏移量并行讀取或?qū)懭攵韫埃@對于處理大規(guī)模數(shù)據(jù)非常有效雌贱;
Slice:每個 Chunk 由一個或多個 Slice 組成。每次寫入時(shí)都會創(chuàng)建一個新的 Slice偿短,它們可以與同一個 Chunk 的其他 Slice 重疊欣孤。在讀取 Chunk 時(shí),會優(yōu)先讀取最新的 Slice昔逗。為了避免過多的 Slice 導(dǎo)致讀取性能下降降传,會定期將它們合并為一個。這使得 JuiceFS 能夠靈活地修改文件勾怒,解決了對象存儲在數(shù)據(jù)修改方面的限制婆排;
Block:在實(shí)際存儲中,Slice 被劃分為基礎(chǔ)大小為 4MB(最大可達(dá) 16MB)的 Block 進(jìn)行存儲笔链。Chunk 和 Slice 主要是邏輯概念段只,而實(shí)際存儲中可見的數(shù)據(jù)單位是 Block。通過分割為較小的 Block 并進(jìn)行并行處理卡乾,JuiceFS 彌補(bǔ)了分布式對象存儲遠(yuǎn)程且較慢的特點(diǎn)翼悴;
元數(shù)據(jù)引擎管理著諸如文件名、文件大小等元數(shù)據(jù)幔妨。此外鹦赎,它還包含了文件與實(shí)際存儲數(shù)據(jù)之間的映射信息。
緩存
JuiceFS 為了提高性能误堡,采用了多個層級的緩存古话。在讀取請求時(shí),首先嘗試從內(nèi)核頁緩存锁施、客戶端進(jìn)程緩存和本地磁盤緩存中讀取數(shù)據(jù)陪踩。若這些緩存未命中杖们,則會從遠(yuǎn)端存儲中讀取所需數(shù)據(jù)。從遠(yuǎn)端存儲中獲取的數(shù)據(jù)隨后會被異步地存儲在各級緩存中肩狂,以便未來能更快速地訪問同樣的數(shù)據(jù)摘完。
02 Alluxio vs JuiceFS
早期引入的 Alluxio 并沒有滿足我們所需的存儲要求。那么 JuiceFS 呢傻谁?以下是對 Alluxio 和 JuiceFS 進(jìn)行比較的表格孝治。
JuiceFS 和 Alluxio 都支持多種接口,并可以通過緩存來提高性能审磁。與 Alluxio 相比谈飒,JuiceFS 具有以下優(yōu)點(diǎn):
完全兼容 POSIX
Alluxio 在某些 POSIX API 上提供有限支持。而 JuiceFS 能夠完全支持 POSIX 標(biāo)準(zhǔn)态蒂,因此可以像本地文件系統(tǒng)一樣使用杭措。這意味著,無需修改存儲在 JuiceFS 中的訓(xùn)練數(shù)據(jù)和代碼钾恢,就可以使用各種 AI 開源工具和庫手素。下面是 POSIX 兼容性測試 pjdfstest 的結(jié)果。與AWS EFS 和 Google Filestore 相比赘那,JuiceFS 在支持 POSIX 方面表現(xiàn)更佳刑桑。[圖片上傳失敗...(image-6155c6-1703647097942)]
強(qiáng)一致性
Alluxio 更接近于對原始存儲進(jìn)行緩存,而 JuiceFS 是一個獨(dú)立的存儲系統(tǒng)募舟。在 JuiceFS 中祠斧,元數(shù)據(jù)由元數(shù)據(jù)引擎管理,不依賴于外部系統(tǒng)拱礁。數(shù)據(jù)存儲僅用于存放 Block 數(shù)據(jù)琢锋。因此,不會像 Alluxio 那樣出現(xiàn)與原始存儲不同步的問題呢灶。
減輕運(yùn)維負(fù)擔(dān)
Alluxio 需要運(yùn)行和維護(hù) master 和 worker 服務(wù)器吴超,這增加了一定的運(yùn)維負(fù)擔(dān)。此外鸯乃,因?yàn)锳lluxio被所有用戶共享鲸阻,一旦發(fā)生故障,可能會對所有用戶造成影響缨睡。JuiceFS 可以直接利用現(xiàn)有熟悉的存儲和數(shù)據(jù)庫作為元數(shù)據(jù)引擎和數(shù)據(jù)存儲鸟悴,僅需 JuiceFS 客戶端即可運(yùn)行,無需部署獨(dú)立服務(wù)器奖年。此外细诸,每個用戶都可以獨(dú)立配置自己的元數(shù)據(jù)引擎和數(shù)據(jù)存儲,從而避免相互干擾陋守。
03 如何使用 JuiceFS 構(gòu)建存儲方案
使用 JuiceFS震贵,需要準(zhǔn)備一個用作元數(shù)據(jù)引擎的數(shù)據(jù)庫和對象存儲利赋。如前所述,JuiceFS 支持多種數(shù)據(jù)庫和對象存儲猩系。為了減輕運(yùn)維負(fù)擔(dān)媚送,我們使用了 NAVER 現(xiàn)有的平臺。
如下圖所示蝙眶,AiSuite 通過以下內(nèi)部平臺使用 JuiceFS季希。
元數(shù)據(jù)引擎
在 NAVER褪那,可以使用 nBase-ARC Redis 服務(wù)或通過 MySQL 支持來設(shè)置元數(shù)據(jù)引擎幽纷。如果是進(jìn)行開發(fā)和測試,也可以通過 Helm chart 直接安裝并使用 Redis博敬、PostgreSQL 等友浸。JuiceFS 默認(rèn)每小時(shí)將元數(shù)據(jù)自動備份到數(shù)據(jù)存儲中,且備份周期是可配置的偏窝。因此收恢,即使元數(shù)據(jù)引擎的數(shù)據(jù)丟失,也可以進(jìn)行恢復(fù)祭往,但由于元數(shù)據(jù)備份周期的設(shè)定伦意,仍有可能會有部分?jǐn)?shù)據(jù)丟失。有關(guān)詳細(xì)信息硼补,請參考元數(shù)據(jù)備份和恢復(fù)驮肉。
數(shù)據(jù)存儲
可以使用 NAVER 內(nèi)部的 HDFS 或 nubes Object Storage 存儲大規(guī)模數(shù)據(jù)。利用這些資源已骇,可以進(jìn)行大容量且穩(wěn)定的數(shù)據(jù)存儲离钝。
nubes
nubes 是 NAVER 的對象存儲。JuiceFS 本身不直接支持 nubes褪储,但可以通過使用具有 MinIO 接口的 nubes-s3-proxy 來訪問卵渴。
HDFS
HDFS 是 JuiceFS 默認(rèn)支持的存儲系統(tǒng)。但是鲤竹,為了在大規(guī)模浪读、多租戶的 HDFS 中應(yīng)用 Kerberos,需要進(jìn)行以下改進(jìn):
支持 Kerberos keytab 文件
NAVER 內(nèi)部的 HDFS 應(yīng)用了 Kerberos辛藻。因此碘橘,當(dāng) JuiceFS 使用 HDFS 時(shí),需要進(jìn)行 Kerberos 認(rèn)證揩尸。原先的 JuiceFS 是通過設(shè)置 KRB5CCNAME 環(huán)境變量為 credential cache 進(jìn)行 HDFS 認(rèn)證蛹屿。但這個方式會在一定時(shí)間后過期失效。為解決這一問題岩榆,進(jìn)行了改進(jìn)错负,可以通過設(shè)置 KRB5KEYTAB坟瓢、KRB5PRINCIPAL 環(huán)境變量使用 keytab 文件。(參見 JuiceFS issue #3283)
支持 base64 編碼的 keytab 文件
AiSuite 是一個多租戶 Kubernetes 集群犹撒,共享給多個用戶折联,目標(biāo)是允許每個用戶使用自己選擇的元數(shù)據(jù)引擎和數(shù)據(jù)存儲來運(yùn)行 JuiceFS。用戶需要自己編寫 Kubernetes Secret识颊,設(shè)置訪問元數(shù)據(jù)引擎和數(shù)據(jù)存儲的路徑和認(rèn)證信息诚镰。但是,KRB5KEYTAB 僅是一個文件路徑祥款,并不能讓用戶傳遞實(shí)際的 keytab 文件清笨。為解決這個問題,進(jìn)行了改進(jìn)刃跛,允許通過設(shè)置 KRB5KEYTAB_BASE64 環(huán)境變量使用 base64 編碼的 keytab 文件字符串抠艾。(參見 JuiceFS issue #3817)
支持用戶指定的 HDFS 路徑
NAVER 內(nèi)部的 HDFS 由多個用戶共享,每個用戶僅在分配給他們的 HDFS 路徑上擁有權(quán)限桨昙。但是检号,原來的 JuiceFS 無法指定用于數(shù)據(jù)存儲的 HDFS 路徑,因此總是必須將數(shù)據(jù)存儲在 root 目錄下蛙酪,這導(dǎo)致用戶遇到了沒有權(quán)限訪問的路徑問題齐苛。為解決這個問題,進(jìn)行了改進(jìn)桂塞,允許用戶設(shè)置自己的 HDFS 路徑凹蜂。(參見 JuiceFS issue #3526)
支持 HDFS 路徑 hdfs://nameservice
NAVER 內(nèi)部的 HDFS 為了大規(guī)模運(yùn)營,采用了 HDFS Federation藐俺,由多個 NameNode 和 Namespace 組成炊甲。原本的 JuiceFS 需要直接指定 NameNode 路徑,如 nn1.example.com:8020欲芹,這對用戶來說確認(rèn)和設(shè)置很不方便卿啡。為了解決這個問題,進(jìn)行了改進(jìn)菱父,現(xiàn)在可以像 hdfs://nameservice 這樣設(shè)置 Namespace颈娜。(參見 JuiceFS issue #3576)
CSI Driver
AiSuite 是一個多租戶 Kubernetes 集群,每個用戶通過 Kubernetes namespace 進(jìn)行區(qū)分浙宜。如果用戶間共享 JuiceFS官辽,可能會相互影響,降低穩(wěn)定性并增加運(yùn)維難度粟瞬。因此同仆,我們的目標(biāo)是使每個用戶都能單獨(dú)準(zhǔn)備自己的元數(shù)據(jù)引擎和數(shù)據(jù)存儲,并獨(dú)立使用 JuiceFS裙品。此外俗批,為了減輕運(yùn)維負(fù)擔(dān)并提高用戶便利性俗或,支持 Dynamic Volume Provisioning,使用戶無需管理員介入岁忘,就能直接定義和使用 PVC(PersistentVolumeClaim)辛慰。為此,需要進(jìn)行以下改進(jìn):
支持模板 Secret
用戶需要創(chuàng)建 Secret干像,以設(shè)置各自準(zhǔn)備的元數(shù)據(jù)引擎和數(shù)據(jù)存儲的訪問路徑和認(rèn)證信息帅腌。然后,需要在 StorageClass 中設(shè)置以引用這些 Secret麻汰。這些設(shè)置的 Secret 會被用于 Dynamic Volume Provisioning速客。但是,原有的 JuiceFS CSI Driver 只能在 StorageClass 中設(shè)置一個固定的 Secret什乙。為解決這一問題挽封,進(jìn)行了改進(jìn),允許通過 {pvc.namespace}, ${pvc.annotations['<annotation style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">']} 等方式臣镣,從用戶創(chuàng)建的 PVC 中引用 Secret。(參見 JuiceFS CSI Driver issue #698)</annotation>
支持 Secret Finalizer
用戶的 Secret 不僅在創(chuàng)建 PVC 時(shí)使用智亮,還在刪除 PVC 時(shí)用于刪除 JuiceFS 數(shù)據(jù)忆某。如果在刪除 PVC 之前關(guān)聯(lián)的 Secret 被移除,JuiceFS 數(shù)據(jù)將不會被清理阔蛉,而會持續(xù)留存弃舒。為了防止這個問題,在 PVC 被刪除之前状原,設(shè)置 Finalizer 以防止關(guān)聯(lián)的 Secret 被移除聋呢。在 StorageClass 的 parameters 中設(shè)置 secretFinalizer: "true" 可以啟用此功能。(參見 JuiceFS CSI Driver issue #707)
支持根據(jù) PVC 元數(shù)據(jù)設(shè)置 mountOptions
AiSuite 中存在多種 AI 工作負(fù)載颠区,如 AI 學(xué)習(xí)削锰、服務(wù)和數(shù)據(jù)處理等。為了實(shí)現(xiàn)最優(yōu)性能毕莱,根據(jù)工作類型可能需要單獨(dú)配置 JuiceFS器贩。例如,在使用只讀數(shù)據(jù)進(jìn)行 AI 訓(xùn)練的情況下朋截,可以通過添加 --open-cache
設(shè)置來提高讀取性能蛹稍。有關(guān)詳細(xì)信息,請參考客戶端內(nèi)存中的元數(shù)據(jù)緩存部服。原先的 JuiceFS 只能應(yīng)用 StorageClass 中固定的配置∷艚悖現(xiàn)在進(jìn)行了改進(jìn),允許根據(jù)用戶創(chuàng)建的 PVC 進(jìn)行設(shè)置廓八,例如使用 {.PVC.name}, {.PVC.annotations.bar} 這樣的方法奉芦。(參見 JuiceFS CSI Driver issue)
04 JuiceFS 應(yīng)用方案
為了在 Kubernetes 中支持 JuiceFS胆描,管理員需要部署 JuiceFS CSI Driver,而用戶則需要定義自己的 Secret 和 PVC仗阅。在多租戶 Kubernetes 環(huán)境 AiSuite 中昌讲,將詳細(xì)說明如何部署和提供 JuiceFS,包括具體的示例减噪。
部署方法
安裝 JuiceFS CSI Driver 后短绸,可以按照標(biāo)準(zhǔn) Kubernetes 卷的使用方式進(jìn)行操作,支持通過 Helm 或 kubectl 進(jìn)行安裝筹裕。有關(guān)詳細(xì)信息醋闭,請參考 JuiceFS CSI Driver 安裝指南。進(jìn)行部署需要 Kubernetes 管理員權(quán)限朝卒。為了讓每個用戶使用自己的元數(shù)據(jù)引擎和數(shù)據(jù)存儲证逻,StorageClass 設(shè)置如下。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: juicefs
provisioner: csi.juicefs.com
parameters:
#配置系統(tǒng)以便用戶可以引用自己創(chuàng)建的 Secret
#用戶需要在 PVC 'csi.juicefs.com/secret-name'注釋中設(shè)置Secret的名稱
csi.storage.k8s.io/provisioner-secret-name: ${pvc.annotations['csi.juicefs.com/secret-name']}
csi.storage.k8s.io/provisioner-secret-namespace: ${pvc.namespace}
csi.storage.k8s.io/node-publish-secret-name: ${pvc.annotations['csi.juicefs.com/secret-name']}
csi.storage.k8s.io/node-publish-secret-namespace: ${pvc.namespace}
csi.storage.k8s.io/controller-expand-secret-name: ${pvc.annotations['csi.juicefs.com/secret-name']}
csi.storage.k8s.io/controller-expand-secret-namespace: ${pvc.namespace}
juicefs/clean-cache: "true"
#激活 secretFinalizer抗斤,以防止用戶定義的 Secret 被隨意刪除
secretFinalizer: "true"
#通過指定 pathPattern來設(shè)置路徑囚企,可以掛載所需的路徑
#用戶可以在 PVC 'csi.juicefs.com/subdir'注釋中設(shè)置所需的路徑
pathPattern: "${.PVC.annotations.csi.juicefs.com/subdir}"
allowVolumeExpansion: true
reclaimPolicy: Delete
mountOptions:
#允許用戶根據(jù)需要設(shè)置各自的選項(xiàng)
#用戶可以在PVC的'csi.juicefs.com/additional-mount-options'注釋中設(shè)置所需的JuiceFS選項(xiàng)。
- ${.PVC.annotations.csi.juicefs.com/additional-mount-options}
使用方法
用戶需要為自己準(zhǔn)備的元數(shù)據(jù)引擎和數(shù)據(jù)存儲創(chuàng)建 Secret瑞眼,包括路徑和認(rèn)證信息等龙宏。
apiVersion: v1
kind: Secret
metadata:
name: myjfs
type: Opaque
stringData:
#JuiceFS文件系統(tǒng)名稱。
name: myjfs
#MINIO_ROOT_USER
access-key: user
#MINIO_ROOT_PASSWORD
secret-key: password
#元數(shù)據(jù)引擎 Redis 路徑
metaurl: redis://:@redis.user1.svc.cluster.local:6379/0
#minio
storage: minio
#bucket1
bucket: http://nubes-s3-proxy.user1.svc.cluster.local:10000/bucket1
#https://juicefs.com/docs/community/command_reference/#format
format-options: trash-days=0,block-size=16384
定義 PVC伤疙。此外银酗,需要設(shè)置以下注釋(annotation):
csi.juicefs.com/secret-name
:指定引用的 Secret 名稱;csi.juicefs.com/subdir
:如果是新的卷徒像,則指定 PVC 名稱黍特。如果需要掛載已存在的 JuiceFS 路徑,則可以指定所需的路徑锯蛀;csi.juicefs.com/additional-mount-options
:可以添加適合工作負(fù)載的 JuiceFS 掛載選項(xiàng)灭衷。有關(guān)詳細(xì)信息,請參考掛載指南谬墙。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myjfs
annotations:
csi.juicefs.com/secret-name: myjfs # 之前創(chuàng)建的Secret名稱
csi.juicefs.com/subdir: myjfs # 在JuiceFS文件系統(tǒng)中的路徑
csi.juicefs.com/additional-mount-options: "writeback,upload-delay=1m" # 如果需要今布,可以添加JuiceFS的配置
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
storageClassName: juicefs
創(chuàng)建 Secret 和 PVC 后,可以像使用普通卷一樣使用它們拭抬。下面是一個將之前創(chuàng)建的 myjfs PVC 掛載到 /data 上的 Pod 示例部默。
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
- name: app
...
volumeMounts:
- mountPath: /data
name: juicefs-pv
volumes:
- name: juicefs-pv
persistentVolumeClaim:
claimName: myjfs
05 性能測試
JuiceFS 性能基準(zhǔn)測試如下所示,與 EFS, S3FS 相比造虎,其性能更高傅蹂。
我們需要驗(yàn)證當(dāng)使用 nubes 對象存儲和 HDFS 作為數(shù)據(jù)存儲時(shí)的性能表現(xiàn)。由于 JuiceFS 的性能可能會根據(jù)所使用的數(shù)據(jù)存儲類型而有所差異,我們還需關(guān)注由于使用 UserSpace 中的 Fuse 而可能出現(xiàn)的性能降低份蝴。特別是需要檢驗(yàn)因 JuiceFS Fuse 引起的性能下降情況犁功。測試的主要目的是確定,相比直接使用數(shù)據(jù)存儲婚夫,JuiceFS 是否會導(dǎo)致性能下降浸卦。如果性能差異不顯著,那么我們可以在保持性能的同時(shí)支持 POSIX 兼容性案糙、并發(fā)訪問等多項(xiàng)功能限嫌。
順序讀寫
參考 Fio Standalone Performance Test,按照以下方式進(jìn)行了測試:
元數(shù)據(jù)引擎使用 Redis时捌;
在單個節(jié)點(diǎn)上使用 fio 進(jìn)行測試時(shí)怒医,調(diào)整
--numjobs
選項(xiàng);單節(jié)點(diǎn)的最大網(wǎng)絡(luò)帶寬為 1200MB/s奢讨,即此測試的可能最高值稚叹;
由于 Object Storage 基本上不支持 POSIX,因此沒有使用 fio拿诸,而是采用了針對 nubes Object Storage 性能優(yōu)化的其他方法扒袖,僅測量 read(1 job), write(1 job) 項(xiàng)目;
JuiceFS 設(shè)置中佳镜,塊大小設(shè)置為 16MB僚稿,其他選項(xiàng)使用默認(rèn)值;
沒有使用 JuiceFS 緩存蟀伸,僅進(jìn)行了讀寫新數(shù)據(jù)的測試;
對于 Alluxio缅刽,由于在執(zhí)行 fio 時(shí)出現(xiàn)“fio: posix_fallocate fails: Not supported”等錯誤而導(dǎo)致失敗啊掏,因此在測試中被排除了。
測試結(jié)果如下:
在讀取方面衰猛,與單獨(dú)的 nubes 相比迟蜜,JuiceFS+nubes 和 JuiceFS+hdfs 的性能更好,并且隨著并發(fā)數(shù)量的增加而提升啡省。這可能是因?yàn)橥ㄟ^ Chunk 進(jìn)行的并發(fā)讀取更為有利娜睛;
在寫入方面,與單獨(dú)的 nubes 相比卦睹,JuiceFS+nubes 和 JuiceFS+hdfs 的性能相似或略低畦戒。并發(fā)數(shù)量增加時(shí),性能會降低结序。這可能是由于多個 Slice 帶來的負(fù)擔(dān)所致障斋。
文件創(chuàng)建
此次測試比較了創(chuàng)建 1 萬個小文件所需的時(shí)間。測量使用 nubes 作為數(shù)據(jù)存儲時(shí)處理元數(shù)據(jù)的性能,并與 JuiceFS 進(jìn)行比較垃环。
元數(shù)據(jù)引擎使用 Redis邀层;
測量了在 10 個進(jìn)程中使用 cp 命令復(fù)制 100 字節(jié)文件 1 萬個時(shí)的每秒文件創(chuàng)建數(shù);
由于 Object Storage 基本上不支持 POSIX遂庄,因此沒有使用 cp寥院,而是采用了針對 nubes Object Storage 性能優(yōu)化的其他方法來測量 nubes 項(xiàng);
也測量了設(shè)置了 JuiceFS 的 writeback 選項(xiàng)的情況涛目。此選項(xiàng)首先在本地進(jìn)行數(shù)據(jù)更新秸谢,然后異步保存到數(shù)據(jù)存儲。更多詳細(xì)信息泌绣,請參考 client-write-cache钮追。
測試結(jié)果如下:
nubes 和 juicefs+nubes 之間沒有顯著差異。這意味著使用 nubes 作為數(shù)據(jù)存儲的 JuiceFS 不會導(dǎo)致性能下降阿迈;
與 HDFS 配合使用時(shí)元媚, JuiceFS+hdfs 和 alluxio 似乎與 HDFS 的元數(shù)據(jù)處理性能,即 NameNode 的性能趨于一致苗沧;
使用 writeback 選項(xiàng)可實(shí)現(xiàn)數(shù)十倍的性能提升刊棕。然而,啟用 writeback 選項(xiàng)可能導(dǎo)致數(shù)據(jù)丟失待逞,因此適用于臨時(shí)數(shù)據(jù)的場景甥角。
測試結(jié)論
JuiceFS 的性能基本上取決于存儲數(shù)據(jù)設(shè)備的性能。它能夠支持 POSIX 兼容性且無性能損失识樱、還能支持并發(fā)訪問等功能嗤无。
在某些工作負(fù)載和使用情況下,JuiceFS 的性能有時(shí)甚至可能優(yōu)于數(shù)據(jù)存儲設(shè)備的原始性能怜庸。盡管本文未進(jìn)行測試当犯,但讀取緩存數(shù)據(jù)時(shí),因?yàn)槭菑谋镜卮疟P讀取割疾,因此有可能提高性能嚎卫。寫入臨時(shí)數(shù)據(jù)時(shí),應(yīng)用 writeback 選項(xiàng)也可以提升性能宏榕。
JuiceFS 支持多種可根據(jù)工作負(fù)載進(jìn)行調(diào)整的緩存選項(xiàng)拓诸。更多詳細(xì)信息,請參考 cache麻昼。
06 小結(jié)
企業(yè)內(nèi)部存儲 + JuiceFS
在 AiSuite 中奠支,我們利用公司內(nèi)部支持的 HDFS 和 nubes 對象存儲來構(gòu)建 JuiceFS。這樣既能為 AI 工作負(fù)載提供適合的存儲涌献,又能減輕運(yùn)維負(fù)擔(dān)胚宦。對于前文中評估的企業(yè)內(nèi)部存儲,可以總結(jié)如下:
在 AiSuite 中,相比于 HDFS枢劝,更推薦使用 nubes Object Storage 用作數(shù)據(jù)存儲井联。這是因?yàn)樵?HDFS 中,如果文件數(shù)量眾多您旁,會對管理 HDFS 元數(shù)據(jù)的 NameNode 造成負(fù)擔(dān)烙常。而 JuiceFS 會將文件分割成小的 Block 來存儲,從而在 HDFS 中產(chǎn)生大量文件鹤盒。即使是最大可設(shè)置的 Block 大小 16MB蚕脏,為了存儲 1TB 數(shù)據(jù),也需要創(chuàng)建超過 62,500 個文件侦锯。雖然考慮過將最大 Block 大小提升至 64MB驼鞭,但 Block 變大可能會導(dǎo)致效率低下。更多詳細(xì)信息尺碰,請參考 Increase the maximum of blockSize to 64MB挣棕。
優(yōu)勢
在 AI 平臺 AiSuite 中,我們評估了 JuiceFS 作為 AI 工作負(fù)載的存儲解決方案的可行性亲桥。JuiceFS 具有以下多種優(yōu)勢:
可以使用大容量洛心、可共享(ReadWriteMany, ReadOnlyMany)卷;
高性能(緩存)题篷,可以替代 hostPath词身、local-path》叮可以輕松實(shí)現(xiàn)有狀態(tài)應(yīng)用的云原生轉(zhuǎn)換法严;
在 AI 分布式學(xué)習(xí)中,可以作為共享的工作區(qū)葫笼、checkpoint渐夸、日志存儲;
能夠處理 AI 學(xué)習(xí)過程中所需的大量小文件(HDFS/Alluxio 的替代品)渔欢;
可利用企業(yè)內(nèi)部的 HDFS、nubes Object Storage 存儲瘟忱,降低運(yùn)維負(fù)擔(dān)奥额;
通過用戶各自的數(shù)據(jù)存儲和元數(shù)據(jù)引擎運(yùn)行,互不影響访诱;
支持多種數(shù)據(jù)存儲和元數(shù)據(jù)引擎垫挨,適用于大多數(shù) k8s 環(huán)境;
可以替代高成本的共享存儲触菜,如 AWS EFS九榔、Google filestore、DDN exascaler。
通過使用 JuiceFS哲泊,能夠?qū)⑵髽I(yè)內(nèi)部傳統(tǒng)的存儲轉(zhuǎn)換為具有高性能和多功能的剩蟀、適合 AI 工作負(fù)載的存儲。JuiceFS 支持多種存儲和多種數(shù)據(jù)庫切威。這篇文章主要介紹了在 NAVER 內(nèi)部的 on-premise 環(huán)境中的應(yīng)用案例育特,但它也可以應(yīng)用于 AWS、Google Cloud 等公共云環(huán)境先朦。希望這篇文章能對面臨類似問題的用戶提供幫助缰冤。
希望這篇內(nèi)容能夠?qū)δ阌幸恍椭绻衅渌蓡枤g迎加入 JuiceFS 社區(qū)與大家共同交流喳魏。