譯 - 高可用的mesos計算框架設計

原文地址
http://mesos.apache.org/documentation/latest/high-availability-framework-guide/
閱讀建議:有寫過或者看過Mesos Framework的開發者,或者對Mesos有較多瞭解的使用者,文章的部分其實包含了分佈式系統設計的一些通用的思路。對於分佈式系統感興趣的人也適合本文。
我基於本文改進了本身的框架的可用性,很是有效。另外Mesos支持restful接口,基於Restful接口,咱們能夠採用更加穩定的、開源的一些服務來代替本身設計的框架,好比使用PHP服務器來管理。mysql

一些翻譯或未翻譯名詞

  • Mesos master 或者 master Mesos的主節點,通常端口爲5050,做用是協調資源分配
  • Scheduler 調度器,獲取資源併產生實際的任務
  • task 任務
  • agent或者客戶端 其實文章中多數狀況下指的就是Mesos-Slavesql

    一些讀起來有點彆扭的詞:

  • 數據存儲:指的是文件或者mysql或者zookeeper等能夠保持數據的東西。
  • 網絡隔離:或者網絡割接描述一種網絡不可達或者不可用的狀況。數據庫

翻譯的不專業,敬請諒解。。。會逐步改進。apache

正文

Mesos框架是用來管理任務的。爲了讓框架有高的可用性,它必須可以在多種失敗的場景下繼續管理任務。做爲一個框架的開發者你須要關注的常見狀況以下:服務器

  • Mesos 的master節點可能失效。好比由於失去網絡鏈接而崩潰。若是master使用了高可用模式,這會致使另外一個Mesos master副本成爲當前的主節點。在這種狀況下,scheduler 會從新註冊到新的主節點並確保任務狀態正常。
  • 框架運行的主機可能失效。爲了確保框架依舊可用而且能夠繼續管理新的任務,框架開發者須要確保有多個Scheduler副本在不一樣的節點中運行。而且在原先主節點失效後,讓副本節點成爲新的主節點。Mesos自己並不會告訴框架開發者如何處理這個狀況,咱們會在下面提供一些建議。它們將會在運行像 Apache Aurora或Marathon這樣長時間任務的時候很是有用。
  • 運行任務的的節點可能失效。另外可能節點自己沒有失效,可是Mesos agent 可能沒法和主節點通訊等等。

請注意,這些問題有可能同時發生。restful

Mesos 架構

在討論以上失效場景以前,有必要強調一下Mesos 是如何設計並影響高可用性的:網絡

  • Mesos在組件之間提供了一種不可靠的消息:消息被最多遞送一次(可能被丟掉)。框架設計者應當考慮到發送的消息可能沒有被收到而且準備好適當的矯正工做。爲了定位這個問題,框架的Scheduler 應該設計一個超時時間用於判斷新的task是否被生成。若是在超時後 Scheduler沒有看到新任務的狀態更新,它應該開始矯正。好比,調節任務狀態(爲失效),而後若是有必要,從新啓動一個任務。架構

    • 通常來講,分發系統沒法區分消息是「丟失」仍是「延時」。在上面的例子中,Scheduler可能在超時後收到狀態更新信息,而且已經開始進行校訂工做了。因此框架設計者應該考慮到這種狀況發生的而可能性而且爲此在程序上作好適配。框架

    • Mesos事實上在進程之間提供一種有序的的(可是不可靠)的消息遞送:好比若是框架發送M1 和 M2給master,那麼框架將收到:沒有任何消息,只有M1 或 M2,M1 而後 M2 ,可是必定不會收到M2 而後 M1。tcp

    • 爲了方便框架開發者,Mesos提供了可靠的任務狀態更新機制(謝天謝地)。客戶端會將狀態更新持久化到磁盤上而後發送到master。master將狀態發送到合適的Framework Scheduler。當一個Scheduler認可狀態更新,master會將這種認可發還給客戶端,這樣容許保存狀態更新的存儲進行垃圾回收。若是客戶端在必定時間內沒有收到狀態更新的確認,它會重複發送狀態更新給master(這裏要當心),一樣也會再發給Scheduler。因此,假設客戶端和Scheduler都是可用的狀況下,任務的狀態更新是「至少」發送一次。要想應付任務狀態可能發送超過一次的狀況,將Framework Scheduler的處理邏輯設計成冪等(每次結果都同樣)是很是有用的。

  • Mesos master 將註冊的框架和活動的任務的信息都保存在內存裏:並無持久化到磁盤上或者試圖在master失效後依舊保持這些數據。這幫助Mesos master 經過許多的任務和框架,擴容爲大型的集羣。這個設計的一個負面影響就是在失效後,須要更多的工做來恢復在內存中丟失的數據。

  • 若是Mesos master 不可用(宕機或者斷網什麼的),集羣將繼續運做:當前的Mesos 客戶端和用戶的任務將繼續運行。可是,新的任務沒法被調度,framework將不會收到資源的offers或者來自於以前啓動過的任務的狀態更新信息。

  • Mesos 並不規定framework應該如何實現,也不爲框架如何處理失敗狀況承擔任何責任。取而代之,Mesos 盡力提供框架的開發者他們須要的工具去實現這些特性。不一樣的框架可能在處理失效的問題上採用不一樣的方案,這取決於他們的實際狀況。

高可用框架的一些建議:

一個高可用的框架能夠按照下面的一些通用方案來設計:

  • 爲了容忍Scheduler失效,框架應該同時運行多個Scheduler 實例(一般是3個)。在任什麼時候候,只有一個實例是他們的頭頭:這個實例和Mesos master鏈接着。接受資源分配和任務狀態更新,啓動新的任務。其餘的Scheduler只是隨從:他們只在頭頭掛掉的時候被使用,在這種狀況下,其中之一被選爲新的頭頭。

  • Scheduler們須要有個機制來判斷當前的頭頭掛了而且選舉一個新的頭頭。常見的是使用一些協調服務好比zookeeper。查看你使用的協調服務器的文檔來獲取更多的關於如何實現頭頭選舉的功能。

  • 當一個Scheduler當選爲新的頭頭,新頭頭要從新和Mesos master鏈接。當註冊到master的時候,框架應該和以前失效的框架使用同一個ID。這確保master會認識到這個鏈接並非一個新的會話,而是繼續以前的失效Scheduler的會話。

注意:當舊的scheduler 頭頭失效的時候,默認狀況下master會立刻殺掉全部的和framework有關的任務和Executors。一個典型的生產環境框架,這個默認行爲是不可容忍的。要避免這個狀況,高可用的框架應該設置failover_timeout字段一個很是大的值。爲了不在生產環境中之外破壞任務,許多框架將failover_timeout設置爲1個星期甚至更多。

  • 在從新鏈接Mesos master以後,新的頭頭應該確保本地環境狀態和整個集羣保持一致。好比,假設以前的頭頭正好要啓動一個新的任務,而後掛了。這個任務應該可以繼續啓動成功,而且在這裏新選舉的頭頭將會收到這個任務狀態更新。爲了應對這個狀況,framework通常使用一種有健壯的一致性的分佈式數據存儲來記錄這些關於活動或暫停的任務信息。事實上,用於頭頭選舉的工具zookeeper也能夠用於這個目的。一些Mesos框架使用Mesos 日誌副原本達到這個目的。

    • 數據存儲應該在執行動做以前,用於記錄Scheduler將要進行的動做。好比,若是一個Scheduler決定建立一個新的task,首先將這個意圖寫入到數據存儲中。而後發送launch task 給Mesos master。若是這時Scheduler失效了,而新的scheduler啓動,新的頭頭能夠查看到數據存儲中全部可能在集羣中的業務。這是一個前置寫入模型,利用數據庫或者文件系統來提高可靠性。這個設計有2個部分須要強調。
    1. Scheduler必須在執行任務前將「意圖」落地:不然可能失去了寫入的機會(其他不翻譯,都是這個狀況會有多糟糕)。

    2. Scheduler必須確保「意圖」可以確實記錄到數據存儲中,在繼續啓動任務以前(一些分佈式數據庫好比Cassandra 可能在寫入一個備份就返回成功了,其餘節點可能尚未寫入)

Task的生命週期

  • 一個Mesos任務要經歷一系列的狀態。只有任務所在的終端才知道任務真正的狀態是什麼。一個Framework Scheduler經過和Mesos master 通訊來了解任務的狀態,確切的說,是監放任務狀態更新和performing task state reconciliation.
  • Framework 能夠經過狀態機描述一個狀態,一個初始狀態和許多種可能的終止狀態。
  • 一個任務始於TASK_STAGING 狀態。一個任務在這個狀態時master收到Framework的關於啓動這個任務的狀態,可是這任務尚未開始跑。在這個狀態中,任務的依賴已經獲取了-for example, using the Mesos fetcher cache.
  • TASK_STARTING是可選的,是自定義Executors的首要選擇。它用於描述自定義Executor已經知道了任務(可能已經在讀取資源了)可是尚未跑起來。

  • 一個任務在確實運行成功後,發送TASK_RUNNING狀態(若是失敗了,須要發送一些失敗的狀態,後面會列出)

  • 當一個framework企圖要啓動一個任務可是在超時後並無收到狀態更新時,framework須要進行適配。它須要主動詢問Master這個task如今的狀態。針對未知的任務master會回覆TASK_LOST。framework能夠用這個區分tasks是啓動慢了仍是master沒有遞送啓動請求(好比請求被丟棄了)

注意這個技術的正確性是基於Scheduler和master直接的消息通訊是有序的。

  • TASK_KILLING 狀態是可選的,它試圖指示殺掉這個進程的請求已經被Executor接到了。可是任務尚未被殺掉。這對於優雅的結束進程很是有用。Executor不要發送這種狀態,除非框架可以兼容。

成功只有一個,失敗的方式卻有不少。。。

TASK_FINISHED 任務正常結束或者關閉
TASK_FAILED 任務由於錯誤被關閉
TASK_KILLED Executor殺掉了任務
TASK_LOST 暗示任務有在跑,可是master監控不到,將來會廢棄
TASK_ERROR 啓動的時候就掛了

對付分離的或者失效的客戶端

Mesos master使用2種不一樣的機制追蹤客戶端的可用狀況和健康狀況

  1. master 和 agent(客戶端)的TCP鏈接狀態
  2. 監控健康是週期性ping 客戶端。master發送「ping」 消息給客戶端,而且期待在超時以前有一個「pong」的反饋給master。若是響應確切數量的ping消息,客戶會被認爲是失效的。這個行爲能夠由 --slave_ping_timeout 和 --max_slave_ping_timeouts 的master選項控制。

若是和客戶端的TCP的長鏈接斷開或者健康檢查失敗(注意是或)。master就認爲節點掛了,而且任務唄移除除了集羣。
特別的:

若是tcp鏈接斷開,agent被認爲沒法鏈接。The semantics when a registered agent gets disconnected are as follows for each framework running on that agent:

若是tcp斷開,客戶端斷開
若是framework在檢查點:沒有立刻要執行的操做。客戶端有機會再超時以前再次連上。
若是framework不在檢查點:全部的framework的任務和Executors都被認爲丟失了。master會立刻爲任務發送一個TASK_LOST狀態。這個更新將不會可靠的遞送給Scheduler(說好狀態是可靠的。。。注意下面的提示)。客戶有一個機會在健康檢查超時前從新鏈接。若是agent重連,任何發出的TASK_LOST狀態更新消息會被kill(原來如此)。

這種行爲模式的根本緣由是,使用典型的TCP設置,master和angent 之間TCP持久鏈接的錯誤更傾向於客戶錯誤(好比slave進程被中斷)而不是網絡隔離,由於Mesos的健康檢查超時比典型的TCP-level的超時要來的小的多。由於不在檢查點的framework將不會 survive a restart of the mesos-slave process,master發送TASK_LOST狀態更新這樣這些任務能夠被從新調度。Of course, the heuristic that TCP errors do not correspond to network partitions may not be true in some environments.

若是一個agent在健康檢查(health checks)中失敗了,它會被計劃移除。移除的速度能夠有master控制(--slave_removal_rate_limit master 配置)以免移除一次性移除一系列的子節點(好比在網絡切割的時候)。

當移除一個客戶端,master將會給客戶端打個removed的標記,並記錄在持久化狀態中(master失效後也在)。master發送slavelost callback 給每個已註冊的scheduler driver;也會發送每個在這個客戶端運行的任務的TASK_LOST 狀態更新

注意:master發送的不管是callback仍是狀態更新,都不是可靠的。好比,master或者Scheduler掛了或者網絡鏈接在發送的時候異常,他們不會重發!

同時,任何一個移除的客戶端的任務會繼續跑,並且客戶端會嘗試從新鏈接master。若是移除的客戶端可以重連到master(好比網絡鏈接又恢復了,shit),從新註冊的請求會被拒絕,並且客戶端會被要求關閉。客戶端會關閉全部的正在跑的任務和executor,移除的客戶端上面的持久化volumes 和 dynamic reservations 將被保護(不理解)。

一個移除的客戶端在啓動一個新的mesos-slave進程後能夠從新加入集羣。當移除的客戶端被master關閉時,Mesos確保下一次mesos-slave 啓動的時候(使用同一個工做目錄和同一個host),客戶端會獲得一個新的agent ID;結果就是,客戶端會被當作一個全新的客戶端加入集羣。agent將會保留以前建立的持久化volumes 和 dynamic reservations,雖然連接這些資源的angent ID已經變了。典型狀況下,框架在應對失效或者隔離的客戶端的時候會調度失效客戶端上的任務到其餘地方。這須要很是當心,儘管失效的客戶端可能還活着,可是和master隔離而且沒法通信。依賴天然的網絡隔離,客戶上的任務可能仍是能夠和其餘客戶端或者集羣節點通信。Framework能夠作些事情來避免這個狀況(好比,使用zookeeper來中止agent工做,若是他們的zk鏈接仍是正常的),可是Mesos將這些細節留給了框架開發者。

處理隔離的或者失效的Master

上面描述的行爲在一個新的Mesos master剛被選舉完的一段時間中是不會被執行的。上面會注意到,多數的Mesos master狀態僅保存在內存中。同時,噹噹前master失效,新的master 選舉後,新的master只有當前集羣的極少數信息。取而代之,他重建他的信息經過通知 framework 和 客戶端新master被選舉,並從新註冊到它上面。

框架從新註冊

當一個master失效發生,鏈接在以前的master的framework須要鏈接到新的master上。MesosSchedulerDriver 持有多數細節of決定何時先前的master失效,何時鏈接到新的master上;當framework成功註冊到新的master上, 「reregistered scheduler driver callback」(一個回調函數) 將被調用。

客戶端從新註冊

當一個新的master被選舉後的一個時期內,在給定的客戶端從新註冊以前或者slave_reregister_timeout被觸發,嘗試調試在這個客戶端上面的任務狀態將不會反回任何信息(由於master還不能確切知道任務狀態)

若是一個客戶端在必定時間 (controlled by the --slave_reregister_timeout configuration flag),內沒有從新註冊到新的master上,master會標記這個agent爲失效而且和上面說的失效流程處理相同。可是,有一個不同,默認狀況下,客戶端被容許重連到失效的master節點,即便在slave_reregister_timeout被觸發後。也就是說,framework可能看到TASK_LOST 的任務狀態更新,可是過一會發現任務其實在跑(覺得這個客戶端是容許重連的)。這個行爲能夠避免,經過容許--registry_strict 這個選項。這個選項在未來的Mesos版本中,會變成默認值。

相關文章
相關標籤/搜索