Kubernetes 學習筆記 4 工作負載 Deployments
https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
工作負載是在 Kubernetes 上執行的應用程式。
無論你的負載是單一元件還是由多個一同工作的元件構成,在 Kubernetes 中你 可以在一組 Pods 中執行它。 在 Kubernetes 中,Pod 代表的是叢集上處於執行狀態的一組 容器。
Kubernetes Pods 有確定的生命週期。 例如,當某 Pod 在你的叢集中執行時,Pod 執行所在的 節點 出現致命錯誤時, 所有該節點上的 Pods 都會失敗。Kubernetes 將這類失敗視為最終狀態: 即使該節點後來恢復正常執行,你也需要建立新的 Pod 來恢復應用。
不過,為了讓使用者的日子略微好過一些,你並不需要直接管理每個 Pod。 相反,你可以使用 負載資源 來替你管理一組 Pods。 這些資源配置 控制器 來確保合適型別的、處於執行狀態的 Pod 個數是正確的,與你所指定的狀態相一致。
Kubernetes 提供若干種內建的工作負載資源:
- Deployment 和 ReplicaSet (替換原來的資源 ReplicationController)。
Deployment
很適合用來管理你的叢集上的無狀態應用,Deployment
中的所有Pod
都是相互等價的,並且在需要的時候被換掉。 - StatefulSet 讓你能夠執行一個或者多個以某種方式跟蹤應用狀態的 Pods。 例如,如果你的負載會將資料作持久儲存,你可以執行一個
StatefulSet
Pod
與某個PersistentVolume
對應起來。你在StatefulSet
中各個Pod
內執行的程式碼可以將資料複製到同一StatefulSet
中的其它Pod
中以提高整體的服務可靠性。
- DaemonSet 定義提供節點本地支撐設施的
Pods
。這些 Pods 可能對於你的叢集的運維是 非常重要的,例如作為網路連結的輔助工具或者作為網路 外掛 的一部分等等。每次你向叢集中新增一個新節點時,如果該節點與某DaemonSet
的規約匹配,則控制面會為該DaemonSet
排程一個Pod
到該新節點上執行。 - Job 和 CronJob。 定義一些一直執行到結束並停止的任務。
Job
CronJob
會根據其時間規劃反覆執行。
在龐大的 Kubernetes 生態系統中,你還可以找到一些提供額外操作的第三方 工作負載資源。通過使用 定製資源定義(CRD), 你可以新增第三方工作負載資源,以完成原本不是 Kubernetes 核心功能的工作。 例如,如果你希望執行一組 Pods
,但要求所有 Pods 都可用時才執行操作 (比如針對某種高吞吐量的分散式任務),你可以實現一個能夠滿足這一需求 的擴充套件,並將其安裝到叢集中執行。
Deployments
一個 Deployment 為 Pods 和 ReplicaSets 提供宣告式的更新能力。
你負責描述 Deployment 中的 目標狀態,而 Deployment 控制器(Controller) 以受控速率更改實際狀態, 使其變為期望狀態。你可以定義 Deployment 以建立新的 ReplicaSet,或刪除現有 Deployment, 並通過新的 Deployment 收養其資源。
用例
以下是 Deployments 的典型用例:
- 建立 Deployment 以將 ReplicaSet 上線。 ReplicaSet 在後臺建立 Pods。 檢查 ReplicaSet 的上線狀態,檢視其是否成功。
- 通過更新 Deployment 的 PodTemplateSpec,宣告 Pod 的新狀態 。 新的 ReplicaSet 會被建立,Deployment 以受控速率將 Pod 從舊 ReplicaSet 遷移到新 ReplicaSet。 每個新的 ReplicaSet 都會更新 Deployment 的修訂版本。
- 如果 Deployment 的當前狀態不穩定,回滾到較早的 Deployment 版本。 每次回滾都會更新 Deployment 的修訂版本。
- 擴大 Deployment 規模以承擔更多負載。
- 暫停 Deployment 以應用對 PodTemplateSpec 所作的多項修改, 然後恢復其執行以啟動新的上線版本。
- 使用 Deployment 狀態 來判定上線過程是否出現停滯。
- 清理較舊的不再需要的 ReplicaSet
建立 Deployment
下面是 Deployment 示例。其中建立了一個 ReplicaSet,負責啟動三個 nginx
Pods:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
在該例中:
- 建立名為
nginx-deployment
(由.metadata.name
欄位標明)的 Deployment。 - 該 Deployment 建立三個(由
replicas
欄位標明)Pod 副本。
-
selector
欄位定義 Deployment 如何查詢要管理的 Pods。 在這裡,你選擇在 Pod 模板中定義的標籤(app: nginx
)。 不過,更復雜的選擇規則是也可能的,只要 Pod 模板本身滿足所給規則即可。說明:
spec.selector.matchLabels
欄位是{key,value}
鍵值對對映。 在matchLabels
對映中的每個{key,value}
對映等效於matchExpressions
中的一個元素, 即其key
欄位是 “key”,operator
為 “In”,values
陣列僅包含 “value”。 在matchLabels
和matchExpressions
中給出的所有條件都必須滿足才能匹配。
template
欄位包含以下子欄位:- Pod 被使用
labels
欄位打上app: nginx
標籤。 - Pod 模板規約(即
.template.spec
欄位)指示 Pods 執行一個nginx
容器, 該容器執行版本為 1.14.2 的nginx
Docker Hub映象。 - 建立一個容器並使用
name
欄位將其命名為nginx
。
- Pod 被使用
1 通過執行以下命令建立 Deployment :
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
2執行 kubectl get deployments
檢查 Deployment 是否已建立。如果仍在建立 Deployment, 則輸出類似於:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 0 0 0 1s
3要檢視 Deployment 上線狀態,執行 kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out
4幾秒鐘後再次執行 kubectl get deployments
。輸出類似於:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 3 3 3 18s
5要檢視 Deployment 建立的 ReplicaSet(rs
),執行 kubectl get rs
。 輸出類似於:
NAME DESIRED CURRENT READY AGE nginx-deployment-75675f5897 3 3 3 18s
6 要檢視每個 Pod 自動生成的標籤,執行 kubectl get pods --show-labels
。返回以下輸出:
NAME READY STATUS RESTARTS AGE LABELS nginx-deployment-75675f5897-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453 nginx-deployment-75675f5897-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453 nginx-deployment-75675f5897-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453
說明: 你必須在 Deployment 中指定適當的選擇算符和 Pod 模板標籤(在本例中為
app: nginx
)。 標籤或者選擇算符不要與其他控制器(包括其他 Deployment 和 StatefulSet)重疊。 Kubernetes 不會阻止你這樣做,但是如果多個控制器具有重疊的選擇算符,它們可能會發生衝突 執行難以預料的操作
Pod-template-hash 標籤
Deployment 控制器將 pod-template-hash
標籤新增到 Deployment 所建立或收留的 每個 ReplicaSet
此標籤可確保 Deployment 的子 ReplicaSets 不重疊。 標籤是通過對 ReplicaSet 的 PodTemplate
進行雜湊處理。 所生成的雜湊值被新增到 ReplicaSet 選擇算符、Pod 模板標籤,並存在於在 ReplicaSet 可能擁有的任何現有 Pod 中。
更新 Deployment
說明: 僅當 Deployment Pod 模板(即
.spec.template
)發生改變時,例如模板的標籤或容器映象被更新, 才會觸發 Deployment 上線。 其他更新(如對 Deployment 執行擴縮容的操作)不會觸發上線動作。
按照以下步驟更新 Deployment:
1 先來更新 nginx Pod 以使用 nginx:1.16.1
映象,而不是 nginx:1.14.2
映象。
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
或者,可以 edit
Deployment 並將 .spec.template.spec.containers[0].image
從 nginx:1.14.2
更改至 nginx:1.16.1
。
kubectl edit deployment.v1.apps/nginx-deployment
2要檢視上線狀態,執行:
kubectl rollout status deployment/nginx-deployment
獲取關於已更新的 Deployment 的更多資訊:
在上線成功後,可以通過執行 kubectl get deployments
來檢視 Deployment
執行 kubectl get rs
以檢視 Deployment 通過建立新的 ReplicaSet 並將其擴容到 3 個副本並將舊 ReplicaSet 縮容到 0 個副本完成了 Pod 的更新操作:
現在執行 kubectlget pods
應僅顯示新的 Pods:
Deployment 可確保在更新時僅關閉一定數量的 Pod。預設情況下,它確保至少所需 Pods 75% 處於執行狀態(最大不可用比例為 25%)。
Deployment 還確保僅所建立 Pod 數量只可能比期望 Pods 數高一點點。 預設情況下,它可確保啟動的 Pod 個數比期望個數最多多出 25%(最大峰值 25%)。
例如,如果仔細檢視上述 Deployment ,將看到它首先建立了一個新的 Pod,然後刪除了一些舊的 Pods, 並建立了新的 Pods。它不會殺死老 Pods,直到有足夠的數量新的 Pods 已經出現。 在足夠數量的舊 Pods 被殺死前並沒有建立新 Pods。它確保至少 2 個 Pod 可用,同時 最多總共 4 個 Pod 可用。
獲取 Deployment 的更多資訊
kubectl describe deployments
翻轉(多 Deployment 動態更新)
Deployment 控制器每次注意到新的 Deployment 時,都會建立一個 ReplicaSet 以啟動所需的 Pods。 如果更新了 Deployment,則控制標籤匹配 .spec.selector
但模板不匹配 .spec.template
的 Pods 的現有 ReplicaSet 被縮容。最終,新的 ReplicaSet 縮放為 .spec.replicas
個副本, 所有舊 ReplicaSets 縮放為 0 個副本。
當 Deployment 正在上線時被更新,Deployment 會針對更新建立一個新的 ReplicaSet 並開始對其擴容,之前正在被擴容的 ReplicaSet 會被翻轉,新增到舊 ReplicaSets 列表 並開始縮容。
例如,假定你在建立一個 Deployment 以生成 nginx:1.14.2
的 5 個副本,但接下來 更新 Deployment 以建立 5 個 nginx:1.16.1
的副本,而此時只有 3 個nginx:1.14.2
副本已建立。在這種情況下,Deployment 會立即開始殺死 3 個 nginx:1.14.2
Pods, 並開始建立 nginx:1.16.1
Pods。它不會等待 nginx:1.14.2
的 5 個副本都建立完成 後才開始執行變更動作。
回滾 Deployment
有時,你可能想要回滾 Deployment;例如,當 Deployment 不穩定時(例如進入反覆崩潰狀態)。 預設情況下,Deployment 的所有上線記錄都保留在系統中,以便可以隨時回滾 (你可以通過修改修訂歷史記錄限制來更改這一約束)。
說明: Deployment 被觸發上線時,系統就會建立 Deployment 的新的修訂版本。 這意味著僅當 Deployment 的 Pod 模板(
.spec.template
)發生更改時,才會建立新修訂版本 -- 例如,模板的標籤或容器映象發生變化。 其他更新,如 Deployment 的擴縮容操作不會建立 Deployment 修訂版本。 這是為了方便同時執行手動縮放或自動縮放。 換言之,當你回滾到較早的修訂版本時,只有 Deployment 的 Pod 模板部分會被回滾。
檢查 Deployment 上線歷史
1檢查 Deployment 修訂歷史
kubectl rollout history deployment.v1.apps/nginx
2要檢視修訂歷史的詳細資訊,執行:
kubectl rollout history deployment.v1.apps/nginx --revision=1
回滾到之前的修訂版本
1假定現在你已決定撤消當前上線並回滾到以前的修訂版本:
kubectl rollout undo deployment.v1.apps/nginx-deployment
或者
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
2檢查回滾是否成功以及 Deployment 是否正在執行,執行:
kubectl get deployment nginx-deployment
縮放 Deployment
kubectl scale deployment.v1.apps/nginx-deployment --replicas=10
比例縮放
RollingUpdate 的 Deployment 支援同時執行應用程式的多個版本。 當自動縮放器縮放處於上線程序(仍在進行中或暫停)中的 RollingUpdate Deployment 時, Deployment 控制器會平衡現有的活躍狀態的 ReplicaSets(含 Pods 的 ReplicaSets)中的額外副本, 以降低風險。這稱為 比例縮放(Proportional Scaling)
例如,你正在執行一個 10 個副本的 Deployment,其 maxSurge=3,maxUnavailable=2。
確保 Deployment 的這 10 個副本都在執行。
更新 Deployment 使用新映象,碰巧該映象無法從叢集內部解析。
暫停、恢復 Deployment
Deployment 狀態
Deployment 的生命週期中會有許多狀態。上線新的 ReplicaSet 期間可能處於 Progressing(進行中),可能是 Complete(已完成),也可能是 Failed(失敗)以至於無法繼續進行。
失敗的 Deployment
你的 Deployment 可能會在嘗試部署其最新的 ReplicaSet 受挫,一直處於未完成狀態。 造成此情況一些可能因素如下:
- 配額(Quota)不足
- 就緒探測(Readiness Probe)失敗
- 映象拉取錯誤
- 許可權不足
- 限制範圍(Limit Ranges)問題
- 應用程式執行時的配置錯誤