K8S優雅升級系列(上) | 如何讓應用和容器優雅下線?

語言: CN / TW / HK

​在生產環境中,如何保證在服務升級的時候,不影響使用者的體驗,這個是一個非常重要的問題。如果在我們升級服務的時候,會造成一段時間內的服務不可用,這就是不夠優雅的。

那什麼是優雅的呢?主要就是指在服務升級的時候,不中斷整個服務,讓使用者無感知,進而不會影響使用者的體驗,這就是優雅的。

微服務釋出方式

說到優雅升級,就不得不瞭解一下常見的微服務的釋出方式,選擇不同的釋出方式,就會達到不同的效果,在產線實踐中最為常用的釋出方式有:

  • 藍綠髮布

  • 灰度釋出

  • 滾動釋出 

藍綠髮布

  • 概念

藍綠部署( Blue Green Deployment)是一種可以保證系統在不間斷提供服務的情況下上線的部署方式,主要的流程為:不停老版本,部署新版本然後進行測試。確認OK後將流量切到新版本,然後老版本同時也升級到新版本。

  • 步驟

其大致步驟為:

  1. 首先把B組從負載均衡中摘除,進行新版本的部署。A組仍然繼續提供服務;

  2. 當B組升級完畢,負載均衡重新接入B組,再把A組從負載列表中摘除,進行新版本的部署,B組重新提供服務;

  3. A組也升級完成,負載均衡重新接入A組,此時,AB組版本都已經升級完成,並且都對外提供服務。

 

  • 特點
  1. 通過LB來實現流量控制,比如Nginx;

  2. 如果出問題,影響範圍較大;

  3. 釋出策略簡單;

  4. 使用者無感知,平滑過渡;

  5. 升級/回滾速度快。

  • 缺點
  1. 需要準備正常業務使用資源的兩倍以上伺服器,防止升級期間單組無法承載業務突發;

  2. 短時間內浪費一定資源成本。

  • Kubernetes中的藍綠髮布

在Kubernetes中,可以使用Service中的Selector標籤結合Pod中的Labels標籤進行流量的切換處理,從而達到藍綠部署的效果。

 

灰度釋出

  • 概念

灰度釋出(Canary Deployment)又叫金絲雀釋出,以前,曠工在下礦洞是面臨的一個重要危險是礦井中的毒氣,他們想到一個辦法來辨別礦井中是否有毒氣,礦工們隨身攜帶一隻金絲雀下礦井,金絲雀對毒氣的抵抗能力比人類要弱,在毒氣環境下會先掛掉起到預警的作用。

  • 步驟

其大致步驟為:

  1. 準備好部署各個階段的工件,包括:構建工件,測試指令碼,配置檔案和部署清單檔案;

  2. 從LB摘掉灰度伺服器;

  3. 升級“金絲雀”應用(切斷原有流量並進行部署);

  4. 對灰度服務進行自動化測試或者少量使用者流量到新版本進行測試;

  5. 如果灰度伺服器測試成功,升級剩餘伺服器(否則就回滾)。

  • 特點
  1. 保證整體系統穩定性,在初始灰度的時候就可以發現、調整問題,影響範圍可控;

  2. 新功能逐步評估效能,穩定性和健康狀況,如果出問題影響範圍很小,相對使用者體驗也少;

  3. 使用者無感知,平滑過渡。

  • 缺點
  1. 自動化要求高,如果釋出自動化程度不夠,釋出期間可引發服務中斷。

  • Kubernetes中的灰度釋出

在Kubernetes中,有很多的方案可以實現灰度釋出,比如Nginx Ingress Controller、Kong Ingress Controller、Istio等,這裡案例展示的是最常用的Nginx Ingress Controller的Canary實現。

基於權重的金絲雀釋出

基於請求的金絲雀釋出(A/B TEST)

 

滾動釋出

  • 概念

滾動釋出(Rolling Update),一種高階的釋出策略,釋出過程中,應用不中斷,使用者體驗平滑,也是Kubernetes應用更新預設的釋出方式

  • 步驟
  1. 先升級1個副本,主要做部署驗證;

  2. 每次升級副本,自動從LB上摘掉,升級成功後自動加入叢集;

  3. 事先需要有自動更新策略,分為若干次,每次數量/百分比可配置;

  4. 回滾是釋出的逆過程,先從LB摘掉新版本,再升級老版本,這個過程一般時間比較長;

  5. 自動化要求高。

  • 特點
  1. 應用不中斷,使用者體驗平滑;

  2. 節約資源。

  • 缺點
  1. 沒有一個確定 OK 的環境。使用藍綠部署,我們能夠清晰地知道老版本是 OK 的,而使用滾動釋出,我們無法確定;

  2. 修改了現有的環境;

  3. 部署時間慢,取決於每階段更新時間;

  4. 釋出策略較複雜;

  5. 如果需要回滾,很困難。舉個例子,在某一次釋出中,我們需要更新 100 個例項,每次更新 10 個例項,每次部署需要 5 分鐘。當滾動釋出到第 80 個例項時,發現了問題,需要回滾,這個時候就會很難回滾;

  6. 有的時候,我們還可能對系統進行動態伸縮,如果部署期間,系統自動擴容/縮容了,我們還需判斷到底哪個節點使用的是哪個程式碼。儘管有一些自動化的運維工具,但是依然令人心驚膽戰。

  • Kubernetes中的滾動釋出

滾動釋出雖然釋出策略複雜,回滾難度高,但是卻是K8S預設的服務更新方式,K8S中,Deployment資源本質上是使用RS+Rollout Update組成的。

這樣完全將服務版本與滾動更新機制結合,自動完成滾動更新的一系列操作,增強使用者體驗、節約資源、易於回滾。Kubernetes中的滾動更新機制如下:

 

如何優雅下線應用

在生產環境中,要保證服務不中斷,服務的上下線是不可避免的,我們希望能夠優雅地下線微服務,在此總結一下Spring Boot中的應用的幾種下線方式。

  • Kill java程序

該方式藉助的是 Spring Boot 應用的 Shutdown hook,應用本身的下線也是優雅的,但如果你的服務發現元件使用的是 Eureka,那麼預設最長會有 90 秒的延遲,其他應用才會感知到該服務下線,這意味著:該例項下線後的 90 秒內,其他服務仍然可能呼叫到這個已下線的例項。

因此,該方式是不夠優雅的。

 

  • /shutdown介面

Spring Boot 提供了/shutdown端點,可以藉助它實現優雅停機。

使用方式:在想下線應用的Application.yml中新增如下配置,從而啟用並暴露/shutdown端點:

management:  endpoint:    shutdown:      enabled: true  endpoints:    web:      exposure:        include: shutdown

傳送 POST 請求到 /shutdown端點Curl -X Http://ip:port/actuator/shutdown

該方式本質和方式一樣也是藉助 Spring Boot 應用的 Shutdown Hook 去實現的,所以不建議使用。

 

  • /pause介面

Spring Boot 應用提供了/pause端點,利用該端點可實現優雅下線。

使用方式:在想下線應用的Application.yml中新增如下配置,從而啟用並暴露/pause端點:

management:  endpoint:    # 啟用pause端點    pause:      enabled: true    # 啟用restart端點    restart:      enabled: true  endpoints:    web:      exposure:        include: pause,restart

傳送 POST 請求到/actuator/pause端點Curl -X http://ip:port/actuator/pause

該應用在Eureka Server 上的狀已被標記為DOWN,但是應用本身其實依然是可以正常對外服務的

 

  • /service-registry介面

在想下線應用的Application.yml中新增配置,從而暴露/service-registry端點。

management:  endpoint    web:      exposure:        include: service-registry

傳送 POST 請求到/actuator/service-registry端點:

curl -X "POST" "http://localhost:8000/actuator/service-registry?status=DOWN" \   -H "Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8"

這個介面會將服務的Eureka的狀態標記為Down,等服務流量變為0,可以進行刪除或者升級操作,算是比較優雅的一種方式。

 

  • EurekaAutoServiceRegistration

除了上述的下線方式之外,還有一種利用EurekaAutoServiceRegistration物件達到優雅下線的目標。

執行EurekaAutoServiceRegistration.start()方法時,當前服務向 Eureka 註冊中心註冊服務;

執行EurekaAutoServiceRegistration.stop()方法時,當前服務會向 Eureka 註冊中心進行反註冊,註冊中心收到請求後,會將此服務從註冊列表中刪除。

@RestController@RequestMapping(value = "/graceful/registry-service")public class GracefulOffline {    @Autowired    private EurekaAutoServiceRegistration eurekaAutoServiceRegistration;    @RequestMapping("/online")    public String online() {        this.eurekaAutoServiceRegistration.start();        return "execute online method, online success.";    }    @RequestMapping("/offline")    public String offline() {        this.eurekaAutoServiceRegistration.stop();        return "execute offline method, offline success.";    }}

可以根據此API去自定義介面去進行服務的下線

 

如何優雅關閉容器

服務在容器里正常跑著,前面講了服務的優雅下線方式,下來就該容器的優雅關閉內容了,要不然,光服務進行優雅關閉了,容器一整個直接被Kill了,也是沒有用的。

  • 訊號

提到容器關閉,就不得不瞭解一個基礎的東西,就是訊號,訊號是事件發生時對程序的通知機制,有時也稱之為軟體中斷,訊號有不同的型別,可以通過 Kill -l 獲取訊號名稱:

 

  • 常用的訊號
  1. 9) SIGKILL 此訊號為 “必殺(Sure Kill)” 訊號,處理器程式無法將其阻塞、忽略或者捕獲,故而 “一擊必殺”,總能終止程式;

  2. 15) SIGTERM 這是用來終止程序的標準訊號,也是 Kill 、 Killall 、 Pkill 命令所傳送的預設訊號。精心設計的應用程式應當為 SIGTERM 訊號設定處理器程式,以便其能夠預先清除臨時檔案和釋放其它資源,從而全身而退。因此,總是應該先嚐試使用 SIGTERM 訊號來終止程序,而把 SIGKILL 作為最後手段,去對付那些不響應 SIGTERM 訊號的失控程序。

 

  • Dockerfile中的ENTRYPOINT 和 CMD 指令

接著說 Dockerfile 中的 ENTRYPOINT 和 CMD 指令,它們的主要功能是指定容器啟動時執行的程式

CMD 有三種格式:

  • CMD["Executable","Param1","Param2"] (Exec 格式, 推薦使用這種格式)

  • CMD ["Param1","Param2"] (作為 ENTRYPOINT 指令引數)

  • CMD Command Param1 Param2 (Shell 格式,預設 /bin/sh -c )

ENTRYPOINT 有兩種格式:

  • ENTRYPOINT ["Executable", "Param1", "Param2"] (Exec 格式,推薦優先使用這種格式)

  • ENTRYPOINT Command Param1 Param2 (Shell 格式)

Docker Stop 停掉容器的時候,預設會發送一個 SIGTERM 的訊號,預設 10s 後容器沒有停止的話,就 SIGKILL 強制停止容器。通過 -t 選項可以設定等待時間。

在停止容器的時候系統底層預設會向主程序傳送 SIGTERM 訊號,而對剩餘子程序傳送 SIGKILL 訊號。系統這樣做的大概原因是因為大家在設計主程序指令碼的時候都不會進行訊號的捕獲和傳遞,這會導致容器關閉時,多個子程序無法被正常終止,所以系統使用 SIGKILL 這個不可遮蔽訊號,而是為了能夠在沒有任何前提條件的情況下,能夠把容器中所有的程序關掉。

不管你 Dockerfile 用其中哪個指令,兩個指令都推薦使用 Exec 格式,而不是 Shell 格式。原因就是因為使用 Shell 格式之後,程式會以 /bin/sh -c 的子命令啟動,Shell會作為主程序,並且 Shell 格式下不會傳遞任何訊號給程式。這也就導致,在 Docker Stop 容器的時候,以這種格式執行的程式捕捉不到傳送的訊號,也就談不上優雅的關閉了。

 

關於微服務釋出、應用優雅下線以及容器優雅關閉的知識點就先講解到這裡,下篇我們將著重介紹hzero服務如何在Kubernetes中優雅滾動。

 

下期預告

K8S優雅升級系列(下) | 如何優雅滾動釋出

往期推薦

1、漢得企業級數字化PaaS平臺 HZERO 1.9.0 版本正式釋出!

2、漢得aPaaS低程式碼平臺-飛搭 2.3.0 RELEASE正式釋出!

3、漢得整合平臺 集星獺 1.4.0 版本正式釋出!

 

                                                            簽約客戶

                                                  *部分統計,持續更新

 

                                  ▲ 更多精彩內容,掃碼關注“四海漢得”公眾號