溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

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

發(fā)布時間:2020-08-07 07:10:26 來源:ITPUB博客 閱讀:156 作者:PaaS小魔仙 欄目:服務(wù)器

在本系列的前兩部分中我們介紹了 API Server 的總體流程,以及 API 對象如何存儲到 etcd 中。在本文中我們將探討如何擴(kuò)展 API 資源。

在一開始的時候,擴(kuò)展 API 資源的唯一方法是擴(kuò)展相關(guān) API 源代碼,集成為你所需的資源?;蛘?,推動一個全新的類型為新的核心對象 API 合入社區(qū)代碼。但是,這樣就會導(dǎo)致核心 API 資源類型的不斷增加,直至 API 過載。為了避免這種 API 資源的無限制擴(kuò)展,在 Kubernetes 中提供兩種擴(kuò)展核心 API 的方法:

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

2.     使用與主 API Servers  并行運行的用戶 API Servers UAS )。這種方式,可能更多的設(shè)計代碼開發(fā),可能需要你投入較多的時間及精力。當(dāng)然,這種方式也能夠讓你對 API 資源有更細(xì)致,全面的了解。

在本文中,我們主要對 CRD 相關(guān)定義以及使用進(jìn)行探討。

CRDs 的聲明及創(chuàng)建

在本系列文章第一部分所提到過的,每個 API 資源根據(jù) Group 群組分類,每個對象都有一個對應(yīng)的版本號與 HTTP 路徑相關(guān)聯(lián)?,F(xiàn)在如果想要實現(xiàn)一個 CRD ,首先需要的是就是命名一個新的 API Group 群組,這個 API 群組不能與已經(jīng)存在的群組重復(fù)。在你自己新建的 API 群組中,你可以擁有任意數(shù)量的資源,并且它們可以與其他群組中的資源具有相同的名稱。下面我們來列舉一個實際的例子:

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

在之前我們有介紹過,每個版本的由 API 群組管理的 Kubernetes 資源是跟 HTTP 路徑相關(guān)的。 CRD 類似于面向?qū)ο缶幊讨幸粋€類的定義,而實際使用的 CR 可以看做為它的一組實例。首先我們對例子中的一些字段作說明,第一行中的 CRD apiVersion kube-apiserver 1.7  之后都是這樣定義的。從第 5 行之后我們定義了 spec  的相關(guān)字段。在第 6 spec.group 是定義了你創(chuàng)建的 CRD API 群組(在本例子中定義為了 example.com )。第 7 行定義了 CRD 對象的版本。每個資源只有一個固定版本,但在 API 群組中還是能有多個不同版本的資源。第 8 行的 spec.names 有兩個必填項: kind ,按照慣例第一個字母大寫, plural ,按照慣例全為小寫,這個字段與最終生成的 HTTP 路徑相關(guān),比如在本例子中,最終的 HTTP 路徑為 https://<server/apis/example.com/v1/namespaces/default/databases 。還有一個可選的 singular 字段,默認(rèn)為小寫類型值,可以在 kubectl 的上下文中使用。此外,在 spec.names 中還有許多可選字段,這些字段將會由 API Server 自動生成并填充。

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

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

現(xiàn)在我們根據(jù)上面的 YAML 文件來創(chuàng)建一個 CRD

$ kubectl create -f databases-crd.yaml

customresourcedefinition "databases.example.com" created

由于這個創(chuàng)建過程是異步進(jìn)行的,所以你必須檢查一下你創(chuàng)建的 CRD 的狀態(tài),確認(rèn)你創(chuàng)建的 CRD 沒有與其它資源沖突,并且 API Server 已經(jīng)調(diào)用相關(guān)處理函數(shù)完成創(chuàng)建。你可以在腳本或代碼中通過輪詢完成這個過程。最后我們能得到以下狀態(tài):

$ 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 可以看到我們之前創(chuàng)建的 CRD ,并且顯示出了 CRD 的一些狀態(tài)信息。

CRDs 的使用

通過 kubectl proxy Kubernetes API  開啟本地代理后,查看我們剛才創(chuàng)建的 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"

        }

    ]

}

請注意,在默認(rèn)情況下十分鐘內(nèi), kubectl 是查看存儲在 ~/.kube/cache/discovery 目錄的緩存。所以,可能會需要 10 分鐘后你才能看到你新創(chuàng)建的 CRD 資源。但是,當(dāng)沒有緩存時, kubectl 發(fā)現(xiàn)不了所需的資源時,那么會重新緩存它。

接下來,我們來看一個 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 來監(jiān)控資源的創(chuàng)建與 更新,你可以通過對某個 resourceVersion (我們通過 curl 來實例對指定版本的 database 做監(jiān)控 )之后的修改做監(jiān)控 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" 進(jìn)行監(jiān)控 watch:

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

現(xiàn)在我們新開一個 shell 對話窗口,刪除 wordpress  CRD 資源,我們可以查看剛才的監(jiān)控 watch 窗口是否接收到了這個消息:

$ kubectl delete databases.example.com/wordpress

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

我們可以看到之前監(jiān)控 watch CRD databases API Server 處返回的更新狀態(tài):

{"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 會話的運行及輸出結(jié)果如下圖所示:

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

最后,讓我們看一下 CRD database  的各個數(shù)據(jù)是如何存儲在 etcd 中的。下面是我們直接通過 HTTP API 進(jìn)入 etcd 訪問得到的數(shù)據(jù):

$ 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 數(shù)據(jù)在 etcd 中最終以一個未解析的的狀態(tài)存在?,F(xiàn)在將 CRD 刪除,所有的 CRD 實例也會跟著刪除,這是一個級聯(lián)刪除操作。

目前 CRDs 的使用現(xiàn)狀,局限及將來的展望

CRDs 的發(fā)展現(xiàn)狀如下所示:

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

2.        TPRs 遷移到 CRDs 實例可以參考文檔 migration

3.        支持一個 CRD 中只有單個 version  版本,當(dāng)然,一個群組中可能有多個 version 版本。

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

5.        CRDs 是多版本多分支穩(wěn)定的基礎(chǔ)。關(guān)于 CRD 資源的 JSON-Schema 的格式有效性校驗可以參考文檔 CRD validation proposal 。相關(guān)資源回收可以參考文檔 Garbage collection 。

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

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

2.        Kubernetes1.7 當(dāng)中,目前并沒有對于 CRD 的相關(guān)校驗 validation 。

3.        沒有快速,實時的準(zhǔn)入( admission  )機(jī)制(但是可以支持 webhooks  形式的初始化及準(zhǔn)入)。

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

5.        CRD 目前不支持默認(rèn)值配置,即不支持為特定的字段配默認(rèn)值(在 Kubernetes1.7 后續(xù)的版本中可能會支持)。

為了解決上述的問題,并且靈活的擴(kuò)展 Kubernetes ,你可以運行一個與主 API Server 并行的用戶 API Servers 。我們將在本博文的以后部分中詳細(xì)介紹如何編寫 UAS ,并編寫一個 custom controller  完整使用 CRD  。https://www.huaweicloud.com/product/cce.html


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI