天天看點

DockOne微信分享(一三六):Kubernetes健康檢查政策

本文講的是<b>DockOne微信分享(一三六):Kubernetes健康檢查政策</b>【編者的話】業務的正常是第一優先保障,是以健康檢查是一個重要能力。Kubernetes作為容器編排平台,對于容器以及容器所承載的業務,需要保證其健康,并且在異常情況下能夠進行處理。這次分享将讨論Kubernetes的健康檢查政策。 

<a href="http://dockone.io/article/2626">【燒腦式Kubernetes實戰訓練營】本次教育訓練理論結合實踐,主要包括:Kubernetes架構和資源排程原理、Kubernetes DNS與服務發現、基于Kubernetes和Jenkins的持續部署方案 、Kubernetes網絡部署實踐、監控、日志、Kubernetes與雲原生應用、在CentOS中部署Kubernetes叢集、Kubernetes中的容器設計模式、開發Kubernetes原生應用步驟介紹等。</a>

在Kubernetes中Pod是最核心的概論,Pod是一個或者多個容器的組合,Pod包含的容器運作在同一台主控端上,這些容器使用相同的網絡命名空間、IP位址和端口,互相之間能通過localhost來發現和通信。另外,這些容器還可共享一塊存儲卷空間。在Kubernetes中建立、排程和管理的最小機關是Pod,而不是容器,Pod通過提供更高層次的抽象,提供了更加靈活的管理模式,但是同時也增加了健康檢查的複雜性。

Kubernetes提供了一整套對于Pod的狀态機制和生命周期管理,Pod的本質是一組容器,Pod的狀态便是容器狀态的展現和概括,同時容器的狀态變化會影響Pod的狀态變化,觸發Pod的生命周期階段轉換。

在使用docker run運作容器的時候,首先會下載下傳容器鏡像。下載下傳成功後運作容器,當容器運作結束退出後(包括正常和異常退出),容器終止,這是一個容器的生命周期過程。相應的,Kubernetes中對于Pod中的容器進行了狀态的記錄,其中每種狀态下包含的資訊如下所示。

Waiting:容器正在等待建立,比如正在下載下傳鏡像。

Running:容器已經建立,并且正在運作。

Terminated:容器終止退出。

Pod的生命周期可以簡單描述為:首先Pod被建立,緊接着Pod被排程到Node進行部署運作。Pod是非常忠誠的,一旦被配置設定到Node後,就不會離開這個Node,直到它被删除,生命周期完結。

Pod的生命周期被定義為以下幾個階段。

Pending:Pod已經被建立,但是一個或者多個容器還未建立,這包括Pod排程階段,以及容器鏡像的下載下傳過程。

Running:Pod已經被排程到Node,所有容器已經建立,并且至少一個容器在運作或者正在重新開機。

Succeeded:Pod中所有容器正常退出。

Failed:Pod中所有容器退出,至少有一個容器是一次退出的。

Pod被建立成功後,首先會進入Pending階段,然後被排程到Node後運作,進入Running階段。如果Pod中的容器停止(正常或者異常退出),那麼Pod根據重新開機政策的不同會進入不同的階段,舉例如下。

一旦被配置設定到Node,Pod就不會離開這個Node,直到被删除。删除可能是人為地删除,或者被Replication Controller删除,也有可能是當Pod進入Succeeded 或者Failed 階段過期,被Kubernetes清理掉。總之Pod被删除後,Pod的生命周期就算結束,即使被Replication Controller進行重建,那也是新的Pod,因為Pod的ID已經發生了變化,是以實際上Pod遷移,準确的說法是在新的Node上重建Pod。

對于Pod是否健康,即Pod中的容器是否健康,預設情況下隻是檢查容器是否正常運作。但有時候容器正常運作不代表應用健康,有可能應用的程序已經阻塞住無法正常處理請求,是以為了提供更加健壯的應用,往往需要定制化的健康檢查。

除此之外,有的應用啟動後需要進行一系列初始化處理,在初始化完成之前應用是無法正常處理請求的。如果應用初始化需要較長時間,而實際上容器建立的時間是可以忽略不計的。

預設情況下,Kubernetes發現容器建立成功并運作,就會認為其準備就緒,真實情況是容器裡的應用可能還處于初始化階段,無法正常接受請求。如果使用者通路就會得到錯誤響應,這不是我們希望看到的情況。同樣的,我們需要更加精确的檢查機制來判斷Pod和容器是否準備就緒,進而讓Kubernetes判斷是否分發請求給Pod。

針對這些需求,Kubernetes中提供了Probe機制,有以下兩種類型的Probe。

Liveness Probe:用于容器的自定義健康檢查,如果Liveness Probe檢查失敗,Kubernetes将殺死容器,然後根據Pod的重新開機政策來決定是否重新開機容器。

Readiness Probe:用于容器的自定義準備狀況檢查,如果Readiness Probe檢查失敗,Kubernetes将會把Pod從服務代理的分發後端移除,即不會分發請求給該Pod。

Probe支援以下三種檢查方法。

ExecAction:在容器中執行指定的指令進行檢查,當指令執行成功(傳回碼為0),檢查成功。

示例:

TCPSocketAction:對于容器中的指定TCP端口進行檢查,當TCP端口被占用,檢查成功。

HTTPGetAction: 發生一個HTTP請求,當傳回碼介于200~400之間時,檢查成功。

一般情況下我們是一個容器運作一個程序,即将應用程序的啟動指令作為容器的CMD,這樣一來當應用程序退出的時候,容器也就退出,可以第一時間發現異常,我們是統一設定 Pod中容器的重新開機政策為Always, Kubernetes中重新開機就是重新建立容器,畢竟建立一個容器的成本很低。是以當容器退出的時候,Kubernetes就會重建容器,這樣一來就無法檢視應用的第一事發現場,因為舊的容器已經被停止了,極端情況下,容器一直在重建,根本無法登陸到容器去排除;是以,我們希望對容器内應用的健康進行監控,并且根據監控情況,做出保留故障現場和故障恢複等政策,為此我們考慮結合Supervisor進行優化。

Supervisor 是由 Python 語言編寫、基于 Linux 作業系統的一款伺服器管理工具,用于監控伺服器的運作,發現問題能立即自動預警及自動重新開機等。在Linux系統啟動之後,第一個啟動的使用者态程序是/sbin/init ,它的PID是1,其餘使用者态的程序都是init程序的子程序。Supervisor在docker容器裡面充當的就類似init程序的角色,其它的應用程序都是Supervisor程序的子程序。

Supervisor維護着程序的狀态機,并且支援着豐富的重新開機政策。

autostart=true; 如果是true的話,子程序将在supervisord啟動後被自動啟動預設就是true 。

autorestart=unexpected; 這個是設定子程序挂掉後自動重新開機的情況,有三個選項,false、unexpected和true。如果為false的時候,無論什麼情況下,都不會被重新啟動,如果為unexpected,隻有當程序的退出碼不在下面exitcodes裡面定義的退出碼的時候,才會被自動重新開機。當為true的時候,隻要子程序挂掉,将會被無條件的重新開機 startsecs=1; 這個選項是子程序啟動多少秒之後,此時狀态如果是running,則我們認為啟動成功了。

startretries=3; 當程序啟動失敗後,最大嘗試啟動的次數。。當超過次數後,supervisor将把此程序的狀态置為FAIL

exitcodes=0,2; 和autorestart=unexpected對應。exitcodes裡面的定義的退出碼是expected的。

這樣一來當程序退出的時候,我們可以利用Supervisor去重新開機程序,并且當程序已經無法正常運作的時候,還可以保留容器現場,友善登入容器進行問題定位。要注意的是我們使用Supervisor的初衷并不是去支援一個容器運作多個程序,本質上我們要求一個容器隻運作一個應用程序(比如Tomcat),然後可以運作幾個附屬程序(crontab、rsyslog)。

另外當應用異常的時候,更重要的是要能夠快速恢複。這時候我們就要利用Kubernetes的Readiness Probe去對Pod進行健康檢查,檢查的次元最好是以上層業務的健康性為标準,比如業務提供健康狀态的Restful API /health。

當Readiness Probe檢查失敗的時候,Pod就設定為NotReady狀态,為了保證業務是不中斷的,我們可以建立一個Pod出來頂替,當然如果建立的Pod仍是異常,就沒必要一直建立了。

整體來說利用Supervisor和Kubernetes Readiness Probe來優化問題排查的支援,邏輯圖:

DockOne微信分享(一三六):Kubernetes健康檢查政策

Q:請問Pod的狀态是crashbackoff 除了下載下傳鏡像失敗有哪些可能? 下載下傳的鏡像能否指定registry? pod如果有一個容器是exit 0, 那是否就是您之前提到的succeed? 使用livenessProbe檢測失敗的是failed還是crashbackoff?

A:Crashbackoff大部分情況下是容器的啟動指令失敗,比如tomcat啟動失敗了,初學者比較容器犯的錯誤是CMD的指令是一個非阻塞指令,這樣容器一運作就馬上退出了。下載下傳的鏡像可以指定registry,根據鏡像的指令來的,比如 test.registry.com/image:version。容器exit 0了,得根據重新開機政策來判斷。而livenessProbe檢測是業務層面的檢測。

Q:請問readinessProbe檢測失敗後,是手動Scale添加Pod確定業務穩定還是可以在ReplicationController的yaml裡面定義?

A:這部分 Kubernetes并不支援,是我們自己準備開發的功能。就是發現Pod NotReady後,一來保留問題容器,二來新增一個Pod頂替。

Q:請問Supervisord是手動在Pod裡面的容器裡面添加麼? 還是有專門的鏡像已經自帶?謝謝! 容器出錯後收集的現場資訊都儲存在哪裡?

A:Supervisord就安裝到容器裡面就行了,比如我們是CentOS基礎鏡像,然後yum install即可。當程序異常的時候,Supervisord可以重新開機程序并且保證容器不會退出,這樣一來就可以登入到容器裡面排查問題,資訊的話根據元件的情況來定了。

Q:請問,如果一個deployment有三個副本,分别部署再三個Node上,當其中一個Node當機了,這時候對應的service中的endpoint更新需要一定的時間,使用者在這個時間段通路就會有1/3的錯誤可能,這種情況怎麼辦?

A:當Pod異常的時候,比如是NotReady,Service的endpoint了馬上就會剔除這個Pod了。Kubernetes的實作都是實時watch的。

Q:保留容器現場如果造成多個僵屍容器怎麼辦?

A:當Pod NotReady的時候,建立Pod頂替,建立的Pod也異常的話,就不能一直重建。然後定位完成後,隻能手動去清理Pod了。

Q:用Supervisor來啟動服務,應用的日志是打到指定的目錄的還是直接std輸出然後再處理的啊?

A:應用的日志列印到檔案處理。Stdout被Supervisor占用了

Q: 一個容器裡面推薦隻跑一個程序,對于遇到一個項目要跑多個服務的情況,是每個服務都單獨生成一個容器嗎?如果是這樣的話代碼是怎麼管理的?每個服務一個分支嗎?而且往往開發、測試、生産是不同的分支,這樣服務多了的話對于代碼管理很麻煩,如果一個容器裡面用Supervisor來跑多個程序的話理論上可以,但是顯然做法不好。

A:每個服務可以做成一個容器。那這個是管理的成本了,可以通過一些工具和腳本來自動化。至于要不要跑多程序,看實際場景,都是可以的,其實隻要保證Pod提供的業務是正常的即可,是以我們用Probe來對業務檢查,

Q:請問Kubernetes的應用的日志是怎麼管理的,用的網絡檔案系統還是其他的方式?

A:我們是要求應用的日志全部輸出到指定目錄,比如/var/log。然後我們針對容器裡面的日志目錄統一挂載到Ceph存儲。

Q:是否可以通過preStop元素在pod failed被移除前執行一些收集現場資訊的指令?

A:也是可以的。但是大部分人定位問題還是希望能夠登入到容器裡面定位,這樣是最快最友善的方式。

Q:Supervisor的方式打亂了Kubernetes原來的容器重新開機方式,可能會帶來更大的問題。不如考慮在Kubernetes的基礎上修改增強。

A:是個問題。可以說Supervisor就覆寫了Kubernetes的重新開機方式,但是一方面Supervisor的重新開機方式更加靈活,另一方面修改Kubernetes的話侵入性比較大。是以我們選擇用Supervisor。

Q:你們的應用日志統一挂載存儲的話,存儲上是為每個容器建立一個目錄嗎?

A:這部門我們是修改了Kubernetes的代碼,為每個pod在主控端建立一個目錄,然後主控端的這個目錄是挂載Cephfs的。

Q:假如APP不能正常進行業務處理(連不上資料等原因),而health check依然正常傳回。怎麼辦?你們會強制要求開發對APP的狀态進行管理,在health check裡傳回嗎?

A:這是個好問題。我們會盡量要求應用提供的health接口盡量準确,但是這也很難保證100%的業務正常,是以目前就是需要權衡,這部門我們也在細化中。

以上内容根據2017年08月08日晚微信群分享内容整理。分享人吳龍輝,網宿科技雲計算架構師,負責設計開發PaaS平台,《Kubernetes實戰》作者。 DockOne每周都會組織定向的技術分享,歡迎感興趣的同學加微信:liyingjiesa,進群參與,您有想聽的話題或者想分享的話題都可以給我們留言。

原文釋出時間為:2017-08-09

本文作者: DockOne

本文來自雲栖社群合作夥伴Dockerone.io,了解相關資訊可以關注Dockerone.io。

原文标題:DockOne微信分享(一三六):Kubernetes健康檢查政策

繼續閱讀