自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Kubernetes聲明式API

云計(jì)算 云原生
那么K8s對(duì)象在K8s API中是如何表示的,我們?cè)趺从?yaml文件描述它們,當(dāng)把一個(gè).yaml文件提交給 K8s后,它究竟又是如何創(chuàng)建出一個(gè)K8s對(duì)象的呢?
?我們知道Kubernetes(以下簡(jiǎn)稱“K8s”)中各種資源對(duì)象的數(shù)據(jù)是通過(guò)K8s的API進(jìn)行提交并持久化到存儲(chǔ)etcd中的(稱為K8s對(duì)象),K8s對(duì)象是使用K8s的接口,kubelet客戶端通過(guò)操作這些對(duì)象來(lái)使用K8s能力。

其中kubectl是我們使用最多的命令行工具。K8s官方對(duì)kubectl管理K8s對(duì)象的技術(shù)做了如下表的總結(jié):

圖片

假如我們現(xiàn)在要在名為test的namespace下創(chuàng)建一個(gè)Deployment對(duì)象來(lái)運(yùn)行nginx容器,接著對(duì)nginx的副本數(shù)量進(jìn)行更改為5,三種方式流程如下:

1)指令式命令方式

創(chuàng)建deployment對(duì)象: 

kubectl create deployment nginx-deployment --image nginx -n test

更改副本數(shù):

kubectl scale deployment nginx-deployment --replicas 5 -n test

2)指令式對(duì)象配置方式

首先創(chuàng)建配置文件定義,定義如圖1-1所示:

圖片

圖1-1 ngin.yaml配置

創(chuàng)建deployment對(duì)象: 

kubectl create -f nginx.yaml

將配置文件中的replicas由2改成5,執(zhí)行命令更改副本數(shù):

kubectl replace -f nginx.yaml

3)聲明式對(duì)象配置方式

使用圖1-1的配置,創(chuàng)建deployment對(duì)象:

kubectl apply -f nginx.yaml

將配置文件中的replicas由2改成5,執(zhí)行命令更改副本數(shù):

kubectl apply -f nginx.yaml

后兩者對(duì)象配置的方式提供了用于創(chuàng)建新對(duì)象的模板,并且能夠提供與更改關(guān)聯(lián)的審核跟蹤,命令除了實(shí)時(shí)內(nèi)容外,不能提供記錄源。所以在生產(chǎn)項(xiàng)目的情況下,我們使用 K8s 對(duì)象的方式往往是通過(guò)編寫(xiě)對(duì)應(yīng)的.yaml文件交給 K8s(聲明式API的形式),而不是直接使用指令式命令。

我們配置文件只是聲明了想要?jiǎng)?chuàng)建的K8s對(duì)象的信息以及想要它們達(dá)到的期望狀態(tài),這是一種聲明式API的交互方式。不同于吃飯、睡覺(jué)等明確的指令(這種方式也稱為:命令式API),使用配置創(chuàng)建的對(duì)象的交互感覺(jué)類似顧客與實(shí)施方的交流模式,因?yàn)轭櫩透鷮?shí)施方相比,往往不清楚為了達(dá)到目標(biāo)而需要進(jìn)行的操作,比如說(shuō):給我搭建一個(gè)標(biāo)準(zhǔn)的籃球場(chǎng)。

聲明式API往往預(yù)備了合并多個(gè)操作的能力,我們?cè)诖罱ㄇ驁?chǎng)時(shí)可以同時(shí)進(jìn)行地板的鋪設(shè)和大屏幕的安裝,命令式API在并發(fā)訪問(wèn)情況下會(huì)十分復(fù)雜、低效,往往通過(guò)加鎖才能保證最后結(jié)果的可預(yù)見(jiàn)性,孩子必須吃完了飯才能睡覺(jué),而不是睡覺(jué)的時(shí)候吃飯。并且聲明式API天然地記錄了現(xiàn)在和最終狀態(tài),便于對(duì)結(jié)果進(jìn)行檢查。每天必須吃3碗飯和保持體重在50kg,不同體重的人吃三碗飯導(dǎo)致的體重結(jié)果是無(wú)法估計(jì)的,不同的人但卻可以通過(guò)調(diào)整熱量的攝入而達(dá)到50kg的目標(biāo)。這也是為什么K8s中聲明式API如此重要的原因,而K8s聲明式API描述的主體便是K8s對(duì)象,正如開(kāi)頭所說(shuō)它是我們操作K8s的媒介和接口。

那么K8s對(duì)象在K8s API中是如何表示的,我們?cè)趺从?yaml文件描述它們,當(dāng)把一個(gè).yaml文件提交給 K8s后,它究竟又是如何創(chuàng)建出一個(gè)K8s對(duì)象的呢?

01K8s對(duì)象

K8s對(duì)象指的是K8s系統(tǒng)中持久化后的實(shí)體,K8s用這些實(shí)體去表示整個(gè)集群的運(yùn)行狀態(tài)。它們特別描述了以下信息:

  • 哪些容器化應(yīng)用在運(yùn)行,以及運(yùn)行在哪些節(jié)點(diǎn)上
  • 可以被應(yīng)用使用的資源
  • 應(yīng)用運(yùn)行時(shí)的表現(xiàn)策略,如重啟策略、升級(jí)策略以及容錯(cuò)策略。

K8s對(duì)象的操作(創(chuàng)建、修改、刪除)都需要使用K8s API,無(wú)論是使用kubectl命令行還是程序中使用客戶端,最終都會(huì)調(diào)用K8s API。

每個(gè)K8s對(duì)象都包含兩個(gè)嵌套的對(duì)象字段spec(規(guī)約)和status(狀態(tài))。其中spec描述的是K8s在創(chuàng)建完畢后應(yīng)該達(dá)到的期望狀態(tài),如期望開(kāi)啟多少個(gè)副本,status描述了對(duì)象的當(dāng)前狀態(tài),它由K8s系統(tǒng)和組件進(jìn)行監(jiān)管設(shè)置并積極地使它與spec相匹配。這兩個(gè)字段也是對(duì)于K8s聲明式API實(shí)現(xiàn)最為關(guān)鍵的一環(huán)。

02K8s是如何描述和管理API對(duì)象的

我們?cè)趧?chuàng)建 Kubernetes對(duì)象時(shí),必須提供對(duì)象的spec字段,告知K8s我們期望這個(gè)對(duì)象所達(dá)到狀態(tài),同時(shí)也必須提供一些關(guān)于對(duì)象的基本信息(例如名稱)。不論我們是通過(guò)kubectl命令行或者是客戶端調(diào)用K8s API創(chuàng)建對(duì)象,API 請(qǐng)求必須在請(qǐng)求體中包含JSON 格式的信息。大多數(shù)情況下,我們都以 .yaml 文件的形式提供這些信息。kubectl 在發(fā)起API請(qǐng)求時(shí),再將這些信息轉(zhuǎn)換成 JSON 格式。以圖1-1舉例,圖中展示了使用.yaml來(lái)描述K8s對(duì)象的必需字段和對(duì)象規(guī)約,以下是其中必需字段的簡(jiǎn)要說(shuō)明:

  • apiVersion - 創(chuàng)建該對(duì)象所使用的K8s API版本
  • kind - 想要?jiǎng)?chuàng)建的對(duì)象類別
  • metadata – 幫助唯一性表示對(duì)象的一些數(shù)據(jù),包括一個(gè)name字符串、UID和可選的namespace
  • spec – 你期望該對(duì)象所達(dá)到的狀態(tài)

其中spec的精確格式對(duì)于不同類別的K8s對(duì)象來(lái)說(shuō)往往是不同的,它是對(duì)管理對(duì)象詳細(xì)描述的主體,會(huì)被K8s持久化到etcd中保存。如果spec被刪除,那么該對(duì)象也會(huì)從系統(tǒng)中被刪除。

一個(gè)API對(duì)象在etcd里的完整資源路徑是由Group(API組)、Version(API版本)、Resource(API資源類型)三個(gè)部分組成。具體案例如圖1-2所示:

圖片

圖1-2 K8s的API結(jié)構(gòu)

從圖中我們可以看出,在K8s內(nèi)API對(duì)象的組織方式是層層遞進(jìn)的,這里我們不去深究具體怎么使用這些api去檢索需要的資源,感興趣的讀者可以參考如下鏈接地址,這是官方的詳細(xì)說(shuō)明:https://kubernetes.io/zh/docs/reference/using-api/api-concepts/

假定現(xiàn)在我們要?jiǎng)?chuàng)建一個(gè)CronJob對(duì)象,且它的yaml文件開(kāi)頭部分如下所示:

apiVersion: batch/v2alpha1
kind: CronJob
...

其中,batch就表示它的API組(Group),v2alpha1就是它的API版本(Version),CronJob即是它所屬API資源類型(Resource)conjobs下的一個(gè)具體類別。而其整體創(chuàng)建流程下圖1-3所示:

圖片

圖1-3 持久化流程

提交階段

當(dāng)我們的yaml提交給K8s集群后(不論是通過(guò)程序客戶端還是kubectl),請(qǐng)求會(huì)被轉(zhuǎn)化成一個(gè)POST,接著交由K8s的API Server進(jìn)行處理。

過(guò)濾和前置處理階段

API Server首先會(huì)對(duì)請(qǐng)求進(jìn)行過(guò)濾,獲取其中的有效信息,再完成諸如:授權(quán)、超時(shí)處理、審計(jì)等前置性工作。

路由查找階段

主要是借由MUX和Routes路由查找CronJob的定義,具體流程大致為:1. 匹配Group。對(duì)于CronJob這類非核心API對(duì)象,K8s會(huì)在如圖1-2所示的/apis層級(jí)內(nèi)查找它的所屬組(核心對(duì)象,如Pod、Node,隸屬于/api層級(jí)且它們的組為””),根據(jù)yaml的開(kāi)頭信息,查找到/apis/batch。2. 匹配版本號(hào)。接著,根據(jù)v2alpha1這個(gè)版本號(hào)進(jìn)一步匹配到/apis/batch/ v2alpha1這個(gè)路徑,在K8s中,同種API對(duì)象可以有多個(gè)版本,這是K8s給予用戶管理共存多版本API的手段。3.匹配資源類型。最后匹配資源類型cronjobs,這時(shí)K8s便可明確知道自己所需要?jiǎng)?chuàng)建的具體資源類型為CronJob。

創(chuàng)建資源階段

在獲取到CornJob的類型定義后,API Server會(huì)進(jìn)行一個(gè)Convert工作:把用戶提交的yaml轉(zhuǎn)換成一個(gè)Super Version的對(duì)象,它是該API資源類型所有版本的字段全集,之后用戶提交其他版本的yaml,也都可以用這個(gè)Super Version對(duì)象來(lái)處理。接著,再進(jìn)行Admit處理,主要是在對(duì)象創(chuàng)建完成后,注入一些公共處理邏輯,例如加入一些標(biāo)簽Label。最后,對(duì)這個(gè)對(duì)象里各個(gè)字段的合法性進(jìn)行校驗(yàn)。

定義存儲(chǔ)階段

若通過(guò)了Validate,會(huì)被API Server保存在名為Registry的結(jié)構(gòu)中。它包含了對(duì)一個(gè)有效K8s API對(duì)象的定義。

持久化階段

API Server會(huì)把通過(guò)驗(yàn)證的API對(duì)象由Super Version版本重新轉(zhuǎn)換為最初提交的版本,再進(jìn)行序列化操作,最后調(diào)用etcd的API將它們變?yōu)镵8s內(nèi)的實(shí)體對(duì)象。

此時(shí),對(duì)象已經(jīng)被創(chuàng)建持久化完成,那么它又是如何一步步達(dá)到我們所期望的狀態(tài)的呢?K8s對(duì)象章節(jié)所提及到的spec和status信息正是這個(gè)解決問(wèn)題的基礎(chǔ),K8s基于此采用了控制器模式來(lái)進(jìn)行實(shí)現(xiàn)。

03控制器模式實(shí)現(xiàn)聲明式API的sepc

K8s是通過(guò)控制器模式來(lái)實(shí)現(xiàn)聲明式API中描述的spec狀態(tài)靠攏的,而控制型模式最核心的就是“控制循環(huán)“的概念。在K8s中,控制器是一個(gè)控制循環(huán),它通過(guò)API服務(wù)器監(jiān)視集群的共享狀態(tài),并進(jìn)行更改,試圖將當(dāng)前狀態(tài)(status)轉(zhuǎn)移到期望狀態(tài)(spec)。

實(shí)際狀態(tài)的獲取往往是通過(guò)K8s本身的一些組件,例如定時(shí)調(diào)用API獲取資源狀態(tài)信息,或kubelet通過(guò)心跳匯報(bào)的容器狀態(tài)和節(jié)點(diǎn)狀態(tài)。所需期望狀態(tài),往往由yaml文件的spec字段進(jìn)行定義提交持久化到K8s的etcd中。圖1-4大致表述了K8s中控制循環(huán)的過(guò)程:

圖片

圖1-4控制循環(huán)

  • 比較spec和status,若相同,不進(jìn)行操作,繼續(xù)進(jìn)行1,否則輸出不同點(diǎn),進(jìn)入2;
  • 控制器(Controller)根據(jù)不同點(diǎn),對(duì)系統(tǒng)發(fā)出調(diào)控操作,系統(tǒng)執(zhí)行操作,進(jìn)入3;
  • 系統(tǒng)上報(bào)當(dāng)前系統(tǒng)狀態(tài)給傳感器(Sensor)或者傳感器主動(dòng)拉取狀態(tài),輸出當(dāng)前狀態(tài)status,返回1。

目的是使status不斷趨近達(dá)到spec,從而完成yaml聲明狀態(tài)的實(shí)現(xiàn)。從圖中也可以看出Sensor和Controller在整個(gè)循環(huán)中扮演了極其重要的角色。

在K8s中,Sensor主要由Reflector、Informer、Indexer 三個(gè)組件構(gòu)成。

Sensor的整體工作流程如圖1-5所示:

圖片

圖1-5 Sensor組件

1.Reflector通過(guò)List和Watch操作從API Server 獲取各個(gè)資源對(duì)象的狀態(tài)。其中,List用來(lái)描述返回多個(gè)資源的集合,主要用于系統(tǒng)資源的全量更新;Watch用于客戶端獲取當(dāng)前狀態(tài),然后訂閱后續(xù)更改,主要用于系統(tǒng)資源的增量更新;

2.Reflector在獲取新的資源數(shù)據(jù)后,會(huì)往Delta隊(duì)列中推入一個(gè)Delta記錄,這個(gè)記錄包含了資源對(duì)象本身的信息以及資源對(duì)象事件的類型。Delta隊(duì)列可以保證同一個(gè)對(duì)象在隊(duì)列中僅有一條記錄,從而避免Reflector重新List和Watch的時(shí)候產(chǎn)生重復(fù)的記錄。

3.Informer組件不斷地從Delta隊(duì)列中彈出delta記錄,然后把資源對(duì)象交給indexer。indexer把資源記錄在一個(gè)默認(rèn)使用命名空間做索引的緩存中,記錄操作是線程安全的并且緩存是可以在Controller Manager或多個(gè)Controller間共享的。之后,informer再把這個(gè)事件交給事件回調(diào)函數(shù)。

Controller的主要流程如圖1-6所示:

圖片

圖1-6 controller組件

控制循環(huán)中的Controller(控制器)組件主要由事件處理函數(shù)以及worker組成,事件處理函數(shù)根據(jù)控制器邏輯決定是否要進(jìn)行相應(yīng)的回調(diào)處理。若需要進(jìn)行事件處理,它會(huì)把事件關(guān)聯(lián)資源的命名空間和資源名字當(dāng)成一個(gè)標(biāo)識(shí)塞入工作隊(duì)列中,由后續(xù)worker池中的一個(gè)worker來(lái)處理,工作隊(duì)列會(huì)對(duì)存儲(chǔ)的對(duì)象進(jìn)行去重,從而避免多個(gè)woker處理同一個(gè)資源的情況。

worker 在處理資源對(duì)象時(shí),一般需要用資源的名字來(lái)重新獲得最新的資源數(shù)據(jù),之后使用這些數(shù)據(jù)會(huì)有三種情況:

  • 創(chuàng)建或者更新資源對(duì)象,
  • 調(diào)用其他的外部服務(wù),
  • worker處理失敗,把資源的名字重新加入到工作隊(duì)列中進(jìn)行重試。

現(xiàn)在假如我們需要將圖1-1所配置的nginx副本由2擴(kuò)容為3個(gè)進(jìn)行舉例說(shuō)明,方便讀者理解,整體流程如圖1-7所示:

圖片

圖1-7副本擴(kuò)展整體流程圖

首先,Reflector會(huì)watch到Deployment發(fā)生變化,在delta隊(duì)列中塞入了對(duì)象是nginx-deployment并且類型是更新的記錄。

Informer一方面把新的Deployment更新到緩存中,并用名為test的namespace作為索引。另外一方面,調(diào)用Update的回調(diào)函數(shù),Deployment控制器發(fā)現(xiàn)Deployment發(fā)生變化后會(huì)把字符串test/nginx-deployment塞入到工作隊(duì)列中,工作隊(duì)列后的一個(gè) worker從工作隊(duì)列中取到了test/nginx-deployment這個(gè)字符串的key,并且從緩存中取到了最新的Deployment數(shù)據(jù)。

worker通過(guò)比較Deployment中spec和status里的數(shù)值,發(fā)現(xiàn)需要對(duì)這個(gè)Deployment進(jìn)行擴(kuò)容,因此Deployment的worker創(chuàng)建了一個(gè)Pod,這個(gè)pod中的Ownereference指向了nginx-deployment。

然后Reflector Watch到的Pod新增事件,在delta隊(duì)列中額外加入了Add類型的deta記錄。

Informer一方面把新的Pod記錄通過(guò)Indexer存儲(chǔ)到了緩存中,另一方面調(diào)用了 Deployment控制器的Add回調(diào)函數(shù),Add回調(diào)函數(shù)通過(guò)檢查pod3的ownerReferences 找到了對(duì)應(yīng)的Deployment為nginx-deployment,把test/nginx-deployment字符串塞入到了工作隊(duì)列中。

Deployment的woker在得到新的工作項(xiàng)之后,從緩存中取到新的Deployment記錄,并得到了其所有的Pod信息,對(duì)比發(fā)現(xiàn)Deployment的狀態(tài)不是最新的(關(guān)聯(lián)的pod數(shù)量已經(jīng)發(fā)生改變)。此時(shí) Deployment更新 status使得spec和 status達(dá)成一致。圖片

04總結(jié)

  • 由于聲明式API具有天然的記錄初始和最終狀態(tài)等特性,K8s采用了其作為最關(guān)鍵部分的API交互方式。
  • 在生產(chǎn)環(huán)境中,對(duì)于K8s的管理往往是通過(guò)管理器API對(duì)象,而API對(duì)象又是通過(guò)yaml進(jìn)行描述的,其中的spec和status是最為關(guān)鍵的信息,K8s會(huì)通過(guò)定位和路由把一個(gè)yaml描述的信息持久化到etcd中成為實(shí)體。
  • K8s所采用的控制器模式,是由聲明式API驅(qū)動(dòng)的。它是實(shí)現(xiàn)K8s聲明式API的關(guān)鍵,資源對(duì)應(yīng)的控制器結(jié)合感應(yīng)器通過(guò)控制循環(huán),異步地將控制系統(tǒng)向設(shè)置的終態(tài)趨近。
  • 因?yàn)榭刂破魇亲灾鬟\(yùn)行的,使得整體系統(tǒng)的自動(dòng)化和無(wú)人值守成為可能。

參考文獻(xiàn)

[1] https://edu.aliyun.com/lesson_1651_18353?spm=5176.10731542.0.0.5f9e7abdivOOXz#_18353

[2] https://kubernetes.io/zh/docs/concepts/overview/working-with-objects/object-management/

[3] https://kubernetes.io/zh/docs/reference/using-api/api-concepts/#efficient-detection-of-changes

[4] https://kubernetes.io/zh/docs/concepts/overview/working-with-objects/kubernetes-objects/

[5] http://borismattijssen.github.io/articles/kubernetes-informers-controllers-reflectors-stores

[6] https://ghostwritten.blog.csdn.net/article/details/119155497

[7] https://www.codercto.com/a/65740.html?

責(zé)任編輯:未麗燕 來(lái)源: 移動(dòng)Labs
相關(guān)推薦

2021-03-03 14:09:57

API命令式聲明式

2020-12-17 07:59:46

聲明式代碼命令式代碼代碼

2009-06-22 09:01:57

Spring聲明式事務(wù)

2022-07-01 17:57:45

KubernetesAPI

2022-02-25 15:08:06

DevEco開(kāi)發(fā)OpenHarmon鴻蒙

2025-03-21 08:55:36

SpringOpenFeignAPI

2024-11-13 19:03:14

2009-08-20 10:34:46

C#中聲明API函數(shù)

2022-06-07 16:17:45

KubernetesAPI Schema

2013-06-27 09:31:37

聲明式編程命令式編程編程

2020-09-04 06:27:22

編碼命令式聲明式代碼

2024-01-30 07:58:41

KubernetesGAMMA網(wǎng)關(guān)

2021-10-15 08:27:14

Kubernetes 工具Mizu

2023-11-07 07:08:57

2024-11-13 10:07:39

Java聲明式Http

2021-09-06 13:42:14

Spring聲明式事務(wù)

2009-10-12 12:54:58

VB.NET聲明API

2023-09-05 23:38:36

Kubernetes集群

2010-05-26 13:56:59

Tomcat 7Servlet 3.0

2022-08-23 16:07:02

ArkUI鴻蒙
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)