本篇文章給大家分享的是有關(guān)更新應(yīng)用時(shí)如何實(shí)現(xiàn)K8s中斷滾動(dòng)更新,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),景泰企業(yè)網(wǎng)站建設(shè),景泰品牌網(wǎng)站建設(shè),網(wǎng)站定制,景泰網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,景泰網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
Kubernetes 集群中,業(yè)務(wù)通常采用 Deployment + LoadBalancer 類型 Service 的方式對(duì)外提供服務(wù),其典型部署架構(gòu)如圖 1 所示。這種架構(gòu)部署和運(yùn)維都十分簡(jiǎn)單方便,但是在應(yīng)用更新或者升級(jí)時(shí)可能會(huì)存在服務(wù)中斷,引發(fā)線上問題。今天我們來詳細(xì)分析下這種架構(gòu)為何在更新應(yīng)用時(shí)會(huì)發(fā)生服務(wù)中斷以及如何避免服務(wù)中斷。
圖1 業(yè)務(wù)部署圖
Deployment 滾動(dòng)更新時(shí)會(huì)先創(chuàng)建新 pod,等待新 pod running 后再刪除舊 pod。
圖 2 服務(wù)中斷示意圖
中斷原因:Pod running 后被加入到 Endpoint 后端,容器服務(wù)監(jiān)控到 Endpoint 變更后將 Node 加入到 SLB 后端。此時(shí)請(qǐng)求從 SLB 轉(zhuǎn)發(fā)到 Pod 中,但是 Pod 業(yè)務(wù)代碼還未初始化完畢,無法處理請(qǐng)求,導(dǎo)致服務(wù)中斷,如圖 2 所示。
解決方法:為 pod 配置就緒檢測(cè),等待業(yè)務(wù)代碼初始化完畢后后再將 node 加入到 SLB 后端。
在刪除舊 pod 過程中需要對(duì)多個(gè)對(duì)象(如 Endpoint、ipvs/iptables、SLB)進(jìn)行狀態(tài)同步,并且這些同步操作是異步執(zhí)行的,整體同步流程如圖 3 所示。
圖 3 Deployment 更新時(shí)序圖
pod 狀態(tài)變更:將 Pod 設(shè)置為 Terminating 狀態(tài),并從所有 Service 的 Endpoints 列表中刪除。此時(shí),Pod 停止獲得新的流量,但在 Pod 中運(yùn)行的容器不會(huì)受到影響;
執(zhí)行 preStop Hook:Pod 刪除時(shí)會(huì)觸發(fā) preStop Hook,preStop Hook 支持 bash 腳本、TCP 或 HTTP 請(qǐng)求;
發(fā)送 SIGTERM 信號(hào):向 Pod 中的容器發(fā)送 SIGTERM 信號(hào);
等待指定的時(shí)間:terminationGracePeriodSeconds 字段用于控制等待時(shí)間,默認(rèn)值為 30 秒。該步驟與 preStop Hook 同時(shí)執(zhí)行,因此 terminationGracePeriodSeconds 需要大于 preStop 的時(shí)間,否則會(huì)出現(xiàn) preStop 未執(zhí)行完畢,pod 就被 kill 的情況;
發(fā)送 SIGKILL 信號(hào):等待指定時(shí)間后,向 pod 中的容器發(fā)送 SIGKILL 信號(hào),刪除 pod。
中斷原因:上述 1、2、3、4步驟同時(shí)進(jìn)行,因此有可能存在 Pod 收到 SIGTERM 信號(hào)并且停止工作后,還未從 Endpoints 中移除的情況。此時(shí),請(qǐng)求從 slb 轉(zhuǎn)發(fā)到 pod 中,而 Pod 已經(jīng)停止工作,因此會(huì)出現(xiàn)服務(wù)中斷,如圖 4 所示。
圖 4 服務(wù)中斷示意圖
解決方法:為 pod 配置 preStop Hook,使 Pod 收到 SIGTERM 時(shí) sleep 一段時(shí)間而不是立刻停止工作,從而確保從 SLB 轉(zhuǎn)發(fā)的流量還可以繼續(xù)被 Pod 處理。
中斷原因:當(dāng) pod 變?yōu)?termintaing 狀態(tài)時(shí),會(huì)從所有 service 的 endpoint 中移除該 pod。kube-proxy 會(huì)清理對(duì)應(yīng)的 iptables/ipvs 條目。而容器服務(wù) watch 到 endpoint 變化后,會(huì)調(diào)用 slb openapi 移除后端,此操作會(huì)耗費(fèi)幾秒。由于這兩個(gè)操作是同時(shí)進(jìn)行,因此有可能存在節(jié)點(diǎn)上的 iptables/ipvs 條目已經(jīng)被清理,但是節(jié)點(diǎn)還未從 slb 移除的情況。此時(shí),流量從 slb 流入,而節(jié)點(diǎn)上已經(jīng)沒有對(duì)應(yīng)的 iptables/ipvs 規(guī)則導(dǎo)致服務(wù)中斷,如圖 5 所示。
圖 5 服務(wù)中斷示意圖
解決方法:
Cluster 模式:Cluster 模式下 kube-proxy 會(huì)把所有業(yè)務(wù) Pod 寫入 Node 的 iptables/ipvs 中,如果當(dāng)前 Node 沒有業(yè)務(wù) pod,則該請(qǐng)求會(huì)被轉(zhuǎn)發(fā)給其他 Node,因此不會(huì)存在服務(wù)中斷,如 6 所示;
圖 6 Cluster 模式請(qǐng)求轉(zhuǎn)發(fā)示意圖
Local 模式:Local 模式下,kube-proxy 僅會(huì)把 Node 上的 pod 寫入 iptables/ipvs。當(dāng) Node 上只有一個(gè) pod 且狀態(tài)變?yōu)?terminating 時(shí),iptables/ipvs 會(huì)將該 pod 記錄移除。此時(shí)請(qǐng)求轉(zhuǎn)發(fā)到這個(gè) node 時(shí),無對(duì)應(yīng)的 iptables/ipvs 記錄,導(dǎo)致請(qǐng)求失敗。這個(gè)問題可以通過原地升級(jí)來避免,即保證更新過程中 Node 上至少有一個(gè) Running Pod。原地升級(jí)可以保障 Node 的 iptables/ipvs 中總會(huì)有一條業(yè)務(wù) pod 記錄,因此不會(huì)產(chǎn)生服務(wù)中斷,如圖 7 所示;
圖 7 Local 模式原地升級(jí)時(shí)請(qǐng)求轉(zhuǎn)發(fā)示意圖
ENI 模式 Service:ENI 模式繞過 kube-proxy,將 Pod 直接掛載到 SLB 后端,因此不存在因?yàn)?iptables/ipvs 導(dǎo)致的服務(wù)中斷。
圖 8 ENI 模式請(qǐng)求轉(zhuǎn)發(fā)示意圖
圖 9 服務(wù)中斷示意圖
中斷原因:容器服務(wù)監(jiān)控到 Endpoints 變化后,會(huì)將 Node 從 slb 后端移除。當(dāng)節(jié)點(diǎn)從 slb 后端移除后,SLB 對(duì)于繼續(xù)發(fā)往該節(jié)點(diǎn)的長(zhǎng)連接會(huì)直接斷開,導(dǎo)致服務(wù)中斷。
解決方法:為 SLB 設(shè)置長(zhǎng)鏈接優(yōu)雅中斷(依賴具體云廠商)。
避免服務(wù)中斷可以從 Pod 和 Service 兩類資源入手,接下來將針對(duì)上述中斷原因介紹相應(yīng)的配置方法。
apiVersion: v1 kind: Pod metadata: name: nginx namespace: default spec: containers: - name: nginx image: nginx # 存活檢測(cè) livenessProbe: failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 30 successThreshold: 1 tcpSocket: port: 5084 timeoutSeconds: 1 # 就緒檢測(cè) readinessProbe: failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 30 successThreshold: 1 tcpSocket: port: 5084 timeoutSeconds: 1 # 優(yōu)雅退出 lifecycle: preStop: exec: command: - sleep - 30 terminationGracePeriodSeconds: 60
注意:需要合理設(shè)置就緒檢測(cè)(readinessProbe)的探測(cè)頻率、延時(shí)時(shí)間、不健康閾值等數(shù)據(jù),部分應(yīng)用啟動(dòng)時(shí)間本身較長(zhǎng),如果設(shè)置的時(shí)間過短,會(huì)導(dǎo)致 POD 反復(fù)重啟。
livenessProbe 為存活檢測(cè),如果失敗次數(shù)到達(dá)閾值(failureThreshold)后,pod 會(huì)重啟,具體配置見 官方文檔;
readinessProbe 為就緒檢查,只有就緒檢查通過后,pod 才會(huì)被加入到 Endpoint 中。容器服務(wù)監(jiān)控到 Endpoint 變化后才會(huì)將 node 掛載到 slb 后端;
preStop 時(shí)間建議設(shè)置為業(yè)務(wù)處理完所有剩余請(qǐng)求所需的時(shí)間,terminationGracePeriodSeconds 時(shí)間建議設(shè)置為 preStop 的時(shí)間再加 30 秒以上。
apiVersion: v1 kind: Service metadata: name: nginx namespace: default spec: externalTrafficPolicy: Cluster ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx type: LoadBalancer
容器服務(wù)會(huì)將集群中所有節(jié)點(diǎn)掛載到 SLB 的后端(使用 BackendLabel 標(biāo)簽配置后端的除外),因此會(huì)快速消耗 SLB quota。SLB 限制了每個(gè) ECS 上能夠掛載的 SLB 的個(gè)數(shù),默認(rèn)值為 50,當(dāng) quota 消耗完后會(huì)導(dǎo)致無法創(chuàng)建新的監(jiān)聽及 SLB。
Cluster 模式下,如果當(dāng)前節(jié)點(diǎn)沒有業(yè)務(wù) pod 會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給其他 Node。在跨節(jié)點(diǎn)轉(zhuǎn)發(fā)時(shí)需要做 NAT,因此會(huì)丟失源 IP。
apiVersion: v1 kind: Service metadata: name: nginx namespace: default spec: externalTrafficPolicy: Local ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx type: LoadBalancer # 需要盡可能的讓每個(gè)節(jié)點(diǎn)在更新的過程中有至少一個(gè)的Running的Pod # 通過修改UpdateStrategy和利用nodeAffinity盡可能的保證在原地rolling update # * UpdateStrategy可以設(shè)置Max Unavailable為0,保證有新的Pod啟動(dòng)后才停止之前的pod # * 先對(duì)固定的幾個(gè)節(jié)點(diǎn)打上label用來調(diào)度 # * 使用nodeAffinity+和超過相關(guān)node數(shù)量的replicas數(shù)量保證盡可能在原地建新的Pod # 例如: apiVersion: apps/v1 kind: Deployment ...... strategy: rollingUpdate: maxSurge: 50% maxUnavailable: 0% type: RollingUpdate ...... affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: deploy operator: In values: - nginx
容器服務(wù)默認(rèn)會(huì)將 Service 對(duì)應(yīng)的 Pod 所在的節(jié)點(diǎn)加入到 SLB 后端,因此 SLB quota 消耗較慢。Local 模式下請(qǐng)求直接轉(zhuǎn)發(fā)到 pod 所在 node,不存在跨節(jié)點(diǎn)轉(zhuǎn)發(fā),因此可以保留源 IP 地址。Local 模式下可以通過原地升級(jí)的方式避免服務(wù)中斷,yaml 文件如上。
apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/backend-type: "eni" name: nginx spec: ports: - name: http port: 30080 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer
Terway 網(wǎng)絡(luò)模式下,通過設(shè)置 service.beta.kubernetes.io/backend-type:
“eni” annotation 可以創(chuàng)建 ENI 模式的 SLB。ENI 模式下,pod會(huì)直接掛載到 SLB 后端,不經(jīng)過 kube-proxy,因此不存在服務(wù)中斷的問題。請(qǐng)求直接轉(zhuǎn)發(fā)到 pod,因此可以保留源 IP 地址。
三種 svc 模式對(duì)比如下表所示。
圖 10 Service 對(duì)比
選用 ENI 模式的 svc + 設(shè)定 Pod 優(yōu)雅終止 + 就緒檢測(cè)。
如果集群中 slb 數(shù)量不多且不需要保留源 ip:選用 cluster 模式 + 設(shè)定 Pod 優(yōu)雅終止 + 就緒檢測(cè);
如果集群中 slb 數(shù)量較多或需要保留源 ip:選用 local 模式 + 設(shè)定 Pod 優(yōu)雅終止 + 就緒檢測(cè) + 原地升級(jí)(保證更新過程中每個(gè)節(jié)點(diǎn)上至少有一個(gè) Running Pod)。
以上就是更新應(yīng)用時(shí)如何實(shí)現(xiàn)K8s中斷滾動(dòng)更新,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站名稱:更新應(yīng)用時(shí)如何實(shí)現(xiàn)K8s中斷滾動(dòng)更新
標(biāo)題URL:http://jinyejixie.com/article26/pgiscg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、企業(yè)建站、建站公司、ChatGPT、網(wǎng)站導(dǎo)航、商城網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)