iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0
Kubernetes

都什麼年代了,還在學 Kubernetes系列 第 9

學 Kubernetes 的第九天 - Pod - 基礎概念與核心特性

  • 分享至 

  • xImage
  •  

Kubernetes 最重要的資源之一是負責管理容器的 Pod。作為應用程序的最小部署單元,理解 Pod 的運作方式對於掌握 Kubernetes 的各種特性至關重要。接下來,我們將從 Pod 開始,深入了解其核心概念及特性。

Pod 的基本概念

Pod 是 Kubernetes 的基本構建單元

在 Kubernetes 中,Pod 是應用程序或其組件的最小部署單元。這意味著無論是單個容器應用還是多個協作容器,它們都封裝在一個 Pod 中。Pod 是 Kubernetes 直接管理的最小實體,而非單個容器。

Pod 可以看作是運行在同一個執行環境中的一組容器,它們共享相同的資源和網路配置。這為容器的協作運行和管理提供了便利。

單容器 Pod

在大多數情況下,一個 Pod 包含單個容器。這種情況適合運行簡單的應用,例如 Node.js Web 服務器或 MySQL 資料庫。即使 Pod 內只有一個容器,它仍然能夠享受 Kubernetes 的完整功能特性,包括:

  • 自動擴展:基於負載自動擴展容器副本。
  • 負載均衡:在多個 Pod 之間進行流量分配。
  • 重啟策略:當容器崩潰時自動重啟。

Pod 會提供容器所需的所有資源,如 CPU、記憶體、網路和存儲卷。這使單容器 Pod 成為 Kubernetes 中簡單且強大的部署單元。

多容器 Pod

有些應用需要多個容器協同工作,這時候多容器 Pod 就非常適用。多容器 Pod 典型的設計模式是運行彼此緊密協作的應用組件,例如主應用和輔助服務。這些容器之間需要共享網路和存儲環境,並且經常需要直接通信。Pod 提供了一個自然的協作環境,確保這些容器能夠高效地運行。

例如,假設有一個主應用容器,負責處理請求;同時還有一個輔助容器,負責監控日誌或管理緩存。這些容器可以在同一個 Pod 中運行,並且共享相同的資源,從而確保它們之間的協同工作

Pod 的共享網路空間

單一網路命名空間

在 Kubernetes 中,每個 Pod 都有自己唯一的 IP 地址,並且 Pod 內的所有容器共享這個 IP 地址和網路命名空間(Network Namespace)。這使得 Pod 內的容器能夠通過 localhost 進行通信,就像它們運行在同一個機器上的同一個網路介面中一樣。

Pod 的網路特性包括:

  • 共享 IP 地址:Pod 內的所有容器共享同一個 IP 地址,這使得它們之間的通信可以直接通過 localhost 進行,而無需通過外部網路。

  • 共享端口空間:Pod 內的容器共享相同的端口空間。這意味著,一個容器在 localhost:8080 上運行服務時,其他容器也可以直接通過該地址訪問。例如,如果一個容器在 localhost:8080 上暴露了一個 Web 服務,其他容器可以直接通過該地址訪問該服務,無需任何額外的網路配置。

Pod 的網路隔離

儘管 Pod 內的容器共享網路空間,Pod 與 Pod 之間的網路是隔離的。這意味著一個 Pod 無法通過 localhost 訪問另一個 Pod。要實現跨 Pod 的通信,必須使用 Pod 的 IP 地址或通過 Kubernetes 的 Service 資源來進行。

這種設計保證了 Pod 內容器的緊密耦合和 Pod 之間的鬆散耦合,從而提高了應用程序的靈活性和安全性。例如,在多層微服務架構中,每個服務可以在自己的 Pod 中運行,而它們之間的通信通過明確的網路策略進行控制。這樣既提供了容器間的高效協作,又增強了整個系統的可維護性與安全性。

Pod 的共享存儲卷

存儲卷的共享機制

在 Kubernetes 中,Pod 內的容器可以共享一個或多個 存儲卷(Volumes)。這些存儲卷可以來自多種存儲後端,例如本地磁碟、NFS(網路檔案系統)或雲端存儲。Pod 內的多個容器可以同時掛載這些存儲卷,從而實現數據共享和持久化。

  • 持久化存儲:存儲卷允許容器持久化數據,即使容器重啟,數據依然保留不變。這對於需要保存狀態的應用程序(如資料庫)非常重要。

  • 數據共享:多個容器可以同時掛載同一個存儲卷,共享數據。例如,一個容器負責生成數據,另一個容器負責處理這些數據。它們可以通過共享的 Volume 協作,無需依賴外部通信機制。

Volume 的類型

Kubernetes 支持多種類型的存儲卷,每種存儲卷都有其特定的使用場景:

  • emptyDir:這是 Pod 啟動時自動創建的空目錄,當 Pod 被銷毀時,數據也隨之消失。因此,emptyDir 適用於臨時存儲需求,例如緩存或臨時文件。

  • hostPath:將主機文件系統中的目錄掛載到 Pod 內的容器中,這通常用於需要訪問主機資源的場景。例如,監控應用可能需要從主機讀取日誌文件。

  • PersistentVolume(PV):結合 PersistentVolumeClaim(PVC) 使用,提供持久化存儲。這類存儲通常來自外部存儲系統,如 NFS、Ceph 或雲端存儲(如 AWS EBS)。PV 提供持久性,即使 Pod 被銷毀,數據仍然會保留在存儲中。

以上是 Kubernetes 中一些常見的 Volume 類型,我們將在後續章節中深入討論各類型的具體用途和配置。

Pod 容器間通信和協作

容器間通信

在 Pod 內,容器之間可以通過多種方式進行通信和協作:

  1. localhost 網路通信:由於 Pod 內的容器共享相同的網路命名空間,它們可以通過 localhost 和相應的端口進行通信。例如,一個容器可以在 localhost:8080 上運行 Web 服務,另一個容器可以通過該地址直接訪問這個服務。

  2. 共享文件系統進行數據交換:Pod 內的容器可以通過共享的存儲卷進行數據交換。例如,一個容器將日誌寫入共享的 Volume,另一個容器可以即時讀取這些日誌,並進行處理或轉發。這種方式無需通過網路即可實現高效的數據共享。

容器間協作模式

https://ithelp.ithome.com.tw/upload/images/20240923/201682127XuzzHI60m.png

在前面的章節中,我們提到 Pod 中的多個容器常常扮演協作的角色。這種協作使得應用程序的架構更加靈活和複雜,能夠實現不同的應用場景。常見的容器協作模式包括:

  1. Sidecar 模式
    • 主容器負責應用程序的核心功能,而 Sidecar 容器則提供輔助功能。
    • 例如,一個 Web 服務器容器可以與一個負責處理日誌的 Sidecar 容器協作。Sidecar 容器可能會將日誌推送到中央日誌系統,或者作為代理,為主容器提供服務。
  2. Ambassador 模式
    • Ambassador 容器作為代理,負責處理所有外部通信,並將請求轉發給主容器。
    • 這種模式通常應用於需要處理複雜通信協議或負載均衡的場景。例如,Ambassador 容器可以處理外部流量,並將其轉發到主容器中執行具體業務邏輯。
  3. Adapter 模式
    • Adapter 容器負責將主容器的輸出轉換為其他系統能夠理解的格式。
    • 例如,一個數據處理容器可以生成數據,Adapter 容器將這些數據轉換成另一種格式,並推送到外部的數據存儲或分析系統。這種模式提高了系統的靈活性,適用於異構系統間的數據交換。

這些協作模式使 Kubernetes 能夠靈活支持不同類型的應用程序架構。應用設計者可以根據具體需求選擇合適的模式,從而提高應用程序的可維護性、擴展性和穩定性。

Pod 的生命周期

Pod 的生命周期由多個階段(Phases)組成,每個階段代表了 Pod 在 Kubernetes 集群中的不同狀態。理解這些階段有助於診斷 Pod 啟動或運行過程中的問題,從而進行有效的排查和故障處理。

https://ithelp.ithome.com.tw/upload/images/20240923/20168212ayTVRdOkTJ.png

Pod 的階段(Phases)

在 Kubernetes 中,Pod 的狀態可以分為以下幾個主要階段:

  1. Pending
    • 當 Pod 剛被創建時,它會處於 Pending 狀態,這意味著 Pod 已經被提交給 Kubernetes 系統,但尚未開始運行其中的容器。
    • Pod 處於 Pending 狀態可能是因為 Kubernetes 調度器尚未找到合適的節點來運行該 Pod,或者因為正在下載容器鏡像時出現延遲。
  2. Running
    • 當 Pod 已經被調度到某個節點上並且至少有一個容器正在運行時,Pod 進入 Running 狀態。
    • 雖然 Pod 處於 Running 狀態,但這並不意味著所有容器都已完全啟動。一些容器可能還在啟動過程中,或者重新啟動中。
  3. Succeeded
    • 當 Pod 內的所有容器都已成功執行並且不會再重新啟動時,Pod 進入 Succeeded 狀態。
    • 這通常發生在一次性任務(例如批處理作業)成功完成之後。
  4. Failed
    • 當 Pod 內的至少一個容器異常終止,且不會再次重啟時,Pod 進入 Failed 狀態。
    • 這意味著 Pod 發生了不可恢復的錯誤,必須進行調查和修復。
  5. Unknown
    • 當 Kubernetes 無法確定 Pod 的具體狀態時,Pod 會進入 Unknown 狀態。
    • 這種情況通常是由於節點與 Kubernetes API 伺服器之間的通信失敗或其他網路問題引起的。
  6. CrashLoopBackOff
    • 當一個 Pod 不斷地啟動、失敗、然後又重新啟動,進入一個循環,便會進入 CrashLoopBackOff 狀態。
    • 這通常發生在 Pod 的重啟策略設為 AlwaysOnFailure 時,Pod 的容器無法穩定啟動。簡單來說, Pod 一直「起不來」,可能需要檢查容器日誌來排查問題。

Pod 的容器狀態

除了 Pod 的整體階段外,Pod 內的每個容器也會有自己的狀態,這些狀態可以幫助診斷容器的具體問題。主要的容器狀態包括:

  • Waiting:容器尚未開始運行,通常在容器正在等待某些資源或依賴時出現。等待狀態下的容器可能正在等待鏡像下載或資源分配。

  • Running:容器已經在節點上運行,這意味著容器處於活動狀態並且正常工作。

  • Terminated:容器已經完成運行並且已終止,無論是正常退出還是由於錯誤導致的退出。這個狀態下,可以查看容器的退出代碼來確定是正常完成還是發生了故障。

理解 Pod 和容器的各種狀態,可以幫助快速排查 Kubernetes 集群中的問題,並確保應用程序的穩定運行。

Pod 的健康檢查

健康檢查探針(Probes)

Kubernetes 提供了健康檢查探針來監控 Pod 內容器的健康狀況,這些探針能夠幫助 Kubernetes 決定何時重啟容器、何時從服務中移除 Pod 或何時允許流量進入 Pod。目前支援三種探針:

  1. Liveness Probe
    • 用來檢查容器是否存活。如果 Liveness Probe 失敗,Kubernetes 將認為容器已經出現問題並自動重啟該容器。這有助於修復由於應用程序死鎖或其他問題導致的容器不可恢復的情況。
    • 常用的檢查方法包括 HTTP 請求、TCP socket 檢查或執行自定義命令。
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 5
  1. Readiness Probe
    • 用來檢查容器是否已準備好接收流量。如果 Readiness Probe 失敗,Kubernetes 將暫時從負載均衡器中移除該 Pod,直到探針成功為止。這通常用於檢查應用程序是否完成初始化並準備好提供服務。
    • Readiness Probe 使用與 Liveness Probe 相同的檢查方法。
readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 5
  1. Startup Probe
    • 用來檢查應用程序的啟動過程是否成功。這個探針專門為那些啟動時間較長的應用程序設計。如果 Startup Probe 存在,在啟動期間,Kubernetes 只會依賴這個探針的結果來判斷容器是否成功啟動。
startupProbe:
  exec:
    command:
    - "cat"
    - "/tmp/ready"
  initialDelaySeconds: 10
  periodSeconds: 10

Pod 的資源限制和請求

資源請求和限制的概念

在 Kubernetes 中,Pod 可以設置資源請求(Resource Requests)和資源限制(Resource Limits)來管理容器對 CPU 和內存的使用。這些設置確保集群資源的合理分配並防止單個 Pod 過度消耗資源。

  1. 資源請求(Requests):資源請求是 Pod 啟動時向 Kubernetes 調度器聲明的最小資源需求,調度器會根據資源請求來選擇適當的節點,以確保 Pod 至少能獲得所需的資源。
resources:
  requests:
    memory: "256Mi"
    cpu: "500m"
  1. 資源限制(Limits):資源限制是 Kubernetes 允許 Pod 使用的最大資源量。如果容器超過了這些限制,Kubernetes 會限流 CPU 使用,並可能終止內存消耗過大的容器。
resources:
  limits:
    memory: "512Mi"
    cpu: "1"

調度行為

當 Kubernetes 調度器選擇節點來運行 Pod 時,它會考慮資源請求,以確保節點有足夠的資源來滿足 Pod 的最低需求。而資源限制則在 Pod 運行時生效,以防止 Pod 消耗過多資源。

  • 如果 Pod 超過了 CPU 限制,系統會對其進行限流(throttling);而如果內存使用超過限制,容器則可能被殺死(OOMKilled)。
  • 如果集群中的資源無法滿足所有 Pod 所有容器的資源請求,Pod 會處於 Pending 狀態,直到有足夠的資源可用。

這些機制確保了 Kubernetes 集群資源的合理分配,防止資源爭奪並保證集群穩定性。

Pod 的重啟策略

Pod 的重啟策略(Restart Policy)定義了 Kubernetes 在容器失敗或退出後應如何處理。這是保持應用高可用性的關鍵機制之一。Pod 的重啟策略有三種選擇:

  1. Always
    • 無論容器是因錯誤退出還是正常停止,Kubernetes 都會自動重啟容器。這是默認策略,適合需要長時間運行的服務型應用,如 Web 服務器。
restartPolicy: Always
  1. OnFailure
    • 只有當容器非正常退出(退出代碼非 0)時,Kubernetes 才會重啟容器。這適合一次性任務或批處理作業,這些作業正常完成後無需重啟。
restartPolicy: OnFailure
  1. Never
    • 無論容器如何退出,Kubernetes 都不會重啟它。這種策略適用於一次性運行的作業,如臨時任務或測試腳本。
restartPolicy: Never

Pod 的標籤和選擇器

Pod 的標籤(Labels)

標籤是 Kubernetes 中的一種鍵值對,用來標識和組織 Pod 及其他資源。標籤是附加在 Pod 等資源上的元數據,用於描述資源的屬性,例如應用名稱、環境、版本等。標籤非常靈活,允許用戶按照需求進行自由標註。

  • 標籤格式
    • 每個標籤是由一個鍵和值組成的鍵值對,例如 app: web-serverenv: production
    • 鍵和值都是字符串,鍵通常會有一個命名空間前綴(如 app.kubernetes.io/name),但這不是必需的。
metadata:
  labels:
    app: my-app
    tier: backend
    version: v1

Pod 的選擇器(Selectors)

選擇器用來查找和選擇符合特定標籤條件的 Pod 或其他資源。這是 Kubernetes 中控制器(如 ReplicaSet、Deployment 和 Service)管理 Pod 的主要方式。

  • 基於標籤的選擇器:通過選擇器,控制器可以選擇符合指定標籤的 Pod,然後對這些 Pod 執行操作,如負載均衡或滾動更新。
spec:
  selector:
    matchLabels:
      app: my-app
      tier: backend

Pod 的親和性和反親和性(Affinity and Anti-affinity)

親和性(Affinity)

親和性規則用於影響 Pod 在叢集中如何調度到節點上。這些規則允許你指定 Pod 與其他 Pod 之間的調度關係,以優化性能和可靠性。親和性規則分為硬性規則(必須遵守)和軟性規則(優先考慮,但可忽略)。

  1. Node Affinity
    • 用於將 Pod 調度到具有特定標籤的節點上。例如,可以將 Pod 調度到具有 SSD 硬碟的節點。這類規則類似於 nodeSelector,但更靈活。
    • Node Affinity 可以設置為 requiredDuringSchedulingIgnoredDuringExecution(硬性規則)或 preferredDuringSchedulingIgnoredDuringExecution(軟性規則)。
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: disktype
          operator: In
          values:
          - ssd
  1. Pod Affinity
    • Pod Affinity 用於將某些 Pod 調度到與其他特定 Pod 位於同一節點或拓撲域(如同一可用區)的節點上,這對於需要低延遲、高效通信的應用場景非常適用,如分布式數據庫的節點之間。
affinity:
  podAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      labelSelector:
        matchLabels:
          app: my-app
      topologyKey: "kubernetes.io/hostname"

反親和性(Anti-affinity)

反親和性規則用來防止某些 Pod 被調度到同一節點上,這在高可用性場景中特別有用。例如,可以使用 Pod Anti-affinity 確保同一應用的多個副本不會運行在同一節點上,以避免單點故障。

  • Pod Anti-affinity
    • 使用 Anti-affinity 可以指定 Pod 應避免與特定的其他 Pod 共享節點。這種規則常用於提高應用的容錯性和穩定性。
affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      labelSelector:
        matchLabels:
          app: my-app
      topologyKey: "kubernetes.io/hostname"

親和性和反親和性的應用場景

  • 高可用性:使用 Pod Anti-affinity 保證相同應用的不同實例不會被調度到同一節點上,從而提高應用的容錯性。
  • 性能優化:使用 Pod Affinity 將緊密耦合的應用容器調度到同一節點上,以減少跨節點通信的延遲。
  • 資源分配優化:使用 Node Affinity 將特定需求的工作負載(如需要 GPU 的應用)調度到符合條件的節點上,從而最大化資源利用率。

親和性和反親和性提供了靈活的調度策略,使 Kubernetes 集群更好地管理資源分配、性能和可靠性。

小結

從 Pod 出發,現在我們對 Kubernetes 的特性有了一個基本的理解。在接下來的章節中,我們將深入探討這些特性,並通過實際操作來體驗這些特性的應用。


上一篇
學 Kubernetes 的第八天 - 部署你的第一個應用程式 (3) - Deployment 部署與退版
下一篇
學 Kubernetes 的第十天 - Networking - Service
系列文
都什麼年代了,還在學 Kubernetes37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言