從YARN遷移到k8s,滴滴機器學習平臺二次開發是這樣做的

 

整理 | 夕顏

出品 | AI科技大本營(ID:rgznai100)

 

【導讀】人工智能時代,機器學習已經滲透進每個領域,改變了這些領域的業務模式、技術架構以及方法論。隨着深度學習技術近年來快速發展,高效、易用的機器學習平臺對於互聯網公司愈發重要,一個高效的機器學習平臺可以爲公司提供更好的人工智能算法研發方面的支持,減少內部重複性、提升資源利用率、提高整體研發效率。

 

在2019 AI開發者大會上,滴滴出行資深軟件工程師唐博在機器學習技術分論壇上分享了kubernetes調度系統在滴滴在機器學習平臺中的落地與二次開發。

 

 

本次演講從滴滴機器學習平臺的特點開始探討,分享了滴滴機器學習場景下的 k8s 落地實踐與二次開發的技術實踐與經驗,包括平臺穩定性、易用性、利用率、平臺 k8s 版本升級與二次開發等內容。此外,唐博還介紹了滴滴機器學習平臺是如何從 YARN 遷移到 k8s,以及 YARN 的二次開發與 k8s 的對比等。最後,唐博還分享了滴滴機器學習平臺正在研發中的功能以及對未來的展望。

 

2019 AI開發者大會是由中國IT社區 CSDN 主辦的 AI 技術與產業年度盛會,2019 年 9 月 6-7 日,近百位中美頂尖 AI 專家、知名企業代表以及千餘名 AI 開發者齊聚北京,進行技術解讀和產業論證。

 

以下爲唐博演講實錄,AI科技大本營(ID:rgznai100)整理:

 

我叫唐博,來自滴滴出行機器學習平臺,負責調度系統,今天分享的題目《是滴滴機器學習平臺kubernetes落地與實踐》,大概分四個部分:

 

 

一、滴滴機器學習平臺簡介

二、平臺調度系統的演進

三、機器學習場景下的k8s落地實踐與二次開發

四、平臺正在開發的功能及未來展望

 

機器學習平臺介紹

 

 

上圖最下方是滴滴學習平臺整體提供的算力、網絡和存儲三個方面,其中算力包括 GPU、CPU,也有第三方合作廠商所提供的專用神經網絡處理器;網絡方面我們內部有一個高速網絡;存儲方面我們提供了分佈式高性能網絡存儲。基於算力、網絡和存儲這三個硬件層面的基礎設施,我們在上面用 kubernetes 調度系統來進行資源管理。

 

我們選擇 kubernetes 的原因很多,首先是 kubernetes 的擴展性較好,它可以適配各種不同的網絡和存儲,且在其他方面,如調度、自定義資源、容器運行時等方面都有很好的擴展能力。其次,因爲 kubernetes 本身給社區的紅利非常好,基於它的設計理念和提供的服務,可以更好地適用於機器學習不同的訓練和預測場景。

 

基於調度層,我們平臺提供了各種對機器學習的支撐,比如高可用/負載均衡;對於不同的訓練,滴滴自研了環狀參數服務器,實現是環狀算法。爲了提高推理服務的性能,我們自己研發了彈性推理服務和前向框架。

 

當用戶在實驗環境裏進行代碼開發,代碼調試到一定程度時,可以把比較成熟的代碼放到我們的離線任務裏進行批量調參,或者進行自動調參,生成一個滿足他們業務需求的模型,並把生成的模型通過我們的前向框架和彈性推理服務,以在線的方式進行推理。

 

基於這些服務,我們提供不同的深度學習和機器學習業務,包括圖像、語音、自然語言處理、知識圖譜、地圖和 AR、VR 等業務。

 

側面這四個是其它部門提供的對於平臺建設的支持類業務,比如智能運維、監控告警服務、日誌收集和鏡像倉庫等,這些合起來構成我們的機器學習平臺架構。

 

平臺調度系統演進

 

下面我們來看第二部分,滴滴機器學習平臺調度系統的演進。

  

 

 

最開始我們選擇了 YARN,並對社區的 Application Master進行了改造,以適合自己的機器學習場景。我們修改了 DockerContainerExecutor以更好地支持 docker 調度,並去除了其中的docker rm命令,從調度層面 100% 保證數據的可靠性。此外,修改了調度器,以支持 GPU 調度,並擴展了 YARN API,讓管控系統和調度系統更好地結合,管控系統可以獲取更多調度方面的信息。然而,隨着業務的逐漸發展,以及業務線和業務形態的多樣化,我們發現 YARN無法滿足我們的需求,於是,我們從 2017 年開始向 kubernetes 遷移。

 

 

對於我們來說,kubernetes 相比於 YARN,在擴展性、CSI、CNI、CRI、CRD、調度等許多其他可以擴展的接口上有很大的提升。從生態系統上來講,kubernetes 依託 CNCF 社區,專注於雲計算領域,更加契合我們的場景。而 YARN 依託 Apache 社區,主要是大數據領域。雲原生設計理念方面,kubernetes 以聲明式 API爲根本,向上在微服務、serverless、持續集成交付等方面可以做更好的集成,這也是我們從YARN 向 kubernetes 遷移的重要原因。

 

右圖是 CNCF 項目全景圖,包括存儲、網絡、容器進行時、調度、監控等諸多方面,雲計算領域應該有的開源項目都包含在其中,包括 Spark 這一子項目。大勢所趨,我們決定從 YARN 向kubernetes 遷移。

 

機器學習場景下的k8s落地實踐與二次開發

 

 

第三點,是關於滴滴機器學習場景下的 k8s 落地實踐與二次開發。

 

滴滴機器學習平臺的主要特點是給用戶提供三種環境,實驗環境、離線任務、在線服務。實驗環境主要是用戶可以登陸裏面,進行代碼開發、調試、修改版本等。離線服務是在代碼基本成型之後進行批量訓練調參,並生成模型。在線服務是使用生成的模型進行預測。

 

下面將就平臺要考慮易用性、利用率、穩定性這三個方面進行 k8s 落地實踐與二次開發的相關介紹。

 

易用性

 

 

 

首先是易用性,平臺給用戶提供了扁平網絡,最開始是使用的是sriov 網絡,給用戶環境分配一個 IP,用戶通過管控系統頁面登陸實驗環境。但是,後來隨着公司整體網絡架構演進,一方面需要更加靈活的網絡配置,另一方面需要更強的隔離性,平臺改爲使用公司內部的SDN,使得配置更靈活,隔離更強,容災之後 IP 不變,且可以指定 IP。這一方面是爲了給用戶更好的用戶體驗,另一方面是如果將內部調度系統和其他系統,如數據庫、分佈式緩存系統等進行打通,我們需要有一個白名單功能,而 IP 不變會方便我們進行白名單打通。

 

這是網絡方面調度易用性的相關介紹。接下來是存儲方面。

 

 

 

最主要的是中間黃色部分,我們給用戶提供了一個分佈式的基於 SSD 盤的 GlusterFS 分佈式存儲系統,用戶可以用他們的項目和個人 IP 訪問存儲空間。但是因爲 GlusterFS 空間不大,我們還提供了 HDFS,用戶可以把一些較冷的數據放到 HDFS 裏,可以多存儲一些。除此之外,用戶在使用過程中,如果想編譯一些小文件較多的框架,網絡存儲的性能並不能滿足他們的需求,所以,基於用戶需求和硬件環境,我們提供第三種存儲方式,在本機節點上隔出來一塊盤,基於local PV提供本機緩存。

 

local PV本身有兩個特點,一是適用高吞吐場景,二是隻存在於一個node 節點上,不保證數據的可靠性。關於 local PV 比較典型的使用樣例是 Uber 提出來的,Uber的M3DB 把數據進行分片,每一個分片複製三份,每一份是一個 local PV,相當於把數據可靠性功能做到分佈式數據系統這一層,所以緩解了 local PV 本身數據不可靠的缺陷。

 

但是對於我們來說,提供 local PV 功能是爲了讓用戶可以更好地編譯而提供緩存,並不需要保證可靠性,只是提供爲了高速存儲。

 

我們對 local PV 的代碼進行了修改,如果在K8S的yaml文件裏面寫了一個 node 節點上不存在的目錄,它會自動創建該目錄,因爲我們的調度系統只能從管控系統來進行 PV 創建,所以安全性可以得到保障。

 

總的來說,如右圖中所示,我們提供了三種不同存儲,從上到下磁盤空間越來越大,從下到上性能逐漸提升。

 

 

 

接下來是易用性方面的輔助性功能。我們修改了調度的代碼, 對docker根目錄大小進行了限制。最開始docker存儲區驅動是devicemapper,後來隨着版本升級變成了overlay2,物理機我們是 xfs 系統,我們用xfs quota功能限制 docker 根目錄大小,保證物理機磁盤足夠用,以及 harbor 磁盤不被佔滿。

 

第二個輔助性功能是增加正在使用的 GPU,APIserver 返回 GPU,kubelet 獲取 container 正在使用的 GPU,返回給 apiserver。

 

 

這是滴滴自研前向框架加上滴滴自研的 serving框架,是爲了提高inference的性能。kube-proxy在這個場景下會增加一層額外的iptables或者ipvs,我們直接使用了 LVS 對接後面的 Pod IP,類似 ingress,不過是 EIP 對接 Pod IP。我們的目的是爲了可以給用戶提供更好的前向預測性能。

 

利用率

 

 

 

利用率方面,首先介紹共享 GPU。目前我們瞭解到,社區和友商也提出了一些共享 GPU 的方案,其中可能比較著名的是 GPU share device plugin,加上 GPU 共享的 scheduler extender解決方案,這種解決方案的特點是,它更適合於 serving 前向推理步驟或者代碼調試,同時需要限制顯存。第二個開源方案是 Fractional GPU,提供強隔離,目前還處於研發階段,只支持 Caffe 一種框架,如果要適配更加普適性的框架,還需要自己對接開發。第三個是社區同學提供的 Multiple device plugin 方案,一個 GPU 會上報多次,也是需要限制顯存。

 

我們的機器學習平臺提供的方法與以上友商和社區的方法有很多相似之處,比如共享 GPU 的方案,我們修改了代碼,允許多個 docker 共同使用一個 GPU,並且hook 了cuMemAlloc 等一系列函數進行顯存限制。後來,隨着業務的演進,我們的實驗環境讓用戶可以進行任何實驗,這時有些用戶會偶爾做一些破壞性的工作,docker 這種軟隔離對他們的限制作用有限,所以我們就採用了英偉達最新提出的 vGPU KVM 供用戶使用。

 

 

接下來是調度方面,我們根據用戶的使用習慣提供了不同套餐的離線任務和實驗環境,比如只有一個 GPU 的一卡離線任務和有四個 GPU 的四卡離線任務,在這種套餐化的場景下,會產生一個問題,即資源的碎片化,所以我們用了調度策略,通過配置優先級函數,實現緊湊調度。如右圖所示,下面四個是節點,分別運行了兩個1卡 GPU,還有三個。第二個和第三個1卡離線任務也是同樣調度到第一個節點上,第一個節點 GPU 目前使用率是集羣中使用的第二個,這時通過緊湊調度,我們會把第三個節點的離線任務分配給四卡,充分調度空閒機器。

 

除此之外,根據用戶的使用情況,滴滴機器學習平臺裏除了有 GPU 的任務,也有不使用 GPU 的純 CPU 離線任務,結合物理機內存和顯存的比例情況,除了提供 GPU 離線任務之外,我們把每臺物理機隔出一塊資源提供給 CPU 離線任務,把 CPU 任務儘量打散,避免影響重要的GPU 任務。另外一點是緊湊調度函數,社區自帶的MostRequestedPriority函數只適用於 CPU 和內存,不支持其他的擴展資源,比如 GPU,所以我們對緊湊調度優先級函數進行修改,讓它可以支持擴展資源。

 

爲了提升用戶體驗和進一步提高利用率,我們對k8s 在調度上進行了改進。

 

 

 

當資源佔有率非常高時,如果用戶還沒有高優先級的任務,就只能讓一些緊急任務搶佔資源。但是在搶佔的同時,我們也希望高優先級的任務到來時,對集羣現有任務所造成的傷害和影響最小,所以,我們爲搶佔的過程加入了一個按照離線任務和 Pod 啓動時間先後順序來進行排序的功能。我們在第二步生成每個 node 上可以被搶佔的 Pod進行了改進,加入了啓動時間。在第四步,社區的算法是遍歷每個 node 上比當前 Pod 優先級低的 Pod,加入 potential victims。將 potential victims 按照優先級排序,同優先級下按照時間排序。如果第一條不能選出最合適的 node 就進行下一條,依次進行。

 

首先選擇違反 PDB 最小的節點。如果第一條就選不出來,第二條從所有可以被搶佔的最高優先級Pod中選出優先級最低那個Pod所在的節點,接着是優先級之和最小的節點,個數最少的節點,最高優先級的 Pod 中啓動時間最晚的節點。我們發現友商也有這個需求,後來我們和友商一起把這個方案貢獻給社區。

 

穩定性

  

 

下面我們來看看穩定性方面。因爲穩定性對於任何一個平臺級的產品和應用來說都是必不可少的,針對穩定性我們也做了或大或小的參數調整和二次開發,我將分別從運行穩定性、數據穩定性和升級穩定性三個方面來講解。

 

運行穩定性,我們調大 pod 驅逐時間和節點監控時間,一方面是爲了更好地應對內部網絡抖動,超時調大之後可以扛住更大的抖動;另一方面也是爲了便於運維操作,如果一個機器掛掉,運維組的同學有足夠的時間來恢復腳本,把集羣恢復到之前的狀態,並把這些 pod 的 IP 也配置成之前的狀態,讓用戶感覺除了重啓之外沒有其他變化。

 

數據穩定性,我們去除了 docker rm 命令,防止異常情況下數據丟失,在調度層面確保數據不丟。

 

升級穩定性,去除了 container hash 檢查,去除了 kubelet 創建環境變量時對 pod.Spec.Enable service Links 的檢查,使Pod在升級時不會重啓。社區相關PR從1.16起升級才管用。

 

同時我們關閉了TaintBasedEviction,使pod 在升級時不會被驅逐。

 

平臺正在開發的功能及未來展望

 

 

最後是關於平臺正在開發的功能以及機器學習相關的未來展望。

 

我們正在進行中的功能開發主要有調度器、再調度器,以及我們自己的 device plugin。

 

 

 

首先是調度器,基於社區的新的調度框架,調度分爲不同的階段,每個階段都是一個擴展點,用戶可以在這些擴展點實現自己的插件和需要的功能。我們正在做的是 Filter 定製,Post-bind定製,並且與監控打通和任務畫像。

 

 

 

再調度器的主要目的是防止集羣中的資源碎片化,比如上圖的集羣中分別有一、二、三不同個數一卡離線任務,如果有四卡離線任務到來,會對這個節點形成搶佔,一卡離線任務之前運行的一些流程就被迫中斷了,或者如果模型沒有保存就沒用了。我們做再調度器是爲了提前發現這種狀況,和監控系統打通,通過再調度器來驅逐一卡離線任務,讓它重新通過調度器的緊湊調度,調度到這臺機器上,這樣就可以提前空出機器,供後續的四卡離線任務使用。但是,這也涉及到當前正在運行的異卡離線任務啓動時間,以及任務的特徵刻畫。舉例來說,驅逐一個卡運行 30 分鐘還是驅逐兩個卡運行 20 分鐘,都是我們需要考慮的問題。

 

 

 

此外,我們也在開發 device plugin,以實現實驗環境和離線任務的混合調度,但暫時不便透露太多信息。

 

 

 

未來,我們希望藉助 k8s 提供多機多卡服務,現在多機多卡是在管控這一層實現的,我們希望放到調度這一層,以更好地利用 k8s 的調度能力,爲用戶提供更好的體驗,打造一站式機器學習平臺。同時也把更多大數據任務放到這個平臺上,比如 Spark等。以及提供更好的在離線混合調度,來進一步提高集羣的資源分配率和利用率。

 

目前,滴滴機器學習平臺着力發展公有云,讓機器學習平臺不但在內部使用,也可以提供給更多外部同行使用。

 

 

 

再細一點講,希望可以爲從硬件選型到基礎設施,到整個上層軟件棧,提供一個內外統一的架構,減少內外兩部分的重複性工作。比如針對上圖中底部的 IaaS 和Paas層,我們希望提供內外統一的資源,如機器學習平臺簡樞、算法市場、模型市場、數據市場等,基於這些底層服務,在 SaaS 層提供人臉、語音、自然語言處理和智能視頻識別和其他圖像、地圖服務。

 

 

 

現在,滴滴機器學習平臺已經在滴滴公有云平臺上,上圖爲架構圖,如果想了解詳細內容可以訪問網站。

 

演講嘉賓:

 

唐博,滴滴出行資深軟件工程師,曾就職於高盛美國、高盛香港,現就職於滴滴出行,負責機器學習平臺調度系統,是kubernetes, istio, kubeflow, alluxio等開源項目的代碼貢獻者。

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