Kubernetes 已經成為事實上的編排平臺的領導者,下一代分散式架構的王者,其在自動化部署、擴展性、以及管理容器化的應用中已經體現出獨特的優勢,在企業中應用落地已經成為一種共識。本次「K8S 技術落地實踐」杭州站,青雲QingCloud 軟體工程師萬宏明為大家帶來《高效運維 K8S 集羣》主題分享。

隨著容器技術的發展,K8S、微服務、DevOps 等相關技術也趨於成熟,逐步在生產環境中得以落地。和傳統的運維體系不同的是,現在藉助 K8S 強大的容器調度編排能力,作為開發者也能很輕鬆的管理線上集羣。

隨著微服務架構和容器技術的普及,應用被拆分的越來越細,這也對開發運維人員提出了新的要求。一旦集羣中運行的應用出現故障,需要面對的是成千上萬個運行中的容器和複雜的網路環境,如果你需要藉助 K8S 強大的容器編排能力,就必須要深入的去了解 K8S 的特性,能夠快速的定位問題,處理故障。

今天給大家帶來的分享主題高效運維 K8S 集羣將從三個話題進行展開,首先帶大家瞭解一下 K8S 的集羣架構,再給大家分享一下我們在集羣運維中的一些經驗,最後和大家探討如何打造一個高可用的 K8S 集羣。

1、K8S 的集羣架構

K8S 的集羣架構主要有兩部分內容,一是 K8S 的設計和架構,二是 K8S 的系統分層。

這是一張 K8S 的組件架構圖,圖中左側是 K8S 中控制平面的一些組件包括 kube-apiserver、etcd、kube-controller-manager、kube-scheduler 等,這些組件是整個 K8S 的核心;右側是 Worker 節點上的核心組件,kubelet、kube-proxy 這兩個組件負責節點上容器的調度和管理 (包括網路和存儲)。

K8S 組件接管了整個節點上的容器調度和管理工作,接受來自控制平面的任務,為容器分配網路和存儲。在節點上,這些組件會定時向控制平面上報當前節點的狀態,方便集羣中的 Scheduler 進行調度。

總結來說,K8S Master 節點上的組件也就是我們現在所說的核心組件。常用的包括 K8S API Server,它提供了所有資源的操作入口,提供了資源操作的唯一入口,並提供認證、授權、訪問控制、API 註冊和發現等機制。在 K8S 集羣中 etcd 是很重要的,K8S 依賴 etcd 保存整個集羣的狀態。

第三個是 Controller-Manager,它負責維護整個集羣中資源的狀態,並且提供 API 。所有的 API 都是聲明式的 API ,聲明式的意思是說我描述我的 Depolyment 需要達到什麼樣的狀態,最後它的狀態轉變是由 Controller 實現的。無論是 Prometheus Operator 還是 Istio 核心組件,都可能用到大量的 CRD 資源,他們需要用這些資源支持 K8S 中沒有的概念。

剛剛討論的是 K8S 的架構。現在大家看到的是另一個層面的東西,整個 K8S 的系統分層。

K8S API 或者架構是如何設計的?

大家看到最底層黃色的是 K8S 最核心的功能,核心功能包括現在所說的 Pod、Namespace、Secret,還有 Service,這些都是 K8S 最基礎的功能。在最基礎的功能之上才能封裝圖中綠色方塊的應用負載,如 DaemonSet、Depolyment,這些都是在應用層上的封裝,都是通過 Controller-Manager 維護的。

其本質是,任何一個 Workload 都是由 Pod 組成的,有了底層 Pod 概念的支持,上面才會有 Depolyment 的資源理念。

再往上層是 K8S 管理者的東西,包括 K8S 中的 RBAC,這需要我們執行運維,我們可能需要對 Pod 的安全進行加固。再後面的是我們需要對 API Server 或者 Controller 進行度量,我們可能需要開發管理插件。這是第三層。

往上是開發者和運維人員用得比較多的介面層,如 kubectl、SDK,這些都是我們開發者直接接觸到的。

總的來說,這分為五層:核心層、應用層、治理層,介面層和外圍生態系統。我們作為 K8S 之上的應用開發者,我們更關注的是構建在 K8S 之上的生態應用,包括我們在 K8S 之上可以構建我們的監控系統,配置 etcd,這些功能都是建立在 K8S 介面之上的。

另一種層面,K8S 與原有的介面、拓展層,包括 CRI、CSI 等機制都結合的非常緊密。通過 K8S CRD API 聚合方式,我們可以把集羣配置做到足夠自動化。有了 K8S 強大的插件機制,可以讓我們集羣運維、使用管理變得非常簡單。

2、常見故障及其處理方式

只有熟悉 K8S 整個集羣的架構體系,我們才能支持 K8S 的運維。在我們運維 K8S 集羣中也遇到了非常多的問題,下面我會講講我們在運行 K8S 集羣過程中遇到的具體問題以及我們收集問題的方式。

主要包括三部分內容:

  • 第一,我們如何處理故障,我們是按照什麼樣的順序排查我們線上應用出現哪些問題。

  • 第二,簡單分享我們常常遇到的問題以及如何解決。

  • 第三,如何避免線上業務出現這樣的問題。

當線上應用出現問題時,突然發現某個服務不能訪問了,我們該如何快速定位這個東西?

也許在之前單機運維場景下,我們很明確的知道不是 LB 的問題,是我們應用的問題。在微服務環節下,應用的調度鏈路變得非常長,一個應用不能訪問,造成問題的點可能非常多,這時候我們需要有序地對整個集羣進行檢查,定位問題、發現問題並且解決問題。

假如我們發現一個服務不可訪問,首先需要檢查集羣幾個點是否正常?K8S 整個集羣是否正常?

我們可以通過查看節點是否正常,一是保證 K8S API Server 是正常的,二是可以查看節點集羣網路中是否存在節點異常。如果我們在第一步發現哪個節點掛掉了,這時候我們可以重啟節點,對節點上的應用進行恢復。假如我們發現這個節點掛掉是因為集羣資源不夠,這時候我們要及時增加集羣節點,否則哪怕是重啟集羣,可能還是會掛掉。

通過第一步,我們並沒有發現集羣中的節點有什麼問題,我可能需要看到應用本身的部分,我們需要查看應用本身的日誌,需要查看涉及的 Pod 日誌。執行時可以看到確認兩點,一是看 Pod 基礎網路是否通暢,通過日誌查看這個應用是不是在運行過程中發現一些問題,是不是有一些錯誤的日誌在裡面。二是解決在啟動時遇到的常見問題。

假設我們發現 Pod 沒有錯誤情況發生,這時候我們可能需要看看 K8S 核心組件,包括 kube-apiserver,kube-scheduler,kube-controller-manager 的日誌。這時候我們可以查看 K8S 核心組件的配置,看有沒有問題。

第四步工作是檢查 Service 是否可以訪問,這時候我們需要查看 DNS 或者 kube-proxy 日誌,可以很簡單的查看 DNS 或者 kube-proxy 有沒有報錯。有些人習慣性地在某些 Pod 上抓包或者在節點上進行抓包,這種效率是非常低的。

實在沒有定位到問題的話,還可以看看每個節點上 Kubelet,如果 Kubelet 上有錯誤信息發生,可能就是因為這個節點上 Kubelet 發生了一場災難,需要我們重新做節點。

以上五種情況可以解決集羣中大部分的網路、存儲和應用本身的異常。核心依賴是本身集羣就有監控系統、監控告警系統,通過這種方式直接在我們監控系統中查看集羣中是不是有哪個節點異常。假如我們是微服務應用,還可以查看是不是某一個微服務中的某個鏈路斷開了。

除了以上談到的集羣故障,我們還會遇到常見的應用故障。

第一種是 Pod 啟動後一直處於 Pending 的狀態,表示這個 pod 沒有被調度到一個節點上。在我們實際場景中,大部分是因為節點上的資源不足引起的。

第二種是使用了 hostPort 導致埠出現衝突,服務無法正常啟動。

第三種是如果你的程序在 Waiting 中,則表示這個 pod 已經調試到節點上,但是沒有運行起來,通過 kubectl describe <pod-name> 這個命令來查看相關信息。最常見的原因是拉取鏡像失敗,這個情況在私有雲環境中非常常見。

第四種跟我們應用本身使用參數或者應用本身的代碼有關係,這裡有一個典型的例子——MySQL。我相信有在 K8S 上部署 MySQL 的用戶,都可能遇到這個問題。MySQL 在使用時,假如你的磁碟中緩存不足,這時候我們需要查一查 MySQL 的報錯,錯誤信息會很明確地告訴你需要調大參數,這是都是通過 Controller 命令就可以查到的。假如 Pod 一直 restart 的話,我們可能需要查看它之前的日誌。

第五種,Service 提供了多個服務和多個 Pod 之間的負載均衡功能。假設你的服務不可訪問時,這時候我們需要考量,可以通過 Controller 查看 Service 下有沒有掛載具體的 Pod。

我們的集羣有時候會出現狀況,比如我們的 CPU 或者內存不足,導致節點異常、宕機,或者整個集羣網路中斷、閃斷。

如果節點異常,這時候需要快速重啟節點,資源不足要增加節點。如果節點頻繁抖動導致業務出現漂移,這時候我們會檢查一下 Controller-Manager 中的參數,配置響應參數,設置它整個節點狀態檢測週期。

如果我們發現 K8S 中發生異常,比如我們發現 Controller-Manager 掛了,或者 Cloud-Controller-Manager 掛了,最核心的是查看日誌,及時把這些節點重啟起來。最核心的需求是我們需要保證關鍵組件高可用,包括我們需要讓這些組件一直保持在多個副本中。

存儲和網路是 K8S 整個環境中最容易出問題的地方,一般像網路出現問題,定位它會像其他似的,我們需要由上至下一層層地篩選,在哪一層的網路出現問題。

由於 K8S 整個集羣的負載是我們平時無法應付的,所以我們要想辦法避免問題,我總結以下四點,幫助我們開發者規避集羣中可能遇到的情況。

第一點是我們集羣搭建起來,真正落地到生產環境中時,我們非常依賴集羣中的監控系統,我們需要 Prometheus,需要 Docker 系統,幫助我們實時監控集羣中的資源狀況。如果哪個節點發生異常,我們需要及時收到通知。

開發者或者運維人員很容易忽略的一點,假設我們集羣中部署了一些 Prometheus 或者日誌的組件,我們可能會忽略這些系統組件本身會消耗掉一部分系統資源。

當我們節點不斷增加,這些系統組件上面會有 overhead ,它還是會消耗資源。如果應用越來越多、Pod 越來越多,這些系統組件也會有更多的資源消耗,如果沒有給系統組件足夠的資源會導致這些關鍵系統組件崩潰,我們需要給他們設置合適的資源限制,需要根據集羣規模不斷地調整。至少保證我們的監控告警系統正常運行。

第二點是很多時候 K8S 往往會暴露出非常多的安全問題,我們要實時關注,及時修復集羣中可能出現的問題。

第三點是應用層的優化,當我們應用出現問題時,如果我們想要快速恢復它,一個大前提是我們要保證應用是無狀態的,不依賴於任何存儲。有狀態應用的恢複比無狀態應用的恢復起來麻煩得多。無狀態應用,我們可以讓應用恢復副本數,充分利用 K8S 調度編排的優勢,這是和普通傳統應用有區別的地方。我們可以通過這種方式避免我們在 K8S 集羣中的應用出現問題。

最重要一點,我們需要及時備份集羣中的數據,之前我們發生了一場線上災難,通過備份數據得以進行恢復,沒有影響到業務。

3、如何打造 K8S 高可用架構

即使我們有高可用架構,還是避免不了監控、告警和日誌的系統組件。這是最典型的 K8S 多節點架構圖:

K8S 高可用架構包括以下四個步驟:

  • 建立一個冗餘的,可靠的存儲層,etcd 集羣

  • K8S apiserver 的高可用,多節點多副本,apiserver 負載均衡

  • kube-scheduler,kube-controller-manager,核心組件支持多副本選主

  • 重新配置 kubelet 和 kube-proxy,--apiserver 指向 apiserver lb

光有高可用的集羣架構只能保證我們 K8S 集羣可用,實際上我們最終還是要用自己的應用,我們需要大量依賴日誌系統、監控系統、高可用系統,對我們集羣中運維實際日誌的業務系統進行監控。

如果需要中的日誌進行收集,我們可以通過 ELK 這種方案,對所有的 Pod 進行收集。我們可以接入可視化的方案進行查看。剛剛有人提到 Prometheus,Prometheus 本身有 Manager 這樣項目,Manager 有非常大的短板,所以在實際過程中有很多開發者都會自己實現。

最簡單的方案是 KubeSphere? 提供一鍵式的部署,下面有監控、日誌、告警所有的解決方案。

4、總結

Kubernetes 發展迅速,今天我總結的是我們常用的調試問題和解決問題的方式,不一定適用於每個人或者每個企業。你在使用 Kubernetes 時,我們需要及時關注新版本的變化,它可能會針對某個環境下的問題修復,我們可以對不熟悉的問題多加實驗,最大程度的減少集羣中可能出現的問題。我們需要熟練應用 K8S 本身的命令行工具,如 Controller 等功能。

最後,我認為命令行操作非常繁瑣,大家可以看看我們如何通過 UI 系統創建 K8S 中的服務,同時我們還集成了一鍵式 CI/CD、Istio 等,歡迎大家下載我們 KubeSphere? 體驗一下。

系列分享回顧:

萬字乾貨 | K8S 技術落地實踐上海站分享

7 月 25 日, 秉承科技前沿與企業實踐並重的 CIC 大會再度來襲,為大家奉上一場科技盛宴。依舊硬核依舊信息過載,乾貨滿滿,絕對讓你不虛此行。點擊此處或長按識別下面二維碼,即刻報名!


推薦閱讀:
相關文章