為什么我們拋棄ECS而選擇了Kubernetes
【編者的話】作者通過實踐,從集群構建、基礎服務配置、部署、服務發現、持久化存儲、端口管理等等多方面詳細地對比了Kubernetes和ECS的優缺點,非常的全面,值得一讀。
在這篇文章中我們將會探討2個主流的Docker編排框架:AWS的ECS(Elastic Container Service)和Google的Kubernetes。
3個月前,我們在 nanit.com 希望選擇一個合適的Docker編排框架,ECS成為了我們的首選,畢竟,我們對AWS的服務較為熟悉,并且我們的基礎設施都是建立在AWS的。經過一段時間的測試,我們發現ECS并不成熟,缺少一些我們需要的關鍵功能,因此我們開始嘗試其他的框架:Kubernetes。令人意外的是,Kubernetes非常成熟,幾乎支持我們需要的所有功能。對于我們來說,Kubernetes在ECS的主場完勝了ECS。接下來,就讓我們一起來看看Kubernetes贏在哪些方面。
注意:ECS一直在更新,我們會盡可能的跟進這些內容,但部分內容可能被忽略了,希望讀者不要介意。
構建集群(Cluster Setup)
ECS:為了啟動一個ECS集群,用戶需要設置一個Auto Scaling Group。用戶可以編輯user-data來將EC2實例添加到指定的ECS集群上。當ASG被設置,實例啟動之后,用戶可以在ECS控制臺看到這部分內容。現在,用戶可以開始進行task-definition,方式類似于Docker-compose。
Kubernetes:想要在AWS上啟動一個Kubernetes,用戶需要先啟動一個具有一定權限的EC2實例(通過IAM)。這將會創建多個AWS constructs來支持你的集群:VPC、ASG、一些安全組(Security Groups)和一個Kubernetes主實例。集群需要幾分鐘來啟動,之后用戶就能夠在上面運行自己的容器。
比較結果:使用這兩種框架來啟動一個集群都非常的簡單和友好。
啟動基礎服務(Basic Service Setup)
我們的任務是啟動一個Nginx 鏡像,并且讓其他人能夠訪問這個Web服務。
ECS: 首先,我們需要創建一個ELB(Elastic Load Balancer),它負責80端口的轉發。然后,我們需要創建一個task-definition,它負責在80端口上啟動一個Docker鏡像。最后,需要創建一個Service,它會顯示出有多少實例會同時運行。我們需要將它綁定到我們之前創建的ELB上。
Kubernetes:首先需要創建一個Replication Controller,它會顯示出我們希望運行的Docker鏡像和有多少鏡像會同時運行。之后,我們需要創建一個Service object,這會啟動一個ELB并且將ELB的流量轉發到對應的容器上。
比較結果:Kubernetes的方式更舒服一些,更簡潔。用戶并不需要手工啟動或者管理ELB。Kubernetes會完全負責管理:當用戶創建了一個service,一個ELB會自動創建;當用戶刪除了一個service,它會自動從AWS上刪除。
服務發現(Service Discovery)
當你使用了微服務架構和Docker,一個好的服務發現解決方案是至關重要的。Docker容器總是在不同虛擬機中遷移,用戶必須有一個可靠的方法來發現在集群內和集群外的服務。
ECS: ECS并沒有提供任何服務發現的解決方案。我能想到的最好方法就是構建一個內部加載平衡器(internal load balancer),并且將每一個service附加到一個平衡器上。平衡器的host name不會被改變,然后你就能夠利用這個host name來作為服務的端點。其他的方法還有集成一個外部的程序,比如 Consul 。
Kubernetes:我認為這是Kubernetes的亮點之一。Kubernetes內置了一個完全的解決方案。它是一個插件,因此用戶可以選擇是否使用,但我強烈建議使用。它能夠和namespace一起很好的工作。簡單來說,當你創建了一個Kubernetes服務,比如說叫做redis,你就能夠在集群的任何地方引用redis這個名字,即便是跨虛擬機。這就像是讓docker網絡跨越了特定的虛擬機,連通了整個集群。Namespaces允許你將多個服務歸納到一個具有邏輯的組中。現在假設我們有兩個命名空間,分別是production和staging,他們都包含有一個redis的服務。一個在production命名空間下的容器可以通過redis來引用在production命名空間下的redis服務,同樣的,在stagin命名空間下的容器也能通過redis來引用到位于stagine命名空間下的redis服務。這種自動化識別使得用戶不需要花費時間去配置信息就能夠構建一個隔離的環境,并且你可以隨意在所有的命名空間中使用redis來引用對應的服務,接下來kunernetes會為你自動解析它們。
比較結果:毫無疑問,Kubernetes小勝一局。使用Kubernetes,用戶完全不用關心服務發現的事情,全部交給Kubernetes來做就好了:)
部署(Deployments)
當我們升級一個服務的時候,即便還在部署,我們也想要確保它百分之百能用。我們的測試包括一個簡單的NginX服務和一些簡單的靜態網頁。我們啟動了一個并發為30個請求的負載測試,并且在負載測試期間,我們會對該服務進行升級。
在部署期間,我們發現ECS丟失了比Kubernetes更多的請求。其中,Kubernetes丟失了0-2個請求,而ECS丟失了9-14個。
比較結果:說實話,我對ECS非常的失望。同樣,我也對Kubernetes表示失望,但是它至少比ECS好多了。值得注意的是,Kubernetes 1.1.1版本應該會對輪詢升級機制(rollong update mechanism)進行改善,還有一些其他的系統系能提升,這些改進都會使得這些數字變得更好看。
持久卷(Persistent Volumes)
我們經常需要掛載一些持久性的文件系統到一個指定的容器上,MySQL就是一個典型的例子。
ECS:ECS支持Docker原生的解決方案——用戶可以啟動一個數據容器,然后使用volumes-from命令來掛載它到其他容器上。就拿MySQL來看,你首先需要設置一個mysql-data容器,這個容器僅僅擁有一個數據卷。然后設置另外一個mysql-db容器,這個容器使用volumes-from命令來掛載之前創建的數據卷容器。這個方法看起來不錯,但是它是host-sepicific的,這意味著你的mysql-db容器不能夠在主機之間移動。你必須指定mysql-db容器在哪一個主機上運行,以此來防止容器被重新分配到其他主機上,最終失去了持久性。
Kubernetes:除了從一個指定的主機上掛載數據卷,Kubernetes還提供了一個選項:掛載一個EBS(Elastic Book Store)數據卷。這意味著一個容器的持久性存儲可以在多個不同的虛擬機之間保留。你再也不需要強制你的MySQL容器必須運行在哪一個具體的虛擬機上。
注意:EBS同一時間只能被一個虛擬機掛載,這意味著如果有一個服務,它有兩個運行在不同虛擬機的容器,他們將不能夠掛載和共享這個EBS。
比較結果:即便Kubernetes的EBS掛載有一定的限制,但它依舊非常的獨特和有用。
健康檢查(Health-Checks)
確保擁有足夠的服務容量是高可用性和冗余性的核心思想。健康檢查就是用來確保服務不僅僅是運行的,并且它們還是健康和可操作的。
ECS:ECS使用ELB(Elastic Load Balancer)健康檢查,這種方式有三個主要的缺點:
1. ELB健康檢查僅僅限于HTTP/TCP檢查
</p>
<p>
2. 如果你想要對一個不開放TCP端口的服務進行檢查,這是不行的。僅僅是為了能夠進行健康檢查,你就必須運行一個HTTP/TCP服務器。
</p>
<p>
3. 即便你擁有一個支持HTTP/TCP的服務,你還需要創建一個ELB,并將它綁定到這個服務上,這樣才能進行健康檢查。
</p>
<p>
Kubernetes:除了基于HTTP/TCP的健康檢查,Kubernetes還提供了一種叫做Exec的方式。Exec可以讓用戶在容器中運行命令。如果命令結束,并且返回0則表示這個服務是健康的,否則這個服務很可能是不健康的,它會被其他的實例所替換。
</p>
<p>
比較結果:Kubernetes的方式更靈活,更簡單配置。用戶并不需要去啟動一個冗余的HTTP/TCP服務器僅僅為了進行健康檢查,并且即便服務沒有綁定ELB,你也可以對它們進行健康檢查。
</p>
<h3>
端口管理(Port Management)
</h3>
<p>
從我們的上篇文章中可以看出,端口管理在Docker中是比較困難的。我們想通過一個簡單的例子來說明Kubernetes如何比ECS更優雅的解決了這個問題。我們擁有一臺虛擬機和兩個監聽80端口的網站。我們不能夠在同一個虛擬機上開2個80端口,因此我們需要尋找一個方法來解決這個問題。
</p>
<p>
ECS:用戶必須手工確定兩個服務沒有使用同一個端口。我們只有一臺虛擬機,因此只能運行一個開放80端口的容器。當我們想要開啟第二個開放80端口的容器時,這是不行的,因為我們沒有多余的虛擬機了。也就是說,能夠開放多少個x端口的服務取決于擁有多少個虛擬機。在小型集群中,這是非常容易滿足的條件,但是當你的服務數量變得越來越多時,這將成為一個頭疼的問題,因為當你想要擴充容器時,你必須確認你還有足夠的端口。
</p>
<p>
Kubernetes:Kubernetes非常優雅的解決了這個問題。它為每一個虛擬機上的容器都分配了一個隨機的端口。然后它創建了2個ELB,一個將80端口轉發到容器A的隨機端口上,另外一個轉發到容器B的隨機端口上。一個內部的路由機制會負責將數據包轉發到對應容器端口。
</p>
<p>
比較結果:Kubernetes使用虛擬端口的方式代替綁定原始端口的方法,很好的解決了這個頭疼的問題。
</p>
<h3>
記錄(Logging)
</h3>
<p>
沒有什么系統不需要記錄功能。
</p>
<p>
我從沒有想過記錄會成為一個大問題,但能夠為你解決問題令我非常的高興,即便這個問題非常簡單。我們之前提到Kubernetes提供了一個服務發現的擴展功能,在這里,我想說的是記錄的擴展功能。它含有兩個不同的記錄和度量收集(metric collection)的機制。第一種是著名的 <a href="/misc/goto?guid=4958977558035362479" target="_blank">ELK</a> 方法,ELK會收集容器的所有記錄,并且能夠讓用戶通過Kibana接口來查詢和可視化這些記錄。第二種是InfluxDB,它使用 <a href="/misc/goto?guid=4958839604626493724" target="_blank">Grafana</a> 作為可視化工具來查詢系統信息,如CPU和內存使用情況。
</p>
<p>
比較結果:Kubernetes的擴展功能更勝一籌。當然,你會說我并不需要這些擴展,系統也能很好工作,但是,它們效果如此之好,并且能適用于99%的用例,為什么不使用呢?ECS并沒有提供內置的記錄功能,用戶想要集成一個進去并不是很困難,但是這些并不能和Kubernetes提供的功能相提并論。
</p>
<h3>
未知的云平臺(Cloud Agnostic)
</h3>
<p>
其實,Kubernetes和ECS之間并不存在競爭:)
</p>
<p>
ECS會專注于AWS平臺,如果你已經在ECS上構建了你的基礎架構,當你想要轉移到其他云平臺時,你將會遇到很多困難。
</p>
<p>
Kubernetes適用于多個云平臺。你可以在AWS,Google Cloud,微軟的ZURE,Rackspace等等上運行你的集群,并且運行效果或多或少都是相同的。在這里,或多或少指的是有一些功能只有部分云供應商提供。你必須確認你選擇的新供應商能夠支持Kubernetes中使用的功能,至少確保遷移是可能的。
</p>
<h3>
開源軟件(OSS)
</h3>
<p>
Kubernetes是開源的項目,而ECS不是。這意味著,所有的一切,從源代碼到未來的發展路線都是對你開放的。發現了漏洞?你可以創建一個issue或者直接提交一個pull 請求來修復它。新的功能會被添加到每一個新版本,其中的貢獻人數和pull請求是驚人的。
</p>
<p>
ECS有著不同的性質,我不能夠在網上找到關于它未來發展路線的規劃。你不能夠獲得一個漏洞和issue的列表,你必須深入到論壇上去尋找想要的答案。并且你尋找的答案往往都是缺乏實際的,并不能夠提供任何幫助(請看 <a href="/misc/goto?guid=4958977558157261039" target="_blank">這里</a> )。也許這僅僅是因為我個人的糟糕經歷,但是不管怎么說,這都是令人煩躁和失望的。
</p>
<p>
比較結果:就我個人而言,我更喜歡開源軟件。我喜歡Kubernetes的開放性,每個人都能夠參與討論和貢獻代碼。我相信社區的力量會給我們帶來一個更好的產品。
</p>
<h3>
多可用區域(Multi-AZ)
</h3>
<p>
當談論到Kubernetes時,有一件事情困擾著我:它不支持AWS上的多可用區域集群(multiple availability-zones cluters)。這意味著所有EC2實例都集中在一個AZ上,這使得你的集群很可能會遭受到中斷問題。
</p>
<p>
ECS有對Multi-AZ有很好的支持。
</p>
<p>
比較結果:在Kubernetes的issue上,已經有一些工作正在進行。我十分確定下個版本會很好的得到改善。因此ECS在這一點上的勝利并不會長久。
</p>
<h3>
總結
</h3>
<p>
很多公司都開始使用Doker作為他們的主要基礎設置,傳遞機制(delivery mechanism)和編排框架(orchestration frameworks)成為了系統的核心,并且影響著我們開發,遷移,運行,升級的方式。當我想要比較ECS和Kubernetes時,我找不到類似的文章。所以我認為把我們的經驗公布出來非常的重要,這樣其他人能夠站在我們的肩膀上看的更遠。
</p>
<p>
對于nanit.com來說,Kubernetes毫無疑問獲得了勝利。如果你有任何的異議,請告訴我理由,我非常想要知道這些內容:)
</p>
<p>
原文鏈接: <a href="/misc/goto?guid=4958977558242274042" target="_blank">Why We Chose Kubernetes Over ECS</a> (翻譯:楊潤青)
</p>
<p>
===========================
</p>
<p>
譯者介紹
</p>
<p>
楊潤青,90后博士僧,研究方向是網絡和信息安全。
</p>
</div>
來自: http://dockone.io/article/955