詳解容器設計模式


(注:本文轉載自阿里巴巴雲原生課堂理解 Pod 和容器設計模式

在基本了解什么是Pod的基礎上,詳細介紹一下 Kubernetes 非常提倡的一個概念,叫做容器設計模式

接下來將會用一個例子來給大家進行講解。

比如我現在有一個非常常見的一個訴求:我現在要發布一個應用,這個應用是 JAVA 寫的,有一個 WAR 包需要把它放到 Tomcat 的 web APP 目錄下面,這樣就可以把它啟動起來了。可是像這樣一個 WAR 包或 Tomcat 這樣一個容器的話,怎么去做,怎么去發布?這里面有幾種做法。

  • 第一種方式:可以把 WAR 包和 Tomcat 打包放進一個鏡像里面。但是這樣帶來一個問題,就是現在這個鏡像實際上揉進了兩個東西。那么接下來,無論是我要更新 WAR 包還是說我要更新 Tomcat,都要重新做一個新的鏡像,這是比較麻煩的;

  • 第二種方式:就是鏡像里面只打包 Tomcat。它就是一個 Tomcat,但是需要使用數據卷的方式,比如說 hostPath,從宿主機上把 WAR 包掛載進我們 Tomcat 容器中,掛到我的 web APP 目錄下面,這樣把這個容器啟用起來之后,里面就能用了。

但是這時會發現一個問題:這種做法一定需要維護一套分布式存儲系統。因為這個容器可能第一次啟動是在宿主機 A 上面,第二次重新啟動就可能跑到 B 上去了,容器它是一個可遷移的東西,它的狀態是不保持的。所以必須維護一套分布式存儲系統,使容器不管是在 A 還是在 B 上,都可以找到這個 WAR 包,找到這個數據。

注意,即使有了分布式存儲系統做 Volume,你還需要負責維護 Volume 里的 WAR 包。比如:你需要單獨寫一套 Kubernetes Volume 插件,用來在每次 Pod 啟動之前,把應用啟動所需的 WAR 包下載到這個 Volume 里,然后才能被應用掛載使用到。

這樣操作帶來的復雜程度還是比較高的,且這個容器本身必須依賴於一套持久化的存儲插件(用來管理 Volume 里的 WAR 包內容)。

InitContainer

在 Kubernetes 里面,像這樣的組合方式,叫做 Init Container。

img

還是同樣一個例子:在上圖的 yaml 里,首先定義一個 Init Container,它只做一件事情,就是把 WAR 包從鏡像里拷貝到一個 Volume 里面,它做完這個操作就退出了,所以 Init Container 會比用戶容器先啟動,並且嚴格按照定義順序來依次執行。

然后,這個關鍵在於剛剛拷貝到的這樣一個目的目錄:APP 目錄,實際上是一個 Volume。而我們前面提到,一個 Pod 里面的多個容器,它們是可以共享 Volume 的,所以現在這個 Tomcat 容器,只是打包了一個 Tomcat 鏡像。但在啟動的時候,要聲明使用 APP 目錄作為我的 Volume,並且要把它們掛載在 Web APP 目錄下面。

而這個時候,由於前面已經運行過了一個 Init Container,已經執行完拷貝操作了,所以這個 Volume 里面已經存在了應用的 WAR 包:就是 sample.war。等到第二步執行啟動這個 Tomcat 容器的時候,去掛這個 Volume,一定能在里面找到前面拷貝來的 sample.war。

像上面這樣的做法,在 Kubernetes 里面就是一個非常經典的容器設計模式,叫做:“Sidecar”。

容器設計模式:Sidecar

什么是 Sidecar?就是說在 Pod 里面,可以定義一些專門的容器,來執行主業務容器所需要的一些輔助工作,比如我們前面舉的例子,其實就干了一個事兒,這個 Init Container,它就是一個 Sidecar,它只負責把鏡像里的 WAR 包拷貝到共享目錄里面,以便被 Tomcat 能夠用起來。回顧xx中的infra container,不就是一個init container嗎?

其它有哪些操作呢?比如說:

  • 原本需要在容器里面執行 SSH 需要干的一些事情,可以寫腳本、一些前置的條件,其實都可以通過像 Init Container 或者另外像 Sidecar 的方式去解決;

  • 日志收集,日志收集本身是一個進程,是一個小容器,那么就可以把它打包進 Pod 里面去做這個收集工作;

  • Debug 應用,實際上現在 Debug 整個應用都可以在應用 Pod 里面再次定義一個額外的小的 Container,它可以去 exec 應用 pod 的 namespace;

  • 查看其他容器的工作狀態,這也是它可以做的事情。不再需要去 SSH 登陸到容器里去看,只要把監控組件裝到額外的小容器里面就可以了,然后把它作為一個 Sidecar 啟動起來,跟主業務容器進行協作,所以同樣業務監控也都可以通過 Sidecar 方式來去做。

這種做法一個非常明顯的優勢就是將輔助功能從業務容器解耦了,所以能夠獨立發布 Sidecar 容器,並且更重要的是這個能力是可以重用的。事實上,任何設計模式的優勢歸結起來不就是解耦復用嗎!

下面介紹 Sidecar 設計模式的幾種常用場景。

Sidecar:應用與日志收集

業務容器將日志寫在一個 Volume 里面,而由於 Volume 在 Pod 里面是被共享的,所以日志容器 —— 即 Sidecar 容器一定可以通過共享該 Volume,直接把日志文件讀出來,然后存到遠程存儲里面,或者轉發到其他容器。現在業界常用的 Fluentd 日志進程或日志組件,基本上都是這樣的工作方式。

img

Sidecar:代理容器proxy

假如現在有個 Pod 需要訪問一個外部系統,或者一些外部服務,但是這些外部系統是一個集群,那么這個時候如何通過一個統一的、簡單的方式,用一個 IP 地址,就把這些集群都訪問到呢?這個時候,就可以通過 Sidecar 代理容器。

img

Sidecar:適配器容器

現在業務暴露出來的 API,比如說有個 API 的一個格式是 A,但是現在有一個外部系統要去訪問我的業務容器,它只知道的一種格式是 API B ,所以要做一個工作,就是把業務容器怎么想辦法改掉,要去改業務代碼。但實際上,你可以通過一個 Adapter 幫你來做這層轉換。

img

現在有個例子:原先業務容器暴露出來的監控接口是 /metrics,可是現在,這個監控系統升級了,它訪問的 URL 是 /health,新系統只認得暴露出 /health 的 URL,才能去做監控,/metrics 不認識。那這個怎么辦?那就需要改代碼了,但可以不去改代碼,而是額外寫一個 Adapter,用來把所有對 /health 的這個請求轉發給 /metrics 就可以了,所以這個 Adapter 對外暴露的是 /health 這樣一個監控的 URL,這就可以了,你的業務就又可以工作了。


總結

本文主要講解的就是容器的設計模式:Sidecar。Sidecar 模式(或者說Sidecar容器)的主要作用就是把業務容器與非業務容器解耦,使得應用的打包、發布工作能夠更加user-friendly。在定義Pod的yaml文件中,我們可以設置相應的initContainer字段,這就是所謂的Sidecar容器,它總是比其他應用容器先啟動。

本文還介紹了幾種常見的使用Sidecar設計模式的場景,比如日志的收集、做代理、適配等等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM