1. 程式人生 > >Kubernetes、Mesos和Swarm:Rancher編排引擎的比較

Kubernetes、Mesos和Swarm:Rancher編排引擎的比較

Kubernetes是Google開源的容器叢集管理系統,其提供應用部署、維護、 擴充套件機制等功能。Mesos是Apache下的開源分散式資源管理框架,它被稱為是分散式系統的核心。Mesos最初是由加州大學伯克利分校的AMPLab開發的,後在Twitter得到廣泛使用。Swarm是Docker公司在2014年12月初新發布的容器管理工具。和Swarm一起釋出的Docker管理工具還有Machine以及Compose。我們來看下Rancher對它們有什麼評價。

題記:這篇文章出版時我們已經要求提供一個可下載版本,你可以點選這裡下載
Kubernetes_Mesos_Swarm-300x87.png
Rancher最新的版本在原有官方標準編排工具Cattle的基礎上,新增支援其他幾種常用的編排引擎。新增支援的編排引擎包括Swarm(Docker未來本地編排引擎)、Kubernetes和Mesos,它們都是Docker社群中最廣泛使用的編排系統,滿足使用者不同梯度的使用性和特性。儘管Docker是既定事實上的行業容器標準,但是在容器編排上還沒有絕對的贏家。這篇文章中我們我們主要介紹三種編排工具的特性,以及適應的場景。


目前Docker原生編排還處於初期階段,但是新的特性在快速迭代增加中。由於原生的編排工具是官方系統的一部分,因此它成為眾多開發者的預設首選編排工具,順理成章地最有可能成為最受社群歡迎支援的工具。Kubernetes是谷歌支援的容器編排工具,它在眾多容器編排工具中用的最廣泛的一個。最近,Mesos和Mesosphere(Marathon的開源版)把更多的精力放在服務管理,將更多的功能留給可插拔外掛和應用程式管理。這樣的話,就使得應用最終容易容易定製部署,因為單個的程式更容易被更新,定製化。然而,這也意味著我們必須要修改一些設定來適配。Kubernetes更關注的是如何構建叢集和在常見場景中用例的通用系統整合。

Docker Native Orchestration

Docker-swarm.png

基礎架構

Docker 1.12引擎中附帶了原生的編排工具,對獨立的Docker Swarm來說是一種替代。Docker本地叢集(Swarm)包涵一系列節點(Docker程序/守護程序),他們同時管理叢集及提供工作服務。你可以在容器中啟動工作程序也可以啟動管理程序維護叢集的狀態。多管理模式保證了系統的高可用性,但是不推薦超過7個以上管理員使用者。內部通過RAFT演算法實現主從的一致性。與所有一致性的演算法是一樣的,多管理中心達到一致性的實現。實際上保持內部管理的一致也意味著Docker本地的編排不依賴外部資源,這樣也是叢集的管理變得更加容易。

可用性

Docker本機使用單節點Docker的概念,並將它們擴充套件到Swarm。如果你使用最新的Docker版本,那麼學習曲線還是相當平緩的。一旦你想新增已經在多節點執行的Docker到Swarm中,Swarm的設定是很簡單的:你只需在其中一個節點上呼叫docker swarm init,然後在任何其他你想新增的節點上呼叫docker swarm join即可。您也可以使用相同的Docker Compose模板和相同的Docker CLI命令集設計單一的Docker。

功能集

Docker本地可以使用與Docker Engine和Docker Compose相同的語法提供編排支援。你仍然可以連結到服務,建立卷,定義開放的埠號。所有的這些操作都適用於單個的節點,除了這些新增了兩個新的概念:服務和網路。

Docker服務是您的節點上啟動的一組容器,並且保持這些批量的容器執行。如果其中一個容器停止,它將被自動替換掉。其中服務分類兩類:複製和全域性。複製服務在叢集中維護指定數量的容器,因為全域性服務在每個叢集節點上執行一個例項。要建立複製服務,請使用下面的命令:
docker service create          \
–name frontend              \
–replicas 5                 \
-network my-network         \
-p 80:80/tcp nginx:latest.  

現在可以使用docker network create –driver overlay NETWORK_NAME建立命名為overlay的網路。使用overlay網路我們可以建立一個孤立、扁平、加密的虛擬網路環境用來啟動容器。你可以使用約束和標籤來做一些非常基本的容器排程。使用約束可以向服務新增關聯,並且它將嘗試僅啟動具有特殊標籤的容器。
docker service create                        \
–name frontend                            \
–replicas 5                               \
-network my-network                       \
--constraint engine.labels.cloud==aws     \
--constraint node.role==manager           \
-p 80:80/tcp nginx:latest.  

此外,你可以使用保留的CPU和保留的記憶體空間標誌來定義服務的每個容器使用的資源,以便在swarm上啟動多個服務時,容器可以處理最小的資源競爭。

你可以使用以下命令進行初步的部署。這樣將會更新容器的映象,但是兩個容器之間有10s的間隔來更新兩個容器。然而,health-checks和自動回滾都不支援。
docker service update        \
–name frontend            \
–replicas 5               \
-network my-network       \
--update-delay 10s        \
--update-parallelism 2    \
-p 80:80/tcp nginx:other-version.  

Docker使用卷驅動程式支援外部卷持久化,並且使用mount服務命令擴充套件器使用。執行以下程式碼段將會將NFS裝入到您的容器中。請注意,這需要在Docker外部的底層主機上設定NFS。在沒有主機支援的情況下,其他對Amazon EBS卷或Google容器引擎卷驅動程式也能夠工作。此外,這個功能還沒有完善的文件,可能需要需要在github的docker專案上建立issues得到交流回復。
--mount type=volume,src=/path/on/host,volume-driver=local,\
dst=/path/in/container,volume-opt=type=nfs,\
volume-opt=device=192.168.1.1:/your/nfs/path  

Kubernetes

K8S-300x300.png

基礎架構

從概念上講,Kubernetes有點類似於Swarm,它使用一個帶有RAFT的管理器(主)節點來達成一致。然而,相似的地方也只有這麼多了。Kubernetes使用外部etcd叢集為此目的。此外,你將需要Kubernetes外部的網路層,這樣overlay 網路就行編織法蘭絨外衣一樣。使用這些外部工具,您可以啟動Kubernetes主元件; API伺服器,控制器管理器和排程程式。這些通常作為主節點上的Kubernetes pod執行。除了這些,你還需要在每個節點上執行kubelet和kubeproxy。如果需要的話,工作節點只執行Kubelet和Kubeproxy以及像一個包裝一樣作為網路層提供者。
KubeDiagram-e1476986142495.png
在這個設定中,kubelet將控制給定節點上的容器(或者pod)與主控制器上的控制器管理器。主節點上的排程器負責資源分配和平衡,並且將幫助在具有最多可用資源的工作節點上放置容器。 API控制器是您的本地kubectl CLI將向叢集發出命令的地方。最後,kubeproxy用於為Kubernetes中定義的服務提供負載平衡和高可用性。

可用性

從頭開始設定Kubernetes是一個不平凡的努力,因為它需要設定etcd,網路外掛,DNS伺服器和證書頒發機構。從頭開始設定Kubernetes的詳細資訊可以在這裡,但幸運的是Rancher為我們完成所有這些設定。我們在前面的文章中介紹瞭如何設定Kubernetes叢集。

除了初始設定,Kubernetes仍然有一些陡峭的學習曲線,因為它使用自己的術語和概念。 Kubernetes使用資源型別,如Pods,部署,複製控制器,服務,守護程序集等來定義部署。這些概念不是Docker專門詞彙的一部分,因此您需要在開始建立第一個部署之前熟悉它們。此外,一些命名與Docker衝突。例如,Kubernetes服務不是Docker服務,也是概念上不同的(Docker服務更貼近地對映到Kubernetes世界中的Deployments)。此外,您使用kubectl而不是docker CLI與叢集互動,並且必須使用Kubernetes配置檔案而不是docker compose檔案。

Kubernetes有這樣一套詳細的概念獨立於core Docker,這本身不是一件壞事。 Kubernetes提供比core Docker更豐富的功能集。然而,Docker將新增更多的功能來與Kubernetes競爭,具有不同的實現和不同或衝突的概念。這將幾乎肯定重複CoreOS / rkt情況,大部分社群在類似但競爭的解決方案。今天,Docker Swarm和Kubernetes定位於不同的使用場景(Kubernetes更適合於使用專用叢集管理團隊的面向服務的架構的大型生產部署),但是隨著Docker 本地編排的成熟,它將遷移到這個空間。

功能集

Kubernetes的完整功能集太大,這篇文章不能涵蓋完整,但我們將介紹一些基本概念和一些有趣的區分。首先,Kubernetes使用Pods的概念作為基本單位,而不是單個容器。每個pod是一組容器(集合大小可以是一個),它們總是在同一節點上啟動,共享相同的卷並分配一個虛擬IP(VIP),以便可以在叢集中定址。單個pod的Kubernetes規範檔案可能如下所示:
kind: Pod
metadata:
name: mywebservice
spec:
containers:
- name: web-1-10
image: nginx:1.10
ports:
- containerPort: 80  

接下來是你的部署。這些鬆散地對映具體到什麼服務是在Docker本地編排。您可以像Docker Native中的服務一樣擴充套件部署,部署將確保正在執行的請求數量的容器。重要的是注意部署僅類似於Docker本地中的複製服務,如Kubernetes使用守護程式集概念來支援其等效的全域性排程服務。部署還支援使用HTTP或TCP可達性或自定義exec命令來確定容器/ pod是否正常的執行狀況檢查。部署還支援使用執行狀況檢查的自動回滾滾動部署,以確定每個pod部署是否成功。
kind: Deployment
metadata:
name: mywebservice-deployment
spec:
replicas: 2 # We want two pods for this deployment
template:
metadata:
  labels:
    app: mywebservice
spec:
  containers:
  - name: web-1-10
    image: nginx:1.10
    ports:
    - containerPort: 80  

接下來你有Kubernetes服務,它為部署提供簡單的負載平衡。部署中的所有pod都將在服務進入和退出時註冊,服務也抽象出多個部署,因此如果您想回滾部署,您將使用相同的服務註冊兩個Kubernetes部署,然後逐個新增pod同時減少pods從其他。您甚至可以進行blue-green部署,您可以一次性將服務指向新的Kubernetes部署。最後,服務對於Kubernetes叢集中的服務發現也很有用,叢集中的所有服務都獲得VIP,並且作為docker連結樣式環境變數以及通過整合的DNS伺服器暴露給叢集中的所有pod。

除了基本服務,Kubernetes支援作業排程計劃作業和Pet Sets。作業建立一個或多個pod,並等待它們終止。作業確保指定數量的pod成功終止。例如,您可以開始一個作業,在最後一天開始處理1小時的商業智慧資料。您將啟動一個包含前一天的24個pod的作業,一旦它們都執行完成,作業完成。作為名稱建議的計劃作業是在給定計劃上自動執行的作業。在我們的例子中,我們可能使我們的BI處理器是每日計劃的工作。作業非常適合向叢集發出批處理工作負載,這些負載不總是需要啟動的服務,而是需要執行到完成然後清理的任務。

Kubernetes提供給基本服務的另一個擴充套件是Pet Sets。Pet Sets支援狀態服務工作負載,通常很難集中化。這包括資料庫和實時連線的應用程式。Pet Sets為集合中的每個“Pet”提供穩定的主機名。Pet就是索引。例如,pet5將獨立於pet3可定址,並且如果第三Pet容器/ pod死掉,則它將在具有相同索引和主機名的新主機上重新啟動。

Pet Sets還提供使用持久卷的穩定儲存,即如果pet1死亡並在另一個節點上重新啟動,它將獲得其重新安裝原始資料的卷。此外,您還可以使用NFS或其他網路檔案系統在容器之間共享卷,即使它們在不同的主機上啟動。這解決了從單主機到分散式Docker環境轉換時最有問題的問題之一。

Pet Sets還提供對等發現,通常可以發現其他服務(通過Docker連結等)。然而,發現服務中的其他容器是不可能的。這使得類似Cassandra和Zookeeper基於gossip協議的服務非常難以啟動。

最後,Pet Sets提供啟動和拆卸排序,這是持久、可擴充套件的服務,例如Cassandra。 Cassandra依賴一組種子節點,當您上下擴充套件服務時,必須確保種子節點是第一個啟動的節點和最後一個要刪除的節點。在撰寫本文時,Pet Sets是Kubernetes的一大特色,因為在沒有這種支援的情況下,持久的有狀態工作負載幾乎不可能在Docker的生產規模上執行。
Kubernetes還提供名稱空間來隔離叢集上的工作負載,保護管理和自動擴充套件支援。所有這些特性更意味著Kubernetes也支援大型,多樣化的工作負載,Docker Swarm目前還沒有準備就緒。

Marathon

Marathon.png

基礎架構

大規模叢集的另一個常見的編排設定是在Apache Mesos之上執行Marathon。 Mesos是一個開源叢集管理系統,支援各種工作負載陣列。 Mesos由在群集中的每個主機上執行的Mesos代理組成,它向主機報告其可用資源。可以有一個或多個Mesos主機使用ZooKeeper叢集進行協調。在任何給定時間,主節點之一使用主選舉過程是活動的。主伺服器可以向任何Mesos代理髮出任務,並報告這些任務的狀態。雖然您可以通過API發出任務,但正常的方法是在Mesos之上使用一個框架。 Marathon是一個這樣的框架,它為執行Docker容器(以及本地Mesos容器)提供支援。

可用性

與Swarm相比,Marathon有一個相當陡峭的學習曲線,因為它不與Docker共用大部分概念和術語。然而,馬拉松並不複雜,因此比Kubernetes更容易學習。然而,管理Marathon部署的複雜性來自於它是分層在Mesos,因此有兩層工具要管理。此外,Marathon的一些更高階功能(如負載平衡)僅作為在Marathon之上執行的附加框架提供。某些功能(如身份驗證)只有在DC / OS上執行Marathon時才可用,而後者又在Mesos上執行 - 為堆疊新增另一層抽象。

功能集

要在Marathon中定義服務,您需要使用其內部JSON格式,如下所示。一個簡單的定義,如下面的一個將建立一個服務,每個執行nginx容器的兩個例項。
{
"id": "MyService"
"instances": 2,
"container": {
"type": "DOCKER",
"docker": {
  "network": "BRIDGE",
  "image": "nginx:latest"
}
}
}  

以上定義稍微更完整的版本如下所示,我們現在新增埠對映和health check。在埠對映中,我們指定一個容器埠,這是docker容器公開的埠。主機埠定義主機公共介面上的哪個埠對映到容器埠。如果為主機埠指定0,則在執行時分配隨機埠。類似地,我們可以可選地指定服務埠。服務埠用於服務發現和負載平衡,如本節後面所述。使用健康檢查,我們現在可以執行滾動(預設)和blue-green 部署。
{
"id": "MyService"
"instances": 2,
"container": {
"type": "DOCKER",
"docker": {
  "network": "BRIDGE",
  "image": "nginx:latest"
  "portMappings": [
    { "containerPort": 8080, "hostPort": 0, "servicePort": 9000, "protocol": "tcp" },
  ]
}
},
"healthChecks": [
{
  "protocol": "HTTP",
  "portIndex": 0,
  "path": "/",
  "gracePeriodSeconds": 5,
  "intervalSeconds": 20,
  "maxConsecutiveFailures": 3
}
]
}  

除了單一服務之外,您還可以定義Marathon應用程式組,使用巢狀樹結構的服務。在組中定義應用程式的好處是能夠將整個組縮放在一起。這在微服務堆疊中非常有用,其中調整單個服務可能是困難的。到目前為止,擴充套件假設所有服務將以相同的速率擴充套件,因此如果您需要一個服務的“n”個例項,您將獲得所有服務的“n”個例項。
{
"id": "/product",
"groups": [
{
  "id": "/product/database",
  "apps": [
     { "id": "/product/mongo", ... },
     { "id": "/product/mysql", ... }
   ]
},{
  "id": "/product/service",
  "dependencies": ["/product/database"],
  "apps": [
     { "id": "/product/rails-app", ... },
     { "id": "/product/play-app", ... }
  ]
}
]
}  

除了能夠定義基本服務之外,Marathon還可以基於指定約束來執行容器的排程,包括指定服務的每個例項必須在不同的物理主機“約束”上:[[“hostname”, “UNIQUE”]]。您可以使用cpus和mem標記來指定該容器的資源利用率。每個Mesos代理報告其總資源可用性,因此排程程式可以以智慧方式在主機上放置工作負載。

預設情況下,Mesos依賴於傳統的Docker埠對映和外部服務發現和負載平衡機制。但是,最近的測試功能添加了對使用Mesos DNS的DNS服務發現或使用Marathon LB的負載平衡的支援。 Mesos DNS是一個在Mesos LB之上執行的應用程式,它查詢Mesos API以獲取所有正在執行的任務和應用程式的列表。然後,它為執行這些任務的節點建立DNS記錄。然後,所有Mesos代理手動更新,以使用Mesos DNS服務作為其主DNS伺服器。 Mesos DNS使用用於向主機註冊Mesos代理的主機名或IP地址;並且埠對映可以查詢為SRV記錄。由於Marathon DNS在代理主機名上工作,並且主機網路埠必須被公開,因此不能發生衝突。 Mesos DNS確實提供了一種方法來為狀態負載持續引用單個容器,例如我們將能夠使用Kubernetes寵物集。此外,與群集中任何容器上可定址Kubernetes VIP不同,我們必須手動將/etc/resolve.conf更新到Mesos DNS伺服器集,並在DNS伺服器更改時更新配置。 Marathon-lb使用馬拉松賽事匯流排跟蹤所有服務的啟動和撤銷。然後,它在代理節點上啟動HAProxy例項,以將流量中繼到必需的服務節點。

Marathon還對永續性卷以及外部持久卷提供測試支援。然而,這兩個特徵都處於非常原始的狀態。持久卷只在容器重新啟動的單個節點上持久化,但是如果刪除使用它們的應用程式,則會刪除卷,但磁碟上的實際資料不會被刪除,必須手動刪除。外部卷需要DC / OS,並且當前只允許您的服務擴充套件到單例項。

最終裁決

今天我們看了Docker容器編排的三個選項:Docker Native(Swarm),Kubernetes和Mesos / Marathon。很難選擇一個系統來推薦,因為最好的系統高度依賴於你的用例,規模和歷史。此外,所有三個系統都在大量開發,一些涵蓋的功能是測試版,可能會很快更改,刪除或替換。

Docker Native給你提供了最快的升級,很少甚至沒有供應商的封閉超出了對Docker的依賴。對Docker的依賴不是一個大問題,因為它已經成為了實際上容器標準。鑑於在編排戰爭中缺乏明確的贏家,而且Docker本機是最靈活的方法,因此它是簡單的web/stateless應用程式的不錯選擇。但是,Docker Native目前還只是一個架子,如果你需要得到複雜的,大規模的應用程式到生產,你需要選擇一個Mesos / Marathon或Kubernetes。

在Mesos / Marathon和Kubernetes之間也不是一個容易的選擇,因為兩者都有自己的優點和缺點。 Kubernetes肯定是更豐富和成熟的兩個,但它也是一個非常有見地的軟體。我們認為很多這些意見是有意義的,但Kubernetes沒有馬拉松的靈活性。這是有道理的,當你考慮非Docker,非容器化的應用程式,可以執行在Mesos除了Marathon(例如Hadoop叢集)的豐富的歷史。如果你正在做一個綠色領域實施,也沒有強烈的意見,如何佈局叢集,或你的意見同意谷歌,那麼Kubernetes是一個更好的選擇。相反,如果你有大的,複雜的遺留工作負載,將逐漸轉移到容器,那麼Mesos / Marathon是要走的路。

另一個問題是規模:Kubernetes已經測試了數千個節點,而Mesos已經測試了成千上萬的節點。如果您正在啟動具有數萬個節點的叢集,則需要使用Mesos來獲得底層基礎架構的可擴充套件性 - 但請注意,將高階功能(例如負載平衡)擴充套件到該範圍仍將保留。然而在這樣的規模下,除了仔細調整和猴子補丁(一種執行時動態替換的熱更新方法,編者注),很少再有現成的解決方案能夠直接使用。