一篇文章為你圖解Kubernetes對(duì)象模型
Kubernetes(以下簡(jiǎn)寫為K8s)的對(duì)象模型是K8s又一精巧的設(shè)計(jì)。我們知道,K8s所建立的容器化生態(tài)是復(fù)雜且多變的,而對(duì)象模型就是將一系列的資源實(shí)體抽象成K8s中所能識(shí)別的對(duì)象。為了方便大家更全面的了解K8s的設(shè)計(jì)思想,本文對(duì)K8s的對(duì)象模型進(jìn)行了梳理,同時(shí)在文章末尾增加了常見面試題問題匯總,章節(jié)內(nèi)容分配如下:
- K8s對(duì)象模型概述-我們?yōu)槭裁匆私鈱?duì)象模型
- K8s常見對(duì)象模型介紹-哪些對(duì)象模型可以為我們所用
- K8s對(duì)象模型的組織形式及yaml創(chuàng)建方法-我們?cè)撊绾问褂脤?duì)象
- 總結(jié)
K8s對(duì)象模型概述-我們?yōu)槭裁匆私鈱?duì)象模型
這問題還用想?存在即合理唄。那咱們就先來(lái)看看他為什么存在。
在官方文檔中,對(duì)K8s的對(duì)象模型有這樣的定義:
“在 Kubernetes 系統(tǒng)中,Kubernetes 對(duì)象是持久化的實(shí)體。Kubernetes 使用這些實(shí)體去表示整個(gè)集群的狀態(tài)。特別地,它們描述了如下信息:
- 哪些容器化應(yīng)用在運(yùn)行(以及在哪個(gè) Node 上)
- 可以被應(yīng)用使用的資源
- 關(guān)于應(yīng)用運(yùn)行時(shí)表現(xiàn)的策略,比如重啟策略、升級(jí)策略,以及容錯(cuò)策略”
簡(jiǎn)單說(shuō)來(lái),對(duì)象模型主要有兩點(diǎn)目標(biāo):
1.服務(wù)于K8s集群
對(duì)象模型一個(gè)功能是用以抽象化描述K8s集群狀態(tài),實(shí)體及實(shí)體間關(guān)聯(lián)。此類的代表就是Label,它建立集群對(duì)象之間的靈活、松耦合的多維關(guān)聯(lián)關(guān)系,我們可以用通過lable selector 查詢和篩選建立對(duì)象間的關(guān)系的。
2.服務(wù)于用戶。
K8s提供多種抽象對(duì)象便于用戶部署自己的應(yīng)用到集群中,這些抽象對(duì)象為用戶屏蔽了復(fù)雜的底層邏輯,讓用戶更專注于如何去使用。此類的例子就比較多,比如Pod,Node,Deployment等。舉個(gè)例子來(lái)說(shuō),比如我們要部署應(yīng)用在8s集群內(nèi),首先要我們的應(yīng)用需要轉(zhuǎn)換為K8s所能管理的實(shí)體對(duì)象如Pod;對(duì)于多副本應(yīng)用,我們需要考慮進(jìn)行統(tǒng)一的管理,可以考慮如Deployment;進(jìn)一步考慮副本間的負(fù)載均衡和服務(wù)發(fā)現(xiàn),我們又可以考慮采用Service來(lái)實(shí)現(xiàn),用戶無(wú)需關(guān)注其內(nèi)部實(shí)現(xiàn),從而更專注于自身的應(yīng)用。
K8s常見對(duì)象模型-哪些對(duì)象模型可以為我們所用
既然把K8s對(duì)象模型吹得這么神,那得看看他是不是真有這么神。下面來(lái)一起看看K8s常見的對(duì)象。
這里再用一幅圖來(lái)更形象地介紹各個(gè)對(duì)象在K8s中的所處位置。
Workload類對(duì)象
Pod
位置:位于圖中標(biāo)有Pod標(biāo)記的位置
說(shuō)明:Pod是集群中可以創(chuàng)建和部署的最小且最簡(jiǎn)單的Kubernetes對(duì)象的單元,其表示單個(gè) 容器 或少量緊密耦合并共享資源的容器集合。
抽象與封裝:Pod封裝了應(yīng)用容器,存儲(chǔ)資源、獨(dú)立的網(wǎng)絡(luò)IP以及容器運(yùn)行的策略選項(xiàng)。目前Docker 是 Kubernetes Pod 中最常用的容器運(yùn)行時(shí),因此在本文中所提到的容器均值docker容器。目前Docker 是 Kubernetes Pod 中最常用的容器運(yùn)行時(shí),因此在本文中所提到的容器均指docker容器。
在K8s中,每個(gè)pod中預(yù)置了一個(gè)Pause容器,其namespace、IPC資源、網(wǎng)絡(luò)和存儲(chǔ)資源被pod內(nèi)其它容器共享。Pod中的所有容器緊密協(xié)作,并且作為一個(gè)整體被管理、調(diào)度和運(yùn)行。
Controllers
位置:位于圖中Master中的Controller-Manager位置。
說(shuō)明:Controller Manager作為集群內(nèi)部的管理控制中心,負(fù)責(zé)集群內(nèi)的Node、Pod、服務(wù)端點(diǎn)(Endpoint)、命名空間(Namespace)、服務(wù)賬號(hào)(ServiceAccount)、資源定額(ResourceQuota)的管理。他們的職責(zé)是保證集群中各種資源的狀態(tài)和用戶定義(yaml)的狀態(tài)一致, 每個(gè)controller通過API Server提供的接口實(shí)時(shí)監(jiān)控整個(gè)集群的每個(gè)資源對(duì)象的當(dāng)前狀態(tài),當(dāng)發(fā)生各種故障導(dǎo)致系統(tǒng)狀態(tài)發(fā)生變化時(shí),會(huì)嘗試將系統(tǒng)狀態(tài)修復(fù)到“期望狀態(tài)”。例如,當(dāng)某個(gè)Node意外宕機(jī)時(shí),Node Controller會(huì)及時(shí)發(fā)現(xiàn)并執(zhí)行自動(dòng)化修復(fù)流程,確保Node始終處于預(yù)期的工作狀態(tài)。下圖列出了部分controller的圖例:
抽象與封裝:從邏輯上講,每個(gè)控制器都是一個(gè)單獨(dú)的進(jìn)程,他們?yōu)橛脩舴庋b了針對(duì)于資源對(duì)象的管理邏輯。用戶在創(chuàng)建資源對(duì)象后,controller會(huì)幫助用戶實(shí)時(shí)監(jiān)控整個(gè)集群的每個(gè)資源對(duì)象的當(dāng)前狀態(tài),自動(dòng)化地確保資源對(duì)象始終處于預(yù)期的工作狀態(tài)。此外。K8s支持用戶自定義擴(kuò)展controller。
Deployment/Statefulset/Daemonset/Job
位置:Deployment位于圖中④位置,Statefulset位于圖中⑤位置,Daemonset/Job位于圖中綠色Pod位置。
說(shuō)明:這一類資源對(duì)象為Pod提供了一個(gè)聲明式定義(declarative)方法,但同時(shí)他們又各自負(fù)責(zé)處理不同的使用場(chǎng)景。Deployment 為 Pod 和 ReplicaSet 提供了一個(gè)聲明式定義(declarative)方法,用來(lái)替代以前的ReplicationController 來(lái)方便的管理應(yīng)用,主要是針對(duì)是 Kubernetes 中用于處理無(wú)狀態(tài)服務(wù)的資源。典型的應(yīng)用場(chǎng)景包括:
- 定義Deployment來(lái)創(chuàng)建Pod和ReplicaSet
- 滾動(dòng)升級(jí)和回滾應(yīng)用
- 擴(kuò)容和縮容
- 暫停和繼續(xù)Deployment
StatefulSet 是用于支持有狀態(tài)服務(wù)的資源,典型的應(yīng)用場(chǎng)景是Zookeeper、Kafka。它可以保證部署和 scale 的順序。其應(yīng)用場(chǎng)景包括:
- 穩(wěn)定的持久化存儲(chǔ)。
- 穩(wěn)定的網(wǎng)絡(luò)標(biāo)志。
- 有序部署和擴(kuò)展。
- 有序收縮和刪除。
DaemonSet不同于上兩個(gè)方式,它解決的場(chǎng)景是在集群中所有節(jié)點(diǎn)上同時(shí)提供基礎(chǔ)服務(wù)和守護(hù)進(jìn)程。DaemonSet 可以保證集群中所有的或者部分的節(jié)點(diǎn)都能夠運(yùn)行同一份 Pod 副本,如kube-router、flannel等都是以DaemonSet部署。
Job負(fù)責(zé)批處理任務(wù),即僅執(zhí)行一次的任務(wù),它保證批處理任務(wù)的一個(gè)或多個(gè)Pod成功結(jié)束,可應(yīng)用的場(chǎng)景如采集數(shù)據(jù)等??赡軙?huì)用人希望能自動(dòng)化的定時(shí)執(zhí)行任務(wù),就像crontab一樣,別急,K8s同樣針對(duì)定時(shí)任務(wù)提供了cronjob資源對(duì)象,能夠支持類似crontab一樣的定時(shí)功能。
Discovery&Loadbalance類對(duì)象
Service/Endpoints/Ingress
位置:Service在圖中①,②位置處。Ingress在圖中③處。
說(shuō)明:Kubernetes Service 是對(duì)一個(gè)個(gè)Pod 的邏輯分組的抽象,它提供了一種可以訪問它們的策略,通常稱為微服務(wù)。
K8s通過抽象出Service概念,為后端綁定的pod服務(wù)提供服務(wù)發(fā)現(xiàn)和負(fù)載均衡功能,為一組具有相同功能的容器應(yīng)用提供一個(gè)統(tǒng)一的入口地址,并將請(qǐng)求進(jìn)行負(fù)載分發(fā)到后端的各個(gè)容器應(yīng)用上的控制器。這一組 Pod 能夠被 Service 訪問到,通常是通過 Label Selector實(shí)現(xiàn)的。
Endpoint是K8s集群中的一個(gè)資源對(duì)象,存儲(chǔ)在etcd中,用來(lái)記錄一個(gè)Service對(duì)應(yīng)的所有pod的訪問地址。Service配置selector,endpoint controller才會(huì)自動(dòng)創(chuàng)建對(duì)應(yīng)的endpoint對(duì)象;否則,不會(huì)生成Endpoint對(duì)象。
Ingress同樣是與Service相關(guān)的資源對(duì)象,它授權(quán)入站連接到達(dá)集群服務(wù)的規(guī)則集合。我們可以給Ingress配置提供外部可訪問的URL、負(fù)載均衡、SSL、基于名稱的虛擬主機(jī)等。用戶通過POST Ingress資源到API server的方式來(lái)請(qǐng)求ingress。 偷個(gè)懶,借用一張網(wǎng)絡(luò)上的圖來(lái)解釋一下三者關(guān)系(圖中的Pod可以理解為是EndPoints):

Config&Storage類對(duì)象
Configmap/ Secret/ Volume/ PersistentVolume
位置:Configmap、Secret位于圖中標(biāo)有Configmap、Secret的位置。PersistentVolume 則位于圖中PV1,PV2,PV3。
說(shuō)明:在K8s中,定義了volume來(lái)解決容器的存儲(chǔ)問題,稱之為Volume。不僅能夠解決 Container 中文件的臨時(shí)性問題,也能夠讓同一個(gè) Pod 中的多個(gè) Container 共享文件。這里提到的卷(Volume)其實(shí)是一個(gè)比較特定的概念,它并不是一個(gè)持久化存儲(chǔ),可能會(huì)隨著 Pod 的刪除而刪除,常見的卷就包括 EmptyDir、HostPath、ConfigMap 和 Secret,這些卷與所屬的 Pod 具有相同的生命周期。與Volume相對(duì)應(yīng)的,是持久卷概念,即PersistentVolume,他提供了持久化存儲(chǔ)的方案,將Pod與卷的聲明周期分離。
抽象與封裝:Volume和PersistentVolume為用戶屏蔽了集群中容器存儲(chǔ)的底層邏輯,集群中的每一個(gè)卷在被 Pod 使用時(shí)都會(huì)經(jīng)歷兩個(gè)操作,也就是掛載(Mount)、卸載(Unmount),有些如Configmap、Secret還會(huì)經(jīng)歷附著(Attach)、分離(Detach)操作,但這些操作用戶都不需要關(guān)心,只需要在yaml中設(shè)置數(shù)據(jù)源和掛載路徑就可以。同時(shí),存儲(chǔ)對(duì)象的管理也是有對(duì)象自動(dòng)進(jìn)行的,創(chuàng)建和刪除存儲(chǔ)資源,對(duì)于用戶來(lái)說(shuō)只需要簡(jiǎn)單的create和delete,但實(shí)際上對(duì)于存儲(chǔ)資源的分配,回收也都有K8s自動(dòng)完成。
Cluster類對(duì)象
Node/Namespace/Role/ClusterRole
位置:Node位于圖中黃色塊并標(biāo)有Node的位置。Namespace是位于圖中標(biāo)有Namespace的框,。Role是圖中位于盾牌位置, ClusterRole是圖中盾牌的全集。
說(shuō)明:Cluster對(duì)象在K8s中代表著某些全局性的資源對(duì)象。Node不必多說(shuō),是K8s存在的物理基礎(chǔ)。Namespace類似編程語(yǔ)言中的作用域,K8s支持通過Namespace在一個(gè)物理集群中劃分出多個(gè)虛擬集群,這些虛擬集群使用單獨(dú)的命名空間。各個(gè)Namespace之間容器是不透明的,也便于用戶進(jìn)行更細(xì)粒度的權(quán)限控制。
Role和ClusterRole負(fù)責(zé)為用戶提供集群內(nèi)的權(quán)限管理。Role對(duì)象用于授予對(duì)某一單一命名空間中資源的訪問權(quán)限,而整個(gè)Kubernetes集群范圍內(nèi)有效的角色則通過ClusterRole對(duì)象實(shí)現(xiàn)。在使用中,我們可以對(duì)以下幾種資源賦予權(quán)限:
- 集群范圍資源(如node)
- 非資源類型endpoint
- 跨命名空間的資源(例如跨namespace的pod)
抽象與封裝:Cluster類型的對(duì)象為用戶屏蔽了對(duì)于集群的管理邏輯。整個(gè)集群被抽象成一種扁平化的結(jié)構(gòu)。我們可以把集群比作一個(gè)象棋棋盤,Pod(棋子)優(yōu)先會(huì)部署在各自的區(qū)域(namespace),有些Pod(棋子)只能在各自區(qū)域操作,有些Pod(棋子)則可以跨區(qū)域操作。用戶只需要學(xué)會(huì)使用這些Pod(棋子),而具體的規(guī)則和執(zhí)行邏輯由K8s制定。
K8s對(duì)象模型的組織形式及yaml創(chuàng)建方法-我們?cè)撊绾问褂脤?duì)象
在K8s中,提供給用戶的組織和創(chuàng)建對(duì)象的方式是通過yaml文件進(jìn)行的,對(duì)于一個(gè)編寫好的yaml文件,可以采用以下指令來(lái)創(chuàng)建對(duì)象資源
- kubectl create/apply -f ***.yaml
通過下列指令就可以看到一個(gè)Pod對(duì)象的組織方式。
- kubectl describe pod *** -n <namespace>
下面,本節(jié)針對(duì)對(duì)象yaml的各個(gè)字段及各資源創(chuàng)建方式進(jìn)行詳細(xì)解析。首先,我們需要建立一個(gè)概念,yaml文件是對(duì)對(duì)象描述的一種形象化,即描述對(duì)象的概念映射到y(tǒng)aml上就是一個(gè)個(gè)kv字段。在描述K8s對(duì)象時(shí),有兩個(gè)嵌套字段是必須的,它們負(fù)責(zé)管理對(duì)象的配置:spec 和 status。spec必須提供,它描述了對(duì)象的期望狀態(tài)——希望對(duì)象所具有的特征。status 描述了對(duì)象的實(shí)際狀態(tài),它是由 K8s系統(tǒng)提供和更新。在任何時(shí)刻,K8s管理模塊一直處于活躍狀態(tài),管理著對(duì)象的實(shí)際狀態(tài)以與我們所期望的狀態(tài)相匹配。
例如:

可以看到Deployment對(duì)象的Spec和Status描述結(jié)構(gòu)。
再說(shuō)yaml,對(duì)于不同的對(duì)象而言,yaml配置的內(nèi)容有所不同,但以下幾項(xiàng)是必選:
- apiVersion # 創(chuàng)建該對(duì)象所使用的 Kubernetes API 的版本
- kind # 想要?jiǎng)?chuàng)建的對(duì)象的類型
- metadata # 識(shí)別對(duì)象唯一性的數(shù)據(jù),包括一個(gè) name 字符串、UID 和可選的 namespace
spec 字段,spec不是強(qiáng)制,但用戶使用時(shí)是有必要提供該字段內(nèi)容的。也是由于各對(duì)象的差異,所以spec 的精確格式對(duì)每個(gè) Kubernetes 對(duì)象來(lái)說(shuō)是不同的,包含了特定于該對(duì)象的嵌套字段。詳細(xì)的字段內(nèi)容可參考K8s API(
https://kubernetes.io/docs/api/)。下面我們對(duì)各資源的創(chuàng)建方式進(jìn)行舉例:
Workload類對(duì)象
Pod類資源我們使用經(jīng)典案例——busybox的創(chuàng)建模板進(jìn)行簡(jiǎn)述:

這則模板中首先指定了yaml的三要素,apiVersion、kind、metadata。在Pod特有的spec中指定了所需的鏡像busybox,并簡(jiǎn)單設(shè)置了鏡像拉取和容器重啟的策略。在使用過程中我們會(huì)發(fā)現(xiàn),簡(jiǎn)單的配置后,因鏡像拉取或容器重啟帶來(lái)的異常管理問題,K8s都會(huì)幫你自動(dòng)完成,也就是之前提到的對(duì)象的實(shí)際狀態(tài)以與我們所期望的狀態(tài)相匹配。
再舉一個(gè)例子,經(jīng)典的nginx模板用例:

Deployment用以描述一類Pod集合,因此這里指定了副本數(shù),并設(shè)置了selector來(lái)簡(jiǎn)歷Pod與Deployment的關(guān)系。
Discovery&Loadbalance類對(duì)象
這一類資源代表具備網(wǎng)絡(luò)特性的對(duì)象,其中的代表對(duì)象就是Service,這里我們也列舉一個(gè)Service的經(jīng)典用例加以說(shuō)明。

Service對(duì)象的yaml模板里,我們可以指定一個(gè)或一組Pod的通信端口及通信協(xié)議,并制定服務(wù)的暴露方式。
Config&Storage類對(duì)象
Configmap作為非持久化存儲(chǔ)的代表,我們先舉一個(gè)例子來(lái)說(shuō)明:

Configmap的部署用例沒有spec域,直接指定了數(shù)據(jù)的內(nèi)容。除了以上使用yaml方式創(chuàng)建外,當(dāng)我們將 ConfigMap 或者 Secret 包裝成卷并掛載到某個(gè)目錄時(shí),我們其實(shí)是在創(chuàng)建 Volume,這些 Volume 并不是 Kubernetes 中的對(duì)象,它們只存在于當(dāng)前 Pod 中,隨著 Pod 的刪除而刪除,但是需要注意的是這些臨時(shí)的Volume的刪除并不會(huì)導(dǎo)致相關(guān) ConfigMap 或者 Secret 對(duì)象的刪除。
我們?cè)倥e持久化存儲(chǔ)的例子。

持久化存儲(chǔ)的創(chuàng)建用例和Pod對(duì)象有些類似,需要制定存儲(chǔ)的預(yù)期狀態(tài),這里設(shè)置了一個(gè)容量為1G,以可讀可寫方式掛載到多個(gè)節(jié)點(diǎn),并使用nfs掛載的PV存儲(chǔ)。這樣在創(chuàng)建完成后,就可以使用PVC在Pod進(jìn)行存儲(chǔ)綁定了。
Cluster類對(duì)象
Cluster類對(duì)象多數(shù)屬于集群集群資源對(duì)象,默認(rèn)可不需要用戶自己使用yaml創(chuàng)建,比如namespace就可以直接使用命令 kubectl create ns **** 來(lái)創(chuàng)建。這里我們舉一個(gè)ClusterRole的yaml例子。

在這個(gè)例子中,我們定義了一個(gè)ClusterRole的對(duì)象,它可以授予對(duì)secrets資源對(duì)象的get,watch,list權(quán)限。接來(lái)下我們就是用ClusterRoleBinding來(lái)使用它。ClusterRoleBinding可以將角色中定義的權(quán)限授予用戶或用戶組,ClusterRoleBinding包含一組權(quán)限列表(subjects),權(quán)限列表中包含有不同形式的待授予權(quán)限資源類型(如USER,GROUP,SERVICEACCOUNT),ClusterRoleBinding適用于集群范圍內(nèi)的授權(quán),與之相對(duì)應(yīng)的RoleBinding適用于某個(gè)命名空間內(nèi)授權(quán)。舉例說(shuō)明:

在這個(gè)用例中,我們將secret這個(gè)ClusterRole綁定到了dazhuang這個(gè)用戶上,授權(quán)用戶dazhuang只能訪問myspace中的secret。
總結(jié)
K8s的對(duì)象模型是 K8s中非常重要的一部分,也是K8s構(gòu)建的基礎(chǔ)。K8s中各個(gè)對(duì)象為使用者屏蔽了復(fù)雜的底層細(xì)節(jié),并通過不斷獲取集群的運(yùn)行狀態(tài)與期望狀態(tài)進(jìn)行對(duì)比,來(lái)幫助使用者確保對(duì)象能在預(yù)期的狀態(tài)下運(yùn)行,希望這篇文章能幫助各位讀者更全面的理解K8s的對(duì)象模型。