EC2容器服務介紹
EC2容器服務 (ECS)是亞馬遜web服務(AWS)新發布的一款產品。
ECS的目的是讓 Docker 容器變的更加簡單,它提供了一個集群和編排的層,用來控制主機上的容器部署,以及部署之后的集群內的容器的生命周期管理。
ECS是諸如 Docker Swarm , Kubernetes , Mesos 等工具的替代,它們工作在同一個層,除了作為一個服務來提供。這些工具和ECS不同的地方在于,前者需要你自己來部署和管理,而ECS是“作為服務”來提供的。
ECS是基于一種專有的集群技術,而不是通過諸如Docker Swarm,Kubernetes,Mesos等引擎實現的。這可以和 Google容器引擎 (GCE)作一對比,GCE后臺使用的就是基于Kubernetes的。
我們為什么需要容器編排?
由ECS,Swarm,或者Kurbernetes所提供的容器編排這一層,在整個部署和運行基于容器的應用程序的整個藍圖中占有非常重要的位置。
首先,我們為了可擴展性需要容器組成集群。隨著我們負載的增長,我們需要增加更多的容器,橫向的擴展它們,跨服務器來并行的處理更高的負載。
第二,我們需要組建容器集群來保證健壯性和高可用性。當一臺主機或一個容器失效時,我們希望容器可以重新構建,或許是在另外一臺健康的主機上重新啟動,從而讓整個系統不會受到任何的影響。
最后,編排層的工具所提供的一個重要功能就是抽象,讓開發者遠離具體的底層實現細節。在容器化的世界中,我們毋需關心每個獨立的主機,只需要關注 我們期望的容器有多少在運行,在‘適當的地方’運行。編排和集群工具為我們做這些,讓我們能夠輕松的將容器部署到集群中,而且還能夠計算出最佳的調度方 式,從而決定容器應該運行在哪些主機上。
設計健壯性和高性能分布式集群系統的難度是非常大的。所以諸如Kubernetes和Swarm這樣的工具讓我們自己毋需去構建集群。ECS借此 更進一步,通過簡化編排層的設置、運行和管理來實現毋需人工參與。基于此緣故,ECS無疑是哪些使用容器來運行應用的開發者們應該密切關注的項目。
ECS架構
ECS并非是一個黑匣子的服務,它運行在你的EC2服務實例中,你可以使用SSH登錄,像管理其它的EC2服務一樣進行管理。
在集群中的EC2服務均會運行著一個ECS代理,ECS代理是一個連接主機到中心的ECS服務的輕量級進程。ECS代理響應主機注冊到ECS服務,且掌控所有的請求,用于容器的部署或者是諸如啟動/停止容器之類的生命周期事件。順便說一下, 使用go實現的ECS代理 已經開源。
當創建一個新的服務器時,我們既可以選擇手動的配置ECS代理,也可以選擇使用預構建的已經配置完畢的AMI鏡像。
通過亞馬遜CTO Werner Vogels的 博客 ,我們得知集中的服務已經邏輯上分為集群管理和在主機上控制容器部署的調度。這背后的緣由就是讓容器的調度成為可插拔式的,所以我們甚至可以使用其它的調 度器,例如Mesos或者是其它開發者自定義的調度器。自定義調度器的文檔在本文撰寫時還在開發當中,但是我們可以閱讀 此博客 以及參考其 源代碼 ,這是目前為止最佳的參考實踐。
下面的示意圖很好的演示了ECS集群的邏輯層次:容器實例包含多個任務,任務包含多個容器,EC2容器實例集群可以分散到多個可用區域中,Elastic Load Balancers可以用于跨任務的動態分布負載。此圖可以幫助讀者在閱讀接下來的內容整理思路。
(點擊放大圖像)
服務和任務
在ECS中,Docker負載被描述為任務。
一個任務本質上是定義了一個或多個容器,其中包括你打算運行的容器的名稱(和 Docker Hub 的名稱保持一致),以及在容器實例啟動時相應的端口和磁盤卷的映射信息。
當任務運行時,則啟動了底層的容器。當所有的容器進程完成使命時,任務也就結束了。任務既可以是很短的也可以是長時間運行的,舉例來說,提供一個數據處理任務的短的事件驅動,或者是一個web服務進程。
這里需要提醒一件事情,那就是架構上給定的一個任務,其所有的容器均運行在同一臺主機中。如果我們打算定位容器的話,那么就使用在同一個任務下來組織它們 的方法來實現。如果我們打算將服務運行在不同的主機,我們則僅需定義多個任務來實現控制即可。初看這似乎是一種約束,但最終它給我們的和 Kubernetes pods 一樣的對容器定位在一定程度的控制能力。
為了說明上述問題,如下面截圖所示,我們可以看到定義了一個特定的任務,此任務擁有一個容器,容器托管nginx web服務。
(點擊放大圖像)
除了任務之外,服務是ECS概念中排名第二重要的。一個服務是給定一個任務所請求運行的特定的實例數量。舉例來說,如果我們有一個如上述所定義的 運行nginx web服務容器的任務的話,我們則要定義一個服務,來請求3個或更多的實例組成集群,從而完成web服務的任務。
服務是ECS如何提供彈性的保證。當一個服務啟動后,服務就會監控其中的任務是否是活動的,實例的數量是否正確,以及其中容器的數量是否正常。如果任務停止運行了,或者是無響應了,又或者是出現問題了。服務就會請求啟動更多的任務,以及必要的話清理任務。
下面截圖所示,在集群中一個nginx服務被定義為3個運行的任務。這些任務個個都處于運行狀態。
(點擊放大圖像)
部署第一個容器
當用戶第一次使用終端訪問ECS服務時,會看到一個簡單的向導。盡管手動的去配置ECS也不是多么繁重的事情,但是第一次的話,使用該向導還是值 得嘗試的,它能夠為你配置好所有-你的EC2服務器,一個合適的安全組,以及一個自動伸縮組,正確的AMI(此AMI內置了ECS代理),等等。這是啟動 和運行,并獲得ECS經驗的最快方法。
(點擊放大圖像)
步驟1 定義任務
首先,作為向導的一部分,我們需要定義任務。這個演示的目的,我們將使用免費的NGINX的Docker鏡像。(NGINX是一款開源的web服務軟件,已經被社區容器化了,并 上傳到了官方hub 。)
以為容器指定一個名稱開始,例如本示例為 nginx-task 。
(點擊放大圖像)
接下來,點擊 添加容器定義 ,即定義nginx容器。 這里主要需提醒的是鏡像的名稱,務必和Docker hub( ngnix )上公開的鏡像名稱一致。當然,也可以 指定專有鏡像 。
內存字段是內存的最大值,以兆字節計算,這是用于分配給運行中的容器的。CPU單元是一個抽象的數字,每個CPU核心有1024個單元,此數字即是要賦予的單元數。
此信息用處非常的大,因為它增加了一定程度的靈活性以及智能的容器調度。ECS將監視那些實例擁有空閑資源,然后智能的分配容器,從而達到實現有效的利用服務器資源的目的。
(點擊放大圖像)
步驟2 定義服務
第二步,我們需要定義服務,即描述為此任務要在集群中運行多少個實例。
選擇創建服務的單選框,為服務命名,本例為nginx-service,然后設置要運行的任務數,本例為3。這就意味著此服務一旦運行起來,就會創建3個任務,每個任務就是一個獨立的實例,每個實例中都運行著nginx容器。
至于更加復雜的配置,你可選擇Elastic Load Balancer (ELB),然后在它們被實例化后動態的將服務注冊到ELB,并實現集群化。這些在后面有詳細的描述。
(點擊放大圖像)
步驟3 創建ECS集群
我們需要創建EC2服務器的集群,這些服務器是用來運行容器的。此演示環境使用3個t2.micro實例即可實現預料的效果。這也就意味著1個任 務和1個容器將分布到這3臺服務器的每一個上。我們當然也可以實現在集群中使用實例多于任務的配置,或者使用這些服務器來運行不同的任務,但是目前還未能 實現在同一臺服務器中運行給定任務的多個實例。
選擇你首要的密鑰對,然后點擊后面的按鈕以創建 IAM角色 ,IAM角色非常重要,有了它,集群中的主機就可訪問中央ECS服務了。
(點擊放大圖像)
步驟4 創建棧
向導的最后一步是展示匯總任務、服務、和集群的配置。
頁面如下所示會展示所生成的JSON代碼,這些代碼同樣可以用于命令行,如果有人習慣于使用命令行的話,或者是打算自動創建它們的集群的話。
(點擊放大圖像)
在創建過程中,你會看到使用Cloud Formation來構建棧。構建棧可能要花上2到3分鐘的時間。
(點擊放大圖像)
步驟5 回顧棧和NGINX服務
現在若是訪問EC2的面板,我們可以看到已經創建好的服務器,且是處于運行狀態的。向導已經幫助我們創建了跨可用區域的主機以演示彈性的好處。
(點擊放大圖像)
然后回到ECS面板,就可以檢查服務了,當然我們希望看到的是它處于準備好的狀態,且擁有3個任務。
記住,在創建實例的過程要花費幾分鐘的時間,從hub拉下容器鏡像啟動也要花費幾分鐘的時間,以及服務達到可用狀態也會花費一些時間,所以,不用擔心這整個過程會稍有些慢。
(點擊放大圖像)
深入服務中某個任務的細節,我們會看到任務處于RUNNING(運行)狀態。
(點擊放大圖像)
展開 nginx-container 。在外部鏈接下方,我們可以看到一個HTTP鏈接,指向任務內的容器。
點擊此鏈接,我們可以看到的是Nginx容器所提供的web歡迎頁面。
(點擊放大圖像)
此時,我們完成了將NGINX容器部署到ECS的步驟,而且可通過web瀏覽器訪問NGINX服務。現在你可以考慮整理下思路和對概念的驗證了。
后續步驟
在建立了一個簡單的容器之后,我們接下來為了將應用部署到生產環境,需要做一些更加高級的配置。
ELB負載均衡
在上述的例子中,我們使用瀏覽器直接鏈接到三個容器中的一個,實現對NGINX的訪問。這不能夠做到健壯性,理論上當容器宕機,或者是重新啟動到不同的服務器上,那么原來指定的靜態IP地址就不在有效了。
我們可以將服務注冊到 EC2 Elastic Load Blance (ELB)以實現動態的地址。作為底層的任務不管如何的啟動、停止以及在EC2實例池中如何的移動,ELB都可以通過服務保持最新,能夠將相應的流量路由到正確的地址。
要配置負載均衡,我們首先需要在EC2的面板中創建一個ELB。然后重新創建服務,在服務創建的過程中將ELB添加進來,如下面截圖所示:
(點擊放大圖像)
自動伸縮
ECS也可以整合 EC2 autoscaling ,而且也是在面臨增加的負載時擴充集群的首選方法。
Autoscaling的工作要依賴于對諸如CPU,內存和IO的計量監控的,而且添加節點或刪除節點是在打破一定的條件時候進行的。
實例化后的新的節點會自動注冊到ECS集群中,然后才有資格成為未來部署容器的實例。
這很實用,但是目前ECS還沒有實現擴充任務數量或者是增長容器集群的Hook。但我們仍然能在新的容器啟動后加入到新的規模的集群中受益,我們可以通過GUI或 API 來引入新的容器到集群,并能在更大規模的集群中分發負載。
容器鏈接
當在任務中定義容器時,是可以使用 Docker原生的容器鏈接 來實現它們之間彼此的互連互通。
這樣就不在需要靜態的端口映射或者是多容器環境中的服務發現了,讓部署分布式的微服務更加的輕松。
AWS 命令行工具
雖然上面的演練是基于UI控制臺,但 ECS完全整合到了AWS命令行中 。
故障排查
若發生了問題,你可以通過SSH直接訪問集群的節點,以進行調試。
為了能夠使用SSH登陸到節點,你需要在安全組中打開22端口,因為通過向導所創建的節點默認不會打開此端口。
登陸到服務器節點后,你就可以查看ECS代理的日志文件:/var/log/ecs了。
你也可以運行標準的Docker命令,例如, docker images 和 docker ps ,來參看服務器上的鏡像和容器的狀態。
總結
本文的目的是對ECS做一介紹,且講述了一個實際演示環境的例子,即部署你的第一個容器集群。
ECS是一款新的產品。很多功能還不是很健全,但是它目前足夠的穩定。我們在我們的測試環境中創建了超過100+個節點的集群,試驗了容器和節點的失效切換,測試了自動伸縮、負載均衡、運行服務,均表現良好。現在我們打算為一些客戶提供ECS到它們的生產環境。
ECS以及和它等同的Googel Container Engine對于容器生態系統來說都是非常重要的。基于容器開發代碼和部署變得更為容易,在其上運行諸如Kubernetes或Mesos的編排層,對于 普通用戶來說這是進入成熟的標記。ECS為容器提供了一個簡單的、可訪問的、穩定的、類似PaaS平臺的產品,這非常的令人興奮,盡管它現在還處于整個進 化過程的早期階段。
關于作者
Benjamin Wootton 是 Contino 的聯合創始人和首席顧問,Contino是一家英國的咨詢公司,主要是為一些企業提供DevOps,持續交付工具等方面的實踐和方法。