本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
分散式系統工具包:複合容器的模式
我有幸在 DockerCon 2015 上介紹了 Kubernetes 的一些想法,我想寫一篇部落格文章來分享這些想法,以饗那些未能到場的朋友。
在過去的兩年裡,容器已成為打包和部署程式碼越來越流行的方式。容器映象解決了現有打包和部署工具的許多實際問題,但除了這些顯著的優勢之外,容器還為我們提供了一個從根本上重新思考分散式應用程式構建方式的機會。正如面向服務架構 (SOA) 鼓勵將應用程式分解為模組化、專注的服務一樣,容器應該鼓勵將這些服務進一步分解為緊密協作的模組化容器。透過建立邊界,容器使使用者能夠使用模組化、可重用的元件構建其服務,這反過來使得服務比由單體容器構建的應用程式更可靠、更具可伸縮性且構建速度更快。
在許多方面,從虛擬機器到容器的轉變就像從 20 世紀 70 年代和 80 年代初期的單體程式到 20 世紀 80 年代後期及以後的模組化面向物件程式的轉變。容器映象提供的抽象層與面向物件程式設計中類的抽象邊界有很大的共同之處,它提供了相同的機會來提高開發人員的生產力和應用程式的質量。正如正確的編碼方式是將關注點分離到模組化物件中一樣,在容器中打包應用程式的正確方式是將關注點分離到模組化容器中。從根本上說,這意味著不僅要分解整個應用程式,還要將任何一臺伺服器中的各個部分分解為多個易於引數化和重用的模組化容器。透過這種方式,就像現代語言中無處不在的標準庫一樣,大多數應用程式開發人員可以將其他人編寫的模組化容器組合在一起,並以更高質量的元件更快地構建他們的應用程式。
模組化容器思維的好處是巨大的,特別是,模組化容器提供了以下優勢:
- 加速應用程式開發,因為容器可以在團隊之間甚至更廣泛的社群中重用
- 將專家知識編纂成文,因為每個人都在一個反映最佳實踐的單一容器化實現上協作,而不是無數具有大致相同功能的自制容器
- 賦能敏捷團隊,因為容器邊界是團隊職責的天然邊界和契約
- 提供關注點分離,並專注於特定功能,從而減少義大利麵式依賴和不可測試的元件
從模組化容器構建應用程式意味著要考慮協同工作的容器組來提供服務,而不是每個服務一個容器。在 Kubernetes 中,這種模組化容器服務的體現是 Pod。Pod 是一組共享檔案系統、核心名稱空間和 IP 地址等資源的容器。Pod 是 Kubernetes 叢集中排程的原子單元,正是因為 Pod 中容器的共生性質要求它們必須共同排程到同一臺機器上,而可靠實現這一點的唯一方法是使容器組成為原子排程單元。
當您開始以 Pod 為單位思考時,自然會出現一些通用的模組化應用程式開發模式。我相信隨著 Kubernetes 的發展,更多這樣的模式將被識別出來,但這裡有三個我們常見的模式:
示例 #1:Sidecar 容器
Sidecar 容器擴充套件並增強“主”容器,它們獲取現有容器並使其變得更好。例如,考慮一個執行 Nginx Web 伺服器的容器。新增一個與 Git 倉庫同步檔案系統的不同容器,在容器之間共享檔案系統,你就構建了 Git 推送到部署。但是你以模組化的方式完成了它,其中 Git 同步器可以由不同的團隊構建,並且可以在許多不同的 Web 伺服器(Apache、Python、Tomcat 等)中重用。由於這種模組化,你只需編寫和測試你的 Git 同步器一次,並在眾多應用程式中重用它。如果其他人編寫它,你甚至不需要這樣做。
示例 #2:大使容器
大使容器將本地連線代理到外部世界。例如,考慮一個帶有讀副本和單個寫主節點的 Redis 叢集。您可以建立一個 Pod,將您的主應用程式與一個 Redis 大使容器組合在一起。大使是一個代理,負責拆分讀寫請求並將它們傳送到適當的伺服器。由於這兩個容器共享一個網路名稱空間,它們共享一個 IP 地址,並且您的應用程式可以在“localhost”上開啟連線並找到代理,而無需任何服務發現。就您的主應用程式而言,它只是連線到 localhost 上執行的 Redis 伺服器。這非常強大,不僅因為關注點分離和不同團隊可以輕鬆擁有元件的事實,還因為在開發環境中,您可以簡單地跳過代理並直接連線到 localhost 上執行的 Redis 伺服器。
示例 #3:介面卡容器
介面卡容器標準化和規範化輸出。考慮監控 N 個不同應用程式的任務。每個應用程式可能以不同的方式匯出監控資料。(例如 JMX、StatsD、應用程式特定統計資訊),但每個監控系統都期望其收集的監控資料具有一致且統一的資料模型。透過使用複合容器的介面卡模式,您可以將來自不同系統的異構監控資料轉換為統一的表示形式,方法是建立將應用程式容器與知道如何進行轉換的介面卡分組的 Pod。同樣,由於這些 Pod 共享名稱空間和檔案系統,這兩個容器的協調簡單明瞭。
在所有這些情況下,我們都將容器邊界用作封裝/抽象邊界,這使我們能夠構建模組化、可重用的元件,然後將它們組合起來構建應用程式。這種重用使我們能夠更有效地在不同開發人員之間共享容器,在多個應用程式中重用我們的程式碼,並通常更快地構建更可靠、更健壯的分散式系統。我希望您已經瞭解 Pod 和複合容器模式如何使您能夠更快地構建健壯的分散式系統,並實現容器程式碼重用。要在您自己的應用程式中嘗試這些模式。我鼓勵您去檢視開源的 Kubernetes 或 Google Container Engine。