【51CTO.com原創(chuàng)稿件】互聯(lián)網(wǎng)技術(shù)飛速發(fā)展的今天,為了承載請(qǐng)求的高并發(fā)和業(yè)務(wù)的多樣性,微服務(wù)的架構(gòu)成了各個(gè)公司的標(biāo)配。11圖片來(lái)自 Pexels 每個(gè)微服務(wù)通過(guò) Docker 進(jìn)行發(fā)布,隨著業(yè)務(wù)的發(fā)展,系統(tǒng)中遍布著各種各樣的容器。于是,容器的資源調(diào)度,部署運(yùn)行,擴(kuò)容縮容就是我們要面臨的問(wèn)題。 基于 Kubernetes 作為容器集群的管理平臺(tái)被廣泛應(yīng)用,今天我們一起來(lái)看看 Kubernetes 的架構(gòu)中有那些常用的組件以及運(yùn)行原理。 Kubernetes 架構(gòu)概述 Kubernetes 是用來(lái)管理容器集群的平臺(tái)。既然是管理集群,那么就存在被管理節(jié)點(diǎn),針對(duì)每個(gè) Kubernetes 集群都由一個(gè) Master 負(fù)責(zé)管理和控制集群節(jié)點(diǎn)。 我們通過(guò) Master 對(duì)每個(gè)節(jié)點(diǎn) Node 發(fā)送命令。簡(jiǎn)單來(lái)說(shuō),Master 就是管理者,Node 就是被管理者。 Node 可以是一臺(tái)機(jī)器或者一臺(tái)虛擬機(jī)。在 Node 上面可以運(yùn)行多個(gè) Pod,Pod 是 Kubernetes 管理的最小單位,同時(shí)每個(gè) Pod 可以包含多個(gè)容器(Docker)。 通過(guò)下面的 Kubernetes 架構(gòu)簡(jiǎn)圖可以看到 Master 和 Node 之間的關(guān)系: Kubernetes 架構(gòu)簡(jiǎn)圖 通常我們都是通過(guò) kubectl 對(duì) Kubernetes 下命令的,它通過(guò) APIServer 去調(diào)用各個(gè)進(jìn)程來(lái)完成對(duì) Node 的部署和控制。 APIServer 的核心功能是對(duì)核心對(duì)象(例如:Pod,Service,RC)的增刪改查操作,同時(shí)也是集群內(nèi)模塊之間數(shù)據(jù)交換的樞紐。 它包括了常用的 API,訪問(wèn)(權(quán)限)控制,注冊(cè),信息存儲(chǔ)(etcd)等功能。在它的下面我們可以看到 Scheduler,它將待調(diào)度的 Pod 綁定到 Node 上,并將綁定信息寫(xiě)入 etcd 中。 etcd 包含在 APIServer 中,用來(lái)存儲(chǔ)資源信息。接下來(lái)就是 Controller Manager 了,如果說(shuō) Kubernetes 是一個(gè)自動(dòng)化運(yùn)行的系統(tǒng),那么就需要有一套管理規(guī)則來(lái)控制這套系統(tǒng)。 Controller Manager 就是這個(gè)管理者,或者說(shuō)是控制者。它包括 8 個(gè) Controller,分別對(duì)應(yīng)著副本,節(jié)點(diǎn),資源,命名空間,服務(wù)等等。 緊接著,Scheduler 會(huì)把 Pod 調(diào)度到 Node 上,調(diào)度完以后就由 kubelet 來(lái)管理 Node 了。 kubelet 用于處理 Master 下發(fā)到 Node 的任務(wù)(即 Scheduler 的調(diào)度任務(wù)),同時(shí)管理 Pod 及 Pod 中的容器。 在完成資源調(diào)度以后,kubelet 進(jìn)程也會(huì)在 APIServer 上注冊(cè) Node 信息,定期向 Master 匯報(bào) Node 信息,并通過(guò) cAdvisor 監(jiān)控容器和節(jié)點(diǎn)資源。 由于,微服務(wù)的部署都是分布式的,所以對(duì)應(yīng)的 Pod 以及容器的部署也是。為了能夠方便地找到這些 Pod 或者容器,引入了 Service(kube-proxy)進(jìn)程,它來(lái)負(fù)責(zé)反向代理和負(fù)載均衡的實(shí)施。 上面就是 Kubernetes 架構(gòu)的簡(jiǎn)易說(shuō)明,涉及到了一些核心概念以及簡(jiǎn)單的信息流動(dòng)。 將一些功能收錄到了 APIServer 中,這個(gè)簡(jiǎn)圖比官網(wǎng)的圖顯得簡(jiǎn)單一些,主要是方便大家記憶。 后面我們會(huì)用一個(gè)簡(jiǎn)單的例子,帶大家把 Kubernetes 的概念的由來(lái)做深入的了解。 從一個(gè)例子開(kāi)始 假設(shè)使用 Kubernetes 部署 Tomcat 和 MySQL 服務(wù)到兩個(gè) Node 上面。其中 Tomcat 服務(wù)生成兩個(gè)實(shí)例也就是生成兩個(gè) Pod,用來(lái)對(duì)其做水平擴(kuò)展。 MySQL 只部署一個(gè)實(shí)例,也就是一個(gè) Pod??梢酝ㄟ^(guò)外網(wǎng)訪問(wèn) Tomcat,而 Tomcat 可以在內(nèi)網(wǎng)訪問(wèn) MySQL。 例子示意圖 這里我們假設(shè) Kubernetes 和 Docker 的安裝都已經(jīng)完成,并且鏡像文件都已經(jīng)準(zhǔn)備好了。重點(diǎn)看 Kubernetes 如何部署和管理容器。 kubectl 和 APIServer 既然我們要完成上面的例子,接下來(lái)就要部署兩個(gè)應(yīng)用。 首先,根據(jù)要部署的應(yīng)用建立 Replication Controller(RC)。RC 是用來(lái)聲明應(yīng)用副本的個(gè)數(shù),也就是 Pod 的個(gè)數(shù)。 按照上面的例子,Tomcat 的 RC 就是 2,MySQL 的 RC 就是 1。 由于 kubectl 作為用戶接口向 Kubernetes 下發(fā)指令,那么指令是通過(guò)“.yaml”的配置文件編寫(xiě)的。 定義 mysql-rc.yaml 的配置文件來(lái)描述 MySQL 的 RC:
從上面的配置文件可以看出,需要對(duì)這個(gè) RC 定義一個(gè)名字,以及期望的副本數(shù),以及容器中的鏡像文件。然后通過(guò) kubectl 作為客戶端的 cli 工具,執(zhí)行這個(gè)配置文件。 通過(guò) kubectl 執(zhí)行 RC 配置文件 執(zhí)行了上面的命令以后,Kubernetes 會(huì)幫助我們部署副本 MySQL 的 Pod 到 Node。 此時(shí)先不著急看結(jié)果,回到最開(kāi)始的架構(gòu)圖,可以看到 kubectl 會(huì)向 Master 中的 APIServer 發(fā)起命令,看看 APIServer 的結(jié)構(gòu)和信息的傳遞吧。 Kubernetes API Server 通過(guò)一個(gè)名為 kube-apiserver 的進(jìn)程提供服務(wù),該進(jìn)程運(yùn)行在 Master 上。 可以通過(guò) Master 的 8080 端口訪問(wèn) kube-apiserver 進(jìn)程,它提供 REST 服務(wù)。 因此可以通過(guò)命令行工具 kubectl 來(lái)與 Kubernetes APIServer 交互,它們之間的接口是 RESTful API。 APIServer 的架構(gòu)從上到下分為四層:
APIServer 分層架構(gòu)圖 當(dāng) kubectl 用 Create 命令建立 Pod 時(shí),是通過(guò) APIServer 中的 API 層調(diào)用對(duì)應(yīng)的 RESTAPI 方法。 之后會(huì)進(jìn)入權(quán)限控制層,通過(guò) Authentication 獲取調(diào)用者身份,Authorization 獲取權(quán)限信息。 AdmissionControl 中可配置權(quán)限認(rèn)證插件,通過(guò)插件來(lái)檢查請(qǐng)求約束。例如:?jiǎn)?dòng)容器之前需要下載鏡像,或者檢查具備某命名空間的資源。 還記得 mysql-rc.yaml 中配置需要生成的 Pod 的個(gè)數(shù)為 1。到了 Registry 層會(huì)從 CoreRegistry 資源中取出 1 個(gè) Pod 作為要?jiǎng)?chuàng)建的 Kubernetes 資源對(duì)象。 然后將 Node,Pod 和 Container 信息保存在 etcd 中去。這里的 etcd 可以是一個(gè)集群,由于里面保存集群中各個(gè) Node/Pod/Container 的信息,所以必要時(shí)需要備份,或者保證其可靠性。 Controller Manager,Scheduler 和 kubelet 前面通過(guò) kubectl 根據(jù)配置文件,向 APIServer 發(fā)送命令,在 Node 上面建立 Pod 和 Container。 在 APIServer,經(jīng)過(guò) API 調(diào)用,權(quán)限控制,調(diào)用資源和存儲(chǔ)資源的過(guò)程。實(shí)際上還沒(méi)有真正開(kāi)始部署應(yīng)用。 這里需要 Controller Manager,Scheduler 和 kubelet 的協(xié)助才能完成整個(gè)部署過(guò)程。 在介紹他們協(xié)同工作之前,要介紹一下在 Kubernetes 中的監(jiān)聽(tīng)接口。從上面的操作知道,所有部署的信息都會(huì)寫(xiě)到 etcd 中保存。 實(shí)際上 etcd 在存儲(chǔ)部署信息的時(shí)候,會(huì)發(fā)送 Create 事件給 APIServer,而 APIServer 會(huì)通過(guò)監(jiān)聽(tīng)(Watch)etcd 發(fā)過(guò)來(lái)的事件。其他組件也會(huì)監(jiān)聽(tīng)(Watch)APIServer 發(fā)出來(lái)的事件。 Kubernetes 就是用這種 List-Watch 的機(jī)制保持?jǐn)?shù)據(jù)同步的,如上圖:
上面的例子 MySQL 應(yīng)用是 1 個(gè)副本,Tomcat 應(yīng)用是兩個(gè)副本。一旦副本數(shù)量少于 RC 中定義的數(shù)量,Replication Controller 會(huì)自動(dòng)創(chuàng)建副本??傊潜WC副本數(shù)量的 Controller。PS:擴(kuò)容縮容的擔(dān)當(dāng)。
換句話說(shuō),Scheduler 的作用是將待調(diào)度的 Pod 按照調(diào)度算法和策略綁定到集群中 Node 上,并將綁定信息寫(xiě)入 etcd 中。
為什么 kubelete 還要一直監(jiān)聽(tīng)呢?原因很簡(jiǎn)單,假設(shè)這個(gè)時(shí)候 kubectl 發(fā)命令,需要把原來(lái)的 MySQL 的 1 個(gè) RC 副本擴(kuò)充成 2 個(gè)。那么這個(gè)流程又會(huì)觸發(fā)一遍。 作為 Node 的管理者 kubelet 也會(huì)根據(jù)最新的 Pod 的部署情況調(diào)整 Node 端的資源。 又或者 MySQL 應(yīng)用的 RC 個(gè)數(shù)沒(méi)有發(fā)生變化,但是其中的鏡像文件升級(jí)了,kubelet 也會(huì)自動(dòng)獲取最新的鏡像文件并且加載。 通過(guò)上面 List-Watch 的介紹大家發(fā)現(xiàn)了,除了之前引入的 kubectl 和 APIServer 以外又引入了 Controller Manager,Scheduler 和 kubelet。 這里給大家介紹一下他們的作用和原理: 聚焦 Scheduler,Controller Manager,kubelet Controller Manager Kubernetes 需要管理集群中的不同資源,所以針對(duì)不同的資源要建立不同的 Controller。 每個(gè) Controller 通過(guò)監(jiān)聽(tīng)機(jī)制獲取 APIServer 中的事件(消息),它們通過(guò) API Server 提供的(List-Watch)接口監(jiān)控集群中的資源,并且調(diào)整資源的狀態(tài)。 可以把它想象成一個(gè)盡職的管理者,隨時(shí)管理和調(diào)整資源。比如 MySQL 所在的 Node 意外宕機(jī)了,Controller Manager 中的 Node Controller 會(huì)及時(shí)發(fā)現(xiàn)故障,并執(zhí)行修復(fù)流程。 在部署了成百上千微服務(wù)的系統(tǒng)中,這個(gè)功能極大地協(xié)助了運(yùn)維人員。從此可以看出,Controller Manager 是 Kubernetes 資源的管理者,是運(yùn)維自動(dòng)化的核心。 它分為 8 個(gè) Controller,上面我們介紹了 Replication Controller,這里我們把其他幾個(gè)都列出來(lái),就不展開(kāi)描述了。 Controller Manager 中不同的 Controller 負(fù)責(zé)對(duì)不同資源的監(jiān)控和管理 Scheduler 與 kubelet Scheduler 的作用是,將待調(diào)度的 Pod 按照算法和策略綁定到 Node 上,同時(shí)將信息保存在 etcd 中。 如果把 Scheduler 比作調(diào)度室,那么這三件事就是它需要關(guān)注的,待調(diào)度的 Pod、可用的 Node,調(diào)度算法和策略。 簡(jiǎn)單地說(shuō),就是通過(guò)調(diào)度算法/策略把 Pod 放到合適的 Node 中去。此時(shí) Node 上的 kubelet 通過(guò) APIServer 監(jiān)聽(tīng)到 Scheduler 產(chǎn)生的 Pod 綁定事件,然后通過(guò) Pod 的描述裝載鏡像文件,并且啟動(dòng)容器。 也就是說(shuō) Scheduler 負(fù)責(zé)思考,Pod 放在哪個(gè) Node,然后將決策告訴 kubelet,kubelet 完成 Pod 在 Node 的加載工作。 說(shuō)白了,Scheduler 是 boss,kubelet 是干活的工人,他們都通過(guò) APIServer 進(jìn)行信息交換。 Scheduler 與 kubelet 協(xié)同工作圖 Service 和 kubelet 經(jīng)歷上面一系列的過(guò)程,終于將 Pod 和容器部署到 Node 上了。 MySQL 部署成功 作為部署在 Kubernetes 中,Pod 如何訪問(wèn)其他的 Pod 呢?答案是通過(guò) Kubernetes 的 Service 機(jī)制。 在 Kubernetes 中的 Service 定義了一個(gè)服務(wù)的訪問(wèn)入口地址(IP+Port)。Pod 中的應(yīng)用通過(guò)這個(gè)地址訪問(wèn)一個(gè)或者一組 Pod 副本。 Service 與后端 Pod 副本集群之間是通過(guò) Label Selector 來(lái)實(shí)現(xiàn)連接的。Service 所訪問(wèn)的這一組 Pod 都會(huì)有同樣的 Label,通過(guò)這樣的方法知道這些 Pod 屬于同一個(gè)組。 Pod 通過(guò) Service 訪問(wèn)其他 Pod 寫(xiě) MySQL 服務(wù)的配置文件(mysql-svc.yaml)如下:
按照慣例運(yùn)行 kubectl,創(chuàng)建 Service: 再用 getsvc 命令檢查 Service 信息: 這里的 Cluster-IP 169.169.253.143 是由 Kubernetes 自動(dòng)分配的。當(dāng)一個(gè) Pod 需要訪問(wèn)其他的 Pod 的時(shí)候就需要通過(guò) Service 的 Cluster-IP 和 Port。 也就是說(shuō) Cluster-IP 和 Port 是 Kubernetes 集群的內(nèi)部地址,是提供給集群內(nèi)的 Pod 之間訪問(wèn)使用的,外部系統(tǒng)是無(wú)法通過(guò)這個(gè) Cluster-IP 來(lái)訪問(wèn) Kubernetes 中的應(yīng)用的。 上面提到的 Service 只是一個(gè)概念,而真正將 Service 落實(shí)的是 kube-proxy。 只有理解了 kube-proxy 的原理和機(jī)制,我們才能真正理解 Service 背后的實(shí)現(xiàn)邏輯。 在 Kubernetes 集群的每個(gè) Node 上都會(huì)運(yùn)行一個(gè) kube-proxy 服務(wù)進(jìn)程,我們可以把這個(gè)進(jìn)程看作 Service 的負(fù)載均衡器,其核心功能是將到 Service 的請(qǐng)求轉(zhuǎn)發(fā)到后端的多個(gè) Pod 上。 此外,Service 的 Cluster-IP 與 NodePort 是 kube-proxy 服務(wù)通過(guò) iptables 的 NAT 轉(zhuǎn)換實(shí)現(xiàn)的。kube-proxy 在運(yùn)行過(guò)程中動(dòng)態(tài)創(chuàng)建與 Service 相關(guān)的 iptables 規(guī)則。 由于 iptables 機(jī)制針對(duì)的是本地的 kube-proxy 端口,所以在每個(gè) Node 上都要運(yùn)行 kube-proxy 組件。 因此在 Kubernetes 集群內(nèi)部,可以在任意 Node 上發(fā)起對(duì) Service 的訪問(wèn)請(qǐng)求。 集群內(nèi)部通過(guò) kube-proxy(Service)訪問(wèn)其他 Pod 正如 MySQL 服務(wù),可以被 Kubernetes 內(nèi)部的 Tomcat 調(diào)用,那么 Tomcat 如何被 Kubernetes 外部調(diào)用? 先生成配置文件,myweb-rc.yaml 看看:
在 kubectl 中使用 Create 建立 myweb 副本。 副本創(chuàng)建完畢以后,創(chuàng)建對(duì)應(yīng)的服務(wù)配置文件 myweb-svc.yaml。
同樣在 kubectl 中運(yùn)行 Create 命令,建立 Service 資源。 從上面的配置文件可以看出,Tomcat 的 Service 中多了一個(gè) nodePort 的配置,值為 30001。 也就是說(shuō)外網(wǎng)通過(guò) 30001 這個(gè)端口加上 NodeIP 就可以訪問(wèn) Tomcat 了。 運(yùn)行命令之后,得到一個(gè)提示,大致意思是“如果你要將服務(wù)暴露給外網(wǎng)使用,你需要設(shè)置防火墻規(guī)則讓 30001 端口能夠通行?!?/p> 由于 Cluster-IP 是一個(gè)虛擬的 IP,僅供 Kubernetes 內(nèi)部的 Pod 之間的通信。 Node 作為一個(gè)物理節(jié)點(diǎn),因此需要使用 Node-IP 和 nodePort 的組合來(lái)從 Kubernetes 外面訪問(wèn)內(nèi)部的應(yīng)用。 如果按照上面的配置,部署了兩個(gè) Tomcat 應(yīng)用,當(dāng)外網(wǎng)訪問(wèn)時(shí)選擇那個(gè) Pod 呢?這里需要通過(guò) Kubernetes 之外的負(fù)載均衡器來(lái)實(shí)現(xiàn)的。 Kubernetes 之外的負(fù)載均衡器 可以通過(guò) Kubernetes 的 LoadBlancerService 組件來(lái)協(xié)助實(shí)現(xiàn)。通過(guò)云平臺(tái)申請(qǐng)創(chuàng)建負(fù)載均衡器,向外暴露服務(wù)。 目前 LoadBlancerService 組件支持的云平臺(tái)比較完善,比如國(guó)外的 GCE、DigitalOcean,國(guó)內(nèi)的阿里云,私有云 OpenStack 等等。 從用法上只要把 Service 的 type=NodePort 改為 type=LoadBalancer,Kubernetes 就會(huì)自動(dòng)創(chuàng)建一個(gè)對(duì)應(yīng)的 Load Balancer 實(shí)例并返回它的 IP 地址供外部客戶端使用。 至此,MySQL(RC 1)和 Tomcat(RC 2)已經(jīng)在 Kubernetes 部署了。并在 Kubernetes 內(nèi)部 Pod 之間是可以互相訪問(wèn)的,在外網(wǎng)也可以訪問(wèn)到 Kubernetes 內(nèi)部的 Pod。 Pod 在 Kubernetes 內(nèi)互相訪問(wèn),外網(wǎng)訪問(wèn) Pod 另外,作為資源監(jiān)控 Kubernetes 在每個(gè) Node 和容器上都運(yùn)行了 cAdvisor。它是用來(lái)分析資源使用率和性能的工具,支持 Docker 容器。 kubelet 通過(guò) cAdvisor 獲取其所在 Node 及容器(Docker)的數(shù)據(jù)。cAdvisor 自動(dòng)采集 CPU、內(nèi)存、文件系統(tǒng)和網(wǎng)絡(luò)使用的統(tǒng)計(jì)信息。 kubelet 作為 Node 的管理者,把 cAdvisor 采集上來(lái)的數(shù)據(jù)通過(guò) RESTAPI 的形式暴露給 Kubernetes 的其他資源,讓他們知道 Node/Pod 中的資源使用情況。 總結(jié) 由于微服務(wù)的迅猛發(fā)展,Kubernetes 作為微服務(wù)治理平臺(tái)被廣泛應(yīng)用。由于其發(fā)展時(shí)間長(zhǎng),包含服務(wù)功能多我們無(wú)法一一列出。 因此,從一個(gè)簡(jiǎn)單的創(chuàng)建應(yīng)用副本的例子入手,介紹了各個(gè)重要組件的概念和基本原理。 Kubernetes 是用來(lái)管理容器集群的,Master 作為管理者,包括 APIServer,Scheduler,Controller Manager。 Node作為副本部署的載體,包含多個(gè) Pod,每個(gè) Pod 又包含多個(gè)容器(container)。用戶通過(guò) kubectl 給 Master 中的 APIServer 下部署命令。 命令主體是以“.yaml”結(jié)尾的配置文件,包含副本的類型,副本個(gè)數(shù),名稱,端口,模版等信息。 APIServer 接受到請(qǐng)求以后,會(huì)分別進(jìn)行以下操作:權(quán)限驗(yàn)證(包括特殊控制),取出需要?jiǎng)?chuàng)建的資源,保存副本信息到etcd。 APIServer 和 Controller Manager,Scheduler 以及 kubelete 之間通過(guò) List-Watch 方式通信(事件發(fā)送與監(jiān)聽(tīng))。 Controller Manager 通過(guò) etcd 獲取需要?jiǎng)?chuàng)建資源的副本數(shù),交由 Scheduler 進(jìn)行策略分析。 最后 kubelet 負(fù)責(zé)最終的 Pod 創(chuàng)建和容器加載。部署好容器以后,通過(guò) Service 進(jìn)行訪問(wèn),通過(guò) cAdvisor 監(jiān)控資源。 作者:崔皓 簡(jiǎn)介:十六年開(kāi)發(fā)和架構(gòu)經(jīng)驗(yàn),曾擔(dān)任過(guò)惠普武漢交付中心技術(shù)專家,需求分析師,項(xiàng)目經(jīng)理,后在創(chuàng)業(yè)公司擔(dān)任技術(shù)/產(chǎn)品經(jīng)理。善于學(xué)習(xí),樂(lè)于分享。目前專注于技術(shù)架構(gòu)與研發(fā)管理。 |
|
來(lái)自: 測(cè)試333 > 《我的圖書(shū)館》