雲原生技術系列-容器叢集排程編排系統Kubernetes

前言

隨著微服務的盛行,使用Docker作為微服務應用部署環境也越來越盛行。伴隨著業務的進一步發展,系統中遍佈著各種各樣的容器,真實的場景可能是這樣的:每一個服務包含成百上千個應用,而每一個應用又有著成百上千個例項。於是,容器的資源排程,部署執行,擴容縮容就是我們要面臨的問題。

基於 Kubernetes 作為容器叢集的管理平臺被廣泛應用,k8s已經成為容器編排排程領域的事實標準,是雲原生組織CNCF主推的頭號專案,容器化時代的作業系統,k8s將成為我們開啟雲原生時代大門的鑰匙。

正文

核心概念

k8s的主要功能:

核心元件

Master 與 Node

k8s叢集有兩類角色,一種是 master ,一種是 Node(也叫worker)。

master 是叢集的“大腦”,是叢集中的控制節點,負責管理整個叢集:排程、更新、擴縮容。

Node 就是具體“幹活”的,是叢集中的工作節點,一個Node一般是一個虛擬機器或物理機。我們的容器就是部署在Node節點上的。

下圖展示的k8s叢集中的一個master節點和多個Node節點。

雲原生技術系列-容器叢集排程編排系統Kubernetes

Pod

出於像易用性、靈活性、穩定性等的考慮,Kubernetes 提出了一個“ Pod ”的概念,作為 Kubernetes 的最小排程單位。所以我們的應用在每個 Node 上執行的其實是一個 Pod。Pod 也只能執行在 Node 上。如下圖:

雲原生技術系列-容器叢集排程編排系統Kubernetes

那麼,肯定有人會問,為什麼提出pod這玩意呢?不是增加複雜度麼?直接排程容器不是更加簡單直接麼?沒錯,筆者也曾經有過這樣的疑問。但是後來慢慢理解了設計者的初衷:

Pod可以理解為容器組的概念。首先,容器本身就是一個小盒子了,Pod 相當於在容器上又包了一層小盒子。這個盒子裡面的容器有什麼特點呢?

可以透過 volume 共享儲存。

有共享相同的網路配置。通俗點說就是有一樣的ip地址,有一樣的網絡卡和網路設定,在進行內網通訊時的成本更低。

簡而言之,在同一個pod內的多個容器可以共享相同的儲存、網路等配置,這樣就無需為每個容器單獨去做配置,極大地降低了配置成本。

雲原生技術系列-容器叢集排程編排系統Kubernetes

service

使用pod部署好了應用,下面我們會考慮如何訪問到我們部署的應用呢?

最直接想到的方法就是直接透過

Pod-ip+port

去訪問,但如果例項數很多呢?好,拿到所有的 Pod-ip 列表,配置到負載均衡器中,輪詢訪問。但上面我們說過,Pod 可能會死掉,甚至 Pod 所在的 Node 也可能宕機,Kubernetes 會自動幫我們重新建立新的Pod。再者每次更新服務的時候也會重建 Pod。而每個 Pod 都有自己的 ip。所以 Pod 的ip 是不穩定的,會經常變化的。

面對這種變化我們就要藉助另一個概念:Service。它就是來專門解決這個問題的。不管部署的Pod有多少個,不管它是更新、銷燬還是重建,Service總是能發現並維護好它的ip列表。那麼這個Service到底是怎麼做到的呢?

Service是一個邏輯上的概念,可以與我們常規意義上理解的服務相對應,是一個大應用內提供單一職責的應用集合體,例如淘寶的賬號服務、淘寶的訂單服務等,都可以理解為這裡的Service。Service為了實現動態路由的功能,對外也提供了多種入口:

ClusterIP:Service 在叢集內的唯一 ip 地址,我們可以透過這個 ip,均衡的訪問到後端的 Pod,而無須關心具體的 Pod。這個IP地址本質上是一個虛擬IP地址,透過node節點上的kube-proxy元件來實現的,這塊我們後面會詳細介紹到。

NodePort:Service 會在叢集的每個 Node 上都啟動一個埠,我們可以透過任意Node 的這個埠來訪問到 Pod。

LoadBalancer:在 NodePort 的基礎上,藉助公有云環境建立一個外部的負載均衡器,並將請求轉發到 NodeIP:NodePort。

ExternalName:將服務透過 DNS CNAME 記錄方式轉發到指定的域名(透過 spec。externlName 設定)。

雲原生技術系列-容器叢集排程編排系統Kubernetes

Label and Label Selector

最容易想到的方法是使用 Deployment 的名字。一個 Service 對應一個 Deployment 。當然這樣確實可以實現。但kubernetes 使用了一個更加靈活、通用的設計 - Label 標籤,透過給 Pod 打標籤,Service 可以只負責一個 Deployment 的 Pod 也可以負責多個 Deployment 的 Pod 了。Deployment 和 Service 就可以透過 Label 解耦了。

雲原生技術系列-容器叢集排程編排系統Kubernetes

滾動升級

滾動升級是Kubernetes中最典型的服務升級方案,主要思路是一邊增加新版本應用的例項數,一邊減少舊版本應用的例項數,直到新版本的例項數達到預期,舊版本的例項數減少為0,滾動升級結束。在整個升級過程中,服務一直處於可用狀態。並且可以在任意時刻回滾到舊版本。

雲原生技術系列-容器叢集排程編排系統Kubernetes

架構設計

Kubernetes 是用來管理容器叢集的,下圖是k8s叢集的系統架構圖,從中我們可以看到整個系統通常由一個Master節點和多個Node節點組成。

Master 作為管理者,包括 APIServer,Scheduler,Controller Manager。

Node作為副本部署的載體,包含多個 Pod,每個 Pod 又包含多個容器(container)。

下面我們再來詳細瞭解下Master節點和Node 節點中的核心元件:

kubectl元件

-命令列客戶端工具,作為控制整個k8s叢集的操作入口。

master節點元件

master節點是主叢集中的大腦,負責處理外部的api請求,分配排程任務以及管理容器的副本數等

kube-scheduler

:負責資源的排程,按照預定的排程策略將Pod排程到相應的機器上

kube-apiserver

:提供了資源(Node,Pod,RC,Service等)操作的唯一入口,以REST API服務形式提供介面,作為整個系統的控制入口。並提供認證、授權、訪問控制、API註冊和發現等機制(kubectl client 連線該server)

kube-controller-manager

:負責維護叢集的狀態,比如故障檢測、自動擴充套件、滾動更新等

Node節點元件

node節點負責幹活,執行master節點指派的相關任務

kubelet

:控制容器執行,負責啟動停止和容器;執行在每個計算節點上,作為agent,接收分配該節點的pods任務及管理容器,週期性獲取容器狀態,反饋給kube-apiserver

kube-proxy

:負責根據service生成網路規則,生成路由規則。

Docker Engine

:Docker容器引擎。

etcd叢集

etcd是kubernetes叢集用來儲存叢集相關資料的資料倉庫,儲存了整個叢集的狀態。kubectl對叢集的配置資訊以及叢集執行時的狀態資訊的持久化儲存都是透過Etcd來完成的。

DNS

一個可選的DNS服務,用於為每個serivce物件建立DNS記錄,這樣所有的pod就可以透過DNS訪問服務。

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

上圖是k8s叢集的系統架構及元件功能圖,下面我們將逐個解析上文提到的各個核心元件。

API Server

這裡,我們在重點介紹一下Master節點中的APIServer元件,它是。APIServer 的架構從上到下分為四層:

API 層

:主要以 REST 方式提供各種 API 介面,針對 Kubernetes 資源物件的 CRUD 和 Watch 等主要 API,還有健康檢查、UI、日誌、效能指標等運維監控相關的 API。

訪問控制層

:負責身份鑑權,核准使用者對資源的訪問許可權,設定訪問邏輯(Admission Control)。

登錄檔層

:選擇要訪問的資源物件。PS:Kubernetes 把所有資源物件都儲存在登錄檔(Registry)中,例如:Pod,Service,Deployment 等等。

etcd 資料庫

:儲存建立副本的資訊。用來持久化 Kubernetes 資源物件的 Key-Value 資料庫。

雲原生技術系列-容器叢集排程編排系統Kubernetes

執行原理

我們來結合上面的互動圖,來看一下k8s執行的原理:

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

使用者透過 kubectl 給 Master 中的 APIServer 下部署命令。命令主體是以“。yaml”結尾的配置檔案,包含副本的型別,副本個數,名稱,埠,模版等資訊。

APIServer 接受到請求以後,會分別進行以下操作:許可權驗證(包括特殊控制),取出需要建立的資源,儲存副本資訊到etcd。

APIServer 和 Controller Manager,Scheduler 以及 kubelete 之間透過 List-Watch 方式通訊(事件傳送與監聽)。

Controller Manager 透過 etcd 獲取需要建立資源的副本數,交由 Scheduler 進行策略分析。

最後 kubelet 負責最終的 Pod 建立和容器載入。部署好容器以後,透過 Service 進行訪問,透過 cAdvisor 監控資源。

模型物件

有印象的讀者應該還記得,上文中曾經提到“使用者透過 kubectl 給 Master 中的 APIServer 下部署命令。命令主體是以“。yaml”結尾的配置檔案,包含副本的型別,副本個數,名稱,埠,模版等資訊。”。

我們在前面瞭解了k8s的核心概念、架構設計、執行原理,在實際使用過程中我們需要直接操作的還是各種各樣的“。yaml”的配置檔案,那麼怎麼配就成了必須要掌握的要點了。再具體實踐怎麼配之前,我們先了解一下模型物件,它是k8s對於各種配置檔案的分類,模型物件決定了配置檔案的骨架,把握它我們才能更好地再一堆複雜的配置中找到關鍵。

雲原生技術系列-容器叢集排程編排系統Kubernetes

那到底都有哪些模型物件?他們之間都有什麼關係呢?透過上圖我們做了一個詳細的總結。

kubernetes物件:

一種宣告式的意圖的記錄,一般使用yaml檔案描述物件

kubernetes叢集使用kubernetes物件來表示叢集狀態

透過API/kubectl管理kubernetes物件

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

透過多層次、多維度的標籤定義,一個對應現實管理結構的k8s物件關係就建立起來了,不同角色的人員可以在同一個k8s叢集上完成不同的工作而不會相互影響。

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

整個k8s叢集都是以pod為中心,其他的各種物件也基本上是為pod提供各種功能服務的。

Controller控制器用於維護pod的狀態,配置儲存物件則為pod注入持久化資料,並且為pod持久化pod執行時產生的產生的資料,service將pod聚合在一起,統一對外提供服務。

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

Pod物件是不穩定了,ip+port的結合體不能保證穩定的存在,那麼如何保證使用者能夠穩定地訪問到我們的服務呢?這個時候就出現了一個抽象的service的概念:

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

雲原生技術系列-容器叢集排程編排系統Kubernetes

全文小結

雲原生技術系列-容器叢集排程編排系統Kubernetes