iT邦幫忙

2024 iThome 鐵人賽

DAY 8
1
Kubernetes

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

學 Kubernetes 的第八天 - 部署你的第一個應用程式 (3) - Deployment 部署與退版

  • 分享至 

  • xImage
  •  

概述

雖然我們在上一章節中完成的部署已經可以使用了。然而,在現代應用部署中,我們還需要考慮高可用性、自動恢復以及部署更新和回滾等需求。為了實現這些目標,我們需要使用 Deployment 來管理和擴展我們的應用部署。

Deployment 是什麼

Deployment 是 Kubernetes 中用來管理 Pod 副本的資源。你可以將 Deployment 視為一組 Pod 的聲明,這些 Pod 具有相同的規格和標籤。Deployment 會自動確保這些 Pod 的數量保持在您指定的副本數,並在 Pod 失敗或節點發生故障時自動替換它們。

Deployment, ReplicaSet, Pod 的關係

Deployment 是 Kubernetes 中用來管理 Pod 副本的資源,它可以自動創建和管理 ReplicaSet,而 ReplicaSet 則確保有足夠數量的 Pod 在運行,這樣 Deployment 可以輕鬆實現應用程式的滾動更新、擴展以及回滾操作,確保應用始終處於穩定的狀態。

簡單來說:Deployment -> 管理 ReplicaSet -> 管理 Pod

https://ithelp.ithome.com.tw/upload/images/20240922/20168212CSqSYnkRmX.png

  • Pod 是 Kubernetes 中最小的可部署單位,通常包含一個或多個容器。Pod 是應用程式的實際執行單元。
  • ReplicaSet 的作用是確保系統中有一組指定數量的 Pod 副本在運行。如果有 Pod 失效或被刪除,ReplicaSet 會自動創建新的 Pod 來補充。
  • Deployment 主要用於聲明式地管理應用程式的生命週期。它可以用來滾動更新、擴展或回滾應用程式版本,並確保應用程式始終保持在期望的狀態。Deployment 會自動創建並管理一個或多個 ReplicaSet

ReplicaSetDeployment 的底層實現部分。雖然你可以直接使用 ReplicaSet,但通常更推薦通過 Deployment 來管理,因為 Deployment 提供了更多高級功能,如滾動更新和回滾。

https://ithelp.ithome.com.tw/upload/images/20240922/20168212odRTb1ghYt.png

應用場景

  • 滾動更新:當需要更新應用程式的版本或配置時,可以使用 Deployment 來逐步替換現有的 Pod,確保應用在更新過程中始終可用。
  • 自動回滾:如果更新後的版本出現問題,Deployment 可以自動回滾到上一個穩定的版本,減少停機時間和風險。
  • 水平擴展:當應用需要應對更多的流量或負載時,可以通過 Deployment 調整副本數量,自動擴展 Pod,從而提高應用的處理能力。
  • 持續部署:在 CI/CD(持續整合/持續部署)流水線中,Deployment 可以用來自動部署新的應用版本,確保快速迭代和部署。
  • 高可用性Deployment 可以在多個節點上運行多個 Pod 副本,確保應用在單個 Pod 或節點故障時仍然可用。
  • 環境隔離:可以使用 Deployment 在不同的環境(如開發、測試、預發布、正式環境)中部署相同的應用版本,確保一致性和隔離性。

組態檔案說明

以下是等下會使用的 Deployment 組態檔案範例,使用 YAML 格式:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: foo
  template:
    metadata:
      labels:
        app: foo
    spec:
      containers:
      - name: foo
        image: lofairy/foo
  • apiVersion: apps/v1:指定使用的 Kubernetes API 版本,這裡使用的是 apps/v1,通常用於 Deployment、DaemonSet、StatefulSet 等資源。
  • kind: Deployment:指定這個資源的類型是 Deployment。
  • metadata:Deployment 的元數據設定。
    • name: foo-deployment:Deployment 的名稱是 foo-deployment
  • spec:Deployment 的規格設定。
    • replicas: 3:指定要運行的 Pod 副本數量為 3,這意味著 Kubernetes 會保持有 3 個相同的 Pod 在集群中運行。
    • selector:定義選擇 Pod 的標準。
      • matchLabels:選擇包含標籤 app: foo 的 Pod,來關聯這些 Pod 到這個 Deployment。
    • template:Pod 模板,Deployment 會根據這個模板來創建 Pod。
      • metadata:Pod 的元數據設定。
        • labels:定義 Pod 的標籤為 app: foo
      • spec:Pod 的規格設定。
        • containers:這個 Pod 包含的容器設定。
          • name: foo:容器的名稱是 foo
          • image: lofairy/foo:容器將使用 lofairy/foo 這個 Docker 鏡像來啟動。

透過這個組態檔案,Kubernetes 會建立一個名為 foo-deployment 的 Deployment,並確保始終有三個使用指定 lofairy/foo 映像檔的 Pod 在集群中運行。

實作

今天我們的目標是將上一章部署的 Pod 改用 Deployment 部署,並模擬回滾需求。示意圖如下:

https://ithelp.ithome.com.tw/upload/images/20240922/20168212JdTZH354Og.png

建立 Deployment

  • 清理 Pod
kubectl delete -f pod.yaml

組態檔案: deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: foo
  template:
    metadata:
      labels:
        app: foo
    spec:
      containers:
      - name: foo
        image: lofairy/foo
  • 建立 Deployment
kubectl apply -f deployment.yaml

儘管我們使用 Deployment 重新創建了 Pod 副本,但不需要對已有的 Service 進行任何修改。Service 是通過選擇器來根據標籤篩選 Pod 並進行流量導向的,它會自動尋找並連接到符合條件的 Pod,對所有目標 Pod 進行基本的負載均衡(Load Balancing)。Deployment 組態檔案設定的 Pod 標籤與昨天的 Pod 組態檔案相同。

  • 驗證 Deployment 建立的應用
for i in {1..10}; do curl -s 0.0.0.0:30000/hostname; echo; done
---
{"hostname":"foo-deployment-66587db9f-vjgdn"}
{"hostname":"foo-deployment-66587db9f-qr9qr"}
{"hostname":"foo-deployment-66587db9f-qr9qr"}
{"hostname":"foo-deployment-66587db9f-qr9qr"}
{"hostname":"foo-deployment-66587db9f-xpltq"}
{"hostname":"foo-deployment-66587db9f-xpltq"}
{"hostname":"foo-deployment-66587db9f-qr9qr"}
{"hostname":"foo-deployment-66587db9f-vjgdn"}
{"hostname":"foo-deployment-66587db9f-vjgdn"}
{"hostname":"foo-deployment-66587db9f-vjgdn"}

Deployment 的 Replica

在 Deployment 中,spec.replicas 欄位用來指定應維持的 Pod 副本數量。透過這個設定,我們可以輕鬆地實現水平擴展,以及在多區域 (節點) 中進行部署。

  • 檢查 Deployment Pod 副本狀況
kubectl get pod -o wide
---
NAME                             READY   STATUS    RESTARTS   AGE     IP            NODE              NOMINATED NODE   READINESS GATES
foo-deployment-66587db9f-8pjsh   1/1     Running   0          15s     10.244.1.8    wslkind-worker    <none>           <none>
foo-deployment-66587db9f-p2mfk   1/1     Running   0          5m35s   10.244.2.15   wslkind-worker2   <none>           <none>
foo-deployment-66587db9f-z544f   1/1     Running   0          5m35s   10.244.1.7    wslkind-worker    <none>           <none>
  • spec.replicas 調整成 5 個
kubectl scale deployment foo-deployment --replicas 5
  • 再次檢查 Deployment Pod 副本狀況
kubectl get pod -o wide
---
NAME                             READY   STATUS    RESTARTS   AGE     IP            NODE              NOMINATED NODE   READINESS GATES
foo-deployment-66587db9f-4wg7c   1/1     Running   0          5s      10.244.2.18   wslkind-worker2   <none>           <none>
foo-deployment-66587db9f-8pjsh   1/1     Running   0          2m25s   10.244.1.8    wslkind-worker    <none>           <none>
foo-deployment-66587db9f-gptw4   1/1     Running   0          5s      10.244.2.19   wslkind-worker2   <none>           <none>
foo-deployment-66587db9f-p2mfk   1/1     Running   0          7m45s   10.244.2.15   wslkind-worker2   <none>           <none>
foo-deployment-66587db9f-z544f   1/1     Running   0          7m45s   10.244.1.7    wslkind-worker    <none>           <none>

Deployment 的 Rollout

Deployment 實現了 Rollout 的特性,無論是初次創建資源,還是更新 Deployment 的 PodTemplateSpec,都會生成 Rollout 的歷史記錄。

  • 查看 Deployment 的 rollout history
kubectl rollout history deployment foo-deployment
---
REVISION  CHANGE-CAUSE
1         <none>

在上面改變副本數量並沒有留下紀錄,因為這個特性是透過 ReplicaSet 實現,而不是 Pod 本身自帶的

接下來我們來更新我們的應用程式,這次我們將 PodTemplateSpec 裡的 image 更新為 lofairy/bar

  • 更新應用 image
kubectl set image deployment foo-deployment foo=lofairy/bar
  • 查看 Deployment 的詳細資訊
kubectl describe deployment foo-deployment

結果如下

Name:                   foo-deployment
Namespace:              default
[...]
Pod Template:
  Labels:  app=foo
  Containers:
   foo:
    Image:        lofairy/bar
 [...]
  • 訪問 Service
curl 0.0.0.0:30000
---
bar

可以看到,新版本應用已經更新部署。

  • 再次查看 Deployment 的 rollout history
kubectl rollout history deployment foo-deployment
---
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

你可能注意到,CHANGE-CAUSE 欄位中沒有任何信息,這使得追踪和判別 Deployment 的變更原因變得困難。CHANGE-CAUSE 的內容實際上是從 Deployment 的 kubernetes.io/change-cause 註解中繼承而來。要設定或修改 CHANGE-CAUSE,可以採取以下兩種方法:

  1. 使用 kubectl annotate 命令為 Deployment 添加註解。
  2. 直接在資源設定檔的 metadata 部分手動修改,添加或更新 kubernetes.io/change-cause 註解,以記錄變更的原因。
  • 使用 kubectl annotate 命令新增註解
kubectl annotate deployment foo-deployment kubernetes.io/change-cause="image changed to lofairy/bar"
  • 再次查看 Deployment 的 rollout history
kubectl rollout history deployment foo-deployment
---
REVISION  CHANGE-CAUSE
1         <none>
2         image changed to lofairy/bar

Deployment 的回滾

假如我們應用出了問題,需要將應用程式退版,可以使用 kubectl rollout undo 指令。

  • 回滾 Deployment 到上一個版本
kubectl rollout undo deployment foo-deployment
  • 訪問 Service
curl 0.0.0.0:30000
---
foo
  • 再次查看 Deployment 的 rollout history
kubectl rollout history deployment foo-deployment
---
REVISION  CHANGE-CAUSE
2         image changed to lofairy/bar
3         <none>

在執行回滾操作時,被回滾的版本號會消失,並且回滾的內容會移到最新的版本位置。也就是說,回滾後的版本號將會變成最新的修訂版本。

當你執行 kubectl rollout undo 時,Kubernetes 會執行以下步驟:

  1. 找到目標版本:定位到你想要回滾的目標版本(通常是前一個版本)。
  2. 應用目標版本:將該版本的配置應用到 Deployment 中,使其成為當前的最新版本。
  3. 更新版本歷史:將當前版本移入歷史修訂中,並將回滾的版本記錄為新的當前版本。

這意味著:

  • 回滾的版本 將被重新應用,並成為最新的修訂版本。
  • 當前的版本 會被移入歷史,成為舊的修訂版本。

清理

記得清理這幾天建立的資源,方便之後的實作練習。

kubectl delete -f pod.yaml -f service.yaml -f deployment.yaml
# 或是一次性的刪除所有對應的組態檔案
kubectl delete -f .

小結

到今天為止,我們已經學會了如何通過程式撰寫、容器編譯和 Kubernetes 部署來實現我們的應用。然而,這只是 Kubernetes 整體中很小的一部分。在接下來的時間裡,我們將按照主題一步步深入了解 Kubernetes 的資源及其設計上的特點。


上一篇
學 Kubernetes 的第七天 - 部署你的第一個應用程式 (2) - Pod & Service
下一篇
學 Kubernetes 的第九天 - Pod - 基礎概念與核心特性
系列文
都什麼年代了,還在學 Kubernetes37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言