自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

在Kubernetes中實(shí)現(xiàn)優(yōu)雅退出

開發(fā) 架構(gòu)
本文需要對(duì)k8s的架構(gòu)和核心組件的職責(zé)有一定的了解,如不了解可參考 Kubernetes Components。

 [[431136]]

隨著持續(xù)部署(Continously Deployment)在項(xiàng)目中的使用,之前定期或者固定時(shí)間的發(fā)布節(jié)奏變?yōu)榱穗S時(shí)高頻率的發(fā)布。這就要求每次發(fā)布都應(yīng)該是零停機(jī)部署(Zero Downtime Deployment),否則將會(huì)引入bug。k8s中有一套完整的機(jī)制保證我們的應(yīng)用能夠?qū)崿F(xiàn)零停機(jī)部署,本文將重點(diǎn)分析其中的優(yōu)雅退出部分。

本文需要對(duì)k8s的架構(gòu)和核心組件的職責(zé)有一定的了解,如不了解可參考 Kubernetes Components。

發(fā)現(xiàn)問題

對(duì)于Kubernetes Deployment的每次部署過程,都是新版本的Pod創(chuàng)建、老版本的Pod刪除的過程。

在這個(gè)過程中如果不使用優(yōu)雅退出,則會(huì)引發(fā)兩個(gè)問題:

  • 問題1:可能會(huì)出現(xiàn)Pod未將正在處理的請(qǐng)求處理完成的情況下被刪除,如果該請(qǐng)求不是冪等性的,則會(huì)導(dǎo)致狀態(tài)不一致的bug。
  • 問題2:可能會(huì)出現(xiàn)Pod已經(jīng)被刪除,Kubernetes仍然將流量導(dǎo)向該P(yáng)od,從而出現(xiàn)用戶請(qǐng)求處理失敗,帶來比較差的用戶體驗(yàn)。

分析問題

在Kubernetes Pod 的刪除過程中,同時(shí)會(huì)存在兩條并行的時(shí)間線,如下圖所示,其中一條時(shí)間線是網(wǎng)絡(luò)規(guī)則的更新過程,另一條時(shí)間線是Pod的刪除過程。

當(dāng)用戶執(zhí)行 kubectl delete pod 命令時(shí),

網(wǎng)絡(luò)規(guī)則生效流程:

  1. Kube-apiserver會(huì)收到Pod刪除的請(qǐng)求,在Etcd中更新Pod的狀態(tài)為Terminating;
  2. Endpoint Controller將該P(yáng)od的ip從Endpoint對(duì)象中刪除;
  3. Kube-proxy根據(jù)Endpoint對(duì)象的改變更新iptables規(guī)則,不再將流量路由到被刪除的Pod。

Pod刪除流程:

  1. Kube-apiserver 會(huì)收到Pod刪除的請(qǐng)求,在Etcd中更新Pod的狀態(tài)為Terminating;
  2. Kubelet在節(jié)點(diǎn)上清理容器的相關(guān)資源,例如存儲(chǔ),網(wǎng)絡(luò);
  3. Kubelet發(fā)送SIGTERM進(jìn)程給容器,如果容器中的進(jìn)程未做任何配置,則容器立即退出;
  4. 如果容器未在默認(rèn)的30秒時(shí)間內(nèi)退出,Kubelet發(fā)送SIGKILL給容器,強(qiáng)制讓容器退出。

從Pod的刪除過程可以知道,如果不對(duì)容器內(nèi)的進(jìn)程進(jìn)行任何配置,容器會(huì)立即退出,會(huì)導(dǎo)致問題1出現(xiàn)。

由于網(wǎng)絡(luò)規(guī)則的更新和Pod的刪除是并行的,所以并不能保證網(wǎng)絡(luò)規(guī)則的更新時(shí)間一定會(huì)早于Pod的刪除時(shí)間,所以,有可能出現(xiàn)問題2。

解決問題

如果要解決以上兩個(gè)問題,我們需要做如下配置

  1. 設(shè)置容器中進(jìn)程的優(yōu)雅退出;

  2. 增加preStopHook;

  3. 修改terminationGracePeriodSeconds。

配置后的時(shí)間線如下圖所示:

設(shè)置容器中進(jìn)程的優(yōu)雅退出

在我們項(xiàng)目中,使用的是Springboot,只需要在Springboot的配置文件中增加配置

  1. server: 
  2.   shutdown: graceful 
  3.  
  4. spring: 
  5.   lifecycle: 
  6.     timeout-per-shutdown-phase: 30s 

進(jìn)行該配置后,Springboot會(huì)保證在接收到SIGTERM之后不會(huì)再接受新的請(qǐng)求[^1], 并在超時(shí)時(shí)間內(nèi)處理完所有正在處理的請(qǐng)求,如果不能處理完成,也會(huì)打印出相應(yīng)的信息并強(qiáng)制退出。超時(shí)時(shí)間的具體值應(yīng)該參考系統(tǒng)中最大允許的請(qǐng)求時(shí)長(zhǎng),所以理論上所有的請(qǐng)求都應(yīng)該在30s內(nèi)處理完,對(duì)于沒有在30s內(nèi)處理完成的請(qǐng)求,我們可以通過監(jiān)控日志然后發(fā)Alert的方式,根據(jù)實(shí)際情況去處理。通過增加此配置,可以解決問題1。對(duì)于使用其它的語(yǔ)言和框架的項(xiàng)目,應(yīng)該也存在類似的配置。

增加preStopHook

針對(duì)問題2,需保證網(wǎng)絡(luò)規(guī)則更新后,也就是說新的流量不再路由到要?jiǎng)h除的Pod后,再開始Pod的刪除。所以需要在 Kubernetes 的Yaml文件中增加 preStopHook[^3],讓Kubelet接收到Pod刪除事件后等待一段時(shí)間,給Kube-proxy足夠的時(shí)間更新iptables網(wǎng)絡(luò)規(guī)則后,再開始刪除Pod。

  1. lifecycle: 
  2.   preStop: 
  3.     exec: 
  4.       command: ["sh""-c""sleep 10"]  # set prestop hook 

這里在我們項(xiàng)目中設(shè)置的10s是參照Springboot官網(wǎng)的配置[^2]。

修改terminationGracePeriodSeconds

參照之前分析的Pod刪除的流程,Kubernetes會(huì)給容器最大的刪除時(shí)長(zhǎng)是30秒[^3],如果我們?cè)赟pring中優(yōu)雅退出的超時(shí)時(shí)長(zhǎng)和在Kubernetes中的preStopHook時(shí)長(zhǎng)大于30s,則可能會(huì)出現(xiàn)Springboot還未處理完所有的請(qǐng)求Kubernetes已經(jīng)開始強(qiáng)制刪除容器。所以如果這個(gè)時(shí)長(zhǎng)大于30秒,我們需要修改 terminationGracePeriodSeconds使其大于Springboot的優(yōu)雅退出超時(shí)時(shí)間和preStopHook之和

  1. terminationGracePeriodSeconds: 45 

最終Kubernetes中的Yaml文件如下所示:

  1. apiVersion: apps/v1 
  2. kind: Deployment 
  3. metadata: 
  4.   name: graceful-shutdown-test-exit-graceful-30s 
  5. spec: 
  6.   replicas: 2 
  7.   selector: 
  8.     matchLabels: 
  9.       app: graceful-shutdown-test-exit-graceful-30s 
  10.   template: 
  11.     metadata: 
  12.       labels: 
  13.         app: graceful-shutdown-test-exit-graceful-30s 
  14.     spec: 
  15.       containers: 
  16.         - name: graeceful-shutdonw-test 
  17.           image: graceful-shutdown-test-exit-graceful-30s:latest 
  18.           ports: 
  19.             - containerPort: 8080 
  20.           lifecycle: 
  21.             preStop: 
  22.               exec: 
  23.                 command: ["sh""-c""sleep 10"]  # set prestop hook 
  24.       terminationGracePeriodSeconds: 45    # terminationGracePeriodSeconds 

可以看出,通過設(shè)置Springboot的優(yōu)雅退出,保證了正在處理的請(qǐng)求能夠處理完成,通過設(shè)置preStopHook,保證了Pod刪除和網(wǎng)絡(luò)規(guī)則更新的時(shí)序關(guān)系。通過配置terminationGracePeriodSeconds,給了容器中進(jìn)程足夠的時(shí)間處理所有的請(qǐng)求。綜合以上三個(gè)步驟,可以解決之前發(fā)現(xiàn)的兩個(gè)問題。

總結(jié)

本文通過結(jié)合Kubernetes的優(yōu)雅退出和Springboot的優(yōu)雅退出機(jī)制,保證在隨時(shí)高頻率部署的情況下,服務(wù)也可以正確處理所有的請(qǐng)求,減少了bug的出現(xiàn),提升了用戶的體驗(yàn)。

 

責(zé)任編輯:張燕妮 來源: Thoughtworks洞見
相關(guān)推薦

2021-12-21 15:17:53

Kubernetes緩存Linux

2023-10-17 08:08:37

Dubbo服務(wù)注冊(cè)中心

2023-10-27 12:36:37

gRPCKubernetes

2024-03-29 12:11:46

2021-06-04 10:52:51

kubernetes場(chǎng)景容器

2022-05-10 10:09:12

KubernetesPod網(wǎng)絡(luò)抓包

2024-02-07 01:47:47

atexit模塊程序

2014-07-22 09:01:53

SwiftJSON

2017-04-12 11:16:08

Python終端編程

2024-03-04 07:47:06

KubernetesUnix系統(tǒng)

2017-03-20 16:30:15

Android退出應(yīng)用優(yōu)雅方式

2023-10-19 19:42:25

IstioPodkubernetes

2021-12-13 10:10:15

IPtablesTCPLinux

2024-05-21 08:14:59

代碼接口依賴注入

2023-10-20 08:00:55

PodRainbow部署

2020-04-29 10:19:29

Python數(shù)據(jù)函數(shù)

2020-09-25 11:30:20

Java判空代碼

2020-04-10 10:22:12

Java判空編程語(yǔ)言

2020-11-06 08:13:03

服務(wù)器Nodejs客戶端

2021-07-15 09:47:20

Docker容器命令
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)