《Docker——容器与容器云》:第五章 构建自己的容器云
我們在第1章介紹了一個云計算平臺應有的層次結構,其中平臺即服務層(PaaS)是本書重點著墨描述的。盡管在一些經典PaaS平臺中,容器技術已經扮演了一個至關重要的角色,但很遺憾,大部分經典PaaS平臺中容器功能被局限在了“資源隔離”這狹小的技術范圍當中了。當擁有了像Docker這樣的容器技術后,是時候開始從一個新的角度來思考容器在云計算平臺當中扮演的角色和地位了。
5.1 再談云平臺的層次架構
回顧一下第1章描述的云計算平臺層次,IaaS平臺接管了所有的資源虛擬化工作,通過軟件定義的方式來為云租戶提供虛擬的計算、網絡和存儲資源。PaaS平臺接管了所有的運行時環境和應用支撐工作,云平臺的租戶因此可以申請配額內的計算單元而不是虛擬機資源來運行自己的服務。當前不少經典PaaS平臺已經采用容器作為計算單元,那些仍然依靠虛擬機提供應用運行時支持的“PaaS平臺”在本書中將被稱為“IaaS+平臺”。云平臺調度這些計算單元用以部署和運行租戶的代碼制品。在這兩層的基礎上,用戶部署的應用和服務通過API響應的方式組成一系列集合服務于最終用戶,這就是所謂SaaS1。上述過程其實描述了一個清晰可見的層次結構,如圖5-1所示。
圖5-1 一個傳統云計算平臺的分層結構
在經典云平臺層次體系里,應用實例運行在PaaS平臺所提供的容器環境中,容器在虛擬機基礎上完成了第二層次基礎設施資源的劃分;容器封裝了應用正常運行所需的運行時環境和系統依賴;同時,容器也成為了租戶調度應用、構建應用多實例集群的最直接手段。與IaaS層不同,通常在PaaS層可以采用更貼近應用的資源調度策略。可是,目前遵循這個體系結構構建的經典PaaS平臺中存在一個有趣的現象:租戶從始至終都無法感受到容器的存在!
相比于基于虛擬機提供運行時支持的IaaS+平臺(比如AWS),經典PaaS平臺的租戶甚至都不能進入自己的計算單元(容器)中,這類PaaS平臺就如同一個黑盒,所有"扔"進去的應用就完全脫離了租戶的控制,進入了完全被托管的狀態。誠然,如果一切都有條不紊的運作,該模式可謂完美,因為“所有用戶都是最懶的”這個假設總是成立,而殘酷的現實卻是:“錯誤總是會發生在任何意想不到角落里”。
舉個簡單的例子,一旦應用運行過程中有錯誤發生,云平臺的PaaS層首先會刪除故障實例,然后立即在其他位置恢復這個實例和容器。這個過程中,甚至平臺默認沒有保存現場的過程。浙江大學SEL實驗室云計算團隊曾在Cloud Foundry中增加了從Websocket日志組件收集容器中的應用日志到ElasticSearch的機制,通過該機制在一定程度上能給用戶提供方便的日志信息診斷處理,但對于日志中無法體現的異常還是無能為力,更談不上調試代碼和保存環境上下文了。這樣的先天缺陷,也是后來云計算領域會出現大量“云DevOps工具”,提供一個類似“白盒PaaS”解決方案的重要原因之一。
經典PaaS平臺中,出于安全、封裝等各個方面的考慮,容器總是被故意隱藏在整個云平臺的運行過程當中(如圖5-1所示),因此開發和運維人員失去了往日對應用及其運行時環境的完全掌控能力,試圖重新獲得控制權所做的努力往往要求助于過分晦澀的交互方式和hack般的自定義過程。再加上經典PaaS平臺通常在應用架構選擇、支持的軟件環境服務等方面有較強限制。因此在生產環境下,部分企業和個人開發者會傾向于放棄PaaS層,直接依靠運維力量來分配和調度虛擬機,靠大量自動化工具來維護和支撐所有運行時、應用環境配置、服務依賴、操作系統管理等。這時,傳統云平臺分層結構就會進化成如圖5-2所示的狀態,即”IaaS+“云平臺。
圖5-2 一個典型的“IaaS+”云平臺
本書認為,這種“返璞歸真”的做法是一種值得一試的云計算運維方法,尤其是在大部分IaaS都能夠提供標準而豐富的API的今天。高效便捷的虛擬機DevOps工具在很大程度上彌補了IaaS平臺脫離應用的缺陷;以虛擬機鏡像為基礎可以保證生產環境、測試環境、開發環境上的嚴格一致;IaaS提供商還在不斷推出關系數據庫、NoSQL、日志、Search、對象存儲等構建在虛擬機上的可對外提供服務的鏡像。事實上,基于IaaS的云生態環境已經具有相當高的成熟度。
當然,如果沒有Docker的話。
經典PaaS平臺和IaaS加DevOps工具組成的“IaaS+平臺”還在分庭抗禮,隨著容器技術逐漸步入視野,云平臺建設已經有了新的思路。
相比“IaaS+平臺”,Docker容器啟停速度比虛擬機提高了一個量級,而在資源利用率上容器獨有的高密度部署能力也非普通IaaS提供商所能提供的。更有吸引力的是,大小僅幾十MB的Docker鏡像就完整封裝了Web容器、運行配置、啟動命令、服務hook和所需環境變量,提供了一種全新的應用分發方式,給應用開發者帶來了彌足珍貴的“全環境一致性”保證。相比之下,動輒GB級的虛擬機鏡像在應用部署和分發上就很難再有競爭力了。
相比經典PaaS平臺,Docker的出現使得構造一個對開發和運維人員更加開放的容器PaaS云成為可能,基于容器鏡像的應用發布流程不僅能覆蓋整個應用生命周期,還減少了經典PaaS平臺對應用架構、支持的軟件環境服務等方面的諸多限制,將更多控制力交還給開發和運維人員。這種“降維攻擊”把曾經引起不少爭論的話題再次擺在了開發者面前:PaaS應該以何種形態存在?
本書無意給上述問題尋找一個完美答案,更希望能與讀者一起研究和探索基于容器的云平臺究竟以什么形態出現才更合理。因此,本書為讀者介紹多種類型的容器云平臺。它們中一類更偏向經典PaaS平臺,提供各類“一鍵xx”服務,它們給予用戶最大的方便和更高度的自動化,也因此附加了對應用架構和開發運維自由度限制;另一類則給用戶最大的開發運維自由度,但自動化程度較低,使用相對復雜。也許到閱讀完第二部分內容后,讀者就能找到怎樣的容器云平臺才是最適合自己的。
值得一提的是,不論是采用哪種形態的云平臺,隨著Docker等面向開發者的容器大行其道,本書下面將要著重討論的云平臺都已經變成了圖5-3所示的結構。
圖5-3 一個基于容器的云平臺
在Docker等容器技術很有成為未來應用發布事實標準的當下,必須指出本書進行討論的一個基本立足點:由于當前容器在內核完整性、安全性和隔離性上的固有缺陷,使得目前在大部分場景下我們必然需要虛擬機、虛擬網絡、虛擬存儲的支持;同時,在本書中將不會再過分強調所謂IaaS、PaaS、SaaS三層云計算劃分方式,更多的是將這些概念視為經典技術作為容器云的對照。
本書接下來討論的所有以容器為核心的云平臺都不會鎖定在某種具體IaaS或者PaaS上面,將始終堅持容器云平臺應無差別地工作在物理機上或者虛擬機上這樣樸素的思想,并以此為基礎剖析各類容器云的原理與本質。這或許不太容易,比如Kubernetes天生就是為GCE定制的,而幾乎所有的容器平臺也都以AWS和DigitalOcean作為默認的下層資源依賴。浙江大學SEL實驗室云計算團隊所做的努力將盡可能屏蔽掉這類外部因素,以中立的技術態度貫穿本書的始終。
5.2 從小工到專家
當一個開發者拿到Docker文檔之后,一定會按捺不住內心的激動,把所有的Getting Started跑一遍,當然中間可能會碰到問題,仔細閱讀過本書第一部分的讀者應該能更加游刃有余地做完這些事情。甚至嘗試過第4章的高級玩法后,當第一個DEMO開始工作時,終于可以當仁不讓地宣布自己已經是個高級玩家。
那么問題來了:接下來該做什么?
以一個開發者的視角繼續往下,往后事情的發展無外乎兩種可能:第一,開發者默默地記住這些技能,然后把Docker當作自己的獨門武器,以至于最后老板都開始懷疑這家伙的開發效率怎么會突然變得這么高。第二,熱心的開發者開始向全組推廣Docker,甚至鼓動運維也加入Docker行列。一般情況下,我們會稱贊第二種開發者為“愿意當將軍的士兵”。
于是,我們的“將軍開發者”決定從最簡單的需求開始演示自己的計劃,只用了幾分鐘,他就搭建好了一個容器集群,這是一個來自The Docker Book的例子,與第2章中我們手把手搭建過的“第一個Docker集群”有點類似。
圖5-4 一個Node.js應用和ELK組合的實例
在這個組合實例中,他成功地將一個Node.js應用運行起來,并且使用Redis集群來存儲這個應用的session信息,最后還使用ELK組合(ElasticSearch+Logstash+Kibana)完成了應用和Redis的日志轉發、存儲和檢索功能。當然最酷的一定是這些內容全是跑在Docker容器里的,他只用了幾條命令外加幾分鐘的時間就全部搞定了。團隊里的其他人只要把Dockerfile拿走,幾分鐘就可以搭建一套一模一樣的環境出來!
“真不錯!”大家紛紛稱贊這種基于容器來構建服務棧的方式是多么地優雅。
“可是要上線的話,負載均衡總要有的吧?”一位不大討人喜歡的開發經理提出了第一個需求。
的確,在經典互聯網應用場景里,無論后端系統多么地復雜強大,最前面放置一般都該是負載均衡設備而非Web服務器,并且Load Balancer這一環節還有很多必須額外設定的配置(比如session sticky、靜態動態內容分離、URL重定向等)。在此基礎上,應用還往往被復制成多份,在負載均衡管理下統一提供對外服務,這項技術對于分流、灰度發布、高可用以及彈性伸縮都是必需的。好在有了Docker的幫助,這一切都不算難,“將軍開發者”撓撓頭的功夫就build了一個HAProxy鏡像啟動起來,然后又啟動了一個完全相同的Node.js應用的容器(得益于鏡像,這類操作非常便捷),最后將兩個應用容器的IP和端口配置到了HAProxy的backend servers里面,完成了負載均衡實現的所有工作。
圖5-5 一個添加了負載均衡的Node.js應用和ELK組合的實例
“好像可以工作了呢。”
“等等,負載均衡里怎么能把后端的實例配置成固定參數呢?”
不招人喜歡的開發經理又提出了第二個需求,而且還有點棘手。
首先要面對的問題是,怎么才能保證后端應用容器失敗重啟或者升級擴展之后,HAProxy能及時更新自己的配置文件呢?要知道Docker容器可沒有靜態IP這個說法(至少在學習過本書高級網絡實踐之前是這樣的)。不過如果求助于GitHub情況就不一樣了,“將軍開發者”很快找到一個專門負責配置文件遠程修改的組件confd。
第二個要面對的問題是,哪個組件負責探測應用容器退出或者創建的事件發生然后通知confd修改HAProxy配置文件呢?這可讓“將軍開發者”著實花了一番心思。
“這好像是一個服務發現的場景呢。”
沒錯!所有應用容器都應該把本身IP和端口信息注冊到etcd當中去(etcd是服務發現存儲倉庫,將在第6章詳細介紹),然后依靠confd定時查詢etcd中數據變化來更新HAProxy的配置文件。不需要寫很多代碼,只需要配置一下confd,然后build一個新的HAProxy和一個etcd容器就足夠了。話音未落,“將軍開發者”的新系統又上線了。
圖5-6 一個添加了負載均衡和自發現特性的Node.js應用和ELK組合的實例
這樣應該可以了吧。確切地說,這個服務棧不僅擁有了負載均衡和多實例的功能,還能夠以一種“發現”的方式向負載均衡節點注冊或者解注冊應用實例,而且整個過程都是平滑升級的,不會出現服務中斷。
“應用健康檢查怎么辦?”一直在旁默不作聲的運維終于坐不住了。
“自發現”機制確實保證了容器自身高可用能力,但是容器中運行著的應用進程實際上并不是完全保險的。最典型的場景是Java Web Server:當應用異常的時候,Web Server是完全有可能不退出的,用戶只能拿到4XX或者5XX的返回值。所以,在一個真實的應用平臺需求下,“垂直監控”是非常有必要的,至少需要能檢測到應用訪問的返回值是2XX。
這還不算完。“將軍開發者”雖然構建了一個多實例的應用集群,但生產環境下,這些實例應該將會分布在不同服務器上。這又會帶來新的問題,如下所示。
- 如何保證同一個應用的不同容器實例分布在不同或者指定的宿主節點上?
- 當一個宿主節點意外退出的時候,如何保證該節點上的容器實例能夠在其他宿主節點上恢復?
- 如何比較當前容器實例的運行情況同期望的運行狀態的差異,用以決定是否要進行上述高可用動作?
- 如何構建一個覆蓋“測試-開發-上線”完整流程的運行機制來充分發揮Docker鏡像的一致性?
- Docker容器本身的網絡應如何配置,尤其是在跨主機環境下怎么處理,是否需要靜態IP?
- 當開發者創建的鏡像非常多時,復雜的鏡像關系會大大拖延容器創建和啟動速度,這時該如何處理復雜關系對容器性能的影響?
- 大量刪除操作可能帶來不可預知的“孤兒”容器,不光占用大量資源,還可能帶來各種莫名異常,造成大量“孤兒”容器的局面該如何應對?
- 掛載Volume的數據該如何進行備份,是否需要實現高可用或跨主機遷移?磁盤寫滿該如何處理?
-
所有CPU、MEM、DISK資源限制如何才算合理?不合理的資源限制加上欠考慮的調度策略會不會產生新的資源浪費?
-
……
“將軍開發者”突然發現,原來說服別人接受自己計劃所面臨的困難要遠比搭建DEMO大得多,尤其是需要涉及現有的生產環境時。事實上,Docker是運維友好的,相比傳統運維方式,通過流程和規范來保證環境一致性的做法,Docker鏡像已經給運維工作帶來了很大便利,更不用說它幾乎可以忽略的啟動時間和簡單高效的配置方式了。同樣,Docker更是開發者友好的,光是它伸手即來的安裝和啟動方式以及靈活通用的Dockerfile就足以讓傳統PaaS提供商汗顏。此外,它不存在任何供應商鎖定和引入特殊依賴的問題了。可是,就是這樣一種對各利益方都友好的技術,在真正用于生產環境時卻需要解決一個棘手的問題:如何使用Docker特性來提供、升級和簡化現有生產環境已經具備的運維能力?
引發這個問題的原因其實很簡單,Docker給工業界帶來的不只是一項技術——容器技術已經足夠普及了——它帶來的更多是一種思維轉變。遺憾的是,Docker的思考方式與目前任何一項業務運行的方式都不是原生兼容的。
這解釋了為什么我們在自建的環境中使用Docker能如魚得水,一旦想要將它推廣至生產環境中,就會感到十分棘手。而且我們發現,這些困難往往不是來自容器技術本身,而是與容器相關的網絡、存儲、集群、高可用等已經在傳統場景中得到解決的“泥潭”。為了解決這些問題,我們的“將軍開發者”就不得不經歷一次又一次“從小工到專家”的歷練,他開始研究HAProxy和etcd,開始寫Docker scheduler、health checker、stager、builder、deployer,終成一代“Docker大神”。
最后,我們的開發經理終于提出了一個終極需求:能不能讓開發愉快地開發,運維輕松地運維,大家一起快樂地做Docker小伙伴呢?
答案當然是:“可以的。”
現在就讓我們來聊聊“容器云”吧。
“容器云”最直觀的形態都是一個頗具規模的容器集群。但它與開發者或者運維人員自己維護的“裸”容器集群不同。容器云中會被按功能或者依賴敏感性劃分成組,不同容器組之間完全隔離,組內容器允許一定程度共享。容器之間的關系不再簡單依靠docker link這類原生命令來進行組織,而往往是借助全局網絡管理組件來進行統一治理。容器云用戶也不需要直接面對Docker API,而是借助某種控制器來完成用戶操作到Docker容器之間的調用轉譯,從而保證底層容器操作對最終用戶的友好性。大多數容器云還會提供完善的容器狀態健康檢查和高可用支持,并盡可能做到旁路控制而非直接侵入Docker體系,從而免除“將軍開發者”們不得不重復造輪子的尷尬。“容器云”會提供一個高效、完善、可配置的調度器,調度器可以說是容器云系統需要解決的第一要務,這也正是“將軍開發者”最頭痛的事情——他面對的容器越多,運維和管理困難程度往往會呈指數級上升。在接下來的章節中,讓我們一起來逐層揭開“容器云”的面紗。
它們或來自于小而美的創業團隊,或來自于數一數二的業界巨頭;有的專注于服務發布,有的專注于數據存儲;有的只解決編排與運維,有的卻幾乎可以媲美一個傳統IaaS。但是,無論是那些靈活輕巧的編排工具還是龐大復雜的容器服務,它們都試圖為熱愛Docker并嘗試真正應用Docker的“將軍開發者”們解決一個核心問題:如何邁過從“容器運行”到“生產使用”之間的這條鴻溝。
1這個描述見http://www.programmableweb.com/news/new-enterprise-big-data-mobile-and-saas-api-economy/analysis/2013/09/25。
from:?http://www.ituring.com.cn/tupubarticle/4444
總結
以上是生活随笔為你收集整理的《Docker——容器与容器云》:第五章 构建自己的容器云的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Docker——容器与容器云》:第一章
- 下一篇: 部分数学课件