从HashiCorp Nomad对上百万容器进行调度所学到的经验
?
Docker在2013年三月實現了開源發布,它的出現讓軟件開發行業對于現代化應用的打包以及部署方式發生了巨大的變化。緊隨著Docker的發布,各種具有競爭性、致敬性以及支持性的容器技術紛紛涌現,為這一領域帶來了極大的關注度,同時也引起了人們的反思。這一系列文章將解答讀者的各種困惑,對如何在企業中實際使用容器進行分析。
這一系列文章首先將對容器背后的核心技術進行觀察,了解開發者目前如何使用容器,隨后將分析在企業中部署容器的核心挑戰,例如如何將容器技術與持續集成和持續交付管道進行集成,并對監控方式進行改進,以支持不斷變化的負載,以及使用短期容器的潛在需求。本系列文章的總結部分將對容器技術的未來進行分析,并探討無核化技術(unikernels)目前在處于技術前沿的組織中所扮演的角色。
本文是本系列文章“實際應用中的容器 —— 遠離炒作”中的其中一篇。你可以通過RSS訂閱該系列文章,以獲取更新的通知。
高效的調度器需要具備三種品質。第一項是能夠滿足多個開發團隊要求同時部署應用的需求。第二項是能夠快速地在跨全球的基礎設施范圍內分發應用。最后一項則是重新調度應用程序,讓有故障的節點重新成為健康的節點,提供集群范圍的應用程序可用性管理,以及自恢復的能力。、以Nomad、Mesos和Kubernetes為代表的調度器的目標是讓組織能夠以更快的步調部署更多的應用程序,同時提高資源的使用率。調度器可將應用程序與基礎設施進行分離,因此在一個host上可運行多個應用,而不再受到一個host僅運行一個應用的限制。這就提高了集群中資源的利用率,并節省基礎設施方面的成本。
由HashiCorp的設計的百萬級容器挑戰(Million Container Challeng)是用于檢測其調度器產品Nomad在5000個host上對100萬容器進行調度的效率的一種測試手段。這一挑戰的目的是觀察Nomad在超大規模部署的情況下的表現,并對其進行優化。現代化企業配備的數據中心規模之大是前所未有的,他們所使用的工具也必須滿足客戶的需求。在完成這一測試并進行了性能優化之后,Nomad在Google Cloud上可做到在5分鐘之內對跨5000個host上的100個容器進行調度。本文將描述從對100萬個容器進行調度的實現中所學到的知識。
(點擊放大圖像)
樂觀并發調度器能夠以線性增長率擴展調度的吞吐量
調度器一般來說可以分為三個類別:集中式(monolithic)調度器、基于offer的調度器,以及狀態共享(shared state)調度器。集中式調度器在一個單一的、中心化的地方處理調度邏輯,通常會綁定在一臺單一的機器上。基于offer的調度器(例如Mesos)同樣在一個單一的地方進行調度決策,但可以通過將資源分配給多個各自具備任務的框架而實現并行化。而狀態共享調度器則在多個地方處理調度決定,通過并發控制,以并行方式進行調度而獲得統一的狀態。
Nomad是一種樂觀并發的共享狀態調度器,這意味著所有服務器都可以并行地參與調度決策。主節點將提供額外的協調功能,這是實現并發決策,并確保客戶端不會產生過量訂閱所不可缺少的。在這次百萬級容器挑戰中,共有5臺Nomad服務運行在Google Cloud上的n1-standard-32實例上,形成了一個CPU總數達到160的Nomad服務器集群。主節點使用了一半的CPU核進行調度工作,因此總共可以并行進行140個調度決策。這種并行性使得Nomad能夠在總時間5分鐘的挑戰中做到每秒大約對3750個容器進行調度。
在對Nomad的設計進行分析之前,有必要解釋一下Nomad的術語:作業(job)是指對提交至調度器的某項工作的聲明,而作業是由多個任務(task)所組成的。一個任務即是指將要運行的應用程序,在這示例中即表示通過一個Docker容器運行一個簡單的Go服務。
Nomad的樂觀并發設計受到了Google?Omega的啟發,后者引入了并發、共享狀態、以及無鎖樂觀并發控制等方式,以應對在其上一代調度器Borg中所遇到的挑戰。并發性使調度器實現了伸縮性,體現在為大量任務(容器或應用程序)找到居所,以及為多個開發團隊提供服務。多個開發團隊可同時提交作業,而調度器則能夠并行地處理這些作業的任務。對于那些無法實現并行調度的調度器來說,一旦某個團隊提交了一項作業,就會阻塞其他團隊同時對其他作業進行調度的操作。在像Google這樣規模的公司中,開發者提交作業以及機器獲取作業的數量都是非常龐大的,因此這種類型的并行設計就顯得非常關鍵。Nomad的出現受益于一些最新的研究成果,它最終為開源社區帶來了一個頂尖水準的調度器。
(點擊放大圖像)
如果讀者想了解Nomad的調度設計的更多信息,請閱讀開源網站上對其架構詳細的描述。
貪心調度算法與擴散調度算法之間的權衡
調度算法共有兩種主要的算法,即貪心(bin pack)算法與擴散(spread)算法。Nomad所使用的是貪心算法,這意味著它會嘗試用盡當前節點的全部資源,隨后再將新的任務傳遞至某個不同的節點。與之相反,擴散算法會盡量保證所有節點的使用率保持均衡。貪心算法的優點在于它可支持更多不同的工作量,最大化資源的利用和使用率,這最終將使基礎設施的成本降至最低。而擴散算法的優點在于它能夠將風險進行分散,如果某臺機器產生了故障,該算法可減少響應及恢復的復雜性。如果某臺機器僅運行一至兩個任務,那么為這些任務找到新的節點非常容易。與之相反,如果某個發生故障的機器運行著200個任務,那么調度器就必須為這200個任務找到新的位置。
使用貪心算法時,隨著節點上處理的任務越多,之后的任務就越有可能匯聚到這個節點上,直到這臺機器的能力達到極限為止。這種方式確保了某個節點將最大化地處理任務,之后調度器才會將新的任務發送至某個新的節點上。此外,如果需要為某個占用大量資源的任務找到合適的節點,這種方式也能更方便地找到一個具有足夠可用資源的節點,也能夠更方便地關閉某些沒有使用的機器。
簡單的作業規范使對作業提交的管理具有可伸縮性
使調度器具備對上百萬容器進行調度的能力只是整個挑戰中的一部分。另一個挑戰在于能否讓開發者方便地提交大規模的作業。Nomad的作業規范采用了一種聲明式的風格,非常易于使用。
在下面這個示例中,“bench-docker-classlogger”這個作業在定義中表示它希望Nomad能夠為“classlogger_tg_1”這個任務組調度20個實例,在該任務組中包含了“classlogger_1”這個任務。這個任務對應著一個Docker鏡像,它需求20MHZ的CPU、15M的內存以及10M的磁盤空間。當這個作業被提交至Nomad后,它會在整個服務器集群中調度20個可用資源的實例,在這些位置運行20個Docker鏡像。如果實例數量從20提升至50,那么Nomad只需再調度30個任務即可。
作業的規范還允許開發者對于任務可在何種類型的host上進行調度加以限制。舉例來說,某個開發者希望將某些任務限制在Windows機器上、某個規格的機器、或將所有作業分散在不同的host上運行。最后,重啟策略這部分定義了Nomad如何對失敗的任務進行重啟。在這個示例中,該Nomad作業設置了一個重啟管理器,可防止某個任務在5分鐘內重啟超過3次。
job "bench-docker-classlogger" {datacenters = ["us-central1"]group "classlogger_tg_1" {count = 20constraint {attribute = "${node.class}"value = "class_1"}restart {mode = "fail"attempts = 3interval = "5m"delay = "5s"}task "classlogger_1" {driver = "docker"config {image = "hashicorp/nomad-c1m:0.1"network_mode = "host"}resources {cpu = 20memory = 15disk = 10}}} }重要的是,作業規范是聲明式的,它定義了被提交作業的理想狀態。用戶只需表示需要運行該作業,而無需表達應當在何處運行該作業。Nomad的職責是確保實際的狀態滿足了用戶所設想的狀態。這就使對大型群集與大量作業提交的管理變得簡單許多,因為用戶不必再設法讓實際狀態去匹配理想狀態,Nomad已經自動地完成了這一工作。
無論是在開發者還是機器在層面,可伸縮性都是必須考慮到的部分。在機器層面上,Nomad的樂觀并發設計使大規模化變得可能。而在開發者或組織層面上,簡單的作業規范使作業的提交很容易實現大規模化。
在進行大規模的容器調度時,服務發現是必不可少的
要使在5000個host上調度100個容器的能力體現出實用性,你必須做到在這些容器已確定位置后發現他們的具體位置。從邏輯上說,以手動方式對這種規模的服務配置進行更新是不可能的,因此必須借助自動化方案的力量。
以HashiCorp的Consul或ZooKeeper為代表的服務發現工具使服務能夠將自身與他們的地址注冊在某個中央注冊表中。群集中的其他服務則通過這個中央注冊表發現他們所需要連接的服務。舉例來說,如果在30個host上調度了50個API的任務,那么每個任務都會它將的地址與端口注冊在服務注冊表中。群集中的其他服務則可以通過這個注冊表查詢這50個實例的地址與端口,以用于配置及負載均衡。如果某個任務失敗了,調度器就可以在不同的地址重新調度它,這個新的地址會在服務注冊表中進行更新,整個集群都將收到這個變更信息。而如果某個host產生了故障,調度器就需要改變運行在該host上的所有任務的地址,這些任務都需要在服務注冊表中更新他們的信息。
在大規模環境中,一個基于調度器的應用交付工作流更能表現出高度的動態能力。作業的調度能力只是應用交付中的一項挑戰而已,整個系統需要具備健壯的服務發現、健康檢查以及配置信息,以確保系統的整體處于健康狀態。Consul或ZooKeeper這樣的服務發現工具對于這些動態系統的維護可謂至關重要。
調度器帶來了應用與組織層面上的大規模化
在進行測試的過程中,Nomad也進行了一些技術改進。我們對基數樹進行了優化,以進一步提升調度器的性能。我們還為調度器加入了一些健壯的特性,例如重試,以及設定了分配的上限,以應對Docker崩潰的情況。我們也克服了libcontainer中的某些奇怪行為,該問題產生于在單一節點上運行大量容器的情況下。我們將以上這些難以重現的條件都添加至Nomad,任何用戶都可以通過最新版本的Nomad重新進行這些測試。容器仍然是一種新興起的技術,這也是為什么Nomad選擇通過VM、chroot(2)與raw-exec中支持容器化的原因。
跨基礎設施進行高速調度的實用性不僅體現在集群的大規模化上。大多數公司都設置了大量的團隊或組織,他們需要對資源展開競爭。傳統的方法是為每個組創建唯一的、分段的集群。雖然這種方式確實提供了隔離性,防止了出現交集的情況,但它往往會導致每個團隊的集群利用率不足。
通過將單一集群中的資源作為池提供,公司就能夠統一并簡化他們的基礎設施,同時為團隊提供了更大的靈活性。如果某個團隊在某一時刻需要使用更多的資源,他們就可以將這部分工作快速地擴展至集群中未使用的部分。正是快速的、集群范圍的資源部署才使得這一點成為可能。
能夠在5分鐘之內對100萬個容器進行調度的能力可解決絕大部分企業在可伸縮性方面的要求。Nomad還將繼續進行性能改進,但這種改進將是邊緣性的,其規模會越來越小。除了性能上的可伸縮性之外,組織上的可伸縮性則是下一個挑戰。能夠應對quota、安全性、charge back更多問題的特性將使調度器工作流更易于在大型組織中得到應用。
關于作者
Kevin Fishner在HashiCorp擔任客戶成功總監,他在為客戶提供HashiCorp的各種開源與商業產品方面有著豐富的經驗。雖然他目前是一位工程師,但在求學期間主攻的卻是哲學專業。可通過@KFishner訪問他的Twitter。
?
Docker在2013年三月實現了開源發布,它的出現讓軟件開發行業對于現代化應用的打包以及部署方式發生了巨大的變化。緊隨著Docker的發布,各種具有競爭性、致敬性以及支持性的容器技術紛紛涌現,為這一領域帶來了極大的關注度,同時也引起了人們的反思。這一系列文章將解答讀者的各種困惑,對如何在企業中實際使用容器進行分析。
這一系列文章首先將對容器背后的核心技術進行觀察,了解開發者目前如何使用容器,隨后將分析在企業中部署容器的核心挑戰,例如如何將容器技術與持續集成和持續交付管道進行集成,并對監控方式進行改進,以支持不斷變化的負載,以及使用短期容器的潛在需求。本系列文章的總結部分將對容器技術的未來進行分析,并探討無核化技術(unikernels)目前在處于技術前沿的組織中所扮演的角色。
?
總結
以上是生活随笔為你收集整理的从HashiCorp Nomad对上百万容器进行调度所学到的经验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Docker网络和服务发现
- 下一篇: golang orm 框架之 gorm