容器是將來在共有云和私有云進行應用開發的主要趨勢,可是容器究竟是什麼,爲何它們成爲了一種廣受歡迎的部署機制,並且你須要怎樣來修改你的應用來爲容器化的環境優化它?html
什麼是容器?前端
容器技術的歷史始於 2000 年的 SELinux 和 2005 年的 Solaris zones。今天,容器是由包括 SELinux、Linux 命名空間和控制組(cgroup)等幾項內核特性構成,提供了用戶進程、網絡空間和文件系統空間的隔離。linux
爲何它們如此流行?數據庫
最近容器技術大規模的應用在很大程度上是因爲旨在使容器更加易於使用的標準的發展,例如 Docker 鏡像格式和分佈模型,這個標準使用不可變鏡像(immutable image),這正是容器運行時環境的起點,不可變鏡像能夠保證開發團隊發佈的鏡像就是通過測試的,和部署到生產環境中的鏡像是一樣的鏡像。緩存
容器所提供的輕量級隔離爲一個應用組件提供了一個更好的抽象。在容器中運行的組件將不會干擾其它可能直接運行在虛擬機上的應用。它們能夠避免對系統資源的爭奪,並且除非它們共享一個持久卷,不然不會阻止對同一個文件的寫請求。容器使得日誌和指標採集的實踐得以標準化,並且它們能夠在物理機和虛擬機上支持更大的用戶密度,全部的這些優勢將致使更低的部署成本。服務器
咱們應該如何構建一個基於容器的應用呢?網絡
將應用改成運行在容器中並非什麼很高的要求。主要的 Linux 發行版都有提供了基礎鏡像,任何能夠在虛擬機上運行的程序均可以在上面運行。可是容器化應用的趨勢是遵循以下最佳實踐:app
1. 實例是一次性的測試
你的應用的任何實例都不須要當心地保持運行。若是你的一個運行了許多容器的系統崩潰了,你還可以轉移到其它可用的系統去建立新的容器。優化
2. 重試而不是崩潰
當你的應用的一個服務依賴於另外一個服務的時候,在另外一個服務不可用的時候它應該不會崩潰。例如,你的 API 服務正在啓動並且監測到數據庫不能鏈接。你應該設計它使得其不斷重試鏈接,而不是運行失敗和拒絕啓動。當數據庫鏈接斷開的時候 API 能夠返回 503 狀態碼,告訴客戶端服務如今不可用。應用應該已經遵照了這個實踐,可是若是你正在一個一次性實例的容器環境中工做,那麼對這個實踐的須要會更加明顯。
3. 持久性數據是特殊的
容器是基於共享鏡像啓動,它使用了寫時複製(COW)文件系統。若是容器的進程選擇寫入文件,那麼這些寫的內容只有在直到容器存在時才存在。當容器被刪除的時候,寫時複製文件系統中的那一層會被刪除。提供給容器一個掛載的文件系統目錄,使之在容器存活以外也能持久保存,這須要另外的配置,並且會額外消耗物理存儲。明確的抽象定義了什麼存儲是持久的,催生出了實例是一次性的觀點。擁有一個抽象層也使得容器編制引擎能夠處理掛載和卸載持久卷的複雜請求,以便這些持久卷能夠用於容器。
4. 使用 stdout 而不是日誌文件
如今你或許會思考,若是持久的數據是特殊的,那麼我用日誌文件來作什麼事情?容器運行時環境和編制引擎項目所採用的方法是進程應該寫入 stdout/stderr,並且具備歸檔和維護容器日誌的基礎設施。
5. 敏感信息(以及其它配置信息)也是特殊的
你毫不應該將敏感信息例如密碼、密鑰和證書硬編碼到你的鏡像中。一般在你的應用與開發服務、測試服務,或者生產服務相交互時,這些敏感信息一般都是不一樣的。大多數開發者並無訪問生產環境的敏感信息的權限,因此若是敏感信息被打包到鏡像中,那麼必須建立一個新的鏡像層來覆蓋這個開發服務的敏感信息。基於這一點來看,你不再能使用與大家開發團隊所建立的和質量測試所測試的相同的鏡像了,並且也失去了不可修改的鏡像的好處。相反的,這些值應該被存儲在環境變量中文件中,它們會在容器啓動時導入。
6. 不要假設服務的協同定位
在一個編排好的容器環境中,你會但願讓編排器將你的容器發送到任何最適合的節點。最適合意味着不少事情:它應該基於那個節點如今擁有最多的空間、容器所需的服務質量、容器是否須要持久卷,等等。這可能意味這你的前端、API 和數據庫容器最終都會放在不一樣的節點。儘管給每一個節點強制分配一個 API 容器是能夠作到的(參考 Kubernetes 的 DaemonSets),但這種方式應該留給執行監控節點自身這類任務的容器。
7. 冗餘/高可用計劃
即便你沒有那麼多負載須要高可用性的配置,你也不該該以單路方式編寫服務,不然會阻止它運行多份拷貝。這將會容許你運用滾動式部署,使得將負載從一個節點移動到另一個節點很是容易,或者將服務從一個版本更新到下一個版本而不須要下線。
8. 實現就緒檢查和靈活性檢查
應用在響應請求以前會有必定的啓動時間是一件很正常的事情,例如,一個 API 服務器須要填充內存數據緩存。容器編排引擎須要一種方法來檢測你的容器是否準備好服務用戶請求。爲一個新的容器提供就緒檢查能夠容許咱們進行滾動式部署,使得舊容器能夠繼續運行直到再也不須要它,這能夠防止服務宕機。相似的,一個存活檢查也是一種容器編排引擎持續檢查容器是否在健康可用狀態的方法。決定容器健康或者說「存活」應該由容器應用的建立者說了算。一個再也不存活的容器將會被結束,並且一個新的容器會被建立來替代它。
想查找更多資料?
我將會出席十月份的格雷絲霍普計算機女性峯會(Grace Hopper Celebration of Women in Computing),你能夠在這裏來看一下關於個人訪談:應用的容器化:是什麼,爲何,和如何實現。今年不去 GHC 嗎?那你能夠在 OpenShift 和 Kubernetes 的項目站點來了解關於容器、編排和應用的相關內容。