1. 程式人生 > >詳解 Kubernetes 的穩定性和可用性_Kubernetes中文社群

詳解 Kubernetes 的穩定性和可用性_Kubernetes中文社群

作者/講師:楊朝樂/才雲科技軟體工程師

才雲基礎設施部分運維開發工程師,專注於 Kubernetes 部署及運維。

來源:K8sMeetup

大家好,我叫楊朝樂,來自才雲科技基礎設施部門。今天給大家分享一個平時可能接觸得較少的話題:關於 Kubernetes 的穩定性和可用性。

下面是今天分享以下 5 個主題:

  • 認識穩定性
  • 認識異常
  • Kubernetes 裡面的高可用方案
  • 如何處理異常
  • 我的經驗分享

認識穩定性

Kubernetes 叢集的穩定性和眾多因素相關。比如我們有一個叢集,上面會有很多應用,這些應用可能是無狀態的,通過 Deployment 來管理;也可能是有狀態的應用,通過 StatefulSet 來管理。Kubernetes 叢集之上,通過多種 Controller 來管理我們的應用。而在叢集之下,比如叢集節點的儲存、網路、資源等,比如物理硬體的好壞,都是影響叢集穩定性的重要一環。

就像有一個叫做 “Jenga” 這個遊戲,某些元素的單個故障不會導致叢集不可用,一旦某些關鍵元素或者多個元素故障,超過了叢集的自恢復能力,叢集便不再可用了。

那麼,Kubernetes 為我們提供了哪些提高叢集可用性的利器呢?下面分享幾個使用較多的特性:Replica,Qos,HPA,Health Check。

我們先來看一個一切正常的 Kubernetes 叢集,包含 3 個節點,每個節點上跑了一些應用。可以注意到,有些應用有多個例項,有些只有一個例項。下面,如果第一個節點的 Console 和第二個節點的 Api 故障了,叢集服務的可用性會怎樣呢?

1、Replica

我們可以聯想到,對於 Console 的故障,當 Console 不可用時,Console 對應的服務也不可用;而 Kubernetes 會保證應用的副本時,所以 Console 這個應用會重新的創建出來,並正常提供服務。但在重新排程和建立起來之前,服務是會中斷的。作為對比,Api 服務因為使用了多個副本,在圖中的故障情況下,服務是仍然可用的。所以這裡我們推薦使用多個副本。

2、QoS

下面再看一張圖,圖中應用的大小對應應用的資源佔用,這裡以佔用的記憶體為例。比如在節點 3 上,Db 因為資源不足,無法正常執行。

這裡列出了幾個可能的場景:

  • 應用(節點 1 上的 Db)使用了過多的記憶體,會發生什麼呢?Db 自己可能會因為記憶體不足或超限而被 kill 掉;Db 可能會導致其他優先順序低的應用被 kill 掉。
  • 應用(節點 3 上的 App)申請了過多的記憶體,導致原先想排程到這個節點上的應用無法排程上來

這些場景會在配置不同的 QoS classes 策略下有所不同,Kubernetes 提供了三種資源使用策略,根據應用的資源申請(request)和資源限額(limit)的不同、對於到 Guaranteed Burstable 和 BestEffort 三種模式。實際場景下,應該合理分配資源,避免資源的浪費和服務的不穩定。

3、HPA

和 Qos 類似的,HPA 是應用水平自動擴容。切換到這樣場景:叢集的 Db 服務負載很低,多個副本顯得浪費;或者,叢集的 Api 服務,突然流量劇增,當前的副本數已經不夠了。這個時候,通過配置 HPA,可以使應用在負載高的時候,自動的新增副本數來減小單個例項的壓力;也可以在壓力小的時候,降低副本數,釋放資源。

說到這裡,可以提一下這裡的負載,目前 Kubernetes HPA 實現上是通過衡量 CPU 的負載來評估服務負載的,實際使用中可能不能滿足我們的需求。不過 Kubernetes 還提供了 Custom metric 讓我們來自定義負載的指標。而與 HPA 類似的,還有叢集的自動擴縮容(Cluster Autoscaler)和應用的垂直擴容(VPA)。

4、Health Check

下面講講健康檢測(Health Check)。比如應用 Api 出現了問題,我們實際訪問 Api 服務時發現這個服務確實不可用了,但我們查詢到的 Api pod 執行的狀態的 Running,也就是正常在跑,Kubernetes 不會知道這個應用不工作了。預設情況下,如果應用沒有異常退出,Kubernetes 會認為這個應用是正常的,不會做特殊處理。

但我們或許會遇到以下 2 種情況:

  1. 應用因為死鎖而卡死;
  2. 應用還在初始化階段等導致服務不可用,我們可以藉助健康檢測來讓 Kubernetes 發現和處理這類異常。

對於狀況 1,我們可以配置存活性檢測(Liveness Probes),如果存活性檢測沒有通過,Kubernetes 會自動來重啟這個應用。

對於狀態 2,我們可以配置可用性檢測(Readiness Probes),這樣在服務初始化完成前,通過 Service 不能訪問到這個服務,避免造成意想不到的後果。

提高叢集的穩定性,Kubernetes 還提供了許多高階功能,這些功能可能沒有前面提到的那幾個常見,但卻也是十分有用的。下面分享兩個功能特性:資源預留和關鍵元件排程保證。

資源預留

實際場景下的資源使用,除開使用者執行的實際業務,作業系統本身也會佔有一定的資源,比如系統核心,比如系統服務(sshd udev 等)。如果使用者業務使用了過多的資源,以至於系統的資源得不到保障,導致系統不穩定,叢集服務就也得不到保障了。這個時候,我們可以通過配置 System-reserved 來給系統預留部分的資源。

但是這樣就夠了麼?我們知道,Kubernetes 叢集本身也有許多控制組件,這些元件如果因為資源不足出現故障,整個叢集也沒法保障穩定了。這個時候,我們可以類似配置 System-reserved 一樣,配置 Kube-reserved,來預留資源給 Kubernetes 相關的元件,比如 Kubelet 和 Docker daemon。這樣一來,哪怕使用者業務負載很高,也可一定程度上通過保證系統核心元件的穩定來提高叢集的穩定性。

關鍵組建排程保證

除了 Kubernetes 的系統元件,還有一些元件,這些元件如果沒有跑起來,整個叢集都可能不可用,比如 dns 服務,比如網路外掛等。這些關鍵的應用(Critical Add-On),Kubernetes 提供了一種機制,來保證這些關鍵應用的存活。

比如這樣一種情況,DNS 排程到了一個節點,這個節點存在一些問題,導致 DNS 一直不停的出錯重啟。預設情況下,除非 Kubernetes 認為這個節點不可用,進而重新排程 DNS,DNS 服務是不會重新排程的,這樣會導致叢集不可用,並且不能自動修復。這個時候,如果配置了 Rescheduler 元件,並且把 DNS 配置成了關鍵應用,DNS 會被重新排程到另外一個節點。這樣,叢集的服務一定程度下,可以自動的修復。

認識異常

講了許多的提高叢集穩定性的方法,下面談談叢集使用中可能遇到的異常。回到最初的那個圖,圖上每一個節點,都可能出現異常,比如:應用沒有跑起來;節點掛掉了;網路故障;Docker 卡死等。下面以電力故障為例,來談談出現異常時候,對叢集服務的影響。

下面三張圖中三個節點上分別跑著一些服務,假設故障分別出現在這三個節點上,會發生什麼呢?前面提到了 Replica,我們知道如果 Replica 為 1,服務是會中斷的。這個中斷時間可能沒有大家想象的那麼短。

預設情況下,從節點狀態變為不可用,到 pod 重新排程到其他可用節點,可能需要幾分鐘的時間。我們可以通過配置 pod-eviction-timeout 來調整這個時間,但不建議配的太小,這樣可能因為比如網路不穩導致 pod 不停地重新排程,造成抖動。

那是否 Replica 配置成 2 或者更多就可以了呢?我們可以想想節點 1 出現故障,服務 Console 全部跑在了節點 1 上,哪怕 Console 有多個服務,故障還是會造成 Console 服務中斷。這個時候,我們可以配置 podAntiAffinity,來保證服務的多個副本不會排程到相同的節點上,以此來進一步提高可用性。

我們繼續假設,如果出現電力故障的節點是 Master 呢?如果這是唯一的 Master,那麼故障的服務不會重新排程和恢復;通過 Service 方式訪問這個應用,有可能訪問到故障的後端服務。

K8S 裡的高可用方案

如果是有多個 Master 呢?理想的情況下,故障節點上的應用會重新排程,故障的服務也會自動恢復。為什麼說理想的情況下呢,這個我們稍後會解釋,在此之前,我們先看看高可用在 Kubernetes 是如何實現和工作的。

圖中描述了一個典型的 Kubernetes HA 方案架構,包括幾個重要的地方:

  • Masters:叢集 Master 節點數不再是一個,而是三個,etcd 作為叢集的模式工作在三個 Master 節點上,每個節點上都會跑一個 apiserver,並連線這個 etcd 叢集;其他有狀態的元件比如 controller scheduler 會採用主備的方式,在三個 Master 上都會執行,但是隻有一個節點上的會選舉為主,提供服務。
  • Nodes:叢集 Node 節點的 Kubelet proxy 服務,連線 apiserver 的負載均衡地址。
  • load balancer:一個負載均衡服務,把流量匯入到存活的 Master 節點的 apiserver 服務上。這個負載均衡即可以是一個外部 IaaS 提供的雲負載均衡,也可以是自己通過keepalived 和 nginx 搭建出來的內部負載均衡。

社群熱門的部署工具 Kubeadm,也有整合 HA master 的計劃,下圖是一個目前的完成度情況,可以發現裡面還有不少工作要做,預計的釋出版本是 v1.10。如果不想等得太久,社群也給出了一個基於 Kubeadm 手動建立一個 HA master 叢集的方案和操作流程。這裡給出了相關文件的連結,感興趣的同學可以自己選擇閱讀。

回到剛才說的理想的情況,HA 方案可以保證叢集高可用。但實際情況呢?

目前的 HA 叢集,在實際使用上,會有一些坑,雖然某些可能在最新的上游版本修復了,但如果沒有更新版本,這些問題還會存在。

  • etcd client 問題:當三臺 Master 節點掛掉一臺時,apiserver 可能仍然連線的是停止服務的那臺 Master 節點上的 etcd ,這樣 apiserver 無法獲取和更新最新的叢集狀態,導致可能通過 kubectl get node 查詢叢集的狀態,在一個節點上查詢到的是三個節點全正常,另外一個節點顯示有一臺 not ready。
  • default/kubernetes svc 問題:一臺 Master 節點故障時,default/kubernetes 這個服務不會像其他服務那樣,去更新它的 endpoint,異常的 Master 節點 IP 仍然會保留在 endpoint 裡面。這樣許多通過 svc 方式來訪問 apiserver 的應用都會出問題。預設 svc 的實現是通過 iptables 規則來實現的。目前的 kubernetes svc 會根據 client IP 做會話保持,這樣如果訪問的恰好是壞掉的 Master 節點 IP,這個節點上的 kubernetes svc 就會一直不可用了。如果去掉會話保持,會有三分之一的概率服務不可用。

拋開上面提到的兩個問題,還是電力故障的情況,這次情況比較糟糕,所有節點都受到了影響。但運氣比較好,電力很快就恢復了,這個時候,叢集服務會怎樣呢?

場景一:負載均衡服務沒有恢復,Master 節點很快恢復正常了。因為負載均衡還未恢復,所有 Node 節點都會認為是不可用的,導致的一個可能後果是,所有 Node 上的服務都重新排程並在 Master 節點建立,Master 節點負載會非常高。哪怕後面 LB 恢復了,master 節點的任務也不會自己遷出,叢集的負載會極度不均衡。

場景二:負載均衡服務正常,Master 節點和 Node 節點都在快速的啟動服務中。這個時候,如果 Node 節點規模很大,apiserver 和 etcd 的請求會非常的多。比較糟糕的情況是,Master 節點的 etcd 因為負載太高不能正常提供服務,導致 Node 節點註冊失敗,然後不斷嘗試重新註冊 Node;哪怕負載降下來後,Node 節點全部註冊成功,大量應用重新排程,產生大量的事件,etcd 很可能馬上又壞掉了。這個時候,就需要對 apiserver 做限流了,防止突發的壓力增長導致叢集不可用。

處理異常

談了很多異常的狀態,那麼有什麼好的辦法來處理這些異常呢?限於時間關係,以下圖為例給大家簡單講講如何處理異常。

  • Symptom:通常發現異常時,是因為發現了一些不尋常的徵狀,比如某個服務不可用了,某個 pod 卡在了 terminating 狀態;某個建立的 deployment 沒有看到執行的 pod。根據這些徵狀,我們對於出現的異常有了一個初步的瞭解,便於藉助工具做進一步的診斷。
  • Tools:診斷問題時,我們可以藉助許多工具。比如 kubectl describe 來檢視事件,kubectl logs 來檢視日誌,nsenter 進入容器的名稱空間診斷問題,tcpdump 抓包來診斷網路問題等。藉助這些工具,和診斷的一些結論,我們可以猜測可能的原因
  • Root Cause:導致異常的原因多種多樣,異常的直接原因,藉助工具可以快速發現,比如建立了 deployment 沒有創建出 pod 原因是節點資源不足。我們可以繼續追蹤這個異常,為什麼會突然資源不足了呢,藉助工具可以發現是有一個節點不可用了。繼續追查,可能是這個節點的 kubelet 異常退出了。通過一步步,找到了根本原因,才能從根源上解決這個問題。

上圖中列出了一些有趣的 Root Cause,比如核心的 panic,dockerd 卡死,錯誤的掛載目錄,配置了錯誤的網路策略等。

我的經驗分享

這裡給大家分享一下經驗:

  • 藉助日誌系統和監控系統發現和診斷異常
  • 優先檢視節點的負載情況,確保不是資源不足,磁碟寫滿導致的
  • 診斷問題不僅限於 Kubernetes 本身,相關的儲存、網路、容器執行時等都可能出問題
  • 不要忽略硬體本身的問題,比如磁碟本身有故障

今天的分享到這裡,感謝大家!