在本系列的前兩部分中我們介紹了 API Server 的總體流程,以及 API 對象如何存儲到 etcd 中。在本文中我們將探討如何擴展 API 資源。
創(chuàng)新互聯(lián)建站-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比靜寧網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式靜寧網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋靜寧地區(qū)。費用合理售后完善,10余年實體公司更值得信賴。在一開始的時候,擴展 API 資源的唯一方法是擴展相關(guān) API 源代碼,集成為你所需的資源?;蛘撸苿右粋€全新的類型為新的核心對象 API 合入社區(qū)代碼。但是,這樣就會導(dǎo)致核心 API 資源類型的不斷增加,直至 API 過載。為了避免這種 API 資源的無限制擴展,在 Kubernetes 中提供兩種擴展核心 API 的方法:
1. 使用自定義資源定義( CRDs ),最開始的時候被稱為第三方資源( TPRs )。通過 CRD 你能夠簡單而靈活的方式定義自己的資源對象類型,并讓 API server 處理整個生命周期。
2. 使用與主 API Servers 并行運行的用戶 API Servers ( UAS )。這種方式,可能更多的設(shè)計代碼開發(fā),可能需要你投入較多的時間及精力。當(dāng)然,這種方式也能夠讓你對 API 資源有更細致,全面的了解。
在本文中,我們主要對 CRD 相關(guā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ù)量的資源,并且它們可以與其他群組中的資源具有相同的名稱。下面我們來列舉一個實際的例子:
在之前我們有介紹過,每個版本的由
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:// 上面的
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)建過程是異步進行的,所以你必須檢查一下你創(chuàng)建的
CRD
的狀態(tài),確認你創(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" } ] } 請注意,在默認情況下十分鐘內(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
(我們通過
$ 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"
進行監(jiān)控
watch: $ curl -f 127.0.0.1:8001/apis/example.com/v1/namespaces/default/databases?watch=true&resourceVersion=2154 現(xiàn)在我們新開一個
shell
對話窗口,刪除
$ 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é)果如下圖所示: 最后,讓我們看一下
CRD database
的各個數(shù)據(jù)是如何存儲在
etcd
中的。下面是我們直接通過
HTTP API
進入
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
開始取代
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
)機制(但是可以支持
webhooks
形式的初始化及準(zhǔn)入)。 4.
在
Kubernetes1.7
中你不能定義子資源(
sub-resources
),比如
scale
或者
status
,不過目前有在這方面
proposal
的討論。 5.
CRD
目前不支持默認值配置,即不支持為特定的字段配默認值(在
Kubernetes1.7
后續(xù)的版本中可能會支持)。 為了解決上述的問題,并且靈活的擴展
Kubernetes
,你可以運行一個與主
API Server
并行的用戶
API Servers
。我們將在本博文的以后部分中詳細介紹如何編寫
UAS
,并編寫一個
custom controller
完整使用
CRD
。https://www.huaweicloud.com/product/cce.html
curl
來實例對指定版本的
database
做監(jiān)控
)之后的修改做監(jiān)控
watch
。
wordpress
CRD
資源,我們可以查看剛才的監(jiān)控
watch
窗口是否接收到了這個消息:
ThirdPartyResources
(TPRs)
,并且
TPRs
將會在
Kubernetes 1.8
被刪除。
文章標(biāo)題:深度剖析KubernetesAPIServer三部曲-part3-創(chuàng)新互聯(lián)
網(wǎng)頁鏈接:http://weahome.cn/article/pcihd.html