Mesos 架構與去哪兒的統一框架實踐

shenxidd 7年前發布 | 9K 次閱讀 Mesos 軟件架構

Mesos 架構

在官方文檔中,Mesos 定義成一個 分布式系統內核 。它使用和 Linux 內核相同的設計原則,只是設計在不同的抽象層級上。它運行在一個機房的所有服務器上并且通過 API 的形式給應用(比如 Hadoop,Spark,Kafka,Elastic Search)提供資源管理、計劃任務等功能。

Mesos 是一個在 2009年 由 Benjamin Hindman 等人聯合發起的伯克利大學研究項目。隨后引入 推ter,如今已經完美運行在 推ter,Airbnb 等環境。

Mesos 的架構圖如下。

在圖中,Master 主要負責 slave 以及 Framework scheduler 的注冊,以及資源分配;Slave 主要接受來自 master 的任務。M esos applications ( 也稱為 frameworks )在 slave 上運行 task。

在官方文檔中,Mesos 的資源分配流程如圖所示。

  1. Slave 1 向 Master 匯報其空閑資源:4 CPU、4GB 內存。然后 Master 調用分配策略模塊,得到的反饋是 Framework 1 要請求全部可用資源。

  2. Master 向 Framework 1 發送資源 offer,描述了Slave 1上 可用資源。

  3. Framework 的調度器(Scheduler)響應 Master,需要在 Slave 上運行兩個任務,第一個任務分配 <2 CPUs, 1 GB RAM> 資源,第二個任務分配 <1 CPUs, 2 GB RAM> 資源。

  4. 最后,Master 向 Slave 下發任務,分配適當的資源給 Framework 的任務執行器(Executor),由執行器啟動這兩個任務(如圖中虛線框所示)。 此時,還有 1 CPU 和 1GB RAM 尚未分配,因此分配模塊可以將這些資源供給 Framework 2。

因此也可以看到,Mesos 一個最大的好處是能夠對分布式集群做細粒度資源分配。 如下圖所示,左邊是粗粒的資源分配,右邊是細粒的資源分配。

Marathon 是一個 Mesos Framework,能夠支持運行長服務,比如 Web 應用等。是集群的分布式 Init.d,能夠運行任何 Linux 二進制發布版本,可以統一對集群做多進程管理。也是一種私有的 PaaS,為部署提供 REST API 服務,通過 HAProxy 實現服務發現和負載平衡。后文會詳細介紹為什么選擇 Marathon 作為統一 framework。

Mesos 在去哪兒的使用

下面給大家分享去哪兒從去年開使用 Mesos 時,在系統實施和擴容階段,對 Framework 部署和使用上的一些思考,也介紹一下 Framework 遷移的過程。

先說一下我們背景和版本使用情況。

Mesos

我們主要還是用 Mesos 做數據分析。Mesos 是從 0.22 開始使用,中間經歷了 0.25,現在在調研 0.28。

Marathon

Marathon 從 0.8 開始使用,目前正在用的是 0.11,正在調研 1.1。 從測試來看,暫時不建議大家上 1.0,因為它有一個非常嚴重的問題,持久化卷處理在機器宕掉重啟以后,帶有持久化卷的任務恢復不了。1.1.0 修復了 BUG,所以大家如果要上新版建議選擇 1.1。

Spark、Alluxio 等

Spark 版本變更比較多,從版本 1.5.0 一直升級到 1.6.0。 Alluxio 是一個開源分布式內存文件系統,也是用作數據加速。Etcd,hdfs 最開始用,用了一半放棄了。因為 Mesos 早期版本對于持久化數據這一塊支持不是很好,etcd 和 HDFS 涉及到數據寫磁盤重新調度以后恢復問題,當時沒有很好的處理辦法。因為 Marathon 1.1 版將持久化功能推出,近期會重新再上。

使用場景

我們主要用 Mesos 來做公司的日志處理,把公司業務線數據收集回來做日志分析工作。

舉個例子,去哪兒客戶端打開酒店后,會有推薦或者猜你喜歡等類似功能,相關數據就是業務線使用平臺推送的數據算出來的,相當于平臺是公司數據流的集散地,清洗完推到各自系統上。 每天 大致的量有 130 億,有很多業務線它的日志是重復消費的,比如無線日志有可能酒店度假都在用。

我們容器的量和其他互聯網公司相比較小,和十萬級和百萬級的容器量相差非常大。在實施過程中,在建立平臺的過程中,主要會遇到兩個問題:

  1. 框架 framework 能不能統一?

  2. 框架 framework 的嵌套有沒有意義,如果做這件事它的性價比是什么樣的?

框架統一

第一個問題就是框架 framework 能否統一?現在 Mesos 上跑的軟件能不能都用 Marathon 來管理?

Spark on Mesos 是 Spark 團隊用來整合 Mesos 的framework,也是 Spark 團隊維護的。 Alluxio 也有自己原生的 framework。

每一個軟件在 Mesos 上運行,基本上都會有一個思路,需要提供一個 Framework 來做自己的事情。

Etcd on Mesos 和 HDFS on Mesos 主要是 Mesosphere 公司配套上自己的 DNS 來做。Spark on Mesos 有兩種運行模式 batch 和 streaming,它對數據的資源管理比如粗粒度和細粒度,調度方式還不太一樣。

這里寫的調度邏輯,更多的意義在于針對軟件特定的使用場景,會有特定的調度策略混在里面。

一個應用一個 framework 的模式的優勢,就是更精確的調度。

調度邏輯這一塊 Marathon 提供了一個約束,去控制任務調度到指定的機器上,或者用 group by 的方式來做一個分 rack/region 的部署的功能。

基于特定軟件的自定義 framework,總要考慮到特性相關的東西,比如 Alluxio,它優先會使用內存,也會用 SSD,所以它的調度會考慮這到臺機器是否安裝有 SSD。

如果用在 Marathon 上,可能要打一個 slave 標簽,告訴它機器上有 SSD,但是打一個標簽就需要把 Mesos slave 重啟。在生產過程中,其實相當于已經在破壞集群的穩定性了。

但是在自定義  framework  的時候,調度過程中可以從 DB 里面去抓機器的信息,看它是否配置有 SSD,完成調度,并且不用重啟 slave。

異常恢復

在 Marathon 上來講,task 一旦被標記成 FAILED 或 LOST 狀態,它會有一次重新調度,重調度在 Marathon 上認為和重新發布是相同意思。

如果做了一個重調度,任務的啟動腳本檢測到已經有 ramfs 以后,它會 umount 掉,導致數據丟了。換成自定義 Framework,如果之前已經調過這臺機器,重起任務的腳本可以重新換一下,換成直接復用數據方式啟動,相當于自己能記錄一些信息,然后做恢復控制,控制力能比 Marathon 好一些。

消息控制

然后是消息控制,通過 Mesos 可以發一些消息,Framework 與 Executor 之間做交互。這個用法在 Spark 也用過,這有一個問題就是消息量和消息的大小稍微控制一下,因為 Spark 的早期版本,用 Framework 來做消息的反饋,結果會把 master 打崩。因此需要注意這一點。

服務發現

最后是服務發現,如果自己寫一個 Framework,宏觀的手段就有很多。用 Marathon,這一塊功能是相對缺失的,因為他要考慮照顧不同的方案,只能滿足通用性更高的的場景,后面會詳細介紹。

自定義  framework  的問題

但是自定義 framework  的劣勢也是非常大的,像 Spark on Mesos,提供的 Framework 還是非常簡單,基本上不了生產環境,功能只能測一下跑的效果怎么樣,導致二次開發的量比較大。

Framework  二次開發里面經常遇到的幾個問題,Framework 發完之后任務的狀態是否需要保存下來。因為在 HA 情況下,如果原有的 Framework 宕掉了,沒有把任務信息記到第三方系統里面(比如 zk),新的 Framework 接管以后,他根本不知道有哪些任務。

比如說任務掛了,Mesos 傳遞過來一個 statusUpdate 消息,他才會知道原來的 leader 發過這么一個東西。所以需要把  HA 和 state 兩個捏在一起來做。就相當于一個應用一個 framework  的情況下,會遇到大量的重復的功能開發,而且這些功能其實都是核心功能。

另外一個劣勢就是監控基本沒有,以上提到的這些 framework ,對于監控還有報警基本上就是沒有的。所以如果在考慮后期維護,沒有監控,沒有報警,生產環境基本上這是一個黑盒,出了問題基本上不知道怎么回事,從這個角度考慮,自定義  framework  就已經被 Pass 掉了。

統一成 Marathon

遇到這些問題以后,就考慮能不能把所有用過的軟件,把他們自己原生的東西廢掉。全部先切換到 Marathon,因為 Marathon 本身 framework  功能和監控非常完善,所以切完了以后對后期的運維和基于 API 的二次開發就會變得簡單一點。

服務發現

基本上就是兩套,四層和七層都支持。四層用 Marathon 的 EventBus,每發一個任務,它把任務信息都發送出來,自己寫一個 callback,通過 etcd + confd + haproxy 做服務發現。

如果不想開發,可以選擇第二種方式,直接用 Bamboo + Haproxy。七層直接用 OpenResty + LUA 寫一個。

異常恢復這一塊相對差一些,因為異常恢復需要在每一個任務里額外寫一些腳本或者小程序,通過這些數據做一個原數據存儲,再基于原數據做一個恢復的過程。在這一塊有一定開發量,但是開發量和之前講到的二次開發量比是非常小。

Spark 遷移

我們主要運行 Spark Streaming 任務,只要發一個 spark driver 就可以了,其他 executor 不用 Spark 原生 framework  啟動,而是換成 Marathon 啟動,把 driver 的 URL 等信息填進去,還有環境變量信息,比如 HADOOP_USER_NAME,把 executor(Spark 非 Mesos)發布以后,就可以從 driver 拿到數據做 streaming 了。這一層相當于我在 Marathon 拆成兩次發,第一次發 driver,第二次發 executor。

ElasticSearch

額外提一下 ES 這一塊,我們集群有 50 臺左右機器,最開始不太關心把 ES 做成一個服務放到 Mesos,也就是不太希望 ES 是混合部署,因為 ES 本身對資源占用率比較大,比如系統文件開銷。

但是隨著了解 ES 在業務線的使用,發現理解有一些錯誤,當時把 ES 定位成日志檢索、還有針對日志解析后數據出報表的一個工具。后來發現所有人把它當成一個二級索引來用,這種情況下 ES 的集群規模非常小,而且數據量很小,但是他們內存的要求比較大。

因此你會發現 ES 用法完全不一樣了,他們的用法是比較傾向于走小集群,把業務線拆分做隔離,所以 ES 變成一個服務的可能性已經出現了。再加上到 Marathon 1.1 以后,基于 Marathon 做 ES 的平臺可能性已經有了。

現在已經在 beta 版測試。ES 在業務線實際上還是小集群為主,然后一個集群里就只有幾個索引,專門服務于某個業務的集群。

框架嵌套

以上是對框架  framework  統一的思考,下面聊一下  framework  嵌套。

在最開始階段,集群驗證功能的屬性更強一點,所以開始時規模非常小,只有一套 Marathon,三個節點的 HA,然后一個 Chronos。

隨著 APP 數量增多,Marathon 效率下降比較快,APP 地址超過了 2200,基本上調度等半天才能反應一次,感覺扛不住了。

再加上通過打標簽的形式來標記應用是干什么,標簽打太多之后管理起來比較麻煩,如果 App Id 超過 24 位會被直接截斷。

當時沒有好的辦法,只能把 Marathon 做一次拆分,拆成了 6 到 8 個不同的 Marathon 跑到 Mesos上,這個縮減 App Id 主要是為了適應 Mesos DNS。

當時在原有的基礎上不停的擴容, Framework 多出來一套,就從別的地方要三臺機器給它布局,布到最后就發現承載 Framework 的機器越來越多了。我們把好多東西拿到集群用,占用虛擬資源,但是沒怎么用。

最后重新思考一下, framework  分散,應用結構就相當于跟著  framework  走,一個 framework  里面應用是一套,另外一個  framework  是另外一套。把應用分攤到 Framework 里,每個 Framework 沒什么關聯。

獨立部署導致這種額外的資源和域名有一些開發量,應用樹構建這塊是一個問題,應用在上面多了以后,總需要有一個類似于服務治理的功能,需要有地方管理服務,包括樹狀結構是什么樣的,要明確地知道這個東西來自于哪一個部門干什么事情。

因為要把日志的應用分配到每一個業務線對應的一個樹結構里面,所以整合時發現樹構架集成很高,因為 Marathon  跑在外面,需要每一個  Marathon  抓一個。

多租戶

再一個就是多租戶,很多時候業務線僅僅是用一下,他就想能不能借用一個 Marathon 做一個測試?這個時候也不好掛靠自己內部資源上,這是當時遇到的一些問題。包括動態分配資源,有時候業務需要 4 核 4G 內存,他就是簡單跑一下測試。這兩個問題當時都沒解決。

我們就決定把所有的 framework  嵌套。只有剛才講的這些東西還不足以做好。還有一個就是標準化,在運維里面,做一件事情最先考慮的就是能不能標準化,標準化以后意味著后面自動化可以做,Marathon 在標準化這塊做得很好,通過 API 就可以把自動化流程串接起來。

面對這些問題,能不能考慮一種相對來講讓所有工作簡單一點的事情?

我們調整一下,還是在集群外部署一套 Marathon,叫他 Root Framework,后面所有的 framework  采用 Root  framework 去發,如果它掛了,Root  framework 會自動切換到其他 standby 節點上,很多運維是 Root  framework 完成,以前維護多個  framework ,現在只要盯著 Root  framework 就可以了。

用這種方式以后,運維量就開始降低了。包括后面開發量也開降低了,有了 Root Framework 以后,之前講的七層服務發現,只要基于 Root framework 做一層就夠了。

有了 Root framework 以后,就可以拿到二級  framework ,甚至拿到三級、四級的 framework。多級  framework 在 Lua 配合下,直接通過泛域名方式訪問所有應用。每一級域名對應著一個 framework ,服務發現與這一級 Framework 綁定,如果他有問題把它的父  framework 直接下掉。

還有應用樹的事,因為 framework 一旦形成了父子關系,整個應用樹的構建,直接基于 Framework 同步應用樹的數據庫就可以了,所以就直接和業務樹對應。這是選擇的另外一個原因。

更多的優化像 HA 或 Failovetimeout,如果  framework 宕掉了,他允許設置一個 failovertimeout 時間,如果超時以后,Framework 還沒有注冊到 Mesos 集群,它就會默認  framework 所有的 executor 和 task 全殺掉。

還有為  framework  申請動態預留,申請動態保留資源跟上面的 HA 還有 failovertime 是有一定關聯的,防止資源不夠的時候恰好 framework 出問題重新部署了,但是資源被其他人都耗盡了導致部署不上。

按需求分配任務,分到不同 Marathon,其實變成了按需求去起動,再發一個  framework ,不再擔心資源的限制,后面那些功能自然而然就帶出來了。

 

 

來自:https://mp.weixin.qq.com/s/b86uI5iR3Ks2z6OWgfzWsw

 

 本文由用戶 shenxidd 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!