基于Docker的開發云提高資源利用率的實踐
Docker的出現,為更簡便、更細粒度地對云資源的調控提供了一個強有力的支撐,WeX5開發者云基于Rancher+Docker,在如何提高物理資源利用率的課題上做了一些探索和研究,在保障用戶體驗良好的前提下,大大提高了物理資源的利用率,有效地降低了運營成本。
一般情況下,開發者從無到有開發一個可用于公網訪問的HTML5的App應用的流程是這樣的:配置開發環境、開發應用、本地調試、租用公網服務器、注冊域名、遠程部署、遠程調試,就算是一個很有經驗的開發者,這整個過程還是需要花費不少時間,尤其是面對一個不斷更新修改的應用。
WeX5作為HTML5 App的開發工具,很有必要為WeX5開發者提供一個從開發到部署、運維的一體化云平臺,實現WeX5之上的DevOps,讓開發者更專注于應用開發,而不再關注應用的部署運維。而WeX5也因此由比較純粹的應用開發工具演變為“開發云”。
對于WeX5開發云來說,在實現DevOps時,其需求場景有兩大特點:首先,開發者眾多,用于測試演示的應用多,但是訪問很少,并發低,資源利用率很低,同時又要求很高的響應速度,另一方面,WeX5開發云還提供在線設計IDE,這類IDE容器非常耗費資源,但是并發占用率不高,用戶連續長時間使用的可能性也不大。
這就要求我們的WeX5開發云在有限的成本支撐下能夠盡可能地提高資源利用率,并且保障應用的可用性,經過一番努力,我們探索出以下幾條途徑:
-
智能路由
-
自動啟停
-
資源調控
-
動態應用部署
-
容器資源池
首先我們來看下WeX5開發云的基礎架構層次,主要是讓大家對整體架構有個映像,跟今天主題其實關系不大。
其中,IaaS層由阿里云支持,Monitor層采用Open-Falcon、Prometheus實現,Container Cluster采用Rancher+Docker實現,Controller Gateway由AutoStart、Regulator、IDE Pool、Proxy等組件組成。
下面來詳細介紹下我們是如何提高資源利用率的:
一、智能路由
應對場景:統一的訪問入口對接各個子網絡,環境與環境之間隔離,并且多個子網關之間要能夠做到一定程度的負載均衡。
實現邏輯:創建應用的時候,會根據LoadBalancer集群的負載情況,選擇一個負載較少的LoadBalancer作為該應用的路由網關,提供負載均衡及路由轉發功能。控制網關接收到訪問請求后,根據請求域名與LoadBalancer的映射關系,將請求轉發到該LoadBalancer上。如上圖所示,ENV_01與ENV_02的Docker網絡是隔離的,在同一個環境中,請求域名與LoadBalancer的綁定可以動態調配。
二、自動啟停
應對場景:目前WeX5開發云上的應用以開發者測試演示應用為主,這類應用的特點是數量多、訪問少,甚至有很多應用創建后訪問一兩次,就再也沒有訪問,長此以往,這類應用會逐步占用大量的物理資源,如果按傳統方法,直接將這些應用清除,又難以保證不會影響開發者的下一次使用,這就要求我們尋找一個既能為開發者不可預期的訪問提供支持,又能保證資源的的最大化利用的解決方案。
實現邏輯:應用創建后系統默認應用是停止狀態,控制網關接收到第一次訪問的時候,會調用Rancher API啟動該應用,并且在redis中為該應用記錄一個生存時間,在該時間范圍內,認為該應用是健康運行的,再次接收到的請求立即轉發并刷新生存時間。若一段時間沒接收到訪問請求,生存時間結束,觸發事件調用Rancher API接口停止該應用,釋放物理資源。
三、資源調控
應對場景:為了最大化地利用物理機的資源,WeX5開發云引入了自動啟停技術,物理資源會處于超售狀態,超售能夠降低成本,最大化地利用物理機的資源,但同時也會帶來資源爭取的情況,甚至會因為節點上運行狀態容器的資源消耗量超出系統負荷,導致節點宕機。
實現邏輯:Redis中記錄應用最后一次訪問的時間,Open-Falcon中監控各個Host主機的物理資源,當某項物理資源指標達到預設閥值的時候,觸發事件調用Regulator API,計算該主機上最后一次訪問時間最早的若干個應用,并調用Rancher API接口將其停止,釋放資源。
四、動態應用部署
應對場景:開發測試過程中的應用往往需要頻繁更新調整,對于有依賴關系的應用來說,頻繁的中斷服務會影響這些應用的可用性,即使是通過灰度滾動升級,也需要不斷地調整鏈接參數。
實現邏輯:采用Rancher中的Sidekick機制,將整個的Wex5應用分為Wex5 App容器(負責運行時環境)、MySQL容器(負責數據存儲)與Deployer容器(負責提供用戶數據),當應用代碼文件等有更新時,提交到Deployer并執行重啟,即可完成整個Wex5應用的更新升級并且保證服務的不間斷運行。
五、容器資源池
應對場景:WeX5開發云上提供了Wex5應用在線設計IDE,這個在線設計的應用也是跑在容器中的,但是由于設計器本身需要加載大量的資源文件,如果由開發者自行創建一個在線IDE的容器,從創建到正常運行大概需要30秒,時間等待較長,即使加入自動啟停功能,第一次訪問啟動容器的時間也在15-20秒左右,用戶體驗太差,所以我們需要一個類似于數據庫資源池的功能,將IDE容器與開發者資源分離,其中的IDE容器長時間處于運行狀態,開發者獲取該資源的使用權限后,只需要加載開發者的資源文件即可正常訪問,這樣就可以大大優化用戶體驗。
實現邏輯:IDE資源池為了節省物理資源,同樣加入了自動啟停機制,將資源池分為POOL_ACTIVE與POOL_INACTIVE兩塊,開發者訪問在線設計功能時,控制網關首先接收到請求,從POOL_ACTIVE資源池中獲取一個運行狀態的IDE容器,與開發者的訪問域名綁定,并且在redis中為記錄一個生存時間,在該時間范圍內,該開發者具有此容器的使用權限,再次接收到的請求立即轉發并刷新生存時間,同時,從POOL_INACTIVE中啟動一個備用資源補充到POOL_ACTIVE資源池中。若開發者一段時間沒有訪問該IDE資源,生存時間結束,該資源釋放到POOL_INACTIVE,并刪除開發者上傳的資源文件。
總的來說,智能路由組件可以融合多個小網絡形成一個大網絡,自動啟停組件及時釋放無訪問的應用所占用的資源,資源調控組件緩解了偶爾出現的峰值訪問壓力,動態應用部署組件讓更新升級不再影響應用的可用性,資源池組件提供更快更穩定的訪問體驗,通過這些手段,可以做到在保障用戶體驗良好的前提下,大大提高了物理資源的利用率,有效地降低了運營成本。
對于開發者來說,開發流程簡化為:本地開發(或在線開發)、一鍵部署、公網訪問,不再繁瑣、便捷高效、隨時可用,這就是WeX5開發云實現此DevOps的意義之所在。
Docker使用過程中遇到的問題:
-
Docker的存儲驅動,早期我們使用的是Docker默認的Devicemapper(loop)的存儲驅動,存在很大問題,尤其是數據盤的大小不是絕對固定的情況下,很容器導致docker數據丟失,建議采用Devicemapper(direct-lvm)、OverlayFS、AUFS等作為Docker的存儲驅動。
-
Docker Daemon服務執行重啟操作的過程中,會執行Docker容器的啟動操作,假如有容器強依賴其他容器的話,這個啟動過程就會出現問題,例如我們使用Convoy NFS服務作為外部卷存儲的統一提供者,其他Docker容器需要掛載的Volume由Convoy NFS統一管理,這時候如果Convoy NFS容器沒有啟動的話,掛載了Volume的容器也無法啟動,Docker Daemon的重啟進程會不斷嘗試啟動各個容器,直到把Convoy NFS容器啟動起來,其他的容器才會慢慢正常啟動,這個情況在容器量不大的情況下并不明顯,但是如果主機上有幾百個容器,這就會耗費很長時間,一度讓我們懷疑系統是由于其他原因導致了宕機。Docker1.12中Docker Daemon添加了一個 –live-restore 的參數,使得當Docker Daemon停止運行時,容器仍然可以保持運行以解決此類問題。
Q&A
Q:你好,你們有做不影響服務的升級和自動伸縮嗎?
A:是的,上邊提到的“動態應用部署”組件就是能夠實現應用的升級更新不受影響,自動伸縮通過Rancher的監控和應用多實例來實現,監控到應用容易的CPU、內存、網絡等如果在一個時間段內一直處于較高的利用率,就增加應用實例,反之則減少,保證應用的連續性。
Q:請問對Docker學習需要看Docker源碼嗎? 還是用Docker等工具來解決問題就可以了?
A:這個得根據實際需要來了,如果是說需要從Docker容器層面上來定制開發,那Docker源碼肯定是需要去研究的,若僅僅是將Docker作為工具使用,那關注點可以放在相關的工具如Rancher、Mesos、Kubernetes等,當然了,若時間允許,了解源碼好處多多,可以從底層弄清楚Docker的各種機制,有利無弊。
Q:請問在容器資源池部分提到的 “運行狀態的IDE容器,與開發者的訪問域名綁定” 假設有兩個用戶 用戶A和用戶B,他們訪問的域名分別是什么?
A:這個是用戶自定義的二級域名,假如基于頂級域名cloudx5.com,用戶A創建一個IDE實例,這是他可以輸入一個二級域名如a.cloudx5.com(或者我們自動生成一個),資源池組件就會將這個域名與獲取的IDE容器綁定,用戶A就可以訪問了。
Q:想問下Docker部署應用,應用配置參數怎么處理?改一個參數就要重新打一包嗎?
A:其實在我們這個結構中,用戶并不需要關心打包及參數配置,他需要做的,就是把開發的代碼上傳,我們后端使用了Jenkins來做統一的打包,打包完成后會調用“動態應用部署”環節提到的Deployer容器,這個Deployer會去約定好的目錄下載打包好的文件做部署配置。
Q:實例收縮的時候能保證釋放的容器沒有業務訪問?
A:這個不需要保證,運行著的實例容器都是無狀態的,實例之間的Session是共享的,需要持久化的數據也是存在別的容器中的如MySQL。
Q:LB路由WebApp的時候是按照IP尋址的嗎?這樣如何保證WebApp重啟時候IP不變化?
A:LB路由的本質是一個帶有服務發現功能的Haproxy,WebApp重啟后IP變化了,LB會得知這個變化并修改配置和reload。
Q:就是說配置文件還是打到Docker里的,比如這時開發要改個配置或加一配置,而代碼都沒變,這時只能在打一個新的包?
A:關于這個我們做了一些約定,例如上邊講到的一個最基本的Wex5應用,我們將其分為Wex5 APP容器、MySQL容器與Deployer容器,APP應用容器訪問MySQL容器都是通過Rancher的內部DNS解析MySQL容器在Rancher中的服務名稱來訪問,這個是相對固定的,例如在外賣APP應用中配置的MySQL的地址是:database.waimai,database是服務名稱,waimai是Rancher的stack名稱。
來自:http://mp.weixin.qq.com/s?__biz=MzA5OTAyNzQ2OA==&mid=2649692270&idx=1&sn=8c477f50a902afa083f6649fcd97a44f&chksm=8893270dbfe4ae1bd4bb12bdc69c0018b57c6670ab8830e006cd7e4831198c05bbf9f0b3fe2c&mpshare=1&scene=1&srcid=1024emINhaZyvglMqbPmrC8d#rd