原做: Abhishek Vermay, Luis Pedrosaz, Madhukar Korupolu, David Oppenheimer, Eric Tune, John Wilkeshtml
http://research.google.com/pubs/pub43438.htmljava
譯者: 難易 http://my.oschina.net/HardySimpsonlinux
Permission to make digital or hard copies of part or all of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for third-party components of this work must be honored.For all other uses, contact the owner/author(s). EuroSys’15, April 21–24, 2015, Bordeaux, France. Copyright is held by the owner/author(s). ACM 978-1-4503-3238-5/15/04. http://dx.doi.org/10.1145/2741948.2741964git
谷歌的Borg系統羣集管理器運行幾十萬個以上的jobs,來自幾千個不一樣的應用,跨多個集羣,每一個集羣有上萬個機器。web
它經過管理控制、高效的任務包裝、超售、和進程級別性能隔離實現了高利用率。它支持高可用性應用程序與運行時功能,最大限度地減小故障恢復時間,減小相關故障機率的調度策略。Borg簡化了用戶生活,經過提供一個聲明性的工做規範語言,名稱服務集成,實時做業監控,和分析和模擬系統行爲的工具。網絡
咱們將會展示Borg系統架構和特色,重要的設計決策,定量分析它的一些策略,和十年以來的運維經驗和學到的東西。架構
集羣管理系統咱們內部叫Borg,它管理、調度、開始、重啓和監控谷歌運行的應用程序的生命週期。本文介紹它是怎麼作到這些的。負載均衡
Borg提供了三個主要的好處:它(1)隱藏資源管理和故障處理細節,使其用戶能夠專一於應用開發;(2)高可靠性和高可用性的操做,並支持應用程序作到高可靠高可用;(3)讓咱們在跨數以萬計的機器上有效運行。Borg不是第一個來解決這些問題的系統,但它是在這個規模,這種程度的彈性和完整性下運行的爲數很少的幾個系統之一。框架
本文圍繞這些主題來編寫,包括了咱們在生產環境運行十年的一些功力。運維
Borg的用戶是谷歌開發人員和系統管理員(網站可靠性工程師 SRE),他們運行谷歌應用與服務。用戶以job的方式提交他們的工做給Borg,job由一個或多個task組成,每一個task含有一樣的二進制程序。一個job在一個Borg的Cell裏面跑,一個Cell是包括了多臺機器的單元。這一節主要講用戶視角下的Borg系統。
Borg Cell主要運行兩種異構的工做負載。第一種是長期的服務,應該「永遠」運行下去,並處理短期的敏感請求(幾微秒到幾百毫秒)。這種服務是面向終端用戶的產品如Gmail、Google Docs、網頁搜索,內部基礎設施服務(例如,Bigtable)。第二種是批處理任務,須要幾秒到幾天來完成,對短時間性能波動不敏感。在一個Cell上混合運行了這兩種負載,取決於他們的主要租戶(好比說,有些Cell就是專門用來跑密集的批處理任務的)。工做負載也隨着時間會產生變化:批處理任務作完就好,終端用戶服務的負載是以天天爲週期的。Borg須要把這兩種狀況都處理好。
Borg有一個2011年5月的負載數據[80],已經被普遍的分析了[68,26,27,57,1]。
最近幾年,不少應用框架是搭建在Borg上的,包括咱們內部的MapReduce[23]、flumejava[18]、Millwheel[3]、Pregel[59]。這中間的大部分都是有一個控制器,能夠提交job。前2個框架相似於YARN的應用管理器[76]。咱們的分佈式存儲系統,例如GFS[34]和他的後繼者CFS、Bigtable[19]、Megastore[8]都是跑在Borg上的。
在這篇文章裏面,咱們把高優先級的Borg的jobs定義爲生產(prod),剩下的是非生產的(non-prod)。大多長期服務是prod的,大部分批處理任務是non-prod的。在一個典型的Cell裏面,prod job分配了70%的CPU資源而後實際用了60%;分配了55%的內存資源而後實際用了85%。在$5.5會展現分配和實際值的差是很重要的。
一個Cell裏面的全部機器都屬於單個集羣,集羣是由高性能的數據中心級別的光纖網絡鏈接起來的。一個集羣安裝在數據中心的一座樓裏面,n座樓合在一塊兒成爲一個site。一個集羣一般包括一個大的Cell還有一些小的或測試性質的Cell。咱們儘可能避免任何單點故障。
在測試的Cell以外,咱們中等大小的Cell大概包括10000臺機器;一些Cell還要大不少。一個Cell中的機器在不少方面都是異構的:大小(CPU,RAM,disk,network)、處理器類型、性能以及外部IP地址或flash存儲。Borg隔離了這些差別,讓用戶單純的選擇用哪一個Cell來跑任務,分配資源、安裝程序和其它依賴、監控系統的健康並在故障時重啓。
(譯者:Cell其實就是邏輯上的集羣)
一個Borg的job的屬性有:名字、擁有者和有多少個task。job能夠有一些約束,來指定這個job跑在什麼架構的處理器、操做系統版本、是否有外部IP。約束能夠是硬的或者軟的。一個job能夠指定在另外一個job跑完後再開始。一個job只在一個Cell裏面跑。
每一個task包括了一組linux進程,跑在一臺機器的一個容器內[62]。大部分Borg的工做負載沒有跑在虛擬機(VM)裏面,由於咱們不想付出虛擬化的代價。並且,Borg在設計的時候還沒硬件虛擬化什麼事兒哪。
task也有一些屬性,包括資源用量,在job中的排序。大多task的屬性和job的通用task屬性是同樣的,也能夠被覆蓋 —— 例如,提供task專用的命令行參數,包括CPU核、內存、磁盤空間、磁盤訪問速度、TCP端口等等,這些都是能夠分別設置並按照一個好的粒度提供。咱們不提供固定的資源的單元。Borg程序都是靜態編譯的,這樣在跑的環境下就沒有依賴,這些程序都被打成一個包,包括二進制和數據文件,能被Borg安裝起來。
用戶經過RPC來操做Borg的job,大可能是從命令行工具,或者從咱們的監控系統($2.6)。大多job描述文件是用一種申明式配置文件BCL -- GCL[12]的一個變種,會產生一個protobuf文件[67]。BCL有一些本身的關鍵字。GCL提供了lambda表達式來容許計算,這樣就能讓應用在環境裏面調整本身的配置。上萬個BCL配置文件超過一千行長,系統中累計跑了了千萬行BCL。Borg的job配置很相似於Aurora配置文件[6]。
圖2展示了job的和task的狀態機和生命週期。
用戶能夠在運行時改變一個job中的task的屬性,經過推送一個新的job配置給Borg。這個新的配置命令Borg更新task的規格。這就像是跑一個輕量級的,非原子性的事務,並且能夠在提交後輕易再改回來。更新是滾動式的,在更新中能夠限制task重啓的數量,若是有太多task停掉,操做能夠終止。
一些task更新,例如更新二進制程序,須要task重啓;另一些例如修改資源需求和限制會致使這個機器不適合跑現有的task,須要中止task再從新調度到別的機器上;還有一些例如修改優先級是能夠不用重啓或者移動task的。
task須要可以接受Unix的SIGTERM信號,在他們被強制發送SIGKILL以前,這樣就有時間去作清理、保存狀態、結束現有請求執行、拒絕新請求。實際的notice的delay bound。實踐中,80%的task能正常處理終止信號。
Borg的alloc(allocation的縮寫)是在單臺機器上的一組保留的資源配額,用來讓一個或更多的task跑;這些資源一直分配在那邊,不管有沒有被用。allocs能夠被分配出來給將來的task,用來保持資源在中止一個task和重啓這個task之間,用來彙集不一樣jobs的tasks到同一臺機器上——例如一個web server實例和附加的,用於把serverURL日誌發送到一個分佈式文件系統的日誌蒐集實例。一個alloc的資源管理方式和一臺機器上的資源管理方式是相似的;多個tasks在一個alloc上跑並共享資源。若是一個alloc必須被從新定位到其餘的機器上,那麼它的task也要跟着從新調度。
一個alloc set就像一個job:它是一組allocs保留了多臺機器上的資源。一旦alloc set被建立,一個或多個jobs就能夠被提交進去跑。簡而言之,咱們會用task來表示一個alloc或者一個top-level task(一個alloc以外的),用job來表示一個job或者alloc set。
當有超量的工做負載在運行的時候會發生什麼事情?咱們的解決方案是優先級和配額。
全部job都有優先級,一個小的正整數。高優先級的task能夠優先獲取資源,即便後面被殺掉。Borg定義了不重疊的優先級段給不一樣任務用,包括(優先級降序):監控、生產、批任務、高性能(測試或免費)。在這篇文章裏面,prod的jobs是在監控和生產段。
雖然一個降級的task總會在cell的其餘地方找到一席之地。降級瀑布也有可能會發生,就是一個task降下來以後,把下面運行的task再擠到別的機器上,如此往復。爲了不這種狀況,咱們禁止了prod級task互相排擠。合理粒度的優先級在其餘場景下也頗有用——MapReduce的master跑的優先級比worker高一點,來保證他們的可用性。
優先級是jobs的相對重要性,決定了jobs在一個cell裏面是跑仍是等(pending)。配額則是用來決定jobs是否運行被調度。配額就是一組資源(CPU, RAM, disk)的數量在一個指定的優先級、一個指定的時間段(月這個量級)。數量決定了這個用戶的job能夠用的最多資源(例子:20TB內存和prod優先級從如今到7月在xx cell內)。配額檢查是管理控制的一部分,不是調度層的:配額不足的任務在提交的時候就會被拒絕。
高優先級的配額老是花費的比低優先級要多。prod級的配額是被限制爲一個cell裏面實際的資源量,因此用戶提交了prod級的job的配額時,能夠期待這個job必定會跑,去掉一些碎片外。即便這樣,咱們鼓勵用戶多買一點比本身須要多一點的配額,不少用戶超買是由於他們的應用程序的用戶數量增加後須要的配額就大了。對於超買,咱們的應對方案是低優先級資源的超售:全部用戶在0優先級均可以用無限的配額,雖然在實際運行中這種狀況很難跑起來。一個低優先級的job在資源不足時會保持等(pending)狀態。
配額分配在Borg系統以外,和咱們的物理資源計劃有關。這些資源計劃在不一樣的數據中心產生不一樣的價格和配額。用戶jobs只在有足夠配額和足夠優先級以後才能啓動。配額的使用讓Dominant Resource Fairness(DRF)[29, 35, 36, 66]不是那麼必要了。
Borg有一個容量系統給一些特殊權限給某些用戶,例如,容許管理員刪除或修改cell裏面的job,或者容許用戶區訪問特定的內核特性或者讓Borg對本身的job不作資源估算($5.5)。
光是建立和部署task是不夠的:一個服務的客戶端和其餘系統須要能找到它們,即便它換了個地方。爲了搞定這一點,Borg創造了一個穩定的「Borg name Service」(BNS)名字給每一個task,這個名字包括了cell名字,job名字,和task編號。Borg把task的主機名和端口寫入到一個持久化高可用文件裏,以BNS名爲文件名,放在Chubby[14]上。這個文件被咱們的RPC系統使用,用來發現task的終端地址。BNS名稱也是task的DNS名的基礎構成部分,因此,cc cell的ubar用戶的jfoo job的第50個task的DNS名稱會是50.jfoo.ubar.cc.borg.google.com。Borg同時還會把job的大小和task的健康信息寫入到Chubby在任何狀況改變時,這樣負載均衡就能知道怎麼去路由請求了。
幾乎全部的Borg的task都會包含一個內置的HTTP服務,用來發布健康信息和幾千個性能指標(例如RPC延時)。Borg監控這些健康檢查URL,把其中響應超時的和error的task重啓。其餘數據也被監控工具追蹤並在Dashboards上展現,當服務級別對象(SLO)出問題時就會報警。
用戶可使用一個名叫Sigma的web UI,用來檢查他們全部的job狀態,一個特殊的cell,或者深刻到某個job的某個task的資源用率,詳細日誌,操做歷史,和最終命運。咱們的應用產生大量的日誌,都會被自動的滾動來避免塞滿硬盤,會在一個task結束後保留一小段時間用來debug。若是一個job沒有被跑起來,Borg會提供一個爲何掛起的解釋,指導用戶怎麼修改這個job的資源需求來符合目前這個cell的狀況。咱們發佈資源的使用方針,按照這個方針來作就容易被調度起來。
Borg記錄全部的job提交和task時間,以及每task的資源使用細節在基礎存儲服務裏面。這個存儲服務有一個分佈式的只讀的SQL-like的交互式接口,經過Dremel[61]提供出來。這些數據在實時使用、debug、系統查錯和長期容量規劃上都頗有用。這些數據也是Google集羣負載追蹤的數據來源之一[80].
全部這些特性幫助用戶理解和debug Borg的行爲和管理他們的job,而且幫助咱們的SRE每一個人管理超過上萬臺機器。