本文就Amazon ECS服務的兩大核心:集群管理和容器調度,進行了簡單的闡述,并介紹了ECS是如何實現支持并發(fā)操作的鍵值對存儲的,為我們實現相關服務提供了一定參考。
在最近一篇關于Amazon EC2容器服務(Amazon ECS)的文章中。我討論了在一個集群中運行現代化分布式應用的兩個關鍵組件:可靠的狀態(tài)管理和靈活的調度。Amazon ECS簡化了構建和運行容器化應用的流程,但是如何實現才是Amazon ECS真正有意思的地方。今天,我想要探討Amazon ECS架構并闡述這個架構能夠做些什么。如下是Amazon ECS的基本組件圖:
我們如何協(xié)調(Coordination)集群
讓我們來談談Amazon ECS到底做了什么。Amazon ECS的核心是集群管理器,它是一個后臺服務,能夠處理集群協(xié)調和狀態(tài)管理的任務。在集群管理器之上是不同的調度器。集群管理和容器調度是互相解耦的,所以Amazon支持客戶使用和創(chuàng)建他們自己的調度器。集群其實就是應用可以使用的計算資源池。而這里的資源池就是根據容器劃分的Amazon EC2實例的CPU、內存和網絡資源。Amazon ECS通過運行在集群中每個EC2實例上的容器代理來協(xié)調集群。代理允許Amazon ECS與集群中的EC2實例進行通信,并根據用戶或調度器的請求來啟動、終止和監(jiān)控容器。代理使用Go語言編寫,資源占用少,目前在GitHub上基于Apache協(xié)議開源。歡迎大家貢獻和反饋。
我們如何管理狀態(tài)
為了協(xié)調集群,我們的集群上需要有一個SSOT[單一數據源]:集群中的EC2實例,運行在EC2實例上的任務,組成任務的容器,可用/占用資源(例如,網絡端口、內存、CPU等)。在獲得精確的集群狀態(tài)信息之前,我們是不可能成功開啟和終止容器的。為了解決這個問題,需要在某個地方存儲狀態(tài),因此現代集群管理器的心臟是鍵值數據庫。
這個鍵值數據庫對任何集群輸入的和存儲于此的信息表現為SSOT。為了保證可靠性和可擴展性,這個鍵值數據庫需要采用分布式來確保持久性和可用性,并規(guī)避網絡劃分和硬件故障帶來的影響。也正因為鍵值數據庫是分布式的,確保數據一致性以及正確的進行并發(fā)修改會變得更加困難,這種情況在狀態(tài)持續(xù)變化的環(huán)境(比如,容器的停止和啟動)中尤甚。對此,為了保證多狀態(tài)修改不會出現沖突,某些形式的并發(fā)控制就需要落實到位了。打個比方,假設有2個開發(fā)者從某個EC2實例請求剩余的內存以供他們的容器使用,這個時候,只有其中一個容器能夠真正得到這些資源,而另一個則會被告知請求未完成。
為了實現并發(fā)控制,我們采用了Amazon分布式系統(tǒng)的核心原語之一來實現Amazon ECS,這是一個基于Paxos的事務日志的數據存儲系統(tǒng),它保存了每一項數據變更的記錄。在日志中,任何數據的寫入均以事務的形式提交,并對應一個特定順序的ID。數據當前的值就是日志中記錄的那些事務的總和。對于任何數據的讀取,得到的都只是日志當前時間點的一個快照。如果寫操作是繼上次讀取操作完成以來最新提交的事務,則判定寫操作成功。這種原語允許Amazon ECS以樂觀鎖的形式存儲集群的狀態(tài)信息,對于共享數據經常變動的場景(比如當需要表達諸如ECS之類的計算資源共享池的狀態(tài)時)而言,這是一種理想的方式。這個架構使得Amazon ECS具有高可用性、低延遲和高吞吐量的特點,因為數據存儲并未使用悲觀鎖(譯者注:作者自己表述得很含糊,大家參見多版本并發(fā)控制MVCC)。
通過API訪問
既然我們有了一個鍵值數據庫,那么我們便能夠成功協(xié)調集群,并確保所需數量的容器正在運行,因為我們有一種可靠的方法來存取集群的狀態(tài)。之前提到過,我們解耦了集群管理和容器調度兩個模塊,因為我們希望客戶能夠充分利用Amazon ECS狀態(tài)管理的能力。我們已經通過一系列API開放了Amazon ECS集群管理器,它允許客戶以結構化的方式訪問存儲在鍵值數據庫中的集群狀態(tài)信息。
通過list命令,客戶可以讀取托管的集群,特定集群中運行的EC2實例,運行中的任務以及組成任務的容器配置(如任務定義)。通過describe命令,客戶可以獲取EC2實例的具體信息以及每個實例上的可用資源。最近,客戶亦可以啟動和停止任何集群中的任務了。近期,我們針對Amazon ECS進行了一系列的負載測試,我們希望分享一些性能要點,客戶在Amazon ECS上創(chuàng)建應用的時候應該會關注它們的。
上圖顯示了一個負載測試的結果,在這次測試中,我們在Amazon ECS集群中添加和刪除實例,并測量72小時的周期內,調用‘Describe Task’API時,百分比排列位于第50位和第99位的延遲。你可以看到,盡管集群數量有較大的波動,但是延遲相對而言并沒有什么抖動。Amazon ECS可以如你所需地進行擴展,不管你的集群規(guī)模有多大,且根本無需操作或擴展集群管理器。
這組API是客戶在Amazon ECS上搭建解決方案的基礎。調度器只是提供了關于何時、何地以及如何開啟和停止容器的邏輯。Amazon ECS的架構為分享集群狀態(tài)而設計,它允許客戶根據需要為應用運行各種調度器(如二進制打包、發(fā)布等)。這個架構允許調度器查詢集群的具體狀態(tài),并從通用池中分配資源。樂觀并發(fā)控制允許調度器無沖突地獲取它們所請求的資源。一些客戶已經在Amazon ECS上創(chuàng)建了各種有趣的解決方案,下面我們來分享一些具體的示例。
Hailo——彈性資源池上的定制調度
Hailo是一個免費的移動APP,它允許人們招呼一輛認證的出租車到其所在地。Hailo擁有一個全球網絡,囊括了超過60000名司機以及一百萬以上的乘客。Hailo于2011年成立,從第一天開始就使用了AWS。在過去的幾年中,Hailo 從AWS單一區(qū)域上運行的應用集合演化為貫穿多個區(qū)域的微服務架構。之前,每個微服務都跑在靜態(tài)劃分的實例集群上。Hailo遇到的問題是跨分區(qū)的資源使用率較低。這個架構并不具備很強的擴展性,并且Hailo也不希望它的工程師關心基礎設施的細節(jié)或者微服務的部署問題。
為此,Hailo決定基于服務優(yōu)先級以及其它的運行時指標對容器進行調度。后來他們選擇了Amazon ECS來作為集群管理器,因為ECS可以輕松的管理任務狀態(tài)并訪問集群狀態(tài)的API。同樣,Hailo可以根據自己的需求來定制調度器。
Remind——平臺即服務
Remind是一個web端和移動端應用,使得老師能夠給學生發(fā)送信息并和家長取得聯系。Remind平臺上擁有24M用戶和超過1.5M的老師。它每月傳遞150M條信息。Remind起初使用Heroku來運行整個應用設施,從消息推送引擎、前后端 API、Web客戶端到聊天后臺。這些設施中的大部分都以龐大的應用塊進行部署。
隨著用戶的增長,Remind希望擁有橫向擴展的能力。因此大約在2014年年底,它的工程師團隊開始摸索著向基于容器的微服務架構遷移。團隊希望基于AWS搭建一個PaaS,確保它能夠兼容Heroku的API。一開始,團隊期望能有一個開源的解決方案(比如,CoreOS和 Kubernetes)來負責集群的管理以及容器的協(xié)作,但是由于團隊的規(guī)模較小,因此他們沒有時間來管理集群的基礎設施,同時保證高可用性。
在簡要評估了Amazon ECS之后,團隊決定在此服務的基礎上搭建PaaS。Amazon ECS是全托管式的,這使得工程資源能夠被集中于開發(fā)和部署應用;這里并沒有集群需要管理和擴展。在6月份,Remind開源了他們基于ECS的PaaS解決方案,名為“Empire”。憑借Empire,Remind得到了可觀的性能提升(例如,延遲和穩(wěn)定性)以及安全優(yōu)勢。他們接下來幾個月的計劃是將90%以上的核心設施遷移到Empire。
Amazon ECS——一個全托管的平臺
上述只是我們從客戶處看到的其中兩個用例。Amazon ECS架構允許我們提供一個具有高可擴展、高可用、低延遲的容器管理服務。通過API樂觀并發(fā)(譯者注:樂觀鎖)地訪問共享集群狀態(tài)的能力,使得用戶得以按需創(chuàng)建任何定制容器解決方案。我們一直致力于為客戶消除重復而繁重的任務。通過Amazone ECS,根本不需要安裝或操作集群管理程序,客戶理應僅僅專注于開發(fā)優(yōu)秀的應用。