深度剖析Kubernetes API Server三部曲 - part 3

PaaS小魔仙發表於2018-08-30

在本系列的前兩部分中我們介紹了 API Server 的總體流程,以及 API 物件如何儲存到 etcd 中。在本文中我們將探討如何擴充套件 API 資源。

在一開始的時候,擴充套件 API 資源的唯一方法是擴充套件相關 API 原始碼,整合為你所需的資源。或者,推動一個全新的型別為新的核心物件 API 合入社群程式碼。但是,這樣就會導致核心 API 資源型別的不斷增加,直至 API 過載。為了避免這種 API 資源的無限制擴充套件,在 Kubernetes 中提供兩種擴充套件核心 API 的方法:

1.     使用自定義資源定義( CRDs ),最開始的時候被稱為第三方資源( TPRs )。透過 CRD 你能夠簡單而靈活的方式定義自己的資源物件型別,並讓 API server 處理整個生命週期。

2.     使用與主 API Servers  並行執行的使用者 API Servers UAS )。這種方式,可能更多的設計程式碼開發,可能需要你投入較多的時間及精力。當然,這種方式也能夠讓你對 API 資源有更細緻,全面的瞭解。

在本文中,我們主要對 CRD 相關定義以及使用進行探討。

CRDs 的宣告及建立

在本系列文章第一部分所提到過的,每個 API 資源根據 Group 群組分類,每個物件都有一個對應的版本號與 HTTP 路徑相關聯。現在如果想要實現一個 CRD ,首先需要的是就是命名一個新的 API Group 群組,這個 API 群組不能與已經存在的群組重複。在你自己新建的 API 群組中,你可以擁有任意數量的資源,並且它們可以與其他群組中的資源具有相同的名稱。下面我們來列舉一個實際的例子:

在之前我們有介紹過,每個版本的由 API 群組管理的 Kubernetes 資源是跟 HTTP 路徑相關的。 CRD 類似於物件導向程式設計中一個類的定義,而實際使用的 CR 可以看做為它的一組例項。首先我們對例子中的一些欄位作說明,第一行中的 CRD apiVersion kube-apiserver 1.7  之後都是這樣定義的。從第 5 行之後我們定義了 spec  的相關欄位。在第 6 spec.group 是定義了你建立的 CRD API 群組(在本例子中定義為了 example.com )。第 7 行定義了 CRD 物件的版本。每個資源只有一個固定版本,但在 API 群組中還是能有多個不同版本的資源。第 8 行的 spec.names 有兩個必填項: kind ,按照慣例第一個字母大寫, plural ,按照慣例全為小寫,這個欄位與最終生成的 HTTP 路徑相關,比如在本例子中,最終的 HTTP 路徑為 。還有一個可選的 singular 欄位,預設為小寫型別值,可以在 kubectl 的上下文中使用。此外,在 spec.names 中還有許多可選欄位,這些欄位將會由 API Server 自動生成並填充。

上面的 kind 主要是用來描述物件的型別,而 resource  資源是與 HTTP 路徑相關的。大多數情況下這兩個是匹配的;但是在某些特定情況下在相同的 API HTTP 路徑下可能返回不通的 kind (比如 Status  錯誤物件會返回另一種 kind )。

值得注意的是 resource  資源(在本例中是 databases )和 group 群組(本例中是 example.com )必須與 metadata.name  欄位匹配(本例為第四行 databases. example.com )。

現在我們根據上面的 YAML 檔案來建立一個 CRD

$ kubectl create -f databases-crd.yaml

customresourcedefinition "databases.example.com" created

由於這個建立過程是非同步進行的,所以你必須檢查一下你建立的 CRD 的狀態,確認你建立的 CRD 沒有與其它資源衝突,並且 API Server 已經呼叫相關處理函式完成建立。你可以在指令碼或程式碼中透過輪詢完成這個過程。最後我們能得到以下狀態:

$ kubectl get crd databases.example.com -o yaml

apiVersion: apiextensions.k8s.io/v1beta1

kind: CustomResourceDefinition

metadata:

  creationTimestamp: 2017-08-09T09:21:43Z

  name: databases.example.com

  resourceVersion: "792"

  selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/databases.example.com

  uid: 28c94a05-7ce4-11e7-888c-42010a9a0fd5

spec:

  group: example.com

  names:

    kind: Database

    listKind: DatabaseList

    plural: databases

    singular: database

  scope: Namespaced

  version: v1

status:

  acceptedNames:

    kind: Database

    listKind: DatabaseList

    plural: databases

    singular: database

  conditions:

  - lastTransitionTime: null

    message: no conflicts found

    reason: NoConflicts

    status: "True"

    type: NamesAccepted

  - lastTransitionTime: 2017-08-09T09:21:43Z

    message: the initial names have been accepted

    reason: InitialNamesAccepted

    status: "True"

    type: Established

以上,我們可以看到透過 kubectl 可以看到我們之前建立的 CRD ,並且顯示出了 CRD 的一些狀態資訊。

CRDs 的使用

透過 kubectl proxy Kubernetes API  開啟本地代理後,檢視我們剛才建立的 CRD:

$ http 127.0.0.1:8001/apis/example.com

HTTP/1.1 200 OK

Content-Length: 223

Content-Type: application/json

Date: Wed, 09 Aug 2017 09:25:44 GMT

 

{

    "apiVersion": "v1",

    "kind": "APIGroup",

    "name": "example.com",

    "preferredVersion": {

        "groupVersion": "example.com/v1",

        "version": "v1"

    },

    "serverAddressByClientCIDRs": null,

    "versions": [

        {

            "groupVersion": "example.com/v1",

            "version": "v1"

        }

    ]

}

請注意,在預設情況下十分鐘內, kubectl 是檢視儲存在 ~/.kube/cache/discovery 目錄的快取。所以,可能會需要 10 分鐘後你才能看到你新建立的 CRD 資源。但是,當沒有快取時, kubectl 發現不了所需的資源時,那麼會重新快取它。

接下來,我們來看一個 CRD 例項:

$ cat wordpress-database.yaml

apiVersion: example.com/v1

kind:       Database

metadata:

  name:     wordpress

spec:

  user:     wp

  password: secret

  encoding: unicode

 

$ kubectl create -f wordpress-databases.yaml

database "wordpress" created

 

$ kubectl get databases.example.com

NAME        KIND

wordpress   Database.v1.example.com

想要透過 API 來監控資源的建立與 更新,你可以透過對某個 resourceVersion (我們透過 curl 來例項對指定版本的 database 做監控 )之後的修改做監控 watch

$ http 127.0.0.1:8001/apis/example.com/v1/namespaces/default/databases

HTTP/1.1 200 OK

Content-Length: 593

Content-Type: application/json

Date: Wed, 09 Aug 2017 09:38:49 GMT

 

{

    "apiVersion": "example.com/v1",

    "items": [

        {

            "apiVersion": "example.com/v1",

            "kind": "Database",

            "metadata": {

                "clusterName": "",

                "creationTimestamp": "2017-08-09T09:38:30Z",

                "deletionGracePeriodSeconds": null,

                "deletionTimestamp": null,

                "name": "wordpress",

                "namespace": "default",

                "resourceVersion": "2154",

                "selfLink": "/apis/example.com/v1/namespaces/default/databases/wordpress",

                "uid": "8101a7af-7ce6-11e7-888c-42010a9a0fd5"

            },

            "spec": {

                "encoding": "unicode",

                "password": "secret",

                "user": "wp"

            }

        }

    ],

    "kind": "DatabaseList",

    "metadata": {

        "resourceVersion": "2179",

        "selfLink": "/apis/example.com/v1/namespaces/default/databases"

    }

}

我們可以對 /apis/example.com/v1/namespaces/default/databases/wordpress CRD HTTP 路徑 透過 curl 命令對的 "resourceVersion": "2154" 進行監控 watch:

$ curl -f 127.0.0.1:8001/apis/example.com/v1/namespaces/default/databases?watch=true&resourceVersion=2154

現在我們新開一個 shell 對話視窗,刪除 wordpress  CRD 資源,我們可以檢視剛才的監控 watch 視窗是否接收到了這個訊息:

$ kubectl delete databases.example.com/wordpress

請注意:我們能夠使用 kubectl delete database wordpress 刪除 CRD 資源,是因為之前在 Kubernetes 沒有定義有 database  資源。此外, database  是我們 CRD 中的 spec.name.singular 欄位 ,從英語語法派生而來。

我們可以看到之前監控 watch CRD databases API Server 處返回的更新狀態:

{"type":"DELETED","object":{"apiVersion":"example.com/v1","kind":"Database","metadata":{"clusterName":"","creationTimestamp":"2017-0[0/515]

:38:30Z","deletionGracePeriodSeconds":null,"deletionTimestamp":null,"name":"wordpress","namespace":"default","resourceVersion":"2154","selfLink":"/apis/example.com/v1/namespaces/

default/databases/wordpress","uid":"8101a7af-7ce6-11e7-888c-42010a9a0fd5"},"spec":{"encoding":"unicode","password":"secret","user":"wp"}}}

上述 shell 會話的執行及輸出結果如下圖所示:

最後,讓我們看一下 CRD database  的各個資料是如何儲存在 etcd 中的。下面是我們直接透過 HTTP API 進入 etcd 訪問得到的資料:

$ curl -s localhost:2379/v2/keys/registry/example.com/databases/default | jq .

{

  "action": "get",

  "node": {

    "key": "/registry/example.com/databases/default",

    "dir": true,

    "nodes": [

      {

        "key": "/registry/example.com/databases/default/wordpress",

        "value": "{\"apiVersion\":\"example.com/v1\",\"kind\":\"Database\",\"metadata\":{\"clusterName\":\"\",\"creationTimestamp\":\"2017-08-09T14:53:40Z\",\"deletionGracePeriodSeconds\":null,\"deletionTimestamp\":null,\"name\":\"wordpress\",\"namespace\":\"default\",\"selfLink\":\"\",\"uid\":\"8837f788-7d12-11e7-9d28-080027390640\"},\"spec\":{\"encoding\":\"unicode\",\"password\":\"secret\",\"user\":\"wp\"}}\n",

        "modifiedIndex": 670,

        "createdIndex": 670

      }

    ],

    "modifiedIndex": 670,

    "createdIndex": 670

  }

}

從上面可以看到, CRD 資料在 etcd 中最終以一個未解析的的狀態存在。現在將 CRD 刪除,所有的 CRD 例項也會跟著刪除,這是一個級聯刪除操作。

目前 CRDs 的使用現狀,侷限及將來的展望

CRDs 的發展現狀如下所示:

1.        Kubernetes 1.7 版本中 CRDs 開始取代 ThirdPartyResources  (TPRs)  ,並且 TPRs  將會在 Kubernetes 1.8 被刪除。

2.        TPRs 遷移到 CRDs 例項可以參考文件

3.        支援一個 CRD 中只有單個 version  版本,當然,一個群組中可能有多個 version 版本。

4.        CRDs 提供一個 API 方案,在使用者角度看它與 Kubernetes 原生的 API 資源基本沒有區別

5.        CRDs 是多版本多分支穩定的基礎。關於 CRD 資源的 JSON-Schema 的格式有效性校驗可以參考文件 。相關資源回收可以參考文件 Garbage collection

接下去我們來看一下一些 CRDs 的侷限:

1.        CRD 不提供版本轉換功能,也就是說,每個 CRD 只能有一個版本(預計不會在近期或中期內看到支援 CRD 版本轉換)。

2.        Kubernetes1.7 當中,目前並沒有對於 CRD 的相關校驗 validation

3.        沒有快速,實時的准入( admission  )機制(但是可以支援 webhooks  形式的初始化及准入)。

4.        Kubernetes1.7 中你不能定義子資源( sub-resources ),比如 scale 或者 status ,不過目前有在這方面   的討論。

5.        CRD 目前不支援預設值配置,即不支援為特定的欄位配預設值(在 Kubernetes1.7 後續的版本中可能會支援)。

為了解決上述的問題,並且靈活的擴充套件 Kubernetes ,你可以執行一個與主 API Server 並行的使用者 API Servers 。我們將在本博文的以後部分中詳細介紹如何編寫 UAS ,並編寫一個 custom controller  完整使用 CRD  。https://www.huaweicloud.com/product/cce.html


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31543630/viewspace-2213245/,如需轉載,請註明出處,否則將追究法律責任。

相關文章