1. 程式人生 > >多容器POD及Kubernetes容器通訊_Kubernetes中文社群

多容器POD及Kubernetes容器通訊_Kubernetes中文社群

容器通常是為了解決一個單一的、特定的問題;如微服務,但在現實世界中,通常需要多個容器,來實現一個完整的解決方案。在這篇文章中,我們將談論結合多個容器整合進單一的Kubernetes節點,即容器互聯通訊。

什麼是Kubernetes節點?

首先讓我們解釋一下容器節點是什麼。容器節點即POD,它是可以由Kubernetes部署和管理的最小單位。換句話說,如果你需要執行在Kubernetes的一個容器,你需要建立一個POD。同時,一個POD可以容納多個容器,通常是因為這些容器是相對緊密耦合的。如何緊密耦合?好吧,這樣想:POD中的容器代表了原來在同一物理伺服器上執行的程序。
這是有道理的。因為在許多方面,一個POD就像一臺伺服器。例如,每個容器可以訪問在POD其他容器,就像訪問本地主機上的不同埠。

Kubernetes為什麼將POD作為最小的可部署單元,而不是一個單一的容器?

雖然直接部署單個容器似乎比較簡單,但是有充分的理由需要新增一個由POD表示的抽象層。容器是一個實體,它指一個特定的事物。這個具體的事物可能Docker容器,但它也可能是一個rkt的容器,或由virtlet管理的虛擬機器。每一種都有不同的要求。

更重要的是,Kubernetes需要更多的資訊來管理一個容器,如重新啟動策略,它定義了當容器終止時,或活性的探針時,進行哪些動作;從應用程式的角度,它定義了檢測動作,判斷容器程序是否還活著,如Web伺服器響應HTTP請求。

區別於在現有的“實體”上超載附加屬性,Kubernetes決定使用一個新的實體,POD。POD可以被認為是邏輯容器,包含一個或多個容器(包裝),作為一個單一的實體被管理。

Kubernetes為什麼讓一個POD裡放置多個容器?

POD中的容器執行在“邏輯主機”上;它們使用相同的網路namespace(換句話說,相同的IP地址和埠空間),以及相同的IPC名稱空間。它們還可以使用共享卷。這些屬性使得這些容器能夠有效地通訊,確保資料本地化。此外,POD使您可以以一個單元的模式管理幾個緊密耦合的應用程式容器。

如果應用程式需要在同一主機上執行多個容器,為什麼不將單個容器與所需的所有內容組合起來呢?首先,這樣做很可能違反“一個容器一個程序”的原則。這很重要,因為同一個容器中有多個過程,系統將很難排錯。因為來自不同過程的日誌將被混合在一起,很難管理程序的生命週期,例如當父程序死亡後處理“殭屍”的過程。其次,一個應用程式使用多個容器將使系統更簡單、更透明,並能使軟體依賴關係解耦。同時,更精細顆粒的容器可以在團隊之間重複使用。

多容器POD的用例

多容器POD的主要用途是支援主要應用程式的共定位、共管輔助程序。在POD中使用輔助程序,有一些通用的模式:

●跨鬥容器“幫助”主容器。示例包括日誌或資料更改監視程式、監視介面卡等。例如,日誌監視程式可以由一個團隊建立一次,並在不同的應用程式中重用。另一個例子,一個跨鬥容器是一個檔案或資料裝載器,為主容器生成資料。

●代理、網橋和介面卡將主容器與外部世界連線起來。例如,Apache HTTP伺服器或Nginx可以提供靜態檔案。它還可以充當主容器中Web應用程式的反向代理,以記錄和限制HTTP請求。另一個例子是輔助容器,它將請求從主容器路由到外部網路。這使得主容器可以連線到本地主機訪問,例如,外部資料庫,但不需任何的服務發現。

雖然你可以在單個POD中託管多層應用程式(如WordPress),但推薦的方法是為每個層使用單獨的POD,原因很簡單,你可以獨立地擴充套件每層,並將它們分佈在叢集節點上。

Pod中容器間的通訊

在一個POD中有多個容器,使它們相對簡單地進行通訊。他們可以用幾種不同的方法做這件事。

在Kubernetes Pod中共享卷

在Kubernetes,你可以使用一個共享的Kubernetes卷作為一種簡單而有效的方式,在一個POD內容器間進行資料共享。在大多數情況下,在主機上使用與容器內所有容器共享的目錄,是足夠的。

Kubernetes卷資料支援容器重啟,但這些卷與POD壽命一樣。這意味著卷容量(所擁有的資料)和POD存在時間一樣。如果那個POD被刪除,即使同類更換建立,共享卷被銷燬和建立。

一個使用共享卷的標準多容器POD的用例是,在一個容器寫日誌和其他檔案到共享目錄中,其他容器從這個共享目錄中可以讀取資料。例如,我們可以建立一個POD:

在這個例子中,我們定義了一個名為HTML的卷。它的型別是emptyDir,這意味著當一個POD被分配到一個節點時,卷先被建立,並只要Pod在節點上執行時,這個卷仍存在。正如名字所說,它最初是空的。第一容器執行nginx的伺服器並將共享卷掛載到目錄/ usr /share/ Nginx /HTML。第二容器使用Debian的映象,並將共享卷掛載到目錄/HTML。每一秒,第二容器添加當前日期和時間到index.html檔案中,它位於共享卷。當用戶發出一個HTTP請求到POD,nginx的伺服器讀取該檔案並將其傳遞給響應請求的使用者。

你可以檢查一下,POD可以通過暴露nginx埠並使用您的瀏覽器訪問它,或通過直接檢查容器中的共享目錄:

程序間通訊(IPC)

一個POD裡的容器共享相同的IPC名稱空間,這意味著他們也可以互相使用標準程序間通訊,如SystemV訊號系統或POSIX共享記憶體。

在下面的示例中,我們定義了一個帶有兩個容器的POD。我們使用相同的容器映象。第一個容器,生產者,建立一個標準的Linux訊息佇列,寫一些隨機訊息,然後寫一個特殊的退出訊息。第二個容器,消費者,開啟相同的訊息佇列以便讀取和讀取訊息,直到接收到退出訊息。我們還將重啟策略設定為“從不”,所以只有在兩個容器都終止後POD停止。

為了驗證這一點,使用kubectl 建立POD,並觀察POD狀態:

現在您可以檢查每個容器的日誌,並驗證第二個容器接收了來自第一個容器的所有訊息,包括退出訊息:

不過,這個POD有一個主要問題,它與容器的啟動有關。

容器依賴項和啟動順序

目前,POD中的所有容器都是並行啟動的,沒有辦法定義一個容器必須在其他容器之後啟動。例如,在IPC示例中,第二個容器可能在第一個容器啟動之前已經結束,並建立了訊息佇列。在這種情況下,第二個容器將失敗,因為它期望訊息佇列已經存在。

一些方案提供某種程度的對容器啟動控制,如Kubernetes初始化容器,開始第一次(依次),正在開發中,但在雲的原生環境,最好準備好直接控制之外的失敗的應對計劃。例如,解決此問題的一種方法是更改應用程式以等待建立訊息佇列。

容器間網路通訊

一個POD裡的容器都可以通過“localhost”訪問;他們使用相同的網路名稱空間。另外,對於容器,可觀察的主機名是POD的名稱。因為容器共享相同的IP地址和埠空間,所以您應該在容器中使用不同的埠來進行連線。換句話說,POD中的應用程式必須協調埠的使用。

在下面的例子中,我們將建立一個多容器的POD,nginx執行在POD一個容器中作為反向代理,為另一個執行一個簡單的Web應用程式中的第二容器提供支援。

步驟1、用nginx的配置檔案建立一個configmap。通過HTTP埠80輸入的請求將被轉發到本地埠5000去:

步驟2、建立一個多容器POD,其上執行2個容器,分別執行簡單的Web應用程式和Nginx。注意,POD,我們只定義了Nginx的埠80。埠5000不能被POD外部訪問。

步驟3、使用nodeport服務來暴露POD:

步驟4、標識並轉發給POD節點上的埠:

現在,您可以使用瀏覽器(或curl)導航到節點的埠,通過反向代理訪問Web應用程式,如:

http://myhost:31418

這個請求將被轉發到webapp容器的5000埠。

在一個POD中暴露多個容器

雖然這個示例展示瞭如何使用單個容器訪問POD中的其他容器,但在一個POD中的幾個容器在POD不同的埠上偵聽是很常見的——所有這些埠都需要公開。要做到這一點,你可以建立一個多埠暴露的服務,或者你可以為每一個想暴露的埠建立一個單一的服務。