作者 | 張振 阿里巴巴高級(jí)技術(shù)專家
公司主營(yíng)業(yè)務(wù):網(wǎng)站制作、網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。成都創(chuàng)新互聯(lián)推出云浮免費(fèi)做網(wǎng)站回饋大家。
我們知道,Kubernetes 的資源對(duì)象組成:主要包括了 Spec、Status 兩部分。其中 Spec 部分用來(lái)描述期望的狀態(tài),Status 部分用來(lái)描述觀測(cè)到的狀態(tài)。
今天我們將為大家介紹 K8s 的另外一個(gè)部分,即元數(shù)據(jù)部分。該部分主要包括了用來(lái)識(shí)別資源的標(biāo)簽:Labels, 用來(lái)描述資源的注解;Annotations, 用來(lái)描述多個(gè)資源之間相互關(guān)系的 OwnerReference。這些元數(shù)據(jù)在 K8s 運(yùn)行中有非常重要的作用。
第一個(gè)元數(shù)據(jù),也是最重要的一個(gè)元數(shù)據(jù)——資源標(biāo)簽。資源標(biāo)簽是一種具有標(biāo)識(shí)型的 Key:Value 元數(shù)據(jù),如下圖所示,展示了幾個(gè)常見的標(biāo)簽。
前三個(gè)標(biāo)簽都打在了 Pod 對(duì)象上,分別標(biāo)識(shí)了對(duì)應(yīng)的應(yīng)用環(huán)境、發(fā)布的成熟度和應(yīng)用的版本。從應(yīng)用標(biāo)簽的例子可以看到,標(biāo)簽的名字包括了一個(gè)域名的前綴,用來(lái)描述打標(biāo)簽的系統(tǒng)和工具, 最后一個(gè)標(biāo)簽打在 Node 對(duì)象上,還在域名前增加了版本的標(biāo)識(shí) beta 字符串。
標(biāo)簽主要用來(lái)篩選資源和組合資源,可以使用類似于 SQL 查詢 select,來(lái)根據(jù) Label 查詢相關(guān)的資源。
最常見的 Selector 就是相等型 Selector。現(xiàn)在舉一個(gè)簡(jiǎn)單的例子:
假設(shè)系統(tǒng)中有四個(gè) Pod,每個(gè) Pod 都有標(biāo)識(shí)系統(tǒng)層級(jí)和環(huán)境的標(biāo)簽,我們通過 Tie:front 這個(gè)標(biāo)簽,可以匹配左邊欄的 Pod,相等型 Selector 還可以包括多個(gè)相等條件,多個(gè)相等條件之間是邏輯”與“的關(guān)系。
在剛才的例子中,通過 Tie=front,Env=dev 的 Selector,我們可以篩選出所有 Tie=front,而且 Env=dev 的 Pod,也就是下圖中左上角的 Pod。另外一種 Selector 是集合型 Selector,在例子中,Selector 篩選所有環(huán)境是 test 或者 gray 的 Pod。
除了 in 的集合操作外,還有 notin 集合操作,比如 tie notin(front,back),將會(huì)篩選所有 tie 不是 front 且不是 back 的 Pod。另外,也可以根據(jù)是否存在某 lable 的篩選,如:Selector release,篩選所有帶 release 標(biāo)簽的 Pod。集合型和相等型的 Selector,也可以用“,”來(lái)連接,同樣的標(biāo)識(shí)邏輯”與“的關(guān)系。
另外一種重要的元數(shù)據(jù)是:annotations。一般是系統(tǒng)或者工具用來(lái)存儲(chǔ)資源的非標(biāo)示的信息,可以用來(lái)擴(kuò)展資源的 spec/status 的描述,這里給了幾個(gè) annotations 的例子:
第一個(gè)例子,存儲(chǔ)了阿里云負(fù)載器的證書 ID,我們可以看到 annotations 一樣可以擁有域名的前綴,標(biāo)注中也可以包含版本信息。第二個(gè) annotation存儲(chǔ)了 nginx 接入層的配置信息,我們可以看到 annotations 中包括“,”這樣無(wú)法出現(xiàn)在 label 中的特殊字符。第三個(gè) annotations 一般可以在 kubectl apply 命令行操作后的資源中看到, annotation 值是一個(gè)結(jié)構(gòu)化的數(shù)據(jù),實(shí)際上是一個(gè) json 串,標(biāo)記了上一次 kubectl 操作的資源的 json 的描述。
最后一個(gè)元數(shù)據(jù)叫做 Ownereference。所謂所有者,一般就是指集合類的資源,比如說(shuō) Pod 集合,就有 replicaset、statefulset,這個(gè)將在后序的課程中講到。
集合類資源的控制器會(huì)創(chuàng)建對(duì)應(yīng)的歸屬資源。比如:replicaset 控制器在操作中會(huì)創(chuàng)建 Pod,被創(chuàng)建 Pod 的 Ownereference 就指向了創(chuàng)建 Pod 的 replicaset,Ownereference 使得用戶可以方便地查找一個(gè)創(chuàng)建資源的對(duì)象,另外,還可以用來(lái)實(shí)現(xiàn)級(jí)聯(lián)刪除的效果。
這里通過 kubectl 命令去連接我們 ACK 中已經(jīng)創(chuàng)建好的一個(gè) K8s 集群,然后來(lái)展示一下怎么查看和修改 K8s 對(duì)象中的元數(shù)據(jù),主要就是 Pod 的一個(gè)標(biāo)簽、注解,還有對(duì)應(yīng)的 Ownerference。
首先我們看一下集群里現(xiàn)在的配置情況:
1.查看 Pod,現(xiàn)在沒有任何的一個(gè) Pod;
2.然后用事先準(zhǔn)備好的一個(gè) Pod 的 yaml,創(chuàng)建一個(gè) Pod 出來(lái);
3.現(xiàn)在查看一下 Pod 打的標(biāo)簽,我們用 --show-labels 這個(gè)選項(xiàng),可以看到這兩個(gè) Pod 都打上了一個(gè)部署環(huán)境和層級(jí)的標(biāo)簽;
4.我們也可以通過另外一種方式來(lái)查看具體的資源信息。首先查看 nginx1 第一個(gè) Pod 的一個(gè)信息,用 -o? yaml 的方式輸出,可以看到這個(gè) Pod 元數(shù)據(jù)里面包括了一個(gè) lables 的字段,里面有兩個(gè) lable;
5.現(xiàn)在再想一下,怎么樣對(duì) Pod 已有的 lable?進(jìn)行修改?我們先把它的部署環(huán)境,從開發(fā)環(huán)境改成測(cè)試環(huán)境,然后指定 Pod 名字,在環(huán)境再加上它的一個(gè)值 test ,看一下能不能成功。 這里報(bào)了一個(gè)錯(cuò)誤,可以看到,它其實(shí)是說(shuō)現(xiàn)在這個(gè) label 已經(jīng)有值了;
6.如果想覆蓋掉它的話,得額外再加上一個(gè)覆蓋的選項(xiàng)。加上之后呢,我們應(yīng)該可以看到這個(gè)打標(biāo)已經(jīng)成功了;
7.我們?cè)倏匆幌卢F(xiàn)在集群的 lable 設(shè)置情況,首先可以看到 nginx1 的確已經(jīng)加上了一個(gè)部署環(huán)境 test 標(biāo)簽;
8.如果想要對(duì) Pod 去掉一個(gè)標(biāo)簽,也是跟打標(biāo)簽一樣的操作,但是 env 后就不是等號(hào)了。只加上 label 名字,后面不加等號(hào),改成用減號(hào)表示去除 label 的 k:v;
9.可以看到這個(gè) label,去標(biāo)已經(jīng)完全成功;
10.下面來(lái)看一下配置的 label 值,的確能看到 nginx1 的這個(gè) Pod 少了一個(gè) tie=front 的標(biāo)簽。有了這個(gè) Pod 標(biāo)簽之后,可以看一下怎樣用 label Selector 進(jìn)行匹配?首先 label Selector 是通過 -l 這個(gè)選項(xiàng)來(lái)進(jìn)行指定的 ,指定的時(shí)候,先試一下用相等型的一個(gè) label 來(lái)篩選,所以我們指定的是部署環(huán)境等于測(cè)試的一個(gè) Pod,我們可以看到能夠篩選出一臺(tái);
11.假如說(shuō)有多個(gè)相等的條件需要指定的,實(shí)際上這是一個(gè)與的關(guān)系,假如說(shuō) env 再等于 dev,我們實(shí)際上是一個(gè) Pod 都拿不到的;
12.然后假如說(shuō) env=dev,但是 tie=front,我們能夠匹配到第二個(gè) Pod,也就是 nginx2;
13.我們還可以再試一下怎么樣用集合型的 label Selector 來(lái)進(jìn)行篩選。這一次我們還是想要匹配出所有部署環(huán)境是 test 或者是 dev 的一個(gè) Pod,所以在這里加上一個(gè)引號(hào),然后在括號(hào)里面指定所有部署環(huán)境的一個(gè)集合。這次能把兩個(gè)創(chuàng)建的 Pod 都篩選出來(lái);
14.我們?cè)僭囈幌略鯓訉?duì) Pod 增加一個(gè)注解,注解的話,跟打標(biāo)是一樣的操作,但是把 label 命令改成 annotate 命令;然后,一樣指定類型和對(duì)應(yīng)的名字。后面就不是加上 label 的 k:v 了,而是加上 annotation 的 k:v。這里我們可以指定一個(gè)任意的字符串,比如說(shuō)加上空格、加上逗號(hào)都可以;
15.然后,我們?cè)倏匆幌逻@個(gè) Pod 的一些元數(shù)據(jù),我們這邊能夠看到這個(gè) Pod 的元數(shù)據(jù)里面 annotations,這是有一個(gè) my-annotate 這個(gè) Annotations;
然后我們這里其實(shí)也能夠看到有一個(gè) kubectl apply 的時(shí)候,kubectl 工具增加了一個(gè) annotation,這也是一個(gè) json 串。
16.然后我們?cè)傺菔疽幌驴?Pod 的 Ownereference 是怎么出來(lái)的。原來(lái)的 Pod 都是直接通過創(chuàng)建 Pod 這個(gè)資源方式來(lái)創(chuàng)建的,這次換一種方式來(lái)創(chuàng)建:通過創(chuàng)建一個(gè) ReplicaSet 對(duì)象來(lái)創(chuàng)建 Pod 。首先創(chuàng)建一個(gè) ReplicaSet 對(duì)象,這個(gè) ReplicaSet 對(duì)象可以具體查看一下;
17.我們可以關(guān)注一下這個(gè) ReplicaSet 里面 spec 里面,提到會(huì)創(chuàng)建兩個(gè) Pod,然后 selector 通過匹配部署環(huán)境是 product 生產(chǎn)環(huán)境的這個(gè)標(biāo)簽來(lái)進(jìn)行匹配。所以我們可以看一下,現(xiàn)在集群中的 Pod 情況;
18.將會(huì)發(fā)現(xiàn)多了兩個(gè) Pod,仔細(xì)查看這兩個(gè) Pod,可以看到 ReplicaSet 創(chuàng)建出來(lái)的 Pod 有一個(gè)特點(diǎn),即它會(huì)帶有 Ownereference,然后 Ownereference 里面指向了是一個(gè) replicasets 類型,名字就叫做 nginx-replicasets;
控制型模式最核心的就是控制循環(huán)的概念。在控制循環(huán)中包括了控制器、被控制的系統(tǒng),以及能夠觀測(cè)系統(tǒng)的傳感器,三個(gè)邏輯組件。
當(dāng)然這些組件都是邏輯的,外界通過修改資源 spec 來(lái)控制資源,控制器比較資源 spec 和 status,從而計(jì)算一個(gè) diff,diff 最后會(huì)用來(lái)決定執(zhí)行對(duì)系統(tǒng)進(jìn)行什么樣的控制操作,控制操作會(huì)使得系統(tǒng)產(chǎn)生新的輸出,并被傳感器以資源 status 形式上報(bào),控制器的各個(gè)組件將都會(huì)是獨(dú)立自主地運(yùn)行,不斷使系統(tǒng)向 spec 表示終態(tài)趨近。
控制循環(huán)中邏輯的傳感器主要由 Reflector、Informer、Indexer 三個(gè)組件構(gòu)成。
Reflector 通過 List 和 Watch K8s server 來(lái)獲取資源的數(shù)據(jù)。List 用來(lái)在 Controller 重啟以及 Watch 中斷的情況下,進(jìn)行系統(tǒng)資源的全量更新;而 Watch 則在多次 List 之間進(jìn)行增量的資源更新;Reflector 在獲取新的資源數(shù)據(jù)后,會(huì)在 Delta 隊(duì)列中塞入一個(gè)包括資源對(duì)象信息本身以及資源對(duì)象事件類型的 Delta 記錄,Delta 隊(duì)列中可以保證同一個(gè)對(duì)象在隊(duì)列中僅有一條記錄,從而避免 Reflector 重新 List 和 Watch 的時(shí)候產(chǎn)生重復(fù)的記錄。
Informer 組件不斷地從 Delta 隊(duì)列中彈出 delta 記錄,然后把資源對(duì)象交給 indexer,讓 indexer 把資源記錄在一個(gè)緩存中,緩存在默認(rèn)設(shè)置下是用資源的命名空間來(lái)做索引的,并且可以被 Controller Manager 或多個(gè) Controller 所共享。之后,再把這個(gè)事件交給事件的回調(diào)函數(shù)
控制循環(huán)中的控制器組件主要由事件處理函數(shù)以及 worker 組成,事件處理函數(shù)之間會(huì)相互關(guān)注資源的新增、更新、刪除的事件,并根據(jù)控制器的邏輯去決定是否需要處理。對(duì)需要處理的事件,會(huì)把事件關(guān)聯(lián)資源的命名空間以及名字塞入一個(gè)工作隊(duì)列中,并且由后續(xù)的 worker 池中的一個(gè) Worker 來(lái)處理,工作隊(duì)列會(huì)對(duì)存儲(chǔ)的對(duì)象進(jìn)行去重,從而避免多個(gè) Woker 處理同一個(gè)資源的情況。
Worker 在處理資源對(duì)象時(shí),一般需要用資源的名字來(lái)重新獲得最新的資源數(shù)據(jù),用來(lái)創(chuàng)建或者更新資源對(duì)象,或者調(diào)用其他的外部服務(wù),Worker 如果處理失敗的時(shí)候,一般情況下會(huì)把資源的名字重新加入到工作隊(duì)列中,從而方便之后進(jìn)行重試。
這里舉一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明一下控制循環(huán)的工作原理。
ReplicaSet 是一個(gè)用來(lái)描述無(wú)狀態(tài)應(yīng)用的擴(kuò)縮容行為的資源, ReplicaSet controler 通過監(jiān)聽 ReplicaSet 資源來(lái)維持應(yīng)用希望的狀態(tài)數(shù)量,ReplicaSet 中通過 selector 來(lái)匹配所關(guān)聯(lián)的 Pod,在這里考慮 ReplicaSet rsA 的,replicas 從 2 被改到 3 的場(chǎng)景。
首先,Reflector 會(huì) watch 到 ReplicaSet 和 Pod 兩種資源的變化,為什么我們還會(huì) watch pod 資源的變化稍后會(huì)講到。發(fā)現(xiàn) ReplicaSet 發(fā)生變化后,在 delta 隊(duì)列中塞入了對(duì)象是 rsA,而且類型是更新的記錄。
Informer 一方面把新的 ReplicaSet 更新到緩存中,并與 Namespace nsA 作為索引。另外一方面,調(diào)用 Update 的回調(diào)函數(shù),ReplicaSet 控制器發(fā)現(xiàn) ReplicaSet 發(fā)生變化后會(huì)把字符串的 nsA/rsA 字符串塞入到工作隊(duì)列中,工作隊(duì)列后的一個(gè) Worker 從工作隊(duì)列中取到了 nsA/rsA 這個(gè)字符串的 key,并且從緩存中取到了最新的 ReplicaSet 數(shù)據(jù)。
Worker 通過比較 ReplicaSet 中 spec 和 status 里的數(shù)值,發(fā)現(xiàn)需要對(duì)這個(gè) ReplicaSet 進(jìn)行擴(kuò)容,因此 ReplicaSet 的 Worker 創(chuàng)建了一個(gè) Pod,這個(gè) pod 中的 Ownereference 取向了 ReplicaSet rsA。
然后 Reflector Watch 到的 Pod 新增事件,在 delta 隊(duì)列中額外加入了 Add 類型的 deta 記錄,一方面把新的 Pod 記錄通過 Indexer 存儲(chǔ)到了緩存中,另一方面調(diào)用了 ReplicaSet 控制器的 Add 回調(diào)函數(shù),Add 回調(diào)函數(shù)通過檢查 pod ownerReferences 找到了對(duì)應(yīng)的 ReplicaSet,并把包括 ReplicaSet 命名空間和字符串塞入到了工作隊(duì)列中。
ReplicaSet 的 Woker 在得到新的工作項(xiàng)之后,從緩存中取到了新的 ReplicaSet 記錄,并得到了其所有創(chuàng)建的 Pod,因?yàn)?ReplicaSet 的狀態(tài)不是最新的,也就是所有創(chuàng)建 Pod 的數(shù)量不是最新的。因此在此時(shí) ReplicaSet 更新 status 使得 spec 和 status 達(dá)成一致。
Kubernetes 控制器模式依賴聲明式的 API。另外一種常見的 API 類型是命令式 API。為什么 Kubernetes 采用聲明式 API,而不是命令式 API 來(lái)設(shè)計(jì)整個(gè)控制器呢?
首先,比較兩種 API 在交互行為上的差別。在生活中,常見的命令式的交互方式是家長(zhǎng)和孩子交流方式,因?yàn)楹⒆忧啡蹦繕?biāo)意識(shí),無(wú)法理解家長(zhǎng)期望,家長(zhǎng)往往通過一些命令,教孩子一些明確的動(dòng)作,比如說(shuō):吃飯、睡覺類似的命令。我們?cè)谌萜骶幣朋w系中,命令式 API 就是通過向系統(tǒng)發(fā)出明確的操作來(lái)執(zhí)行的。
而常見的聲明式交互方式,就是老板對(duì)自己?jiǎn)T工的交流方式。老板一般不會(huì)給自己的員工下很明確的決定,實(shí)際上可能老板對(duì)于要操作的事情本身,還不如員工清楚。因此,老板通過給員工設(shè)置可量化的業(yè)務(wù)目標(biāo)的方式,來(lái)發(fā)揮員工自身的主觀能動(dòng)性。比如說(shuō),老板會(huì)要求某個(gè)產(chǎn)品的市場(chǎng)占有率達(dá)到 80%,而不會(huì)指出要達(dá)到這個(gè)市場(chǎng)占有率,要做的具體操作細(xì)節(jié)。
類似的,在容器編排體系中,我們可以執(zhí)行一個(gè)應(yīng)用實(shí)例副本數(shù)保持在 3 個(gè),而不用明確的去擴(kuò)容 Pod 或是刪除已有的 Pod,來(lái)保證副本數(shù)在三個(gè)。
在理解兩個(gè)交互 API 的差別后,可以分析一下命令式 API 的問題。
在大規(guī)模的分布式系統(tǒng)中,錯(cuò)誤是無(wú)處不在的。一旦發(fā)出的命令沒有響應(yīng),調(diào)用方只能通過反復(fù)重試的方式來(lái)試圖恢復(fù)錯(cuò)誤,然而盲目的重試可能會(huì)帶來(lái)更大的問題。
假設(shè)原來(lái)的命令,后臺(tái)實(shí)際上已經(jīng)執(zhí)行完成了,重試后又多執(zhí)行了一個(gè)重試的命令操作。為了避免重試的問題,系統(tǒng)往往還需要在執(zhí)行命令前,先記錄一下需要執(zhí)行的命令,并且在重啟等場(chǎng)景下,重做待執(zhí)行的命令,而且在執(zhí)行的過程中,還需要考慮多個(gè)命令的先后順序、覆蓋關(guān)系等等一些復(fù)雜的邏輯情況。
然而,因?yàn)檠矙z邏輯和日常操作邏輯是不一樣的,往往在測(cè)試上覆蓋不夠,在錯(cuò)誤處理上不夠嚴(yán)謹(jǐn),具有很大的操作風(fēng)險(xiǎn),因此往往很多巡檢系統(tǒng)都是人工來(lái)觸發(fā)的。
假如有多方并發(fā)的對(duì)一個(gè)資源請(qǐng)求進(jìn)行操作,并且一旦其中有操作出現(xiàn)了錯(cuò)誤,就需要重試。那么最后哪一個(gè)操作生效了,就很難確認(rèn),也無(wú)法保證。很多命令式系統(tǒng)往往在操作前會(huì)對(duì)系統(tǒng)進(jìn)行加鎖,從而保證整個(gè)系統(tǒng)最后生效行為的可預(yù)見性,但是加鎖行為會(huì)降低整個(gè)系統(tǒng)的操作執(zhí)行效率。
不需要額外的操作數(shù)據(jù)。另外因?yàn)闋顟B(tài)的冪等性,可以在任意時(shí)刻反復(fù)操作。在聲明式系統(tǒng)運(yùn)行的方式里,正常的操作實(shí)際上就是對(duì)資源狀態(tài)的巡檢,不需要額外開發(fā)巡檢系統(tǒng),系統(tǒng)的運(yùn)行邏輯也能夠在日常的運(yùn)行中得到測(cè)試和錘煉,因此整個(gè)操作的穩(wěn)定性能夠得到保證。
最后,因?yàn)橘Y源的最終狀態(tài)是明確的,我們可以合并多次對(duì)狀態(tài)的修改。可以不需要加鎖,就支持多方的并發(fā)訪問。
最后我們總結(jié)一下:
這里為大家簡(jiǎn)單總結(jié)一下本文的主要內(nèi)容:
阿里巴巴云原生微信公眾號(hào)(ID:Alicloudnative)關(guān)注微服務(wù)、Serverless、容器、Service Mesh 等技術(shù)領(lǐng)域、聚焦云原生流行技術(shù)趨勢(shì)、云原生大規(guī)模的落地實(shí)踐,做最懂云原生開發(fā)者的技術(shù)公眾號(hào)。
文章標(biāo)題:從零開始入門K8s|K8s的應(yīng)用編排與管理
分享地址:http://www.rwnh.cn/article22/igiecc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、企業(yè)網(wǎng)站制作、網(wǎng)站導(dǎo)航、網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)公司、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)