天天看點

建構容器應用的8個最佳實踐

容器是未來在共有雲和私有雲進行應用開發的主要趨勢,但是容器到底是什麼,為什麼它們成為了一種廣受歡迎的部署機制,而且你需要怎樣來修改你的應用來為容器化的環境優化它?

容器是未來在共有雲和私有雲進行應用開發的主要趨勢,但是容器到底是什麼,為什麼它們成為了一種廣受歡迎的部署機制,而且你需要怎樣來修改你的應用來為容器化的環境優化它?

建構容器應用的8個最佳實踐

什麼是容器?

容器技術的曆史始于 2000 年的 SELinux 和 2005 年的 Solaris zones。今天,容器是由包括 SELinux、Linux 命名空間和控制組(cgroup)等幾項核心特性構成,提供了使用者程序、網絡空間和檔案系統空間的隔離。

為什麼它們如此流行?

最近容器技術大規模的應用在很大程度上是由于旨在使容器更加易于使用的标準的發展,例如 Docker 鏡像格式和分布模型,這個标準使用不可變鏡像(immutable image),這正是容器運作時環境的起點,不可變鏡像可以保證開發團隊釋出的鏡像就是經過測試的,和部署到生産環境中的鏡像是同樣的鏡像。

容器所提供的輕量級隔離為一個應用元件提供了一個更好的抽象。在容器中運作的元件将不會幹擾其它可能直接運作在虛拟機上的應用。它們可以避免對系統資源的争奪,而且除非它們共享一個持久卷,否則不會阻止對同一個檔案的寫請求。容器使得日志和名額采集的實踐得以标準化,而且它們可以在實體機和虛拟機上支援更大的使用者密度,所有的這些優點将導緻更低的部署成本。

我們應該如何建構一個基于容器的應用呢?

将應用改為運作在容器中并不是什麼很高的要求。主要的 Linux 發行版都有提供了基礎鏡像,任何可以在虛拟機上運作的程式都可以在上面運作。但是容器化應用的趨勢是遵循如下最佳實踐:

建構容器應用的8個最佳實踐

1. 執行個體是一次性的

你的應用的任何執行個體都不需要小心地保持運作。如果你的一個運作了許多容器的系統崩潰了,你還能夠轉移到其它可用的系統去建立新的容器。

2. 重試而不是崩潰

當你的應用的一個服務依賴于另一個服務的時候,在另一個服務不可用的時候它應該不會崩潰。例如,你的 API 服務正在啟動而且監測到資料庫不能連接配接。你應該設計它使得其不斷重試連接配接,而不是運作失敗和拒絕啟動。當資料庫連接配接斷開的時候 API 可以傳回 503 狀态碼,告訴用戶端服務現在不可用。應用應該已經遵守了這個實踐,但是如果你正在一個一次性執行個體的容器環境中工作,那麼對這個實踐的需要會更加明顯。

3. 持久性資料是特殊的

容器是基于共享鏡像啟動,它使用了寫時複制(COW)檔案系統。如果容器的程序選擇寫入檔案,那麼這些寫的内容隻有在直到容器存在時才存在。當容器被删除的時候,寫時複制檔案系統中的那一層會被删除。提供給容器一個挂載的檔案系統目錄,使之在容器存活之外也能持久儲存,這需要另外的配置,而且會額外消耗實體存儲。明确的抽象定義了什麼存儲是持久的,催生出了執行個體是一次性的觀點。擁有一個抽象層也使得容器編制引擎可以處理挂載和解除安裝持久卷的複雜請求,以便這些持久卷可以用于容器。

4. 使用 stdout 而不是日志檔案

現在你或許會思考,如果持久的資料是特殊的,那麼我用日志檔案來做什麼事情?容器運作時環境和編制引擎項目所采用的方法是程序應該寫入 stdout/stderr,而且具有歸檔和維護容器日志的基礎設施。

5. 敏感資訊(以及其它配置資訊)也是特殊的

你絕不應該将敏感資訊例如密碼、密鑰和證書寫死到你的鏡像中。通常在你的應用與開發服務、測試服務,或者生産服務互相動時,這些敏感資訊通常都是不同的。大多數開發者并沒有通路生産環境的敏感資訊的權限,是以如果敏感資訊被打包到鏡像中,那麼必須建立一個新的鏡像層來覆寫這個開發服務的敏感資訊。基于這一點來看,你再也不能使用與你們開發團隊所建立的和品質測試所測試的相同的鏡像了,而且也失去了不可修改的鏡像的好處。相反的,這些值應該被存儲在環境變量中檔案中,它們會在容器啟動時導入。

建構容器應用的8個最佳實踐

6. 不要假設服務的協同定位

在一個編排好的容器環境中,你會希望讓編排器将你的容器發送到任何最适合的節點。最适合意味着很多事情:它應該基于那個節點現在擁有最多的空間、容器所需的服務品質、容器是否需要持久卷,等等。這可能意味這你的前端、API 和資料庫容器最終都會放在不同的節點。盡管給每個節點強制配置設定一個 API 容器是可以做到的(參考 Kubernetes 的 DaemonSets),但這種方式應該留給執行監控節點自身這類任務的容器。

7. 備援/高可用計劃

即使你沒有那麼多負載需要高可用性的配置,你也不應該以單路方式編寫服務,否則會阻止它運作多份拷貝。這将會允許你運用滾動式部署,使得将負載從一個節點移動到另外一個節點非常容易,或者将服務從一個版本更新到下一個版本而不需要下線。

8. 實作就緒檢查和靈活性檢查

應用在響應請求之前會有一定的啟動時間是一件很正常的事情,例如,一個 API 伺服器需要填充記憶體資料緩存。容器編排引擎需要一種方法來檢測你的容器是否準備好服務使用者請求。為一個新的容器提供就緒檢查可以允許我們進行滾動式部署,使得舊容器可以繼續運作直到不再需要它,這可以防止服務當機。類似的,一個存活檢查也是一種容器編排引擎持續檢查容器是否在健康可用狀态的方法。決定容器健康或者說“存活”應該由容器應用的建立者說了算。一個不再存活的容器将會被結束,而且一個新的容器會被建立來替代它。

想查找更多資料?

我将會出席十月份的格雷絲霍普計算機女性峰會(Grace Hopper Celebration of Women in Computing),你可以在這裡來看一下關于我的訪談:應用的容器化:是什麼,為什麼,和如何實作。今年不去 GHC 嗎?那你可以在 OpenShift 和 Kubernetes 的項目站點來了解關于容器、編排和應用的相關内容。

https://www.linuxprobe.com/eight-apply-practice.html