想學習更多相關知識請看博主的個人部落格地址:https://blog.huli.com/
1.kubernetes快速入門
Kubernetes 叢集將所有節點上的資源都整合到一個大的虛擬資源池裡,以代替一個個單獨的伺服器,而後開放諸如 CPU、記憶體和 I/O 這些基本資源用於執行其基本單元 —— Pod 資源物件。Pod 的容器中執行著隔離的任務單元,它們以 Pod 為原子單位,並根據其資源需求聰虛擬資源池中為其動態分配資源。若可以將整個叢集類比為一臺傳統的伺服器,那麼 Kubernetes(Master)就好比是作業系統核心,其主要職責在於抽象資源並排程任務,而 Pod 資源物件就是那些執行於使用者空間中的程式。於是,傳統意義上的向單節點或叢集直接部署、配置應用的模型日漸式微,取而代之的是向 Kubernetes 的 API Server 提交執行 Pod 物件。
API Server 是負責接受並相應客戶端提交任務的介面,使用者可使用諸如 CLI 工具(如 kubectl)、UI 工具(如 Dashboard)或程式程式碼(客戶端開發庫)發起請求,其中,kubectl 是最為常用的互動式命令列工具。快速瞭解 kubernetes 的辦法之一就是部署一個測試叢集,並嘗試測試使用他的各項基本功能。本章在簡單介紹核心資源物件後將嘗試使用 kubectl 建立 Deployment 和 Service 資源部署並暴露一個 Web 應用,以便讀者快速瞭解如何在 Kubernetes 系統上執行應用程式的核心任務。
2.1 Kubernetes 的核心物件
2.1.1 Pod 資源物件
Pod 資源物件是一種集合了一到多個應用容器、儲存資源、專用IP及支撐容器執行的其他選項的邏輯元件,如下圖所示。換言之,Pod 代表著 Kubernetes 的部署單元及原子執行單元,即一個應用程式的單一執行例項,它通常由共享資源且關係緊密的一個或多個應用容器組成。
Kubernetes 的網路模型要求其各 Pod 物件的 IP 地址位於同一網路平面內(同一 IP 網段),各 Pod 之間可使用其 IP 地址直接進行通訊,無論他們執行於叢集內的哪個工作節點之上,這些 Pod 物件都像是執行於同一區域網中的多個主機。
讀者可以將每個 Pod 物件想象成一個邏輯主機,它類似於現實世界中的物理主機或VM(Virtual Machine),執行於同一個 Pod 物件中的多個程式也類似於物理機或 VM 上獨立執行的程式。不過,Pod 物件中的各程式均執行於彼此隔離的容器中,並於各容器間共享兩種關鍵資源:網路和儲存卷。
-
網路(networking):每個 Pod 物件都會被分配一個叢集內專用的 IP 地址,也稱為 Pod IP,同一 Pod 內部的所有容器共享 Pod 物件的 Network 和 UTS 名稱空間,其中包括主機名、IP 地址和埠等。因此,這些容器間的通訊就可以基於本地迴環介面 lo 進行,而與 Pod 外的其他元件的通訊則需要使用 Service 資源物件的 ClusterIP 及其相應的埠完成。
-
儲存卷(volume): 使用者可以為 Pod 物件配置一組“儲存卷”資源,這些資源可以共享給其內部的所有容器使用,從而完成容器間資料的共享。儲存卷還可以確保在容器終止後被重啟,甚至是被刪除後也能確保資料不會丟失,從而保證了生命週期內的 Pod 物件資料的持久化儲存。
一個 Pod 物件代表某個應用程式的一個特定例項,如果需要擴充套件應用程式,則意味著為此應用程式同時建立多個 Pod 例項,每個例項均代表應用程式的一個執行的“副本”(replica)。這些副本化的 Pod 物件的建立和管理通常由一組稱之為“控制器”(Controller)的物件實現,例如,Deployment 控制器物件。
建立 Pod 時,還可以使用 Pod Preset 物件為 Pod 注入特定的資訊,如 ConfigMap、Secret、儲存卷、卷掛載和環境變數等。有了 Pod Preset 物件,Pod 模版的建立者就無須為每個模版顯示提供所有資訊,因此,也就無須事先了解需要配置的每個應用的細節即可完成模版定義。這些內容將在後面的章節中予以介紹。
基於期望的目標狀態和各節點的資源可用性,Master 會將 Pod 物件排程至某選定的工作節點執行,工作節點於指向的映象倉庫(image registry)下載映象,並於本地的容器執行時環境中啟動容器。Master 會將整個叢集的狀態儲存與 etcd 中,並通過 API Server 共享給叢集的各個元件及客戶端。
2.1.2 Controller
Kubernetes 叢集的設計中,Pod 是有生命週期的物件。使用者通過手工建立或由 Controller(控制器)直接建立的 Pod 物件會被“排程器”(Scheduler)排程至叢集中的某工作節點執行,待到容器應用程式執行結束之後正常終止,隨後就會被刪除。另外,節點資源耗盡或故障也會導致 Pod 物件被回收。
但 Pod 物件本身並不具有“自愈”功能,若是因為工作節點甚至是排程器自身導致了執行失敗,那麼它將會被刪除;同樣,資源耗盡或節點故障導致的回收操作也會刪除相關的 Pod 物件。在設計上,Kubernetes 使用“控制器”實現對一次性的(用後即棄)Pod 物件的管理操作, 例如,要確保部署的應用程式的 Pod 副本數量嚴格反應使用者期望的數目,以及基於 Pod 模版來重建 Pod 物件等,從而實現 Pod 物件的擴縮容、滾動更新和自愈能力等。例如,某節點發生故障時,相關的控制器會將此節點上執行的 Pod 物件重新排程到其他節點上進行重建。
控制器本身也是一種資源型別,它有著多種實現,其中與工作負載相關的實現 Reqlication Controller、Deployment、StatefulSet、DeamonSet 和 Jobs 等,也可統稱它們為 Pod 控制器。如下圖中的 Doployment 就是這類控制器的代表實現,是目前最常用的管理無狀態應用的 Pod 控制器。
Pod 控制器的定義通常由期望的副本數量、Pod 模版和標籤選擇器(Label Selector)組成。Pod 控制器會根據標籤選擇器對 Pod 物件的標籤進行匹配檢查,所有滿足選擇條件的 Pod 物件都將受控於當前控制器並計入其副本總數,並確保此數目能夠精確反映期望的副本數。
需要注意的是,在實際的應用場景中,在接受到請求流量負載顯著低於或接近於已有 Pod 副本的整體承載能力時,使用者需要手動修改 Pod 控制器中的期望副本數量以實現應用規模的擴容或縮容。不過,若叢集中部署了 HeapSter 或 Prometheus 一類的資源指標監控附件時,使用者還可以使用“HorizontalPodAutoscaler”(HPA) 計算出合適的 Pod 副本數量,並自動修改 Pod 控制器中期望的副本數以實現應用規模的動態伸縮,提高叢集資源利用率,如下圖所示。
Kubernetes 叢集中的每個節點都執行著 cAdvisor 以收集容器及節點 CPU、記憶體及磁碟資源的利用率指標資料,這些統計資料由 Heapster 聚合後可通過 API Server 訪問。HorizontalPodAutoscaler 基於這些統計資料監控容器健康狀態並做出擴充套件決策。
2.1.3 Service
儘管 Pod 物件可以擁有 IP 地址,但此地址無法確保在 Pod 物件重啟或被重建後保持不變,這會為叢集中的 Pod 應用間依賴關係的維護帶來麻煩:前端 Pod 應用(依賴方)無法基於固定地址持續跟蹤後端 Pod 應用(被依賴方)。於是,Service 資源被用於在被訪問的 Pod 物件中新增一個有著固定 IP 地址的中間層,客戶端向此地址發起訪問請求後由相關的 Service 資源排程並代理至後端的 Pod 物件。
換言之,Service 是“微服務”的一種實現,事實上它是一種抽象:通過規則定義出由多個 Pod 物件組合而成的邏輯集合,並附帶訪問這組 Pod 物件的策略。Service 物件挑選,關聯 Pod 物件的方式和 Pod 控制器一樣,都是要基於 Label Selector 進行定義,其示意圖如下圖所示。
![Service 物件功能示意圖][1]
Service IP 是一種虛擬 IP,也稱為 Cluster IP,它專用於叢集內通訊,通常使用專用的地址段,如 “10.96.0.0/12” 網路,各 Service 物件的 IP 地址在此範圍內由系統動態分配。
叢集內的 Pod 物件可直接請求此類的 Cluster IP,例如,上圖中來自 pod client 的訪問請求即可以 Service 的 Cluster IP 作為目標地址,但叢集網路屬於私有網路地址,它們僅在叢集內部可達。將叢集外部的訪問流量引入叢集內部的常用方法是通過節點網路進行,實現方法是通過工作節點的 IP 地址和某埠(NodePort)接入請求並將其代理至相應的 Service 物件的 Cluster IP 上的服務埠,而後由 Service 物件的 Cluster IP 上的服務埠,而後由 Service 物件將請求代理至後端的 Pod 物件的 Pod IP 及應用程式監聽的埠。因此,諸如上圖中 External Clients 這種來自叢集外部的客戶端無法直接請求此 Service 提供的服務,而是需要事先經由某一個工作節點(如 Node Y)的 IP 地址進行,這類請求需要兩次轉發才能到達目標 Pod 物件,因此在通訊效率上必然存在負面影響。
事實上,NodePort 會部署於叢集中的每一個節點,這就意味著,叢集外部的客戶端通過任何一個工作節點的 IP 地址來訪問定義好的 NodePort 都可以到達相應的 Service 物件。此種場景中,如果存在叢集外部的一個負載均衡器,即可將使用者請求負載均衡至叢集中的部分或者所有節點。這是一種稱為 “LoadBalancer” 型別的 Service,它通常是由 Cloud Provider 自動建立並提供的軟體負載均衡器,不過,也可以是由管理員手工配置的諸如 F5 Big-IP 一類的硬體裝置。
簡單來說,Service 主要由三種常用型別:第一種是僅用與叢集內部通訊的 ClusterIP 型別:第二種是接入叢集外部請求的 NodePort 型別,它工作於每個節點的主機 IP 之上;第三種是 LoadBalacer 型別,它可以把外部請求負載均衡至多個 Node 的主機IP的 NodePort 之上。此三種型別中,每一種都以前一種為基礎才能實現,而且第三種型別中的 LoadBalacer 需要協同叢集外部的組建才能實現,並且此外部組建並不接受 Kubernetes 的管理。
2.1.4 部署應用程式的主體過程
Docker 容器技術使得部署應用程式從傳統的安裝、配置、啟動應用程式的方式轉為於容器引擎上基於映象建立和執行容器,而 Kubernetes 又使得建立和執行容器的操作不必再關注其位置,並在一定程度上賦予了它動態擴縮容及自愈的能力,從而讓使用者從主機、系統及應用程式的維護工作中解脫出來。
用到某應用程式時,使用者只需要向 API Server 請求建立一個 Pod 控制器,由控制器根據映象等資訊向 API Server 請求建立出一定數量的 Pod 物件,並由 Master 之上的排程器指派至選定的工作節點以執行容器化應用。此外,使用者一般還需要建立一個具體的 Service 物件以便為這些 Pod 物件建立起一個固定的訪問入口,從而使得其客戶端能夠通過其服務名稱或 ClusterIP 進行訪問,如下圖所示:
API Server 的常用客戶端程式是 Kubernetes 系統自帶的命令列工具 kubectl,它通過一眾子命令用於實現叢集及相關資源物件的管理操作,並支援直接命令式、命令式配置清單及宣告式配置清單等三種操作方式,特性豐富且功能強大。而需作為叢集附件額外部署的 Dashboard 則提供了基於 Web 介面的圖形客戶端,它是一個通用目的的管理工具,與 Kubernetes 緊密整合,支援多級別使用者授權,能在一定程度上替代 kubectl 的大多數操作。
本章後面的篇幅將介紹在部署完成的 Kubernetes 叢集環境眾如何快速部署如圖所示的示例應用程式,並簡單說明如何完成對容器化應用的訪問,以及如何進行應用規模的動態伸縮,並藉此讓讀者瞭解 kubectl 命令的基本功能和用法。
3.Kubernetes應用管理模型
下圖展示了Kubernetes的應用管理模型:
Pod是Kubernetes中的最小排程資源。Pod中會包含一組容器,它們一起工作,並且對外提供一個(或者一組)功能。對於這組容器而言它們共享相同的網路和儲存資源,因此它們之間可以直接通過本地網路(127.0.0.1)進行訪問。當Pod被建立時,排程器(kube-schedule)會從叢集中找到滿足條件的節點執行它。
如果部署應用程式時,需要啟動多個例項(副本),則需要使用到控制器(Controller)。使用者可以在Controller定義Pod的排程規則、執行的副本數量以及升級策略等等資訊,當某些Pod發生故障之後,Controller會嘗試自動修復,直到Pod的執行狀態滿足Controller中定義的預期狀態為止。Kubernetes中提供了多種Controller的實現,包括:Deployment(無狀態應用)、StatefulSet(有狀態應用)、Daemonset(守護模式)等,以支援不同型別應用的部署和排程模式。
通過Controller和Pod我們定義了應用程式是如何執行的,接下來需要解決如何使用這些部署在Kubernetes叢集中的應用。Kubernetes將這一問題劃分為兩個問題域,第一,叢集內的應用如何通訊。第二,外部的使用者如何訪問部署在叢集內的應用?
對於第一個問題,在Kubernetes中通過定義Service(服務)來解決。Service在Kubernetes叢集內扮演了服務發現和負載均衡的作用。在Kubernetes下部署的Pod例項都會包含一組描述自身資訊的label,而建立Service,可以宣告一個Selector(標籤選擇器)。Service通過Selector,找到匹配標籤規則的Pod例項,並將對Service的請求轉發到代理的Pod中。Service建立完成後,叢集內的應用就可以通過使用Service的名稱作為DNS域名進行相互訪問。
而對於第二個問題,Kubernetes中定義了單獨的資源Ingress(入口)。Ingress是一個工作在7層的負載均衡器,其負責代理外部進入叢集內的請求,並將流量轉發到對應的服務中。
最後,對於同一個Kubernetes叢集其可能被多個組織使用,為了隔離這些不同組織建立的應用程式,Kubernetes定義了Namespace(名稱空間)對資源進行隔離。
4. Kubernetes架構模型
為了能夠更好的理解Kubernetes下的監控體系,我們需要了解Kubernetes的基本架構,如下所示,是Kubernetes的架構示意圖:
Kubernetes的核心元件主要由兩部分組成:Master元件和Node元件,其中Matser元件提供了叢集層面的管理功能,它們負責響應使用者請求並且對叢集資源進行統一的排程和管理。Node元件會執行在叢集的所有節點上,它們負責管理和維護節點中執行的Pod,為Kubernetes叢集提供執行時環境。
Master元件主要包括:
- kube-apiserver:負責對外暴露Kubernetes API;
- etcd:用於儲存Kubernetes叢集的所有資料;
- kube-scheduler: 負責為新建立的Pod選擇可供其執行的節點;
- kube-controller-manager: 包含Node Controller,Deployment Controller,Endpoint Controller等等,通過與apiserver互動使相應的資源達到預期狀態。
Node元件主要包括:
- kubelet:負責維護和管理節點上Pod的執行狀態;
- kube-proxy:負責維護主機上的網路規則以及轉發。
- Container Runtime:如Docker,rkt,runc等提供容器執行時環境。