天天看點

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

作者 | 陳顯鹭  阿裡巴巴進階技術專家

本文整理自《CNCF x Alibaba 雲原生技術公開課》第 23 講,點選“閱讀原文”直達課程頁面。

關注“阿裡巴巴雲原生”公衆号,回複關鍵詞“入門”,即可下載下傳從零入門 K8s 系列文章 PPT。

導讀:在 Kubernetes 裡面, API 程式設計範式也就是 Custom Resources Definition(CRD)。我們常講的 CRD,其實指的就是使用者自定義資源。為什麼會存在使用者自定義資源問題呢?本文将會從其需求來源出發,對此概念進行逐漸深入的講解。

一、需求來源

首先我們先來看一下 API 程式設計範式的需求來源。

在 Kubernetes 裡面, API 程式設計範式也就是 Custom Resources Definition(CRD)。我們常講的 CRD,其實指的就是使用者自定義資源。

為什麼會有使用者自定義資源問題呢?

随着 Kubernetes 使用的越來越多,使用者自定義資源的需求也會越來越多。而 Kubernetes 提供的聚合各個子資源的功能,已經不能滿足日益增長的廣泛需求了。使用者希望提供一種使用者自定義的資源,把各個子資源全部聚合起來。但 Kubernetes 原生資源的擴充和使用比較複雜,是以誕生了使用者自定義資源這麼一個功能。

二、用例解讀

CRD 的一個執行個體

我們首先具體地介紹一下 CRD 是什麼。

CRD 功能是在 Kubernetes 1.7 版本被引入的,使用者可以根據自己的需求添加自定義的 Kubernetes 對象資源。值得注意的是,這裡使用者自己添加的 Kubernetes 對象資源都是 native 的、都是一等公民,和 Kubernetes 中自帶的、原生的那些 Pod、Deployment 是同樣的對象資源。在 Kubernetes 的 API Server 看來,它們都是存在于 etcd 中的一等資源。

同時,自定義資源和原生内置的資源一樣,都可以用 kubectl 來去建立、檢視,也享有 RBAC、安全功能。使用者可以開發自定義控制器來感覺或者操作自定義資源的變化。

下面我們來看一個簡單的 CRD 執行個體。下圖是一個 CRD 的定義。

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

首先最上面的 apiVersion 就是指 CRD 的一個 apiVersion 聲明,聲明它是一個 CRD 的需求或者說定義的 Schema。

kind 就是 CustomResourcesDefinition,指 CRD。name 是一個使用者自定義資源中自己自定義的一個名字。一般我們建議使用“頂級域名.xxx.APIGroup”這樣的格式,比如這裡就是 foos.samplecontroller.k8s.io。

spec 用于指定該 CRD 的 group、version。比如在建立 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 可以被建立到不同的命名空間裡,那麼它們的 scope 就是 Namespaced 的。這裡的 CRD 就是 Namespaced 的。

下圖就是上圖所定義的 CRD 的一個執行個體。

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結
  • 它的 apiVersion 就是我們剛才所定義的 samplecontroller.k8s.io/v1alpha1;
  • kind 就是 Foo;
  • metadata 的 name 就是我們這個例子的名字;
  • 這個執行個體中 spec 字段其實沒有在 CRD 的 Schema 中定義,我們可以在 spec 中根據自己的需求來寫一寫,格式就是 key:value 這種格式,比如圖中的 deploymentName: example-foo, replicas: 1。當然我們也可以去做一些檢驗或者狀态資源去定義 spec 中到底包含什麼。

帶有校驗的 CRD

我們來看一個包含校驗的 CRD 定義:

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

可以看到這個定義更加複雜了,validation 之前的字段我們就不再贅述了,單獨看校驗這一段。

它首先是一個 openAPIV3Schema 的定義,spec 中則定義了有哪些資源,以 replicas 為例,這裡将 replicas 定義為一個 integer 的資源,最小值為 1,最大值是 10。那麼,當我們再次使用這個 CRD 的時候,如果我們給出的 replicas 不是 int 值,或者去寫一個 -1,或者大于 10 的值,這個 CRD 對象就不會被送出到 API Server,API Server 會直接報錯,告訴你不滿足所定義的參數條件。

帶有狀态字段的 CRD

再來看一下帶有狀态字段的 CRD 定義。

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

我們在使用一些 Deployment 或 Pod 的時候,部署完成之後可能要去檢視目前部署的狀态、是否更新等等。這些都是通過增加狀态字段來實作的。另外,Kubernetes 在 1.12 版本之前,還沒有狀态字段。

狀态實際上是一個自定義資源的子資源,它的好處在于,對該字段的更新并不會觸發 Deployment 或 Pod 的重新部署。我們知道對于某些 Deployment 和 Pod,隻要修改了某些 spec,它就會重新建立一個新的 Deployment 或者 Pod 出來。但是狀态資源并不會被重新建立,它隻是用來回應目前 Pod 的整個狀态。上圖中的 CRD 聲明中它的子資源的狀态非常簡單,就是一個 key:value 的格式。在 "{}" 裡寫什麼,都是自定義的。

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

以一個 Deployment 的狀态字段為例,它包含 availableReplicas、目前的狀态(比如更新到第幾個版本了、上一個版本是什麼時候)等等這些資訊。在使用者自定義 CRD 的時候,也可以進行一些複雜的操作來告訴别的使用者它目前的狀态如何。

三、操作示範

下面我們來具體示範一下 CRD。

我們這裡有兩個資源:crd.yaml 和 example-foo.yaml。

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

首先建立一下這個 CRD 的 Schema 讓我們的 Kubernetes Server 知道該 CRD 到底是什麼樣的。建立的方式非常簡單,就是 "kuberctl create -f crd.yaml"。

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

通過 "kuberctl get crd" 可以看到剛才的 CRD 已經被建立成功了。

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

這個時候我們就可以去建立對應的資源 "kuberctl create -f example-foo.yaml":

下面來看一下它裡面到底有什麼東西 "kubectl get foo example-foo -o yaml" :

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

可以看到它是一個 Foo 的資源,spec 就是我們剛才所定義的,被選中的部分是基本上所有的 Kubernetes 的 metadata 資源中都會有的。是以,建立該資源和我們正常建立一個 Pod 的差別并不大,但是這個資源不是一個 Pod,也不是 Kubernetes 本身内置的資源,這就是一個我們自己建立的資源。從使用方式和使用體驗上來說,和 Kubernetes 内置資源的使用幾乎一緻。

四、架構設計

控制器概覽

隻定義一個 CRD 其實沒有什麼作用,它隻會被 API Server 簡單地計入到 etcd 中。如何依據這個 CRD 定義的資源和 Schema 來做一些複雜的操作,則是由 Controller,也就是控制器來實作的。

Controller 其實是 Kubernetes 提供的一種可插拔式的方法來擴充或者控制聲明式的 Kubernetes 資源。它是 Kubernetes 的大腦,負責大部分資源的控制操作。以 Deployment 為例,它就是通過 kube-controller-manager 來部署的。

比如說聲明一個 Deployment 有 replicas、有 2 個 Pod,那麼 kube-controller-manager 在觀察 etcd 時接收到了該請求之後,就會去建立兩個對應的 Pod 的副本,并且它會去實時地觀察着這些 Pod 的狀态,如果這些 Pod 發生變化了、復原了、失敗了、重新開機了等等,它都會去做一些對應的操作。

是以 Controller 才是控制整個 Kubernetes 資源最終表現出來的狀态的大腦。

使用者聲明完成 CRD 之後,也需要建立一個控制器來完成對應的目标。比如之前的 Foo,它希望去建立一個 Deployment,replicas 為 1,這就需要我們建立一個控制器用于建立對應的 Deployment 才能真正實作 CRD 的功能。

控制器工作流程概覽

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

這裡以 kube-controller-manager 為例。

如上圖所示,左側是一個 Informer,它的機制就是通過去 watch kube-apiserver,而 kube-apiserver 會去監督所有 etcd 中資源的建立、更新與删除。Informer 主要有兩個方法:一個是 ListFunc;一個是 WatchFunc。

  • ListFunc 就是像 "kuberctl get pods" 這類操作,把目前所有的資源都列出來;
  • WatchFunc 會和 apiserver 建立一個長連結,一旦有一個新的對象送出上去之後,apiserver 就會反向推送回來,告訴 Informer 有一個新的對象建立或者更新等操作。

Informer 接收到了對象的需求之後,就會調用對應的函數(比如圖中的三個函數 AddFunc, UpdateFunc 以及 DeleteFunc),并将其按照 key 值的格式放到一個隊列中去,key 值的命名規則就是 "namespace/name",name 就是對應的資源的名字。比如我們剛才所說的在 default 的 namespace 中建立一個 foo 類型的資源,那麼它的 key 值就是 "default/example-foo"。Controller 從隊列中拿到一個對象之後,就會去做相應的操作。

下圖就是控制器的工作流程。

從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結

首先,通過 kube-apiserver 來推送事件,比如 Added, Updated, Deleted;然後進入到 Controller 的 ListAndWatch() 循環中;ListAndWatch 中有一個先入先出的隊列,在操作的時候就将其 Pop() 出來;然後去找對應的 Handler。Handler 會将其交給對應的函數(比如 Add(), Update(), Delete())。

一個函數一般會有多個 Worker。多個 Worker 的意思是說比如同時有好幾個對象進來,那麼這個 Controller 可能會同時啟動五個、十個這樣的 Worker 來并行地執行,每個 Worker 可以處理不同的對象執行個體。

工作完成之後,即把對應的對象建立出來之後,就把這個 key 丢掉,代表已經處理完成。如果處理過程中有什麼問題,就直接報錯,打出一個事件來,再把這個 key 重新放回到隊列中,下一個 Worker 就可以接收過來繼續進行相同的處理。

五、本文總結

本文的主要内容就到此為止了,這裡為大家簡單總結一下:

  • CRD 是 Custom Resources Definition 的縮寫,也就是使用者自定義資源,使用者可以使用這個功能擴充自己的Kubernetes 原生資源資訊;
  • CRD 和普通的 Kubernetes 資源一樣,都可以受 RBAC 權限控制,并且支援 status 狀态字段;
  • CRD-controller 也就是 CRD 控制器,能夠實作使用者自行編寫,并且解析 CRD 并把它變成使用者期望的狀态。
從零開始入門 K8s | Kubernetes API 程式設計範式一、需求來源二、用例解讀三、操作示範四、架構設計五、本文總結
阿裡巴巴雲原生 關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術圈。”
上一篇: css 字型
下一篇: 等寬字型

繼續閱讀