Kubernetes Deployment 為管理無狀態應用程式提供宣告式方法,實作 Pod 複製、自動重啟、水平擴充套件、版本控制和回復。Deployment 建立在 ReplicaSet 基礎上,並透過 Pod 範本定義期望狀態,Kubernetes 則負責協調底層 ReplicaSet 以維持該狀態。搭配 Service 物件,Deployment 能夠將應用程式暴露給外部流量,實作負載平衡和服務發現。這對於構建高用性和可擴充套件的無狀態應用程式至關重要,也是 Kubernetes 應用程式佈署和管理的核心概念。瞭解 Deployment 的運作機制和最佳實踐,能有效提升應用程式佈署效率和穩定性。

使用 Kubernetes Deployment 管理無狀態工作負載

在前一章中,我們介紹了兩個重要的 Kubernetes 物件:ReplicationController 和 ReplicaSet。到目前為止,你已經知道它們在維護相同、健康的 Pod 副本方面具有相似的目的。事實上,ReplicaSet 是 ReplicationController 的後繼者,在最新版本的 Kubernetes 中,應該優先使用 ReplicaSet 而不是 ReplicationController。 現在,是時候介紹 Deployment 物件了,它為你的無狀態 Kubernetes 應用程式和服務提供了簡單的擴充套件性、滾動更新和版本化回復。Deployment 物件建立在 ReplicaSet 之上,它們提供了一種宣告式的方式來管理 ReplicaSet - 只需在 Deployment 清單中描述所需狀態,Kubernetes 就會以可控、可預測的方式協調底層的 ReplicaSet。與下章將介紹的 StatefulSet 一起,它是 Kubernetes 中最重要的工作負載管理物件。這將是你進行 Kubernetes 開發和維運的核心!本章的目標是確保你具備使用 Deployment 物件佈署無狀態應用程式元件所需的所有工具和知識,以及使用 Deployment 的滾動更新安全地發布新版本的元件。

本章將涵蓋以下主題:

  • 介紹 Deployment 物件
  • Kubernetes Deployment 如何無縫地處理修訂和版本發布
  • Deployment 物件的最佳實踐

技術需求

在本章中,你需要以下內容:

  • 一個已佈署的 Kubernetes 叢集。你可以使用本地或雲端叢集,但為了完全理解本章中展示的概念,我們建議使用多節點的雲端 Kubernetes 叢集(如果可用的話)。
  • Kubernetes CLI(kubectl)必須安裝在你的本地機器上,並組態為管理你的 Kubernetes 叢集。

Kubernetes 叢集佈署(本地和雲端)和 kubectl 安裝在第 3 章《安裝你的第一個 Kubernetes 叢集》中已經介紹過。

介紹 Deployment 物件

Kubernetes 為執行不同型別的工作負載提供了開箱即用的靈活性,具體取決於你的使用場景。透過瞭解哪種工作負載型別適合你的應用程式需求,你可以做出更明智的決定,最佳化資源使用,並確保雲端應用程式的更好效能和可靠性。這種基礎知識幫助你解鎖 Kubernetes 靈活性的全部潛力,讓你能夠自信地佈署和擴充套件應用程式。讓我們簡要地看看支援的工作負載,以瞭解 Deployment 物件的適用位置及其目的。

圖 11.1:Kubernetes 中的應用程式工作負載型別

在實施雲端應用程式時,你通常需要以下型別的工作負載:

  • 無狀態:在容器世界中,無狀態應用程式是指不將資料(狀態)儲存在容器本身內的應用程式。想像兩個 Nginx 容器服務於相同的目的:一個將使用者資料儲存在容器內的一個檔案中,而另一個使用像 MongoDB 這樣的單獨容器進行資料持久化。儘管它們都實作了相同的目標,但第一個 Nginx 容器變成了有狀態的,因為它依賴於內部儲存。第二個 Nginx 容器,利用外部資料函式庫,保持無狀態。這種無狀態的方法使應用程式在 Kubernetes 中更易於管理和擴充套件,因為它們可以輕鬆地重新啟動或替換,而不必擔心資料丟失。通常,Kubernetes 中的 Deployment 物件用於管理這些無狀態工作負載。
  • 有狀態:在容器和 Pod 的情況下,如果它們在自身內部儲存任何可修改的資料,我們稱它們為有狀態的。這種 Pod 的一個很好的例子是 MySQL 或 MongoDB Pod,它們將資料讀寫到 PersistentVolume。有狀態工作負載的管理要困難得多 - 你需要在發布、回復和擴充套件過程中小心地管理粘性會話或資料分割。作為經驗法則,盡可能將有狀態工作負載保持在 Kubernetes 叢集之外,例如使用根據雲端的軟體即服務(SaaS)資料函式庫產品。在 Kubernetes 中,StatefulSet 物件用於管理有狀態工作負載。第 12 章《StatefulSet - 佈署有狀態應用程式》提供了有關這些型別物件的更多詳細資訊。
  • Job 或 CronJob:這種工作負載執行作業或任務處理,可以是排程的,也可以是按需的。根據應用程式的型別,批次工作負載可能需要成千上萬個容器和很多節點 - 這可以是任何在後台發生的事情。用於批次處理的容器也應該是無狀態的,以便更容易地還原被中斷的工作。在 Kubernetes 中,Job 和 CronJob 物件用於管理批次工作負載。第 4 章《在 Kubernetes 中執行你的容器》提供了有關這些型別物件的更多詳細資訊。
  • DaemonSet:在某些情況下,我們希望在每個 Kubernetes 節點上執行工作負載以支援 Kubernetes 功能。它可以是監控應用程式、日誌記錄應用程式、儲存管理代理(用於 PersistentVolume)等。對於這種工作負載,我們可以使用一種特殊的佈署型別,稱為 DaemonSet,它將保證工作負載的一個副本將在叢集中的每個節點上執行。第 13 章《DaemonSet - 在節點上維護 Pod Singleton》提供了有關這些型別物件的更多詳細資訊。

使用 Deployment 物件管理無狀態工作負載

透過瞭解 Kubernetes 中的不同型別的工作負載,我們可以更深入地瞭解如何使用 Deployment 物件管理無狀態工作負載。簡而言之,它們為 Pod 和 ReplicaSet 提供了宣告式和可控的更新。

你可以使用 Deployment 物件宣告式地執行以下操作:

  • 新 ReplicaSet 的發布:Deployment 在管理可控的發布方面表現出色。你可以在 Deployment 物件中定義一個具有所需 Pod 範本的新 ReplicaSet。然後,Kubernetes 將協調一個漸進的發布,透過擴充套件新的 ReplicaSet 同時縮小舊的 ReplicaSet,從而最小化停機時間並確保平滑過渡。
  • 使用 Pod 範本變更進行受控發布:Deployment 允許你更新 Deployment 定義中的 Pod 範本。當你佈署更新的 Deployment 時,Kubernetes 將執行滾動更新,擴充套件具有修改後的範本的新 ReplicaSet,並縮小舊的 ReplicaSet。這使你能夠以可控的方式將變更引入應用程式的 Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

程式碼解析:

此 YAML 程式碼定義了一個名為 nginx-deployment 的 Deployment 物件。

  1. apiVersionkind 指定了物件的 API 版本和型別。
  2. metadata 部分包含物件的中繼資料,如名稱。
  3. spec 部分定義了物件的期望狀態。
    • replicas 指定了要執行的 Pod 副本數量。
    • selectortemplate.metadata.labels 確保 Deployment 管理具有正確標籤的 Pod。
    • template 部分定義了要建立的 Pod 範本。
      • spec.containers 列出了要在 Pod 中執行的容器。
      • image 指定了要使用的 Docker 映象。
      • ports 指定了要公開的容器連線埠。

透過這個 YAML 組態檔,你可以建立一個 Deployment 物件來管理 Nginx 應用程式的 Pod。Kubernetes 將根據指定的設定自動處理 Pod 的建立、擴充套件和更新。

圖表說明

此圖示展示了 Kubernetes 中不同的應用程式工作負載型別,包括無狀態、有狀態、Job/CronJob 和 DaemonSet。每種型別的工作負載都有其特定的使用場景和管理方式。

詳細解析:

  • 無狀態工作負載適合不需要儲存內部狀態的應用程式,例如網頁伺服器。它們易於擴充套件和管理,因為不需要擔心資料的一致性。
  • 有狀態工作負載則需要儲存內部狀態,例如資料函式庫。它們的管理更加複雜,因為需要確保資料的一致性和可用性。
  • Job 和 CronJob 用於執行一次性或排程任務,例如批次處理或定時任務。它們適合用於不需要持續執行的任務。
  • DaemonSet 用於在每個節點上執行一個 Pod,例如日誌收集或監控代理。它們適合用於需要在每個節點上執行的服務。

使用 Kubernetes Deployment 管理無狀態工作負載

Kubernetes Deployment 提供了一種宣告式的方式來管理無狀態應用程式的佈署和更新。它們建立在 ReplicaSet 之上,並提供了額外的功能,如滾動更新、回復和擴充套件。

Deployment 的優勢

  • 滾動更新:Deployment 可以逐步替換舊版本的 Pod,而不會造成服務中斷。
  • 回復到先前版本:如果新版本出現問題,可以輕鬆回復到先前的穩定版本。
  • 擴充套件 ReplicaSet:可以直接擴充套件 Deployment,Kubernetes 會自動調整底層的 ReplicaSet。
  • 暫停和還原佈署:可以在佈署過程中暫停,解決問題後再還原佈署。

建立 Deployment 物件

可以使用 kubectl create deployment 命令建立 Deployment 的 YAML 檔案。例如:

$ kubectl create deployment my-deployment --replicas=1 --image=my-image:latest --dry-run=client --port=80 -o yaml > my-deployment.yaml

以下是一個範例 Deployment YAML 檔案 nginx-deployment.yaml

# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-example
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
      environment: test
  minReadySeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: nginx
        environment: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.17
        ports:
        - containerPort: 80

內容解密:

  • replicas:定義了應該執行的 Pod 複本數量。
  • selector:定義瞭如何識別屬於該 Deployment 的 Pod。
  • template:定義了 Pod 的範本。
  • strategy:定義了替換舊 Pod 的策略。

Deployment 的結構

Deployment 的結構與 ReplicaSet 類別似,但多了一些額外的引數來組態滾動更新的策略。

使用 Deployment 管理無狀態工作負載

一旦建立了 Deployment,就不能更改其選擇器。可以對現有的 Deployment 物件執行兩種重要的操作:

  • 修改範本:更改 Pod 的定義以使用新的映像版本。
  • 修改副本數量:更改副本數量以擴充套件或縮減 ReplicaSet。

可以使用 kubectl apply 命令將 Deployment YAML 檔案應用到叢集:

$ kubectl apply -f ./nginx-deployment.yaml

圖示說明

以下圖示說明瞭 Deployment、其底層 ReplicaSet 和 Pod 之間的關係: 此圖示說明瞭一個 Deployment 控制一個 ReplicaSet,而 ReplicaSet 又控制多個 Pod。

Kubernetes 佈署與服務暴露:無狀態工作負載的管理

使用 Kubernetes 佈署無狀態工作負載

Kubernetes 佈署(Deployment)是一種用於管理無狀態應用程式的強大工具。它提供了 Pod 複製、自動重啟、擴充套件、版本控制和回復等功能。在本章中,我們將探討如何使用 Deployment 物件來管理無狀態工作負載,並使用 Service 物件將其暴露給外部流量。

建立和檢查 Kubernetes 佈署

首先,我們建立一個名為 nginx-deployment-example 的 Deployment 物件:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-example
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

內容解密:

此 YAML 檔案定義了一個 Deployment 物件,名稱為 nginx-deployment-example。它指定了三個副本,使用 nginx:1.14.2 映象,並開放了 80 埠。

建立 Deployment 物件後,使用 kubectl rollout 命令跟蹤其狀態:

$ kubectl rollout status deployment nginx-deployment-example

內容解密:

此命令提供了 Deployment 滾動更新的實時狀態。它顯示了更新的進度,直到所有副本都成功更新。

我們還可以使用 kubectl getkubectl describe 命令檢查 Deployment 的狀態:

$ kubectl get deploy nginx-deployment-example
$ kubectl get rs
$ kubectl get pods

內容解密:

這些命令分別顯示了 Deployment、ReplicaSet 和 Pod 的狀態。它們提供了有關應用程式當前狀態的詳細資訊。

使用 Service 物件暴露 Deployment

Service 物件是 Kubernetes 中用於暴露 Pod 給其他 Pod 或外部使用者的重要資源。它們提供了負載平衡功能,將流量路由到健康且就緒的 Pod。

下圖展示了 Kubernetes 中不同的網路: 此圖示展示了客戶端如何透過 Service 與多個 Pod 進行通訊。

在 Kubernetes 中,Deployment 物件管理 Pod 的生命週期,但 Pod 的 IP 地址可能會變化。因此,我們需要使用 Service 物件提供穩定的網路介面。

Service 物件的工作原理

Service 物件透過標籤選擇器來定位一組 Pod。它們提供了可靠的 DNS 名稱和 IP 地址,並監控標籤選擇器的結果,更新相關的端點物件。

下圖展示了客戶端 Pod 如何透過 ClusterIP Service 與 Deployment 中的 Pod 進行通訊:

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Kubernetes Deployment 無狀態負載管理

package "Kubernetes Cluster" {
    package "Control Plane" {
        component [API Server] as api
        component [Controller Manager] as cm
        component [Scheduler] as sched
        database [etcd] as etcd
    }

    package "Worker Nodes" {
        component [Kubelet] as kubelet
        component [Kube-proxy] as proxy
        package "Pods" {
            component [Container 1] as c1
            component [Container 2] as c2
        }
    }
}

api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2

note right of api
  核心 API 入口
  所有操作經由此處
end note

@enduml

此圖示展示了客戶端 Pod 如何透明地與由 Deployment 物件建立的 Pod 進行通訊。

kube-proxy 是 Kubernetes 中的一個關鍵元件,負責管理叢集中的路由邏輯。它使用 iptables 或 IPVS 來維護必要的路由規則,確保流量被正確路由到健康的 Pod。

總之,Kubernetes 中的 Deployment 和 Service 對像是管理無狀態工作負載和暴露應用程式給外部流量的強大工具。透過結合這兩種資源,我們可以建立高度可用和容錯的應用程式。