這篇文章給大家介紹如何理解Kubernetes API 編程范式,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
在遷安等地區(qū),都構建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都網(wǎng)站設計、做網(wǎng)站 網(wǎng)站設計制作按需設計,公司網(wǎng)站建設,企業(yè)網(wǎng)站建設,品牌網(wǎng)站建設,成都全網(wǎng)營銷,外貿(mào)網(wǎng)站制作,遷安網(wǎng)站建設費用合理。
首先我們先來看一下 API 編程范式的需求來源。
在 Kubernetes 里面, API 編程范式也就是 Custom Resources Definition(CRD)。我們常講的 CRD,其實指的就是用戶自定義資源。
為什么會有用戶自定義資源問題呢?
隨著 Kubernetes 使用的越來越多,用戶自定義資源的需求也會越來越多。而 Kubernetes 提供的聚合各個子資源的功能,已經(jīng)不能滿足日益增長的廣泛需求了。用戶希望提供一種用戶自定義的資源,把各個子資源全部聚合起來。但 Kubernetes 原生資源的擴展和使用比較復雜,因此誕生了用戶自定義資源這么一個功能。
我們首先具體地介紹一下 CRD 是什么。
CRD 功能是在 Kubernetes 1.7 版本被引入的,用戶可以根據(jù)自己的需求添加自定義的 Kubernetes 對象資源。值得注意的是,這里用戶自己添加的 Kubernetes 對象資源都是 native 的、都是一等公民,和 Kubernetes 中自帶的、原生的那些 Pod、Deployment 是同樣的對象資源。在 Kubernetes 的 API Server 看來,它們都是存在于 etcd 中的一等資源。
同時,自定義資源和原生內(nèi)置的資源一樣,都可以用 kubectl 來去創(chuàng)建、查看,也享有 RBAC、安全功能。用戶可以開發(fā)自定義控制器來感知或者操作自定義資源的變化。
下面我們來看一個簡單的 CRD 實例。下圖是一個 CRD 的定義。
首先最上面的 apiVersion 就是指 CRD 的一個 apiVersion 聲明,聲明它是一個 CRD 的需求或者說定義的 Schema。
kind 就是 CustomResourcesDefinition,指 CRD。name 是一個用戶自定義資源中自己自定義的一個名字。一般我們建議使用“頂級域名.xxx.APIGroup”這樣的格式,比如這里就是 foos.samplecontroller.k8s.io。
spec 用于指定該 CRD 的 group、version。比如在創(chuàng)建 Pod 或者 Deployment 時,它的 group 可能為 apps/v1 或者 apps/v1beta1 之類,這里我們也同樣需要去定義 CRD 的 group。
圖中的 group 為 samplecontroller.k8s.io;
verison 為 v1alpha1;
names 指的是它的 kind 是什么,比如 Deployment 的 kind 就是 Deployment,Pod 的 kind 就是 Pod,這里的 kind 被定義為了 Foo;
plural 字段就是一個昵稱,比如當一些字段或者一些資源的名字比較長時,可以用該字段自定義一些昵稱來簡化它的長度;
scope 字段表明該 CRD 是否被命名空間管理。比如 ClusterRoleBinding 就是 Cluster 級別的。再比如 Pod、Deployment 可以被創(chuàng)建到不同的命名空間里,那么它們的 scope 就是 Namespaced 的。這里的 CRD 就是 Namespaced 的。
下圖就是上圖所定義的 CRD 的一個實例。
它的 apiVersion 就是我們剛才所定義的 samplecontroller.k8s.io/v1alpha1;
kind 就是 Foo;
metadata 的 name 就是我們這個例子的名字;
這個實例中 spec 字段其實沒有在 CRD 的 Schema 中定義,我們可以在 spec 中根據(jù)自己的需求來寫一寫,格式就是 key:value 這種格式,比如圖中的 deploymentName: example-foo, replicas: 1。當然我們也可以去做一些檢驗或者狀態(tài)資源去定義 spec 中到底包含什么。
我們來看一個包含校驗的 CRD 定義:
可以看到這個定義更加復雜了,validation 之前的字段我們就不再贅述了,單獨看校驗這一段。
它首先是一個 openAPIV3Schema 的定義,spec 中則定義了有哪些資源,以 replicas 為例,這里將 replicas 定義為一個 integer 的資源,最小值為 1,最大值是 10。那么,當我們再次使用這個 CRD 的時候,如果我們給出的 replicas 不是 int 值,或者去寫一個 -1,或者大于 10 的值,這個 CRD 對象就不會被提交到 API Server,API Server 會直接報錯,告訴你不滿足所定義的參數(shù)條件。
再來看一下帶有狀態(tài)字段的 CRD 定義。
我們在使用一些 Deployment 或 Pod 的時候,部署完成之后可能要去查看當前部署的狀態(tài)、是否更新等等。這些都是通過增加狀態(tài)字段來實現(xiàn)的。另外,Kubernetes 在 1.12 版本之前,還沒有狀態(tài)字段。
狀態(tài)實際上是一個自定義資源的子資源,它的好處在于,對該字段的更新并不會觸發(fā) Deployment 或 Pod 的重新部署。我們知道對于某些 Deployment 和 Pod,只要修改了某些 spec,它就會重新創(chuàng)建一個新的 Deployment 或者 Pod 出來。但是狀態(tài)資源并不會被重新創(chuàng)建,它只是用來回應當前 Pod 的整個狀態(tài)。上圖中的 CRD 聲明中它的子資源的狀態(tài)非常簡單,就是一個 key:value 的格式。在 “{}” 里寫什么,都是自定義的。
以一個 Deployment 的狀態(tài)字段為例,它包含 availableReplicas、當前的狀態(tài)(比如更新到第幾個版本了、上一個版本是什么時候)等等這些信息。在用戶自定義 CRD 的時候,也可以進行一些復雜的操作來告訴別的用戶它當前的狀態(tài)如何。
下面我們來具體演示一下 CRD。
我們這里有兩個資源:crd.yaml 和 example-foo.yaml。
首先創(chuàng)建一下這個 CRD 的 Schema 讓我們的 Kubernetes Server 知道該 CRD 到底是什么樣的。創(chuàng)建的方式非常簡單,就是 “kuberctl create -f crd.yaml”。
通過 “kuberctl get crd” 可以看到剛才的 CRD 已經(jīng)被創(chuàng)建成功了。
這個時候我們就可以去創(chuàng)建對應的資源 “kuberctl create -f example-foo.yaml”:
下面來看一下它里面到底有什么東西 “kubectl get foo example-foo -o yaml” :
可以看到它是一個 Foo 的資源,spec 就是我們剛才所定義的,被選中的部分是基本上所有的 Kubernetes 的 metadata 資源中都會有的。因此,創(chuàng)建該資源和我們正常創(chuàng)建一個 Pod 的區(qū)別并不大,但是這個資源不是一個 Pod,也不是 Kubernetes 本身內(nèi)置的資源,這就是一個我們自己創(chuàng)建的資源。從使用方式和使用體驗上來說,和 Kubernetes 內(nèi)置資源的使用幾乎一致。
只定義一個 CRD 其實沒有什么作用,它只會被 API Server 簡單地計入到 etcd 中。如何依據(jù)這個 CRD 定義的資源和 Schema 來做一些復雜的操作,則是由 Controller,也就是控制器來實現(xiàn)的。
Controller 其實是 Kubernetes 提供的一種可插拔式的方法來擴展或者控制聲明式的 Kubernetes 資源。它是 Kubernetes 的大腦,負責大部分資源的控制操作。以 Deployment 為例,它就是通過 kube-controller-manager 來部署的。
比如說聲明一個 Deployment 有 replicas、有 2 個 Pod,那么 kube-controller-manager 在觀察 etcd 時接收到了該請求之后,就會去創(chuàng)建兩個對應的 Pod 的副本,并且它會去實時地觀察著這些 Pod 的狀態(tài),如果這些 Pod 發(fā)生變化了、回滾了、失敗了、重啟了等等,它都會去做一些對應的操作。
所以 Controller 才是控制整個 Kubernetes 資源最終表現(xiàn)出來的狀態(tài)的大腦。
用戶聲明完成 CRD 之后,也需要創(chuàng)建一個控制器來完成對應的目標。比如之前的 Foo,它希望去創(chuàng)建一個 Deployment,replicas 為 1,這就需要我們創(chuàng)建一個控制器用于創(chuàng)建對應的 Deployment 才能真正實現(xiàn) CRD 的功能。
這里以 kube-controller-manager 為例。
如上圖所示,左側是一個 Informer,它的機制就是通過去 watch kube-apiserver,而 kube-apiserver 會去監(jiān)督所有 etcd 中資源的創(chuàng)建、更新與刪除。Informer 主要有兩個方法:一個是 ListFunc;一個是 WatchFunc。
ListFunc 就是像 “kuberctl get pods” 這類操作,把當前所有的資源都列出來;
WatchFunc 會和 apiserver 建立一個長鏈接,一旦有一個新的對象提交上去之后,apiserver 就會反向推送回來,告訴 Informer 有一個新的對象創(chuàng)建或者更新等操作。
Informer 接收到了對象的需求之后,就會調(diào)用對應的函數(shù)(比如圖中的三個函數(shù) AddFunc, UpdateFunc 以及 DeleteFunc),并將其按照 key 值的格式放到一個隊列中去,key 值的命名規(guī)則就是 “namespace/name”,name 就是對應的資源的名字。比如我們剛才所說的在 default 的 namespace 中創(chuàng)建一個 foo 類型的資源,那么它的 key 值就是 “default/example-foo”。Controller 從隊列中拿到一個對象之后,就會去做相應的操作。
下圖就是控制器的工作流程。
首先,通過 kube-apiserver 來推送事件,比如 Added, Updated, Deleted;然后進入到 Controller 的 ListAndWatch() 循環(huán)中;ListAndWatch 中有一個先入先出的隊列,在操作的時候就將其 Pop() 出來;然后去找對應的 Handler。Handler 會將其交給對應的函數(shù)(比如 Add(), Update(), Delete())。
一個函數(shù)一般會有多個 Worker。多個 Worker 的意思是說比如同時有好幾個對象進來,那么這個 Controller 可能會同時啟動五個、十個這樣的 Worker 來并行地執(zhí)行,每個 Worker 可以處理不同的對象實例。
工作完成之后,即把對應的對象創(chuàng)建出來之后,就把這個 key 丟掉,代表已經(jīng)處理完成。如果處理過程中有什么問題,就直接報錯,打出一個事件來,再把這個 key 重新放回到隊列中,下一個 Worker 就可以接收過來繼續(xù)進行相同的處理。
這里為大家簡單總結一下:
CRD 是 Custom Resources Definition 的縮寫,也就是用戶自定義資源,用戶可以使用這個功能擴展自己的Kubernetes 原生資源信息;
CRD 和普通的 Kubernetes 資源一樣,都可以受 RBAC 權限控制,并且支持 status 狀態(tài)字段;
CRD-controller 也就是 CRD 控制器,能夠?qū)崿F(xiàn)用戶自行編寫,并且解析 CRD 并把它變成用戶期望的狀態(tài)。
關于如何理解Kubernetes API 編程范式就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。