天天看點

将已有應用程式遷移到Mesos上(Part 2)

作者簡介:David Greenberg是Two Sigma公司的首席架構師,他負責公司交易戰略的分布式計算環境。他也是Cook的設計師,Cook是一個開源的Mesos架構,用來做搶占式作業的排程。

譯者簡介:崔婧雯,現就職于IBM,進階軟體工程師,負責IBM業務流程管理軟體的系統測試工作。曾就職于VMware從事桌面虛拟化産品的品質保證工作。對分布式叢集管理,虛拟化,業務流程管理都有濃厚的興趣。

本文節選自《用Mesos架構建構分布式應用》第三章,以下内容承接“将已有應用程式遷移到Mesos上(Part 1)”。

搭建Marathon上的HAProxy

我們在上文中已經學習了Marathon,并且一起體會到為什麼說Marathon是應用程式的絕佳平台。至此,應用程式已經能夠在Marathon上運作了,但是還有一個問題:外部世界是如何真正連接配接到應用程式上去的呢?一些類型的應用程式,比如Celery或者Resque worker,不需要任何額外的配置:它們通過共享資料庫通信。其他類型的應用程式,比如HTTP伺服器和Redis執行個體,需要確定其很容易被發現。在Mesos叢集裡解決這個問題的最流行方式是在靜态,非Mesos管理的主機上運作代理,并且自動更新這些代理,将其指向應用程式運作着的執行個體。這樣,應用程式在已知主機和端口(也就是代理)上持續保持可用,同時仍然可以在背景動态擴充其能力。另外,每個代理主機都能夠服務很多應用程式,每個應用程式放在不同的端口上,這樣少量的代理主機就能夠運作上百個背景程式。通常來說,如果代理提供SSL終止功能,它會受所有活躍連接配接的總帶寬,或者CPU使用總量的限制。(SSL終止功能是當用戶端通過安全SSL連接配接和代理通信時,代理會處理SSL,這樣背景無須在加解密上浪費CPU資源,甚至無須支援加解密。)

有兩種代理無疑是現代應用程式棧使用最多的方案:HAProxy和Nginx。HAProxy是功能很有限的代理:它能夠代理HTTP和TCP連接配接,執行基本的健康檢查,并且提供SSL終止功能。它是為穩定性和性能而建構的:HAProxy在13年裡都沒有出現任何崩潰或死鎖問題。這也正是現在HAProxy在Mesos使用者中如此受歡迎的原因。

與之對比,Nginx擁有很多特性。除了作為代理,它還能夠運作自定義的,用Lua、JavaScript,或者基于JVM的語言編寫的使用者代碼。這些代碼可能會影響代理的操作,甚至能夠直接作出響應。很多系統實際上使用這兩種代理:用戶端連接配接到HAProxy執行個體上,随後HAProxy将請求轉發給Nginx執行個體。Nginx執行個體随後要麼直接回複,要麼發送到背景處理請求的伺服器上。

本節僅僅讨論HAProxy,但是如果需要使用Nginx所提供的額外功能,那麼要知道Nginx也完全可以按照本節介紹的方式使用。

haproxy-marathon-bridge:在Marathon存儲庫裡,有一個名為bin/haproxymarathon-bridge的腳本。該腳本意圖為Marathon生成一份HAProxy的配置檔案。不幸的是,它并不允許使用者指定Marathon上服務的哪個端口會綁定到HAProxy主機上。是以,該腳本基本沒什麼用。

下文介紹搭建Mesos代理的最為流行的配置。

Bamboo

Bamboo是一個帶有web接口的HAProxy配置背景程式。它提供UI來檢視以及管理HAProxy規則的目前狀态。Bamboo的核心功能是監控Marathon上應用程式的更改,并且保證HAProxy執行個體的背景程式使用的是最新版本。Bamboo還提供一些有用的特性,所有這些都通過web接口和HTTP REST API暴露出來。

最重要的是,Bamboo支援為每個Marathon應用程式使用HAProxy ACL規則。ACL規則能夠基于其URL、cookie、頭資訊和其他因素來路由請求。比如,可以使用ACL規則将路徑由/static開頭的請求路由到處理靜态内容的背景程式,同時将所有其他請求路由到應用程式伺服器。ACL規則相當強大,因為它們允許使用者将自己的應用程式分隔成獨立的元件或者服務,進而分别擴充這些元件,同時暴露給用戶端的URL仍然是唯一的。使用ACL規則,使用者可以選擇将匿名訪客路由到某個伺服器池,登入使用者路由到另一個伺服器池,并且将靜态資料請求路由到第三個伺服器池,進而可以單獨擴充這些伺服器池的能力。

Bamboo還有一個強大的模闆系統,基于GO語言的text/template包。該模闆系統很靈活,但是和更簡單更流行的系統,比如mustache模闆相比,其學習曲線更陡峭一些。

所有代理配置資訊都存儲在ZooKeeper裡,這樣可以通過保證Bamboo所有執行個體的同步來簡化配置管理。

Bamboo使用Marathon事件總線來發現背景配置的變更,這意味着HAProxy配置在Marathon上的變更通常僅僅會延時數百微秒。

另外,Bamboo能夠和StatsD內建,進而報告配置事件發生的時間。

Bamboo為Marathon應用程式的精确HAProxy配置提供了完備的方案。

微服務的HAProxy

如今,微服務是一種非常流行的架構模式。Mesos和Marathon是建構基于微服務的應用程式的堅實基礎:使用者可以在Marathon上托管所有的服務。不幸的是,服務發現是微服務部署時必須要解決的一個重要問題。下文介紹如何使用Mesos和Marathon建立類似于SmartStack的系統。

這裡需要考慮兩個問題:如何做服務發現?标準方案的問題是什麼?标準方案包括:

  • DNS

    可以選擇使用輪詢DNS來給所有背景伺服器相同的DNS名稱。但是這裡會遇到兩個問題:通常需要花費至少幾秒鐘才能在整個基礎架構上完成DNS的變更,而且一些應用程式會永遠緩存DNS解析(意味着這些應用程式永遠不會知道DNS的變更)。另一個問題是,除非使用者編寫自定義的使用SRV記錄的用戶端庫函數,否則DNS并不能提供簡單的方案在同一個伺服器上運作多個應用程式,并且讓這些應用程式使用不同或者随機配置設定的端口。

  • 中央化的負載均衡

    這一點類似于“Bamboo”小節所讨論的問題。對于一些應用程式而言,這的确是個偉大的設計,但是,該方案要求全局可通路的負載均衡器池。這樣的中央化讓應用程式的安全隔離工作顯得很枯燥:為了隔離應用程式,使用者必須為特定的隔離需求配置Nginx或者HAProxy規則。(另一種方案,DNS和應用内發現,将通信直接委托給每個應用程式,這樣就無須為隔離而配置任何中央系統。相反,每個應用程式能夠在和其他應用程式完全隔離的情況下,處理認證授權。)

  • 應用内發現

    Twitter和Google這樣的公司使用特别定制的服務請求和發現層,使用的分别是Finagile和Stubby。這些RPC層将服務發現直接內建進應用程式内,在需要找到可以發送請求的伺服器時,查詢ZooKeeper或Chubby(Google内部的類似ZooKeeper的系統)。如果可以在環境裡這麼實作,那麼使用特别定制的服務發現層能夠給路由、負載均衡和可靠性方面提供最大的靈活度,因為使用者可以控制該系統所有方面的細節。不幸的是,如果需要和用多種語言編寫的應用程式內建,就會變得很麻煩并且很費時間,因為需要為每種語言開發平行的發現系統。此外,如果需要和已有的,沒有遵守内建服務發現機制開發的應用程式內建的話,該方案則完全不可行。

上述這些方案的缺點導緻很多工程師選擇了第四種模式:聯合中央化負載均衡的易于內建的特點和去中央化方案的容錯特點的方案。使用該方案,使用者會在資料中心裡的每台單獨機器上運作一個HAProxy的副本,然後給每個應用程式配置設定一個端口(不是主機名)。最後,将所有HAProxy執行個體都分别指向其背景應用程式的端口,無論這些背景程式運作在叢集的什麼位置。

這一方案有兩大優勢:

  • 易于搭建

    使用者可以在叢集内每台機器上使用Bamboo或者一個簡單的cron作業來保持HAProxy本地執行個體和Marathon的同步。即使基礎架構的某些部分暫時不可用,本地HAProxy也會繼續将路由流量直接發送給背景程式。也就是說,即使Marathon崩潰了,也不會影響到應用程式的營運。

  • 易于使用

    每個應用程式都可以簡單地連接配接到localhost:$PORT和其他微服務通信,這裡$PORT是配置設定給微服務的端口。不需要為應用程式編寫任何特别的或者自定義的代碼,因為所有需要做的事情就是記住哪個端口對應哪個應用程式而已。

該方案也有一些缺陷。其中之一是使用者需要仔細維護服務到端口的映射。如果使用者嘗試全局存儲這樣的映射,讓應用程式在啟動時讀取映射資訊,那麼就必須再次為每種語言編寫自定義代碼。另一方面,如果本身寫死了端口,就等于自挖陷阱,出現問題時調試會非常困難。

另一個缺陷是代理間缺少協調。即使發生局部故障,系統還會繼續工作,因為每台機器都是獨立操作的。也正是由于每台機器的獨立操作,可能某些HAProxy會路由到相同的背景程式上,進而加重這個背景程式的負載,造成層級故障。随着叢集内節點數的增加,經常會看到請求時間的方差也會随之增加。

如今,服務映射到端口,并且每個用戶端都連接配接到localhost的HAProxy上的方案似乎已經成為管理Mesos叢集上服務發現最為流行的方式了。

在Marathon上運作Mesos架構

Mesos叢集裡的常見方案是在Marathon上運作叢集的Mesos架構。但是Marathon本身就是一種Mesos的架構!那麼在Marathon上運作Mesos架構意味着什麼呢?不用考慮如何将每種架構的排程器部署到特定的主機上并且處理這些主機的故障,Marathon能夠確定架構的排程器總是在叢集裡的某處運作着。這樣大幅簡化了在高可用配置裡部署新架構的複雜度。

如何給由Marathon運作的架構配置設定資源?Mesos的新使用者通常都會問,“如果我在Marathon上運作一個架構,這會如何影響資源的配置設定呢?”實際上,雖然架構的排程器是由Marathon運作的,但是排程器仍然必須直接連接配接到Mesos上,并且排程器會以和在特定機器上直接運作它們完全一樣的方式接受資源。當然,在Marathon上運作排程器的優勢是任意Mesos slave上都能夠運作排程器,并且當slave發生故障時,Marathon能夠自動重新開機排程器。

Chronos是什麼

Chronos是一種Mesos架構,提供高可用性,分布式基于時間的作業排程器,比如cron。借助于Chronos,使用者能夠啟動指令行程式(可能是從URI處下載下傳的)或者Docker容器。和Marathon一樣,Chronos有web UI,以及易于程式設計的REST API。雖然Chronos端點和Marathon端點的接口有細微的不同,但是本書不會加以詳細介紹,因為線上文檔非常詳盡。Chronos提供了排程作業的四大核心特性:

  • 間隔排程

    Chronos使用标準ISO 8601注釋指定重複間隔。通過web UI或者REST API,使用者可以指定重新運作作業的頻率。這使得Chronos很适合每隔幾分鐘運作一次快速作業,或者運作夜間的資料生成作業。

  • 依賴跟蹤

    理論上,Chronos支援依賴性作業。依賴性作業僅僅在其前提條件成功運作之後才會運作。不幸的是,Chronos依賴性作業的實作實際上有些出入。在Chronos裡,如果父作業最近一次的調用成功了,那麼就認為滿足了該依賴性作業的前提條件。隻要依賴性作業的所有前提條件都至少運作過一次,那麼這個依賴性作業就會運作。這意味着除非每個父作業的運作間隔嚴格一緻,否則這個依賴性作業可能就會在非預期時間運作。本書“Chronos運維注意事項”部分會詳細介紹這個問題的正常處理政策。

  • 延遲啟動

    Chronos也能夠用來運作一次性的或者在未來的某個時間點重複間隔地執行作業。當指定重複執行作業的ISO 8601間隔時,還可以指定希望什麼時候首次運作該作業。這意味着使用者可以使用Chronos在未來的每天、每周或者每月排程作業的執行,這很有助于做計劃。

  • worker可擴充性

    Chronos和大多數其他作業排程器的關鍵差別在于Chronos在Mesos上的容器内部運作其作業。這意味着作業是互相隔離的,worker是可擴充的,是以無論Chronos生成什麼樣的負載,使用者都能夠添加新的Mesos slave來處理額外的工作,并且確定作業能夠接收到所需資源。

和所有可以用于生産環境的Mesos架構類似,Chronos通過熱備支援高可用性——大多數Chronos的部署都會運作至少兩個排程器的執行個體,來確定即使排程器或者其主機發生故障時,Chronos也永遠不會掉線超過幾秒鐘。Chronos還帶有一個同步工具,chronos-sync.rb,使用者可以通過将檔案送出到版本控制系統裡,将要在叢集裡運作的作業版本化。這是確定可重複性而使用最多的方案,因為這樣做允許使用者在存儲庫裡儲存Chronos配置。

在Marathon上運作Chronos

Mesos架構部署裡最常見的技術之一是在Marathon上運作架構排程器。這麼做是因為這些排程器可以依賴Marathon來確定它們一直在某處運作着。這給運維人員減輕了大量負擔,否則運維人員需要確定每個排程器都有良好監控,并且部署在多台機器上。

為了可以在Marathon上部署,排程器必須實作一定程度上的選主。在第4章裡會介紹,排程器是從單台主機連接配接到Mesos上的。也就是說,如果想在兩個地方運作排程器(比如,有一個熱備),使用者需要給出某種類型的信号確定某個時間點隻有一個排程器在運作。最常見的方式是使用ZooKeeper來解決這個問題,因為ZooKeeper帶有一個簡單內建的選主元件(細節見“加入高可用”部分)。Marathon和Chronos都是采用的這種方案。

讓我們一起看看Marathon上啟動Chronos的樣例JSON表達式(示例3-16)。為了最大化端口配置設定的效率,允許Chronos綁定任意端口。要連接配接到Chronos上,要麼在Marathon的UI上點選,要麼使用之前介紹的HAProxy服務發現機制之一。

示例3-16 Chronos JSON描述符

{
    "cmd": "java -jar chronos.jar -Xmx350m -Xms350m ---port $PORT0",
    "uris": [
        "http://fetchable/uri/with/chronos.jar"
    ],
    "cpus": , 
    "mem": , 
    "instances": , 
    "id": "chronos",
    "ports": [], 
    "constraints": [["hostname", "UNIQUE"]]
}
           
  • 假定所有Mesos slave上都已經安裝了Java。是以隻需要将動态配置設定的端口傳遞給Chronos,它就能成功啟動了。
  • 與其在每台Mesos slave上都安裝Chronos,不如将其.jar檔案存儲到某個已知位置。這樣.jar檔案會被動态下載下傳到被配置設定運作Chronos排程器的任意slave上,進而簡化部署的複雜度。
  • 選擇比對允許JVM配置設定的記憶體總量(為JVM本身預留了34MB的headroom)的容器大小。
  • 運作Chronos兩個執行個體就可以實作幾乎即時的故障轉移,因為備用Chronos排程器也會一直運作着。
  • Chronos僅僅需要配置設定一個端口。
  • 使用UNIQUE主機限制,確定備用Chronos執行個體運作在不同的機器上。如果slave有屬性指定每個slave所在的機架,最好将排程器及其熱備運作在不同的機架上。

驗證Chronos在運作的最簡單方式是從Marathon應用程式視圖裡點選配置設定的端口數量。每個任務的端口配置設定都是一個主機和端口的組合連結,點選會加載Chronos UI。Chronos UI有些已知的問題,是以推薦使用curl或者chronos-sync.rb來配置Chronos執行個體。

Chronos運維注意事項

Chronos是Mesos生态系統的重要一環,但是,要注意不能過度依賴它。在生産環境裡運作Chronos時需要注意以下事項:

  • 依賴性作業的特性并沒有什麼用——一定要使用工作流管理器。
  • Chronos仍然是一個複雜的分布式系統——隻有當需要在容器裡可擴充地運作作業時才有必要使用。

幾乎沒有人使用Chronos依賴性作業的特性。相反,大多數人使用Chronos來排程流行的資料工作流工具的調用。對于簡單工作流(比如順序運作一些流程)而言,Bash腳本是常用的方案,但是,如果超過20行的話,Bash腳本就會很笨重,對于複雜循環和條件的文法支援也很弱。make是另一種表達依賴關系的流行方式,因為其支援工作流的進階文法,并且支援基本的并行機制。Luigi是功能更為豐富也更為強大的工作流管理器。它支援HDFS和資料庫裡的檢查點,可以改進中間節點失敗作業重試的效率,因為不需要重做檢查點之前的工作。無論你的特别需求和用例是什麼,都必須使用一些其他工具來管理Chronos負責排程的作業的執行順序。

如果已經完成了所有上述搭建,就幾乎已經可以在生産環境使用Chronos了!最後需要考慮的是,是否真的需要Chronos從Mesos得到的可擴充隔離性。即使已經運作着一個Mesos的叢集,也并不一定需要使用Chronos來做任務管理。有很多其他作業排程伺服器在Marathon上能夠更容易地運作,僅僅在每個作業都運作在自己的容器裡時才需要使用Chronos。

Marathon上的Chronos:小結

Chronos是一個強大的工具,幫助Mesos叢集實作可靠性,可擴充性以及基于間隔的作業排程。它在很多公司(包括Airbnb)裡幫助強化了資料生成流程。要記住本書介紹的一些略顯怪異的模式、變通方法以及建議!

Marathon上的Chronos僅僅是一個例子,展示了Marathon如何提供高可用以及如何簡化其他Mesos排程器的部署。一個商業化的Mesos産品——DCOS,在該領域更進一步,要求所有DCOS上的架構都由Marathon托管。不管部署的是Chronos、Kafka還是Cotton、Marathon,都是托管其他Mesos架構排程器的絕佳選擇。

Marathon+Chronos的備選方案

當然,Marathon(和Chronos)無法滿足所有的叢集需求。在本節中簡單看看其他兩種流行的Mesos PaaS架構:Aurora和Singularity。這兩種架構學習曲線都更為陡峭,但是它們也提供了更多額外的特性。

Singularity

Singularity是HubSpot開發的一個Mesos架構。它提供了像Marathon一樣的部署服務的能力(包括Docker化的應用程式)。在這之上,如果某個服務在部署後無法通過其健康檢查,Singularity會自動将部署復原。和Chronos類似,Singularity也支援重複性作業,以及一次性作業,可以通過REST API觸發。這樣的設計簡化了給任何服務或者重複性作業添加容器化,異步背景的處理過程。在管理服務發現和代理方面,Singularity和另一個稱為Baragon的工具內建,Baragon管理并且內建HAProxy、Nginx以及Amazon的Elastic Load Balancer。

Aurora

Aurora是Twitter開發的Mesos架構。Aurora帶有由Python編寫的特别先進的作業描述API。這個API,稱為Thermos,允許使用者指定如何建構并且安裝在Mesos執行器裡運作的應用程式,以及工作流和流程式列。Aurora有高性能的分布式服務發現API,支援C++、Java和Python的綁定。能夠運作cron風格文法的重複性作業。和Singularity類似,Aurora還能夠自動檢測什麼時候服務的健康檢查開始失敗,然後復原到之前工作的版本。Aurora最為強大的特性是多租戶控制:Aurora允許一些任務使用空閑的叢集能力,并且随後在需要排程高優先級生産任務時将這些任務取代。還可以在使用者間強制使用quotas。這些特性都來自于在大規模Mesos叢集上運作由上百個開發人員編寫的海量應用程式的企業需求。如果你為之建構Mesos叢集的企業聽上去屬于這一類型,那麼便值得深入研究Aurora。

本章小結

本章學習了如何使用Mesos建構标準、無狀态、基于伺服器的應用程式。并且建構出了自修複、自重新開機且十分簡單的服務發現——在Mesos建構了一個基本的PaaS!這些都是通過使用Marathon,一種流行的Mesos架構而實作的。

Marathon跨Mesos叢集啟動、監控,并且重新開機程序。它簡化了這一切,讓使用者點選按鈕就可以實作擴充伸縮,并且提供了很容易實作內建的JSON API。

本章首先介紹了如何啟動Marathon,如何保護它,以及如何確定其是高可用的。随後,介紹了如何編寫Marathon服務描述符,允許使用者啟動無處不在的SimpleHTTPServer。這僅僅是一個示例應用程式,任何其他應用程式都可以通過簡單變更指令行而啟動。還介紹了如何程式設計查詢Marathon上應用程式的狀态。

接下來,本書深入探讨Marathon上應用程式的擴充。最重要的是,讨論了位置限制,以及如何輕松確定應用程式運作在正确的slave機器組上,并且在機架間均勻分布。

Docker是最流行的應用程式容器化技術。本章介紹了如何在Marathon上花最小的代價啟動Docker化的應用程式,以及如何配置各種Docker特定的參數,比如加載主機磁盤。

如果不包含健康檢查、動推送和復原,應用程式就不足夠健壯。本章讨論了如何配置TCP、HTTP和基于指令行的監控檢查,以及在更新中如何指定應用程式的行為。還探讨了從Marathon裡如何建構自定義內建來訂閱某個事件流。

然後,學習Marathon和服務發現代理的內建。Bamboo是一種開源HAProxy配置管理器,是同步HAProxy和Marathon任務的強大工具。本章還介紹了使用HAProxy和Marathon建構可擴充、多語言微服務架構的流行方案。

最後,介紹如何使用Marathon托管其他Mesos架構的排程器,使用一種分布式,類似于cron的架構Chronos作為示例。還概覽了Marathon的可替代PaaS架構,這些架構提供了很多額外的特性(代價是學習曲線更陡)。

可能Marathon及其備選方案都不能滿足你的應用程式的需求,還需要對如何啟動程序,或者如何處理失敗等這些有更多的控制。這樣的話,就需要編寫自己的架構。下一章會介紹建構Marathon的技術,這樣大家就可以建構出屬于自己的自定義Mesos架構。

将已有應用程式遷移到Mesos上(Part 2)

《用Mesos架構建構分布式應用》

由CSDN主辦的中國雲計算技術大會(CCTC 2017)将于5月18-19日在北京召開,Spark、Container、區塊鍊、大資料四大主題峰會震撼襲來,包括Mesosphere CTO Tobi Knaup,Rancher labs 創始人梁勝、Databricks 工程師 Spark commiter 範文臣等近60位技術大牛齊聚京城,為雲計算、大資料以及人工智能領域開發者帶來一場技術的盛大Party。現在報名,隻需599元就可以聆聽近60場的頂級技術專家分享,還等什麼,登陸官網,趕快報名吧!
将已有應用程式遷移到Mesos上(Part 2)

繼續閱讀