您可以配置preStop Hook,實現ALB Ingress后端Pod的平滑下線,使Pod在被ALB Ingress Controller完全從后端服務組中移除后才正式下線。配置后,容器在滾動更新期間能夠保障服務的流量無縫切換,避免出現中斷。
前提條件
已創建ACK托管集群或ACK專有集群,且集群為v1.18及以上版本。具體操作,請參見創建ACK托管集群、創建ACK專有集群;如需升級集群,請參見手動升級集群。
已為集群安裝ALB Ingress Controller組件。具體操作,請參見管理ALB Ingress Controller組件。
說明若需要在ACK專有集群中通過ALB Ingress訪問服務,在部署服務前需要為ALB Ingress Controller授權。具體操作,請參見為ACK專有集群授予ALB Ingress Controller訪問權限。
已通過kubectl工具連接集群。具體操作,請參見獲取集群KubeConfig并通過kubectl工具連接集群。
已創建ALBConfig和IngressClass。具體操作,請參見創建ALBConfig。
原理介紹
Pod生命周期
Pod中的容器包括兩種類型:
初始化容器(Init容器):運行服務的主容器前置依賴的容器,完成一些初始化操作。
主容器(工作容器):運行服務進程的容器。
Pod啟動過程如下:
運行初始化容器:在主容器啟動之前,要運行的容器,為主容器執行預置操作。
運行主容器:
容器啟動后執行postStart Hook函數。
容器執行存活性探測(Liveness Probe)、就緒性檢測(Readiness Probe)。
在容器退出前執行preStop Hook函數。
Pod終止流程和網絡規則更新流程
在刪除Pod時K8s會同時進行Pod終止和網絡規則更新兩個主要的流程。Pod終止流程和網絡更新流程如下。
Pod終止流程
kube-apiserver收到Pod刪除請求,將Pod標記為
Terminating
狀態。如果Pod定義了preStop Hook,將執行preStop Hook。
K8s集群向容器發送SIGTERM信號。
等待容器停止,或等待Pod刪除寬限期超時。
說明Pod中容器刪除寬限期
terminationGracePeriodSeconds
默認為30秒。超時Pod刪除寬限期后容器仍未終止,K8s發送SIGKILL信號給容器。
Pod被完全刪除。
網絡規則更新流程
kube-apiserver收到Pod刪除請求,將Pod標記為
Terminating
狀態。Endpoint Controller從Endpoint對象中刪除Pod的IP。
ALB Ingress Controller進行Server節點調諧,將Service Endpoints從后端服務器組中移除,不再將流量路由到被刪除的Pod。
使用preStop Hook來實現Pod平滑下線
當Pod滾動升級過程中,如果舊的Pod沒有平滑退出,將導致應用無法正常處理業務請求,出現如下錯誤狀態碼,影響應用的可用性。
狀態碼 | 問題原因 |
504 | 當舊Pod在未處理完正常請求情況下被刪除,并且該請求為非冪等。 |
502 | 當ACK集群已經刪除舊Pod,容器收到終止信號(SIGTERM)并迅速終止,但ALB Ingress Controller仍在調諧流程中,導致Pod未及時從后端服務器組中移除,流量依然被錯誤地路由到已終止的舊Pod上。 |
為了避免以上的情況發生,您可以采取如下方案。
在kube-apiserver接收到Pod刪除請求時,通過在Deployment配置內添加preStop Hook,可以為容器設置一個"Sleep"暫停期。這個暫停期是讓容器有時間在收到SIGTERM之前完成網絡規則的更新,并等待ALB Ingress Controller完成Server調諧事件并確保Pod已從后端服務器組中移除。這一步驟對于保障Pod的平穩下線至關重要,避免在滾動更新或服務重啟期間造成流量中斷。
同時,Kubernetes為容器設定了在接收到SIGTERM后能持續運行的最大寬限期(terminationGracePeriodSeconds)為30秒。當程序關閉時間與preStop Hook指定的操作時間之和超過了30秒時,默認寬限期將不足以讓容器完成所有的關閉步驟。kubelet會在等待2秒后直接給容器發送立即終止(SIGKILL)信號,導致容器強制退出。
如果程序的關閉時間和在Deployment配置的preStop Hook之和超過30秒,應將terminationGracePeriodSeconds
重新設置,調整為大于30秒,確保容器優雅退出。
步驟一:并配置Pod平滑退出preStop Hook
創建并保存tea-service.yaml,配置確保Pod平滑退出的preStop Hook。
apiVersion: apps/v1 kind: Deployment metadata: name: tea spec: replicas: 3 selector: matchLabels: app: tea template: metadata: labels: app: tea spec: containers: - name: tea image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest ports: - containerPort: 80 lifecycle: # 設置preStop Hook函數,使kube-apiserver等待10秒后再向Pod發送SIGTERM信號。 preStop: # preStop鉤子設置。 exec: # 通過執行命令的方式來實現preStop操作。 command: # 定義要執行的命令。 - /bin/sh - -c - "sleep 10" # 執行sleep操作,暫停10秒。 terminationGracePeriodSeconds: 45 # 設置Pod刪除寬限期。 --- apiVersion: v1 kind: Service metadata: name: tea-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: app: tea type: NodePort
執行以下命令,部署示例Deployment和Service。
kubectl apply -f tea-service.yaml
創建并保存tea-ingress.yaml文件,用于配置Ingress。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: metadata: name: tea-ingress spec: ingressClassName: alb rules: - host: demo.ingress.top http: paths: - path: / pathType: Prefix backend: service: name: tea-svc port: number: 80
執行以下命令,部署Ingress。
kubectl apply -f tea-ingress.yaml
執行以下命令,獲取ALB Ingress的
ADDRESS
。kubectl get ingress
預期輸出:
NAME CLASS HOSTS ADDRESS PORTS AGE tea-ingress alb demo.ingress.top alb-110zvs5nhsvfv*****.cn-chengdu.alb.aliyuncs.com 80 7m5s
步驟二:結果驗證
啟動測試腳本。
使用以下內容,創建
test.sh
測試腳本文件。此腳本用于測試應用的可用性,按每秒一次的頻率請求Nginx服務并查看狀態碼。#!/bin/bash HOST="demo.ingress.top" DNS="alb-110zvs5nhsvfv*****.cn-chengdu.alb.aliyuncs.com" # 填寫ALB Ingress的ADDRESS值。 printf "Response Code|| TIME \n" >> log.txt while true; do RESPONSE=$(curl -H Host:$HOST -s -o /dev/null -w "%{http_code}" -m 1 http://$DNS/) TIMESTAMP=$(date +%Y-%m-%d_%H:%M:%S) echo "$TIMESTAMP - $RESPONSE" >> log.txt sleep 1 done
執行以下命令運行測試腳本
test.sh
。bash test.sh
執行以下命令,重新部署應用,觸發Pod滾動升級。
kubectl rollout restart deploy tea
驗證Pod滾動升級。
初始階段應用副本數為3。
在重新部署應用時,新Pod創建階段由于新Pod沒有就緒,舊Pod仍在提供服務,會同時運行新舊兩個Pod。
新Pod就緒且成功掛載至ALB后端服務器組后,會終止舊Pod。
所有舊Pod完成preStop Hook函數或超出
terminationGracePeriodSeconds
超時時間后,kubectl
會向Container發送信號終止舊的Pod,此時滾動更新完成。
查看測試腳本執行結果。檢查滾動更新過程中請求的狀態碼,可以看到狀態碼全部為200,更新過程沒有中斷。
執行如下命令,查看測試腳本執行結果。
cat log.txt
預期輸出:
相關文檔
您可以使用ALB Ingress將來自不同域名或URL路徑的請求轉發給不同的后端服務器組、將HTTP訪問重定向至HTTPS以及實現灰度發布等功能,請參見ALB Ingress服務高級用法
您可以通過配置ReadinessGate來保證Pod上線階段的可用性,請參見使用ReadinessGate實現ALB Ingress后端Pod滾動升級時平滑上線。
如在使用ALB Ingress過程中遇到問題,您可以參見ALB Ingress FAQ、ALB Ingress異常問題排查進行自排查。