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