本文討論了單個容器所無法解決的問題和局限性,本文介紹了容器編排的必要性和復雜性及常用工具的比較,提到了諸如Kubernetes, Mesos等容器管理工具
就像之前已被證實的那樣,要在一個機器上生成成千上萬個容器還是相對容易的。但你如何去部署成千上萬個容器呢?如何管理并且追蹤它們?如何管理、如何去做故障恢復?這些事情看似容易,但解決起來困難重重。讓我們來解析一下究竟難在何處。
用一個簡單的命令,就可以設立Docker環境,來跑一個Docker直到你將停其掉為止。但如果你需要在兩臺機器上跑Docker容器呢?如果50臺呢?或者如果1萬臺呢?現在,你可能會問為何要這么做。這里有一些好的理由:
1) 為了服務更多的用戶,你可能會遇到你Nginx網絡服務器縱向擴容的瓶頸,也就是說,在一個云供應商那兒使用一個更大的實例類型或者在你的披薩盒子里塞下更多的內存。如果你已經碰到那堵墻,你就會需要這么一個選項,可以橫向的擴容,典型性的就是采用代理服務器/冗余控制來作為服務穩定的切入口。
2) 另一個方面是容錯。如果你可愛的Redis容器停止存在了,該怎么辦?有可能是底下的機器死了?你會想要做故障轉移。在容器工作的情景下,這意味著你的編排器得在另一個健康的機器中重新啟動你需要運行的容器。
所以,這都取決于你的目標動機——容量、容錯或者兩者皆有——如果你有10個或者1千個機器,那挑戰就存在著:如何在這些不同的機器間有效率且有效果地進行容器擴容。
然而,在我們跨入這些挑戰之前,讓我們來理清一些術語。來自微軟和谷歌關于集群的研究表明了如下的工作量的區分:
1) 有一些長期在跑的服務,那應該一直在跑。那些通常是做交互、對延遲敏感的例如面向終端用戶的網絡應用這樣的任務;或者是底層的服務,類似于Cassandra, ArangoDB, HDFS, 或者 Quobyte。
2) 然后,就有一些批量任務,延續時間從幾秒到很多小時。他們通常對表現波動沒有那么敏感,然而可能存在例如像獨立管理等完成時間上的總體服務水平協議(SLAs)。
除了以上這些工作任務的類別區分,還想要支持工作優先度劃分:比如對業務尤為關鍵的、對頂層收入產生直接影響的生產性工作,以及非生產性工作比如質量測試、測試和研發這類。
從一個到兩個
把術語理清之后,讓我們直接來面對在超過一臺服務器上跑容器需要克服的挑戰。
最為基本的問題是:在一臺服務器上能裝下多少容器?我們發現,在bare metal上不同負載的測試表明每個機器容納250個容器是可能的,這是Docker daemon的潛在極限。對一個平均跑20個Docker鏡像的簡單的微服務構架的應用而言,產生大約10倍的容量(scale factor)。顯而易見,當你在一個機器上跑超過一個應用,這將會非常容易的降低到2倍。另外,資源消耗會產生一個自然的極限:比如,假設一個單獨的容器可能消耗內存的為100MB,對于一個32GB的內存(除去操作系統需要的2GB),那就留給我們3萬MB或者相當于300個容器。這比我們之前討論的極限要高的多。因此,即便在中等的負荷下,擴容顯得不可避免。
一旦當你跑了兩臺機器來服務你的容器,你需要關注以下事項:
1) 任何一個容器的健康情況是怎樣的?它是否還在運行、在服務,而且如果是這樣的話,它的核心健康數據(監控)是怎樣的?
2) 我到哪里能找到特定的那個容器?也就是說,在容器的邏輯ID和具體的(路由)IP之間能有一個匹配:端口匹配必須建立和保持,這也被稱為服務發現。
3) 應用版本和更新。不管何時當應用的一個新版本被部署時,Docker鏡像需要被傳遞到服務器上(即鏡像的實時性和信任)。
上述羅列的這些功能要求是在編排系統核心任務之外的,也就是如何來編排容器(或者,換句話說,來決定在哪臺機器上來跑容器)。盡管這個描述,是一個真實情況的簡略版,但它能幫助我們理解在多臺機器上跑容器的基本挑戰。對于兩臺機器來說,任何包括Docker Swarm, Kubernetes和Mesos的解決方案都適合;有了后兩個,盡管是可取的,但似乎也大材小用。直到你的應用被使用的非常厲害,而且當你添加到第三臺、第二十臺或者第487臺機器為止。那么,然后呢?
從兩個到多個
今年早些時候,谷歌發布了他們主要的生產集群管理的細節,Borg.
谷歌在10萬臺機器的區間內,他們中位數集群尺寸大約在1萬臺機器,也有一些更大的。谷歌稱,一個單獨的Borgmaster(其專有的分配集群的首腦)在一個cell(谷歌對于集群的術語)內能管理成千上萬臺機器。一個忙碌的Borgmaster使用10至14個CPU內核以及高至50GB的內存。另外,幾個cell有任務到達率在每分鐘1萬個任務以上。盡管不是每個人都是谷歌或者Twitter,在這個事情上,對于企業級別的需要應對成千上萬用戶或者一個流行的移動端應用即需要面對百萬數量級潛在的多進程用戶而言的復雜應用,還是非常容易會到達成百上千個機器的范疇。
在一個分布式系統內,去追蹤成千上萬件事情(進程、連接等)以及她們的狀態是一件很難的事情。真相的來源是什么呢?你是從中心的位置每隔一段時間去檢查一下嗎?你去跑代理來推送狀態到上游嗎?這些都是一些已經被討論了一陣的相關問題,比如從1990年代晚期以C10K問題的形式。
另外,跑成千上萬個容器(我們已經從上面描述知道了這需要成百上千的服務器)會給你一個分布式的系統,存在許多復雜的失敗模式:從超時引起的問題,到網絡劃分的問題,到CPU垃圾清理的問題或者是內存耗盡問題。最后的但不僅僅限于此的問題是,為了有效利用服務器,容器需要被以最有效的方式bin- packed;有一件特別難的事,尤其當要考慮到做兩種類型的任務(長時期跑的和批量的)和任務優先級劃分。你當然不想因為一個以周為單位的Spark批量任務以為它需要你集群中的一大塊兒,然后把你企業的應用給耗盡從而喪失每小時10萬美金的利潤。
總結一下,在集群層面上以最優方式來安排容器意味著要這么做:
1) 如果發生故障,你的服務要能繼續跑
2) 你的最大化利用要很嚴格、很動態
另外,故障處理,意味著確保發生故障后能重新安排,要潛在地把其他工作事先清空也是很難且動態的。我說“很難”和“動態”的意思是,這些需要很多計劃安排,而且我們在討論的是一個迅速且一直在變化的環境,這本身是計算機相對于人類而言擅長之初的完美例子。
現在,既然我們已經探索過了存在問題的空間,讓我們再來看一下解決辦法的空間。
Mesos滿足了以上列表的要求,很成熟,而且得益于它的兩層安排體系,也使得它極度靈活。和“一種尺寸適應所有情況”的單一安排體系不同的是,Mesos把實際工作分配決定委派給所謂專門的框架安排體系,而它自己則通過應用“專用資源公平算法”(Domain Resource Fairness algorithm,簡稱DRF算法)來關注資源抽象和管理。DRF算法本質上讓不同的工作得以公平地分享不同類型的資源(CPU、RAM等等)。
或許,對這個討論更為重要的是,Mesos可以線性擴容。早在2010年,在Mesos原始的技術報告中(精確的說,在6.5部分),在AWS上的一個有 99個EC2實例的集群進行了一個實驗,每個集群都有八個CPU內核和6GB的內存。在集群上跑有5萬個slave daemons,結果是一個線性的向上的增加(總在1秒以內),說明在主從daemon之間存在線性擴容的關系。
線性擴容是Mesos一個非常關鍵的特征,用來跑容器化的工作負載,不管是在某一個云環境中還是在一個混合的云設置中(比如:混合了在終端的云或者不同云提供商之間的云)。迄今為止,Mesos在這方面是唯一一個被證明有追蹤記錄的開源的社區項目(Twitter,Airbnb, Apple和50多個公司),我們未來也看看它會朝何處發展。
從谷歌10多年前在跑容器擴容方面學到的經驗(不管是Kubernetes中的pod概念還是基于谷歌Omega的優化方案),都已經引入了Mesos核心。從另外一方面來說,人們可以得益于使用Data Center Operating System,是Apache Mesos的商業版本,和Kubernetes和Swarm包一起使用。
我們會持續紀錄這方面的進展。要了解更多關于Mesos如何擴容,請繼續關注Next Platform。