為保障ACK叢集應用程式更新不中斷服務,可通過配置Deployment的就緒探針、readinessGates、preStop鉤子和SLB優雅中斷等,實現流量的平滑遷移,保障業務持續高可用。
工作原理
為確保服務升級時的高可用性,可基於無狀態(Deployment)應用的變換(Rolling Update)策略,通過逐個替換Pod的方式確保應用始終存在能夠接入流量的Pod。其核心流程可分為以下幾個階段:
啟動階段:首先,建立新版本(v2)的Pod。Kubernetes會等待新Pod通過就緒檢查,確認其能夠正常處理請求。在此之前,它不會接收任何來自Service的流量。
流量切換階段:啟用
readinessGates後,新Pod需先完成就緒檢查,然後將其IP註冊到Service關聯的Endpoints中,並且同步到負載平衡器(SLB)的後端組才能開始接入流量。隨後,系統向舊版本(v1)Pod發送終止訊號,並將其IP從Endpoints中移除,使其不再接收新的業務請求。詳細原理解釋,請參考readinessGate工作原理。
優雅下線階段:舊Pod在被徹底刪除前,會先執行預定義的preStop鉤子,並利用優雅終止寬限期(
terminationGracePeriodSeconds)處理完已建立的串連,與此同時SLB也會進行存量串連優雅中斷。此過程確保了所有正在處理的請求都能正常完成,最終實現零中斷變換。
適用範圍
叢集版本為1.24及以上,請參見升級叢集。
cloud-controller-manager組件為v2.10.0或更高版本,請參見Cloud Controller Manager。
部署樣本應用
以下為一個Nginx無狀態應用的部署樣本。
控制台
在ACK叢集列表頁面,單擊目的地組群名稱,在叢集詳情頁左側導覽列,選擇。
在無狀態頁面,單擊使用YAML建立資源,然後將以下內容複寫到模板地區,單擊建立。
在彈窗中找到目標無狀態應用,單擊查看,確認Pod狀態為
Running。
kubectl
將以下YAML內容儲存為nginx-demo.yaml檔案。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment-demo spec: replicas: 1 # 生產環境建議配置2以上保證高可用,此處方便驗證滾動部署設定為1 selector: matchLabels: app: nginx-demo # 變換策略:保證更新期間服務不中斷, # strategy: # type: RollingUpdate # Deployment工作負載預設為RollingUpdate策略 # rollingUpdate: # maxUnavailable: "25%" # 預設值,更新過程中最多允許25%的Pod副本處於不可用狀態 # maxSurge: "25%" # 預設值,更新過程中允許建立的Pod總數最多可超出期望副本數的 25% template: metadata: labels: app: nginx-demo spec: # Pod層級的優雅下線總時限。必須大於 preStop 鉤子執行時間與應用清理時間之和 terminationGracePeriodSeconds: 60 readinessGates: - conditionType: service.readiness.alibabacloud.com/nginx-demo-service # 設定nginx-demo-service服務的Readiness Gate containers: - name: nginx image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6 ports: - containerPort: 80 resources: requests: cpu: 500m memory: 1Gi limits: cpu: 500m # --- 健全狀態檢查探針 --- # 啟動探針 (Startup Probe): 確保容器內應用已完成啟動 startupProbe: httpGet: path: / # Nginx預設根路徑可訪問即代表啟動成功 port: 80 # 給予應用足夠長的啟動時間。總逾時 = failureThreshold * periodSeconds # 總逾時時間為 failureThreshold * periodSeconds,即 30 * 10 = 300 秒 failureThreshold: 30 periodSeconds: 10 # 就緒探針 (Readiness Probe): 判斷容器是否準備好接收流量 readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 # 容器啟動後5秒開始探測 periodSeconds: 5 # 每5秒探測一次 timeoutSeconds: 2 # 探測逾時時間 successThreshold: 1 # 1次成功即標記為就緒 failureThreshold: 3 # 連續3次失敗即標記為不就緒 # --- 服務優雅下線配置 --- lifecycle: preStop: exec: # 建議根據業務自行設定鉤子方法,等待存量串連處理完成然後關閉應用 # 若只使用sleep命令可能會導致優雅下線無法正常退出 command: ["sh", "-c", "sleep 30 && /usr/sbin/nginx -s quit"] --- apiVersion: v1 kind: Service metadata: name: nginx-demo-service annotations: # 設定串連優雅中斷逾時時間,此值應接近應用preStop中處理存量串連的時間長度,取值範圍[10, 900] service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain-timeout: "30" # 開啟串連優雅中斷功能 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain: "on" spec: type: LoadBalancer selector: app: nginx-demo ports: - protocol: TCP port: 80部署Nginx應用並建立服務(Service)。
kubectl apply -f nginx-demo.yaml確認目標應用Pod狀態為
Running。kubectl get pod | grep nginx-deployment-demo
Pod就緒檢查
startupProbe(啟動探針):用於啟動較慢的應用(如Java)檢測是否完成啟動。啟動探測成功前,就緒探針和存活探針不會被執行,防止啟動緩慢而被Kubelet誤判為失敗並重啟。readinessProbe(就緒探針):用於判斷容器是否準備好處理外部請求。就緒檢查成功後,Pod的IP地址會加入其關聯的所有 Service 的Endpoints中,表示可以接入流量。readinessGates:在readinessProbe的基礎上等待readinessGates的狀態也可用時,才視為Pod完全就緒,然後正式接入流量。
優雅下線
應用優雅下線
preStop:容器終止前執行的鉤子命令,可設定應用優雅下線的命令,確儲存量串連處理完成,保障服務無損下線。建議根據業務自行設定鉤子方法,若只使用sleep命令可能會導致優雅下線無法正常退出。
terminationGracePeriodSeconds:Pod從被標記為終止到被強制殺死(SIGKILL訊號)前的總時間長度,預設為30秒。該值必須充足,以覆蓋preStop鉤子的執行時間與容器自身清理時間之和。
SLB串連優雅中斷
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain註解:為SLB開啟串連優雅中斷功能。service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain-timeout註解:SLB存量串連優雅中斷逾時時間長度(單位:秒)。建議配置為接近preStop中處理存量串連請求的時間長度。
變換策略
strategy:Deployment的預設更新策略為RollingUpdate,採用漸進式替換方式,逐步建立新版本Pod,並在新Pod就緒後刪除對應的舊版本Pod,確保服務在更新過程中持續可用。maxUnavailable:變換過程中最大不可用Pod副本數。預設值25%,可填寫數字。maxSurge:變換過程中,允許超出期望副本數的 Pod 數量上限。配置越大,更新速度越快,但佔用資源更多。預設值25%,可填寫數字。
驗證零中斷滾動部署
擷取樣本應用訪問地址。
export NGINX_ENDPOINT=$(kubectl get service nginx-demo-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}{":"}{.spec.ports[0].port}') echo $NGINX_ENDPOINT安裝壓測工具hey。進行壓力測試,以200的並發度執行50000次請求(按照樣本的資源配置單副本運行通常在1分鐘左右)。
hey -c 200 -n 50000 -disable-keepalive http://$NGINX_ENDPOINT同時立即開啟一個新命令列視窗執行Deployment重啟操作。
kubectl rollout restart deployment nginx-deployment-demo預期輸出結果對照。
部署方案類型
預期輸出
未配置零中斷滾動部署
流量有損。
Status code distribution: [200] 49644 responses Error distribution: [320] Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: connection refused [18] Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: no route to host [18] Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: operation timed out已配置零中斷滾動部署
流量無損。
Status code distribution: [200] 50000 responses
常見問題
Pod啟動時一直處於Running但未就緒狀態(
)
原因說明:通常由於啟動探測或就緒探測失敗導致。
解決方案:
就緒檢查配置:進入目標工作負載的編輯頁,確認健全狀態檢查請求路徑(如/healthz)和連接埠與實際應用提供的是否一致。如啟動時間較長,可增加不健康閾值,避免過早判定為失敗。
可臨時關閉就緒檢查,進入Pod終端或其所在宿主機,使用命令(如curl)驗證健全狀態檢查方法是否能正確響應。
排查業務異常:結合Pod事件和日誌(勾選顯示上個容器退出時的日誌)排查。