此篇文章是《Using Docker》一書的作者 Adrian Mouat 編寫,詳細對比分析了Swarm、Fleet、K8s以及Mesos的區別。
大部分軟件系統是隨時間演進的,添加新的修改舊的功能,不斷變化的用戶需求意味著一個高效的系統必須能夠迅速擴展或收縮資源。為了達到接近零宕機的需求,通常在一個單獨的數據中心或區域需要自動地將故障轉移到預設的備份系統。
在此之上,一些大型企業經常會運行多個這樣的系統或是偶爾需要運行一些獨立于主系統的任務比如數據挖掘,但又需要現存系統內更多資源或通訊交互。
當使用多個資源時,重要的是確保他們得到有效地使用而不被閑置,但是還可以應對需求高峰。成本效益與迅速擴展的規模之前的權衡是困難的任務,但是可以用各種方式加以處理。
所有這一切都意味著一個非凡系統的運行充滿了各種管理任務、挑戰以及不應低估的復雜性。很快在個體層面一個接一個地修補和更新某個機器將變為不可能,他們必須同等對待。當一臺機器發生問題時,它應該被摧毀并更換,而不是調養修復后再上線。
當前有各種工具和解決方案能夠幫助解決這些挑戰,這里主要集中講解幾個編排工具,這些工具能幫助我們以集群方式在主機上啟動容器,并能夠彼此連接,同時也考慮到了擴展性和自動故障轉移的重要特性。
Swarm
Swarm是Docker的原生集群工具,Swarm使用標準的Docker API,這意味著容器能夠使用docker run命令啟動,Swarm會選擇合適的主機來運行容器,這也意味著其他使用Docker API的工具比如Compose和bespoke腳本也能使用Swarm,從而利用集群而不是在單個主機上運行。
Swarm的基本架構很簡單:每個主機運行一個Swarm代理,一個主機運行Swarm管理器(在測試的集群中,這個主機也可以運行代理),這個管理器負責主機上容器的編排和調度。Swarm能以高可用性模式(etcd、Consul 或ZooKeeper 中任何一個都可以用來將故障轉移給后備管理器處理)運行。當有新主機加入到集群,有幾種不同的方式來發現新加的主機,在Swarm中也就是discovery。默認情況下使用的是token,也就是在Docker Hub上會儲存一個主機地址的列表。
Fleet
Fleet是一個來自CoreOS的集群管理工具,自詡為“底層的集群引擎”,也就意味著它有望形成一個“基礎層”的更高級別的解決方案,如Kubernetes。
Fleet最顯著的特點是基于systemd(systemd提供單個機器的系統和服務初始化)建立的,Fleet將其擴展到集群上,Fleet能夠讀取systemd單元文件,然后調度單個機器或集群。
每個機器運行一個引擎和一個代理,任何時候在集群中只激活一個引擎,但是所有代理會一直運行,Systemd單元文件被提交給引擎,然后在 least-loaded機器上調度任務,單元文件會簡單運行一個容器,代理會啟動單元和報告狀態,Etcd用來激活機器間的通訊以及存儲集群和單元的狀態。
這個架構用來設計容錯的,如果一個機器宕機了,這個機器上的所有單元會在新的主機上被重新啟動。
Fleet支持各種調度提示與約束。在最基本的層面,單元的調度可以是全局的:一個實例將在所有機器上運行,或者作為一個單獨的單元運行在一臺機器上。全局調度對于如日志和監控容器任務非常實用。支持各種關聯類型約束,因此,例如規定在應用服務器上運行健康檢查的容器。元數據也可以連接到主機用于調度,所以你可以讓你的容器在某一區域或某些硬件設備上運行。
由于Fleet是基于systemd的,它也支持socket activation概念;容器可以綁定到一個給定端口的連接響應上。這樣做的主要優點是進程可以即時創建而不是閑置等待某些任務。有可能涉及到sockets管理的其他好處,如容器重啟的消息不丟失。
Kubernetes
Kubernetes是一個由google基于他們上個世紀容器產品化的經驗而推出的容器編排工具,Kubernetes有些固執己見對于容器如何組織和網絡強制了一些概念,你需要了解的主要概念有:
Pods – Pods是容器一起部署與調度的群體。Pods與其他系統的單一容器相比,它組成了Kubernetes中調度的原子單元。Pod通常會包括1-5個一起提供服務的容器。除了這些用戶容器,Kubernetes還會運行其他容器來提供日志和監控服務。在Kubernetes中Pods壽命短暫;隨著系統的進化他們不斷地構建和銷毀。
Flat Networking Space – Kubernetes的網絡是跟默認的Docker網絡不同。在默認Docker網絡中, 容器存在于一個私有子網絡中,它需要賺翻主機上的端口或者使用代理才能與其他主機上的容器通訊。在Kubernetes,pod中的容器會分享一個IP地址,但是該地址空間跟所有的pods是“平”的,這意味著所有pods不用任何網絡地址轉換(NAT)就可以互相通訊。這就使得多主機群集更容易管理,不支持鏈接的代價使得建立單臺主機(更準確地說是單個pod)網絡更為棘手。由于在同一個pod中的容器共享一個IP,它們可以通過使用本地主機地址端口進行通信(這并不意味著你需要協調pod內的端口使用)。
Labels – Labels是附在Kubernetes對象(主要是pods)上用于描述對象的識別特征的鍵值對,例如版本:開發與層級:前端。通常Labels不是唯一的;它們用來識別容器組。Labels選擇器可以用來識別對象或對象組,例如設置所有在前端層的pods與環境設置為production。使用Labels可以很容易地處理分組任務,例如分配pods到負載均衡組或者在組織之間移動pods。
Services – Services是通過名稱來定位的穩定的節點。Services使用label選擇器來連接pods,比如“緩存”Service可以連接到標識為 label選擇器“type”為“redis”的某些“redis”pods。該service將在這些pods之間自動循環地請求。以這種方式,Services可用于連接一個系統各部件。使用Services會提供一個抽象層,這意味著應用程序并不需要知道他們調用的service的內部細節,例如pods內部運行的應用程序只需要知道調用的數據庫service的名稱和接口,它不必關心有多少pods組成了那個數據庫,或者上次它調用了哪個pod。 Kubernetes會為集群建立一個DNS服務器,用于監視新的services并允許他們在應用程序代碼和配置文件中按名稱定位。
它也可以設置services不指向pods而是指向其他已經存在的services,比如外部API或數據庫。
Replication Controllers - Replication controllers是Kubernetes實例化pods的正常方式(通常情況下,在Kubernetes中不使用Docker CLI)。它們為service來控制和監視運行的pods數量(稱為replicas)。例如,一個replication controller可以負責維持5個Redis的pods的運行。如果一個失敗,它會立即啟動一個新的。如果replicas的數量減少,它會停止多余的pods。雖然使用Replication Controllers來實例化所有pods會增加一層額外的配置,但是它顯著提高容錯性和可靠性。
Mesos 和 Marathon
Apache Mesos是一個開源的集群管理器。它是為涉及數百或數千臺主機的大規模集群而設計的。 Mesos支持在多租戶間分發工作負載,一個用戶的Docker容器運行緊接著另一個用戶的Hadoop任務。
Apache Mesos始于加州大學伯克利分校的一個項目,用來驅動Twitter的底層基礎架構,并且成為許多大公司如eBay和Airbnb的重要工具。后來 Mesosphere(共同創辦人之一:Ben Hindman - Mesos原始開發人員 )做了很多持續性的Mesos開發和支持工具(如Marathon)。
Mesos的體系結構是圍繞高可用性和彈性而設計的。在一個Mesos群集的主要組成部分是:
Mesos Agent Nodes - 負責實際的運行任務。所有代理向Master提交其可用資源。通常會有數十到上千的節點。
Mesos Master - 負責給Agents發送任務。它維護一個現有資源的列表并且將此“提供”給Frameworks。Master基于分配策略來決定提供多少資源。通常會有2個或4個備用Master來接替故障的Master。
ZooKeeper - 用于選擇和查找當前Master地址。通常情況下會運行3個或5個ZooKeeper實例以確保可用性和故障處理。
Frameworks - 與Master協調調度任務到Agent節點。Frameworks由兩部分組成:executor進程會運行代理并維護運行的任務以及那些已注冊的寄存器,還可以選擇使用那些基于來自主機提供的資源。Mesos集群為不同種類的任務可以運行多種Frameworks。用戶希望與frameworks交互來提交任務而不是和Mesos交互。
上圖中我們可以看到Mesos集群使用framework作為調度器。Marathon調度器使用ZooKeeper來定位當前要提交任務的Mesos master。無論是Marathon調度器還是Mesos master都有備用以便當前master不可用的時候使用。
通常情況下,ZooKeeper,作為Mesos master以及備用,它會運行在同一臺主機上。在一個小的集群中,這些主機也可以運行代理,但是更大的集群做這些就不可行,因為它們需要與master通信。Marathon也可以運行在同一個主機上,或者運行在存在于網絡邊界的獨立主機上,而且還可以為客戶端形成接入點,從而保持客戶端與Mesos集群分離。
Marathon(來自 Mesosphere)是為開啟、監控以及擴展長期運行應用程序規模而設計的。Marathon啟動應用程序的設計是靈活的,它甚至可以啟動其他互補的 frameworks,如Chronos(數據中心的“cron”)。可以選擇使用framework來運行Docker容器,Marathon直接支持這樣做。就像我們見過的其他編排架構,Marathon支持各種親和與約束規則。客戶端通過REST API與Marathon交互。其他功能還包括支持健康檢查以及可用于與負載平衡器或分析指標交互的事件流。
結論
編排、集群以及管理容器顯然有多種選擇。話雖如此,但這些選擇一般都是高度分化的。在編排方面,我們可以說:
Swarm具有使用標準Docker接口的優勢(及劣勢)。雖然這樣使得它與現有的工作流程交互起來簡單易用,但也可能對于支持更為復雜的定義在定制接口的調度變得更加困難。
Fleet是底層級的而且相當簡單的編排層,它被于運行更高級別的編排工具,例如Kubernetes或者自定義系統。
Kubernetes是帶有服務發現和復制的編排工具。它可能需要重新設計一些現有的應用程序,但是正確地使用可以提供一個可容錯和可擴展的系統。
Mesos 是一種底層級、久經沙場的調度器,對于容器的編排,它支持多種frameworks,包括Marathon、Kubernetes、和Swarm。在寫這篇文章的時候,Kubernetes和Mesos比Swarm開發的更多以及更為穩定。在規模上,只有Mesos已經證明了支持成百上千個節點的大型系統。但是,對于小的集群比方說,還不到十幾個節點的集群,用Mesos可能過于復雜。