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 物件。
apiVersion和kind指定了物件的 API 版本和型別。metadata部分包含物件的中繼資料,如名稱。spec部分定義了物件的期望狀態。replicas指定了要執行的 Pod 副本數量。selector和template.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 get 和 kubectl 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 對像是管理無狀態工作負載和暴露應用程式給外部流量的強大工具。透過結合這兩種資源,我們可以建立高度可用和容錯的應用程式。