Kubernetes Deployment 提供了管理無狀態應用程式生命週期的完整機制。透過 Deployment,可以輕鬆地佈署、更新和縮放應用程式。Service 則負責將應用程式暴露給外部流量,並提供穩定的存取入口。本文以 Nginx 為例,示範瞭如何使用 Deployment 和 Service 佈署一個簡單的 Web 應用程式。同時,也介紹了 Readiness Probe 的作用,以及如何組態和測試 Readiness Probe,以確保應用程式在準備就緒後才接收流量。最後,文章也演示瞭如何透過修改 Deployment 的副本數量來實作應用程式的彈性縮放,以適應不同的負載需求。
使用 Kubernetes Deployment 管理無狀態工作負載
在 Kubernetes 中,Deployment 是一種用於管理無狀態工作負載的重要資源。無狀態工作負載意味著應用程式不依賴於特定的 Pod 或儲存狀態。在本章中,我們將探討如何使用 Deployment 和 Service 物件來佈署和管理無狀態應用程式。
Service 物件的作用
Service 物件的主要作用是定義一組準備就緒的 Pod,並將它們隱藏在一個穩定的 ClusterIP 後面。通常,內部客戶端不會直接使用 ClusterIP 來呼叫 Service Pod,而是使用 DNS 短名稱(與 Service 名稱相同),例如 nginx-service-example。這將由叢集的內部 DNS 服務解析為 ClusterIP。或者,它們也可以使用完全合格的網域名稱(FQDN),例如 <serviceName>.<namespaceName>.svc.<clusterDomain>,例如 nginx-service-example.default.svc.cluster.local。
宣告式建立 Service
在這一部分,我們將使用 nginx-service-example Service 物件(型別為 LoadBalancer)來暴露我們的 nginx-deployment-example Deployment。步驟如下:
- 建立一個名為
nginx-service.yaml的 manifest 檔案,內容如下:
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service-example
spec:
selector:
app: nginx
environment: test
type: LoadBalancer
ports:
- port: 80
protocol: TCP
targetPort: 80
Service 的標籤選擇器與我們的 Deployment 物件相同。Service 的規範指示我們在雲端負載平衡器的 80 埠上暴露我們的 Deployment,並將流量從目標埠 80 路由到底層的 Pod。
內容解密:
apiVersion和kind定義了資源的型別和版本。metadata包含了 Service 的後設資料,如名稱。spec定義了 Service 的規範,包括選擇器、型別和埠組態。selector用於選擇符合特定標籤的 Pod。type指定了 Service 的型別,這裡是 LoadBalancer。ports定義了 Service 的埠組態,包括埠、協定和目標埠。
- 建立
nginx-service-exampleService,並使用kubectl get或kubectl describe命令來收集有關新 Service 和相關負載平衡器的資訊:
$ kubectl apply -f nginx-service.yaml
service/nginx-service-example created
$ kubectl describe service nginx-service-example
Name: nginx-service-example
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=nginx,environment=test
...<removed for brevity>...
Endpoints: 10.244.1.2:80,10.244.2.2:80,10.244.2.3:80
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
- 現在,讓我們嘗試從另一個 Pod 存取 Service,如同在第 8 章中所做的那樣。讓我們建立一個名為
k8sutils的 Pod,並測試 Service 存取:
$ kubectl apply -f ../Chapter07/k8sutils.yaml
pod/k8sutils created
$ kubectl exec -it k8sutils -- curl nginx-service-example.default.svc.cluster.local |grep Welcome -A2
<title>Welcome to nginx!</title>
<style>
body {
--
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p>
這表明瞭如何使用 Service 將 Deployment Pod 暴露給外部流量。
使用指令式命令建立 Service
可以使用指令式的 kubectl expose 命令來達到類別似的效果。這個命令將為我們的 Deployment 物件建立一個 Service。使用以下命令:
$ kubectl expose deployment --type=LoadBalancer nginx-deployment-example
service/nginx-deployment-example exposed
內容解密:
--type=LoadBalancer指定了 Service 的型別。nginx-deployment-example是要暴露的 Deployment 物件的名稱。
就緒性、存活性和啟動探針的作用
在第 8 章中,我們瞭解到可以為每個在 Pod 中執行的容器組態三種探針:
- 就緒性探針(Readiness probe)
- 存活探針(Liveness probe)
- 啟動探針(Startup probe)
這些探針對於組態 Deployment 至關重要。總是嘗試預測容器中執行的程式的可能生命週期場景,並相應地組態探針。
內容解密:
- 就緒性探針用於檢查容器是否準備好接受流量。
- 存活探針用於檢查容器是否存活,如果探針失敗,容器將被重新啟動。
- 啟動探針用於檢查容器是否已完成啟動,如果探針失敗,容器將被重新啟動。
預設情況下,Pod 中執行的容器上沒有組態任何探針。Kubernetes 將向 Service 後面的 Pod 容器提供流量,但前提是容器已成功啟動,並使用預設的始終重新啟動策略重新啟動當機的容器。這意味著您需要為您的特定案例確定所需的探針型別和設定,並瞭解錯誤組態探針的可能後果和注意事項。
組態與測試 Kubernetes Deployment 的 Readiness Probe
在 Kubernetes 中,readiness probe 是用於檢測 Pod 是否準備好接收流量的機制。本章節將示範如何在 Deployment 中組態 readiness probe,並即時觀察其運作。
為何需要 Readiness Probe
預設情況下,Kubernetes 會假設 Pod 在啟動後即可接收流量。然而,在某些情況下,Pod 可能需要一些時間來完成初始化或預熱,此時 readiness probe 可以幫助我們避免將流量導向尚未準備好的 Pod。
建立測試環境
首先,我們需要建立一個簡單的 nginx Deployment,並組態 readiness probe。為了方便測試,我們將透過修改容器內的檔案來模擬 readiness probe 的成功與失敗。
- 刪除現有的 Deployment
$ kubectl delete deployment nginx-deployment-example
- 建立新的 Deployment YAML
# nginx-deployment-readinessprobe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-readiness
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.25.4
ports:
- containerPort: 80
command:
- /bin/sh
- -c
- |
touch /usr/share/nginx/html/ready
echo "You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html
nginx -g "daemon off;"
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 2
timeoutSeconds: 10
successThreshold: 1
failureThreshold: 2
程式碼解析:
此 YAML 組態檔定義了一個名為 nginx-deployment-readiness 的 Deployment,具有以下特點:
- 使用
nginx:1.25.4映象,並將容器內的 80 連線埠暴露出來。 - 在容器啟動時執行自訂的 shell 命令:
touch /usr/share/nginx/html/ready:建立一個名為ready的空檔案,用於 readiness probe 的測試。echo "You have been served by Pod with IP address: $(hostname -i)" > /usr/share/nginx/html/index.html:將 Pod 的 IP 位址寫入index.html檔案,用於顯示在網頁上。nginx -g "daemon off;":啟動 nginx 服務。
- 組態 readiness probe:
- 使用
httpGet型別,探測/ready路徑是否可存取。 initialDelaySeconds: 5:容器啟動後 5 秒開始探測。periodSeconds: 2:每 2 秒探測一次。timeoutSeconds: 10:探測超時時間為 10 秒。successThreshold: 1:連續成功一次即視為成功。failureThreshold: 2:連續失敗兩次即視為失敗。
- 使用
建立與驗證 Deployment
- 套用新的 YAML 組態檔
$ kubectl apply -f ./nginx-deployment-readinessprobe.yaml
- 驗證 Service 與 Endpoint
$ kubectl describe svc nginx-service-example
輸出結果應該顯示三個 endpoint 對應到我們的 Deployment Pods,並且都已準備好接收流量。
此圖示說明瞭 readiness probe 的工作流程:
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title 建立與驗證 Deployment
rectangle "延遲5秒" as node1
rectangle "探測/ready路徑" as node2
rectangle "成功" as node3
rectangle "失敗" as node4
rectangle "接收流量" as node5
rectangle "不接收流量" as node6
node1 --> node2
node2 --> node3
node3 --> node4
node4 --> node5
node5 --> node6
@enduml此圖示呈現了 readiness probe 的運作流程,從容器啟動到探測結果的處理。透過這個機制,我們可以有效地管理 Pod 的流量分配,確保系統的穩定運作。
使用 Kubernetes Deployment 管理無狀態工作負載
測試 Nginx Web 伺服器存取與準備度探針
在前面的章節中,我們已經建立了一個名為 k8sutils 的 Pod。現在,我們將使用這個 Pod 來測試 nginx-service-example 服務的存取。
$ kubectl exec -it k8sutils -- curl nginx-service-example.default.svc.cluster.local
You have been served by Pod with IP address: 10.244.1.7
每次執行請求時,您可能會遇到不同的 Pod。這是因為我們的 Deployment 組態了三個 Pod 複本。
內容解密:
kubectl exec -it k8sutils -- curl nginx-service-example.default.svc.cluster.local:使用k8sutilsPod 對nginx-service-example服務發起 HTTP 請求。- 由於 Deployment 有多個 Pod 複本,請求會被分配到不同的 Pod 上。
模擬準備度失敗
現在,讓我們模擬第一個 Pod 的準備度失敗。假設第一個 Pod 名稱為 nginx-deployment-readiness-69dd4cfdd9-4pkwr,其 IP 位址為 10.244.1.7。我們可以透過刪除容器內的 ready 檔案來模擬準備度失敗:
$ kubectl exec -it nginx-deployment-readiness-69dd4cfdd9-4pkwr -- rm /usr/share/nginx/html/ready
內容解密:
kubectl exec -it nginx-deployment-readiness-69dd4cfdd9-4pkwr -- rm /usr/share/nginx/html/ready:刪除指定 Pod 中的ready檔案,使其準備度探針失敗。- 準備度探針組態為每 2 秒檢查一次,若連續兩次檢查失敗,則認為該 Pod 未準備好。
檢查服務狀態
當準備度探針失敗後,我們可以檢查 nginx-service-example 服務的狀態:
$ kubectl describe svc nginx-service-example | grep Endpoints
Endpoints: 10.244.1.6:80,10.244.2.6:80
內容解密:
kubectl describe svc nginx-service-example | grep Endpoints:檢視服務的端點列表,確認未準備好的 Pod 已被移除。
進一步模擬全部 Pod 準備度失敗
若刪除所有 Pod 中的 ready 檔案,將導致整個服務失敗:
$ kubectl exec -it nginx-deployment-readiness-69dd4cfdd9-7n2kz -- rm /usr/share/nginx/html/ready
$ kubectl exec -it nginx-deployment-readiness-69dd4cfdd9-t7rp2 -- rm /usr/share/nginx/html/ready
此時,所有 Pod 都處於 Running 狀態,但沒有一個是 Ready 狀態。
還原服務
透過重新建立 ready 檔案,可以使其中一個 Pod 還原 Ready 狀態:
$ kubectl exec -it nginx-deployment-readiness-69dd4cfdd9-4pkwr -- touch /usr/share/nginx/html/ready
內容解密:
kubectl exec -it nginx-deployment-readiness-69dd4cfdd9-4pkwr -- touch /usr/share/nginx/html/ready:在指定 Pod 中重新建立ready檔案,使其準備度探針成功。
縮放 Deployment
Kubernetes Deployment 的一大優勢是可以快速縮放。無論是擴充套件還是縮減,新的 Pod 都會被自動發現或從端點列表中移除。
調整 Deployment 組態
首先,修改 nginx-deployment-readinessprobe.yaml 清單檔案中的副本數量:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-readiness
spec:
replicas: 10
...
套用變更
使用 kubectl apply 命令將變更套用到叢集中:
$ kubectl apply -f ./nginx-deployment-readinessprobe.yaml
deployment.apps/nginx-deployment-readiness configured
檢視 Deployment 狀態
檢查 Pods 狀態,可以看到新的 Pods 正被建立:
$ kubectl get pods
檢視 Deployment 的詳細資訊,可以看到相關事件:
$ kubectl describe deployments.apps nginx-deployment-readiness
...
Events:
Type Reason Age From Message
---
-
---
---
---
-
---
-
---
-
---
Normal ScalingReplicaSet 32m deployment-controller Scaled up replica set nginx-deployment-readiness-69dd4cfdd9 to 3
Normal ScalingReplicaSet 9s deployment-controller Scaled up replica set nginx-deployment-readiness-69dd4cfdd9 to 10 from 3
內容解密:
kubectl apply -f ./nginx-deployment-readinessprobe.yaml:將更新後的 Deployment 組態套用到叢集中。kubectl describe deployments.apps nginx-deployment-readiness:檢視 Deployment 的詳細資訊,包括事件日誌,以確認副本集的縮放情況。