為什麼我們需要 Pods

為什麼我們需要 Pods

關於 Pods

Pods 是 Kubernetes 中最小的 API 單元。用更技術性的術語來說,Pods 是 Kubernetes 中的原子調度單元。但為什麼我們需要 Pods?要回答這個問題,我們首先需要了解容器的本質:容器本質上就是一個進程。沒錯。容器是雲端運算系統中的進程,而容器映像則相當於此系統的「.exe」安裝套件。Kubernetes 在這種類比中扮演著作業系統的角色。

進程與進程組

讓我們登入一台 Linux 機器並執行以下指令:

$ pstree -g

此指令會顯示系統中當前運行進程的樹狀結構。輸出可能如下所示:

systemd(1)-+-accounts-daemon(1984)-+-{gdbus}(1984)
           | `-{gmain}(1984)
           |-acpid(2044)
          ...      
           |-lxcfs(1936)-+-{lxcfs}(1936)
           | `-{lxcfs}(1936)
           |-mdadm(2135)
           |-ntpd(2358)
           |-polkitd(2128)-+-{gdbus}(2128)
           | `-{gmain}(2128)
           |-rsyslogd(1632)-+-{in:imklog}(1632)
           |  |-{in:imuxsock) S 1(1632)
           | `-{rs:main Q:Reg}(1632)
           |-snapd(1942)-+-{snapd}(1942)
           |  |-{snapd}(1942)
           |  |-{snapd}(1942)
           |  |-{snapd}(1942)
           |  |-{snapd}(1942)

如你所見,在真實的作業系統中,進程並非孤立運行。相反,它們被組織成進程組。例如,程式「rsyslogd」負責 Linux 中的日誌處理。rsyslogd 的主程式「main」以及它所使用的核心日誌模組「imklog」都屬於進程組 1632。這些進程協作完成 rsyslogd 程式的職責。Kubernetes 本質上將「進程組」的概念映射到容器技術,並使其成為此雲端運算「作業系統」中的「一級公民」。Kubernetes 採用這種方式是因為 Google 的工程師發現他們部署的應用程式經常表現出類似於「進程與進程組」的關係。具體來說,這些應用程式需要緊密協作,因此必須部署在同一台機器上。如果沒有「組」的概念,管理這種運行關係將會極具挑戰性。以 rsyslogd 為例,它由三個進程組成:imklog 模組、imuxsock 模組以及 rsyslogd 本身的 main 函數進程。這三個進程必須運行在同一台機器上;否則,它們基於 socket 的通訊和檔案交換會遇到問題。

容器間通訊

如上圖所示,這個 Pod 包含兩個使用者容器 A 和 B,以及一個 Infra 容器。在 Kubernetes 中,Infra 容器設計為消耗最少資源,並使用一個名為「k8s.gcr.io/pause」的特殊映像。這個映像代表一個用組合語言編寫的容器,它永遠處於「暫停」狀態,未壓縮大小僅為 100–200 KB。一旦 Infra 容器「持有」Network Namespace,使用者容器就可以加入這個 Namespace。因此,如果你在主機上檢查這些容器的 Namespace 檔案(先前提到過這個檔案的路徑),它們會指向完全相同的值。這意味著在 Pod 內的容器 A 和 B 可以直接使用「localhost」進行通訊。它們感知到與 Infra 容器相同的網路設備。一個 Pod 只有一個 IP 位址,就是與 Pod 的 Network Namespace 關聯的 IP 位址。自然,所有其他網路資源都是以 Pod 為單位分配,並由 Pod 內的所有容器共享。Pod 的生命週期僅與 Infra 容器相關,與容器 A 和 B 無關。此外,對於同一個 Pod 內的所有使用者容器,它們的進出流量都可以視為通過 Infra 容器。這點至關重要,因為如果你將來要為 Kubernetes 開發網路外掛程式,你的主要焦點應該是配置 Pod 的 Network Namespace,而不是每個使用者容器如何使用你的網路配置。後者是無關緊要的。這意味著如果你的網路外掛程式依賴於在容器內安裝套件或配置,那麼這不是一個可行的解決方案。Infra 容器映像的根檔案系統幾乎是空的,你沒有自訂的空間。反之,這也意味著你的網路外掛程式不需要關心使用者容器的啟動狀態,只需要專注於配置 Pod,也就是 Infra 容器的 Network Namespace。透過這種設計,共享儲存卷變得更加簡單。Kubernetes 可以在 Pod 層級定義所有儲存卷配置。因此,一個儲存卷對應的主機目錄是 Pod 獨有的,Pod 內的任何容器只需要宣告掛載此目錄即可。這種 Pod 的設計理念,促進容器之間「超級緊密的關係」,旨在鼓勵使用者考慮:如果在單個容器中運行多個功能上不相關的元件,那麼將其表示為 Pod 內的多個容器可能更好。要理解這種思維方式,試著將其應用於難以用單一容器解決的情境。例如,想像一個應用程式不斷將日誌檔案輸出到容器內的「/var/log」目錄。在這種情況下,你可以在 Pod 內掛載一個儲存卷到應用程式容器的「/var/log」目錄。然後,在同一個 Pod 內運行一個 sidecar 容器,該容器也宣告將相同的儲存卷掛載到其「/var/log」目錄。接著,sidecar 容器的唯一任務就是不斷從其「/var/log」目錄讀取日誌檔案,並將其轉發到 MongoDB 或 Elasticsearch 等儲存解決方案。這種設定就建立了一個基本的日誌收集機制。與第一個範例類似,sidecar 在此情境下的主要功能也是利用共享儲存卷進行檔案操作。然而,不要忽略 Pod 的另一個重要特性:Pod 內的所有容器共享同一個 Network Namespace。這使得許多與 Pod 網路相關的配置和管理任務都可以委託給 sidecar,完全不需要干擾使用者容器。Istio 服務網格專案就是一個很好的例子。

總結

在這篇文章中,我們深入探討了為什麼需要 Pods。本質上,Pod 是 Kubernetes 叢集中的基本單元,封裝了一個或多個容器(通常是 Docker 容器)。這些容器共享網路和儲存資源。從進程和進程組的角度來看,Pod 可以被視為一個輕量級的進程組。它使得將多個緊密協作的進程(容器)作為一個凝聚的單元進行部署、擴展和管理成為可能,簡化了複雜應用程式的部署和操作。在下一篇文章中,我們將對 Pod 進行更深入的解釋。

Novita AI 是滿足您 AI 抱負的一體化雲端平台。透過無縫整合的 API、無伺服器運算和 GPU 加速,我們提供經濟高效的工具,幫助您快速建立和擴展 AI 驅動的業務。消除基礎架構的煩惱,免費開始使用 – Novita AI 讓您的 AI 夢想成真。

推薦閱讀:

  1. 如何為初學者編寫 Dockerfile
  2. Docker 初學者指南:告別部署噩夢!