敲黑板:關(guān)于 Kubernetes 架構(gòu),運(yùn)維同仁一定要懂這些
打開(kāi)這篇文章的同學(xué),想必對(duì) Docker 都不會(huì)陌生。Docker 是一種虛擬容器技術(shù),它上手比較簡(jiǎn)單,只需在宿主機(jī)上起一個(gè) Docker Engine,然后就能愉快的玩耍了,如:拉鏡像、起容器、掛載數(shù)據(jù)、映射端口等等。相對(duì)于 Kubernetes(K8S)的上手,可謂簡(jiǎn)單很多。
那么 K8S 是什么,又為什么上手難度大?K8S 是一個(gè)基于容器技術(shù)的分布式集群管理系統(tǒng),是谷歌幾十年來(lái)大規(guī)模應(yīng)用容器技術(shù)的經(jīng)驗(yàn)積累和升華的一個(gè)重要成果。所以為了能夠支持大規(guī)模的集群管理,它承載了很多的組件,而且分布式本身的復(fù)雜度就很高。又因?yàn)? K8S 是谷歌出品的,依賴(lài)了很多谷歌自己的鏡像,所以對(duì)于國(guó)內(nèi)的同學(xué)環(huán)境搭建的難度又增加了一層。
下面,我們帶著問(wèn)題,一步步來(lái)看 K8S 中到底有哪些東西?
首先,既然是個(gè)分布式系統(tǒng),那勢(shì)必有多個(gè) Node 節(jié)點(diǎn)(物理主機(jī)或虛擬機(jī)),它們共同組成一個(gè)分布式集群,并且這些節(jié)點(diǎn)中會(huì)有一個(gè) Master 節(jié)點(diǎn),由它來(lái)統(tǒng)一管理 Node 節(jié)點(diǎn)。
如圖所示:
問(wèn)題一:主節(jié)點(diǎn)和工作節(jié)點(diǎn)是如何通信的呢?
首先,Master 節(jié)點(diǎn)啟動(dòng)時(shí),會(huì)運(yùn)行一個(gè) kube-apiserver 進(jìn)程,它提供了集群管理的 API 接口,是集群內(nèi)各個(gè)功能模塊之間數(shù)據(jù)交互和通信的中心樞紐,并且它頁(yè)提供了完備的集群安全機(jī)制(后面還會(huì)講到)。
在 Node 節(jié)點(diǎn)上,使用 K8S 中的 kubelet 組件,在每個(gè) Node 節(jié)點(diǎn)上都會(huì)運(yùn)行一個(gè) kubelet 進(jìn)程,它負(fù)責(zé)向 Master 匯報(bào)自身節(jié)點(diǎn)的運(yùn)行情況,如 Node 節(jié)點(diǎn)的注冊(cè)、終止、定時(shí)上報(bào)健康狀況等,以及接收 Master 發(fā)出的命令,創(chuàng)建相應(yīng) Pod。
在 K8S 中,Pod 是最基本的操作單元,它與 docker 的容器有略微的不同,因?yàn)?Pod 可能包含一個(gè)或多個(gè)容器(可以是 docker 容器),這些內(nèi)部的容器是共享網(wǎng)絡(luò)資源的,即可以通過(guò) localhost 進(jìn)行相互訪(fǎng)問(wèn)。
關(guān)于 Pod 內(nèi)是如何做到網(wǎng)絡(luò)共享的,每個(gè) Pod 啟動(dòng),內(nèi)部都會(huì)啟動(dòng)一個(gè) pause 容器(google的一個(gè)鏡像),它使用默認(rèn)的網(wǎng)絡(luò)模式,而其他容器的網(wǎng)絡(luò)都設(shè)置給它,以此來(lái)完成網(wǎng)絡(luò)的共享問(wèn)題。
如圖所示:
問(wèn)題二:Master 是如何將 Pod 調(diào)度到指定的 Node 上的?
該工作由 kube-scheduler 來(lái)完成,整個(gè)調(diào)度過(guò)程通過(guò)執(zhí)行一些列復(fù)雜的算法最終為每個(gè) Pod 計(jì)算出一個(gè)最佳的目標(biāo) Node,該過(guò)程由 kube-scheduler 進(jìn)程自動(dòng)完成。常見(jiàn)的有輪詢(xún)調(diào)度(RR)。當(dāng)然也有可能,我們需要將 Pod 調(diào)度到一個(gè)指定的 Node 上,我們可以通過(guò)節(jié)點(diǎn)的標(biāo)簽(Label)和 Pod 的 nodeSelector 屬性的相互匹配,來(lái)達(dá)到指定的效果。
如圖所示:
關(guān)于標(biāo)簽(Label)與選擇器(Selector)的概念,后面會(huì)進(jìn)一步介紹
問(wèn)題三:各節(jié)點(diǎn)、Pod 的信息都是統(tǒng)一維護(hù)在哪里的,由誰(shuí)來(lái)維護(hù)?
從上面的 Pod 調(diào)度的角度看,我們得有一個(gè)存儲(chǔ)中心,用來(lái)存儲(chǔ)各節(jié)點(diǎn)資源使用情況、健康狀態(tài)、以及各 Pod 的基本信息等,這樣 Pod 的調(diào)度來(lái)能正常進(jìn)行。
在 K8S 中,采用 etcd 組件 作為一個(gè)高可用強(qiáng)一致性的存儲(chǔ)倉(cāng)庫(kù),該組件可以?xún)?nèi)置在 K8S 中,也可以外部搭建供 K8S 使用。
集群上的所有配置信息都存儲(chǔ)在了 etcd,為了考慮各個(gè)組件的相對(duì)獨(dú)立,以及整體的維護(hù)性,對(duì)于這些存儲(chǔ)數(shù)據(jù)的增、刪、改、查,統(tǒng)一由 kube-apiserver 來(lái)進(jìn)行調(diào)用,apiserver 也提供了 REST 的支持,不僅對(duì)各個(gè)內(nèi)部組件提供服務(wù)外,還對(duì)集群外部用戶(hù)暴露服務(wù)。
外部用戶(hù)可以通過(guò) REST 接口,或者 kubectl 命令行工具進(jìn)行集群管理,其內(nèi)在都是與 apiserver 進(jìn)行通信。
如圖所示:
問(wèn)題四:外部用戶(hù)如何訪(fǎng)問(wèn)集群內(nèi)運(yùn)行的 Pod ?
前面講了外部用戶(hù)如何管理 K8S,而我們更關(guān)心的是內(nèi)部運(yùn)行的 Pod 如何對(duì)外訪(fǎng)問(wèn)。使用過(guò)Docker 的同學(xué)應(yīng)該知道,如果使用 bridge 模式,在容器創(chuàng)建時(shí),都會(huì)分配一個(gè)虛擬 IP,該 IP 外部是沒(méi)法訪(fǎng)問(wèn)到的,我們需要做一層端口映射,將容器內(nèi)端口與宿主機(jī)端口進(jìn)行映射綁定,這樣外部通過(guò)訪(fǎng)問(wèn)宿主機(jī)的指定端口,就可以訪(fǎng)問(wèn)到內(nèi)部容器端口了。
那么,K8S 的外部訪(fǎng)問(wèn)是否也是這樣實(shí)現(xiàn)的?答案是否定的,K8S 中情況要復(fù)雜一些。因?yàn)樯厦嬷v的 Docker 是單機(jī)模式下的,而且一個(gè)容器對(duì)外就暴露一個(gè)服務(wù)。在分布式集群下,一個(gè)服務(wù)往往由多個(gè) Application 提供,用來(lái)分擔(dān)訪(fǎng)問(wèn)壓力,而且這些 Application 可能會(huì)分布在多個(gè)節(jié)點(diǎn)上,這樣又涉及到了跨主機(jī)的通信。
這里,K8S 引入了 Service 的概念,將多個(gè)相同的 Pod 包裝成一個(gè)完整的 service 對(duì)外提供服務(wù),至于獲取到這些相同的 Pod,每個(gè) Pod 啟動(dòng)時(shí)都會(huì)設(shè)置 labels 屬性,在 Service 中我們通過(guò)選擇器 Selector,選擇具有相同 Name 標(biāo)簽屬性的 Pod,作為整體服務(wù),并將服務(wù)信息通過(guò) Apiserver 存入 etcd 中,該工作由 Service Controller 來(lái)完成。同時(shí),每個(gè)節(jié)點(diǎn)上會(huì)啟動(dòng)一個(gè) kube-proxy 進(jìn)程,由它來(lái)負(fù)責(zé)服務(wù)地址到 Pod 地址的代理以及負(fù)載均衡等工作。
如圖所示:
問(wèn)題五:Pod 如何動(dòng)態(tài)擴(kuò)容和縮放?
既然知道了服務(wù)是由 Pod 組成的,那么服務(wù)的擴(kuò)容也就意味著 Pod 的擴(kuò)容。通俗點(diǎn)講,就是在需要時(shí)將 Pod 復(fù)制多份,在不需要后,將 Pod 縮減至指定份數(shù)。K8S 中通過(guò) Replication Controller 來(lái)進(jìn)行管理,為每個(gè) Pod 設(shè)置一個(gè)期望的副本數(shù),當(dāng)實(shí)際副本數(shù)與期望不符時(shí),就動(dòng)態(tài)的進(jìn)行數(shù)量調(diào)整,以達(dá)到期望值。期望數(shù)值可以由我們手動(dòng)更新,或自動(dòng)擴(kuò)容代理來(lái)完成。
如圖所示:
問(wèn)題六:各個(gè)組件之間是如何相互協(xié)作的?
最后,講一下 kube-controller-manager 這個(gè)進(jìn)程的作用。我們知道了 ectd 是作為集群數(shù)據(jù)的存儲(chǔ)中心, apiserver 是管理數(shù)據(jù)中心,作為其他進(jìn)程與數(shù)據(jù)中心通信的橋梁。而 Service Controller、Replication Controller 這些統(tǒng)一交由 kube-controller-manager 來(lái)管理,kube-controller-manager 作為一個(gè)守護(hù)進(jìn)程,每個(gè) Controller 都是一個(gè)控制循環(huán),通過(guò) apiserver 監(jiān)視集群的共享狀態(tài),并嘗試將實(shí)際狀態(tài)與期望不符的進(jìn)行改變。關(guān)于 Controller,manager 中還包含了 Node 節(jié)點(diǎn)控制器(Node Controller)、資源配額管控制器(ResourceQuota Controller)、命名空間控制器(Namespace Controller)等。
如圖所示:
總結(jié)
本文通過(guò)問(wèn)答的方式,沒(méi)有涉及任何深入的實(shí)現(xiàn)細(xì)節(jié),從整體的角度,概念性的介紹了 K8S 中涉及的基本概念,其中使用相關(guān)的包括有:
Node
Pod
Label
Selector
Replication Controller
Service Controller
ResourceQuota Controller
Namespace Controller
Node Controller
以及運(yùn)行進(jìn)程相關(guān)的有:
kube-apiserver
kube-controller-manager
kube-scheduler
kubelet
kube-proxy
pause
這也是我學(xué)習(xí) K8S 后對(duì)其整體架構(gòu)的一次總結(jié),因?yàn)閯偵鲜謺r(shí),閱讀官方文檔,確實(shí)被如此多的內(nèi)容搞得有點(diǎn)暈,所在在這里進(jìn)行了簡(jiǎn)單的梳理。文中有理解不到位的地方,歡迎指正!
企業(yè)級(jí) Kubernetes 實(shí)踐沙龍專(zhuān)場(chǎng)現(xiàn)在免費(fèi)贈(zèng)票了!!
企業(yè)級(jí) Kubernetes 實(shí)踐沙龍旨在分享交流 Kubernetes 的企業(yè)級(jí)整體實(shí)踐方案與案例,幫助您掌握實(shí)現(xiàn)容器云的核心技術(shù)。