在上一篇介紹了Kubernetes(以下簡稱K8s)最小單位Pod,接著要介紹的就是Deployment,它和Pod的關係就像廚師與盤子中的菜色一樣,廚師需要決定要做哪些菜品,就像在Deployment中設置Pod模板一樣,你需要設置應用程式的基本配置和資源要求。接下來,你需要準備一些盤子,這些盤子就是Pod。每個盤子都可以裝載一道菜,就像Pod可以容納一個或多個容器(以上其實是ChatGPT幫我幻想的XDD)
編寫Deployment定義檔
我們建立一個my-first-deployment.yml的定義檔案,VSCode打開後直接輸入「k-deployment」快速產出簡單的範例
接著我們修改幾個部分:
- 將上一篇寫好的Pod【點我前往】從metadata開始貼到deployment的spec.template裡面
- spec.selector.mathLabels.app設定成template.metadata.labels
- 將spec.replicas設定成2
apiVersion: apps/v1
kind: Deployment
metadata:
name: wadweb-deployment
labels:
app: wadweb-deployment
spec:
selector:
matchLabels:
app: wadweb
replicas: 2
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
name: wadweb
labels:
app: wadweb
spec:
containers:
- name: wadwebapp
image: "你的registryURL/wad-web:v2.0.0"
imagePullPolicy: Always
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 80
name: http
- name: wadwebapi
image: "你的registryURL/wad-web-api:v2.0.0"
imagePullPolicy: Always
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 1000m
memory: 1Gi
env:
- name: DOTNET_RUNNING_IN_CONATINER
value: "true"
- name: ASPNETCORE_ENVIRONMENT
value: "Development"
- name: ASPNETCORE_URLS
value: "http://+:8080"
- name: ConnectionStrings__DefaultConnection
value: "Server=你的SQLServer Connection;Initial Catalog=WADREQM;Persist Security Info=False;User ID=你的SQLServer帳號;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=true;Connection Timeout=30;"
- name: Connection__Key
value: "我是密碼"
- name: HostUrl__RemoteHost
value: "http://192.168.1.34:8080"
- name: TZ
value: "Asia/Taipei"
volumeMounts:
- name: fileupload
mountPath: /app/upload
ports:
- containerPort: 8080
name: http
volumes:
- name: fileupload
hostPath:
path: /run/desktop/mnt/host/d/Kubernetes/fileupload
type: DirectoryOrCreate
restartPolicy: Always
- spec.selector.matchLabels:用於指定Deployment、Service、ReplicaSet等資源對象所要選擇的Pod標籤(Label),以範例來說就是套用Deployment到有app=wadweb的Pod身上
- spec.replicas:設定要運行的Pod副本數量💡 如果設定0就會直接刪除所有的Pod,在某些情況真的會設定成0,不過我還沒遇到就是了XD
- spec.strategy:指定Deployment或ReplicaSet的更新策略💡 有兩個可選的更新策略:Recreate和RollingUpdate,Recreate是默認的更新策略。當需要更新Deployment或ReplicaSet時,Kubernetes會停止所有的Pod副本,然後重新創建新的Pod副本,它優點是簡單易行,缺點是在更新過程中會導致服務中斷。而RollingUpdate則會逐步地將現有的Pod副本替換成新的Pod副本,從而實現無停機更新,因此建議需要無痛升級的可以選RollingUpdate
- spec.strategy.rollingUpdate:設定為滾動更新
- spec.strategy.rollingUpdate.maxSurge:更新時可以額外創建的Pod副本數量💡 預設值是25%,可以是固定值或是百分比(%)
允許的格式:
1(1個Pod)
25% - spec.strategy.rollingUpdate.maxUnavailable:更新時可以同時關閉的Pod副本數量💡 maxSurge和maxUnavailable我也是搞了好久才弄懂,總之如果我們希望在更新過程中維持足夠的Pod副本,以確保應用程式的可用性,那麼可以將maxUnavailable設置為0,以禁止同時關閉Pod副本。這樣一來,在更新期間始終會保持足夠的Pod副本運行也就是1上1下的概念,只是速度上可能會慢一點就是了XD
- spec.template:就是Pod的定義檔案內容
執行Deployment
建立好定義檔之後使用kubectl來建立Deployment,目前在Docker Desktop上一樣是沒有任何容器在執行
執行以下指令
kubectl apply -f my-first-deployment.yml
部署後我們可以使用以下語法查看一下剛剛部署的Deployment資訊
kubectl get deployment
這邊需要視容器情況等待一下,等待的過程如果想要即時監控Deployment的部署狀況則可以使用下列語法
kubectl rollout status deployment/wadweb-deployment
等待完成後就重新下Deployment的指令就可以看到READY是2/2並且AVAILABLE數量不會是0,另外也可以使用指令查看Pod的狀態或是從Docker Desktop上看也可以哦!
💡 由於spec.replicas是設定2因此我們可以看到總共是1個Deployment對上2個Pod,2個Pod共有4個容器
更新Deployment
成功部署Deployment後日後要做的就是
- 增加/減少Replicas的數量
- 新增容器
- 修改容器內容
- 刪除容器
- 等等等
我們先試著關掉Web API這個容器,關掉後定義檔會是以下這樣
apiVersion: apps/v1
kind: Deployment
metadata:
name: wadweb-deployment
labels:
app: wadweb-deployment
spec:
selector:
matchLabels:
app: wadweb
replicas: 2
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
name: wadweb
labels:
app: wadweb
spec:
containers:
- name: wadwebapp
image: "你的registryURL/wad-web:v2.0.0"
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 80
name: http
restartPolicy: Always
接著就直接使用Apply的方式執行,讓K8s覆蓋掉原本的定義檔,覆蓋完成後基本上K8s就會依照你的定義檔去調整相對應的理想狀態
滾動升級
想像一下你正在經營一家餐廳,每天有很多客人來用餐。為了滿足客人的需求,你需要在餐廳中同時運行多個服務生,以便能夠及時地為客人提供服務。當你需要更新服務生的工作內容或調整他們的排班時,你不能直接把他們全部叫回家,然後再讓他們重新開始工作,因為這樣會影響餐廳的正常運營,因此你需要採用一種滾動更新的方式,逐步地調整服務生的工作內容和排班,使得餐廳始終能夠保持正常運營。在K8s中,滾動升級也採用了類似的策略。當你需要更新一個Deployment物件中的Pod時,K8s會先啟動一些新的 Pod,然後再逐步地停止舊的 Pod。在這個過程中,控制器會根據 maxSurge 和 maxUnavailable 屬性來決定同時運行的 Pod 數量,以及最多可以停止的 Pod 數量。這樣可以保證應用程式始終能夠保持正常運營,同時還能進行必要的更新或調整呢!首先把剛剛的Deployment全數刪除掉
然後重新調整一下定義檔內容
kubectl delete deployment wadweb-deployment
然後重新調整一下定義檔內容
- spec.replicas 改成5
- spec.strategy.rollingUpdate.maxSurge 改為2
- spec.strategy.rollingUpdate.maxUnavailable 改為2
- 把剛剛刪除的Web API加回來
apiVersion: apps/v1
kind: Deployment
metadata:
name: wadweb-deployment
labels:
app: wadweb-deployment
spec:
selector:
matchLabels:
app: wadweb
replicas: 5
strategy:
rollingUpdate:
maxSurge: 2
maxUnavailable: 2
type: RollingUpdate
template:
metadata:
name: wadweb
labels:
app: wadweb
spec:
containers:
- name: wadwebapp
image: "你的registryURL/wad-web:v2.0.0"
imagePullPolicy: Always
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 80
name: http
- name: wadwebapi
image: "你的registryURL/wad-web-api:v2.0.0"
imagePullPolicy: Always
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 1000m
memory: 1Gi
env:
- name: DOTNET_RUNNING_IN_CONATINER
value: "true"
- name: ASPNETCORE_ENVIRONMENT
value: "Development"
- name: ASPNETCORE_URLS
value: "http://+:8080"
- name: ConnectionStrings__DefaultConnection
value: "Server=你的SQLServer Connection;Initial Catalog=WADREQM;Persist Security Info=False;User ID=你的SQLServer帳號;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=true;Connection Timeout=30;"
- name: Connection__Key
value: "我是密碼"
- name: HostUrl__RemoteHost
value: "http://192.168.1.34:8080"
- name: TZ
value: "Asia/Taipei"
volumeMounts:
- name: fileupload
mountPath: /app/upload
ports:
- containerPort: 8080
name: http
volumes:
- name: fileupload
hostPath:
path: /run/desktop/mnt/host/d/Kubernetes/fileupload
type: DirectoryOrCreate
restartPolicy: Always
接著我們修改一下Web APP改成一個不存在的容器的版本v2.0.0.21,修改完後直接部署上去然後使用指令觀察Pod的狀態
apiVersion: apps/v1
kind: Deployment
metadata:
name: wadweb-deployment
labels:
app: wadweb-deployment
spec:
selector:
matchLabels:
app: wadweb
replicas: 5
strategy:
rollingUpdate:
maxSurge: 2
maxUnavailable: 2
type: RollingUpdate
template:
metadata:
name: wadweb
labels:
app: wadweb
spec:
containers:
- name: wadwebapp
image: "你的registryURL/wad-web:v2.0.0.21"
imagePullPolicy: Always
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 80
name: http
- name: wadwebapi
image: "你的registryURL/wad-web-api:v2.0.0"
imagePullPolicy: Always
.
.
.
略過
maxSurge=2時表示在更新期間最多可以同時啟動 2 個額外的 Pod,因此會看到總共有 7 個 Pod 在運行,同時又因為maxUnavailable=2,表示在更新期間最多可以停止 2 個 Pod。因此當我們開始更新時,最少會有 3 個 Pod 在運行,直到新 Pod 完全啟動後,舊的 Pod 才會被停止,但又因為我們設定了不存在Image,因此圖片才會看到兩個Pod的ImagePullBackOff的狀態、兩個處於Pending的狀態、三個持續運作中,所以在整個滾動升級的過程中要確保有足夠數量的Pod服務提供給客戶使用,而這個足夠的數量就是介於「3 ≤ 實際運作中的Pod ≤ 7」這個區間內哦!
回滾機制
假設你經營的餐廳,為了吸引更多的客人,你決定將菜單上的產品進行更新。你找了一位經驗豐富的廚師進行新產品的製作,但在進行更新時,你發現新產品的味道不如預期,而且還影響到了其他產品的銷售。此時,如果你有一個回滾機制,就可以快速恢復到之前的菜單,避免進一步損失。K8s中提供了回滾機制,當你需要回滾一個Deployment物件時,可以使用回滾指令並指定回滾到指定的版本。K8s會自動從指定的版本開始回滾,將舊的 Pod 啟動起來,同時停止新的 Pod。當回滾完成後,應用程式就可以快速恢復到之前的穩定狀態,簡單來說就是上一步(Undo)的概念。
要使用回滾功能可以直接使用下面的命令
kubectl rollout undo deployment/wadweb-deployment
另外也可以增加參數來指定要恢復到哪一個版本,恢復版本前還可以先用以下命令查詢一下歷史版本
kubectl rollout history deployment wadweb-deployment
接著只要在回滾的命令加上上圖的對應版本(VERSION)即可
kubectl rollout undo deployment/wadweb-deployment --to-revision=[REVISION]
0 Comments
張貼留言