【云原生】Kubernetes CRD 詳解(Custom Resource Definition)
一、概述
CRD(Custom Resource Definition) 本身是一種 Kubernetes 內(nèi)置的資源類型,即自定義資源的定義,用于描述用戶定義的資源是什么樣子。CRD 的相關(guān)概念:
- CRD 是 v1.7 +新增的無需改變代碼 就可以擴(kuò)展 Kubernetes API 的機(jī)制,用來管理自定義對(duì)象。它實(shí)際上是ThirdPartyResources(TPR) 的升級(jí)版本,而 TPR 已經(jīng)在 v1.8 中刪除。
- 從 Kubernetes 的用戶角度來看,所有東西都叫資源 Resource,就是 Yaml 里的字段 Kind 的內(nèi)容,例如 Service、Deployment 等。
- 除了常見內(nèi)置資源之外,Kubernetes 允許用戶自定義資源 Custom Resource,而 CRD 表示自定義資源的定義。
- 當(dāng)你創(chuàng)建新的 CustomResourceDefinition(CRD)時(shí),Kubernetes API 服務(wù)器會(huì)為你所指定的每個(gè)版本生成一個(gè)新的 RESTful 資源路徑。
- 基于 CRD 對(duì)象所創(chuàng)建的自定義資源可以是名字空間作用域的,也可以是集群作用域的, 取決于 CRD 對(duì)象 spec.scope 字段的設(shè)置。
- 定義 CRD 對(duì)象的操作會(huì)使用你所設(shè)定的名字和模式定義(Schema)創(chuàng)建一個(gè)新的定制資源, Kubernetes API 負(fù)責(zé)為你的定制資源提供存儲(chǔ)和訪問服務(wù)。 CRD 對(duì)象的名稱必須是合法的 DNS 子域名。
DNS 子域名
很多資源類型需要可以用作 DNS 子域名的名稱。名稱必須滿足如下規(guī)則:
- 不能超過 253 個(gè)字符
- 只能包含小寫字母、數(shù)字,以及 '-' 和 '.'
- 必須以字母數(shù)字開頭
- 必須以字母數(shù)字結(jié)尾
CRD 官方文檔:https://kubernetes.io/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
二、定制資源
定制資源(Custom Resource) 是對(duì) Kubernetes API 的擴(kuò)展。
1)定制資源 和 定制控制器
- 資源(Resource) 是 Kubernetes API 中的一個(gè)端點(diǎn), 其中存儲(chǔ)的是某個(gè)類別的 API 對(duì)象的一個(gè)集合。例如內(nèi)置的 Pod 資源包含一組 Pod 對(duì)象。
- 定制資源(Custom Resource) 是對(duì) Kubernetes API 的擴(kuò)展, 定制資源所代表的是對(duì)特定 Kubernetes 安裝的一種定制。不過,很多 Kubernetes 核心功能現(xiàn)在都用定制資源來實(shí)現(xiàn),這使得 Kubernetes 更加模塊化。
- 定制資源可以通過動(dòng)態(tài)注冊(cè)的方式在運(yùn)行中的集群內(nèi)或出現(xiàn)或消失,集群管理員可以獨(dú)立于集群更新定制資源。
- 一旦某定制資源被安裝,用戶可以使用 kubectl 來創(chuàng)建和訪問其中的對(duì)象, 就像他們?yōu)?Pod 這種內(nèi)置資源所做的一樣。
2)定制控制器
- 就定制資源本身而言,它只能用來存取結(jié)構(gòu)化的數(shù)據(jù)。當(dāng)你將定制資源與定制控制器(Custom Controller) 結(jié)合時(shí), 定制資源就能夠提供真正的聲明式 API(Declarative API)。
- Operator 模式就是將定制資源與定制控制器相結(jié)合的。
3)Operator 介紹
Kubernetes CRD Operator = kubernetes CRD + custom controller
- Operator 是由 CoreOS 開發(fā)的,用來擴(kuò)展 Kubernetes API,特定的應(yīng)用程序控制器,它用來創(chuàng)建、配置和管理復(fù)雜的有狀態(tài)應(yīng)用,如數(shù)據(jù)庫、緩存和監(jiān)控系統(tǒng)。
- Operator 基于 Kubernetes 的資源和控制器概念之上構(gòu)建,但同時(shí)又包含了應(yīng)用程序特定的領(lǐng)域知識(shí)。創(chuàng)建Operator 的關(guān)鍵是CRD(自定義資源)的設(shè)計(jì)。
- Operator是 Kubernetes 的擴(kuò)展軟件, 它利用定制資源管理應(yīng)用及其組件。Operator 遵循 Kubernetes 的理念,特別是在控制器方面。
- Operator 模式會(huì)封裝你編寫的(Kubernetes 本身提供功能以外的)任務(wù)自動(dòng)化代碼。
- Kubernetes 的 Operator 模式概念允許你在不修改 Kubernetes 自身代碼的情況下, 通過為一個(gè)或多個(gè)自定義資源關(guān)聯(lián)控制器來擴(kuò)展集群的能力。
- Operator 是 Kubernetes API 的客戶端。Operator 旨在為其管理的資源提供強(qiáng)大的自動(dòng)化功能,因此它還需要一些額外的支持性代碼。
1、Operator Framework
Operator Framework 同樣也是 CoreOS 開源的一個(gè)用于快速開發(fā) Operator 的工具包,該框架包含兩個(gè)主要的部分:
- Operator SDK——無需了解復(fù)雜的 Kubernetes API 特性,即可讓你根據(jù)你自己的專業(yè)知識(shí)構(gòu)建一個(gè) Operator 應(yīng)用。
- Operator Lifecycle Manager OLM——幫助你安裝、更新和管理跨集群的運(yùn)行中的所有 Operator(以及他們的相關(guān)服務(wù))
2、Operator 安裝
Operator SDK 提供以下工作流來開發(fā)一個(gè)新的 Operator:
- 使用 SDK 創(chuàng)建一個(gè)新的 Operator 項(xiàng)目
- 通過添加自定義資源(CRD)定義新的資源 API
- 指定使用 SDK API 來 watch 的資源
- 定義 Operator 的協(xié)調(diào)(reconcile)邏輯
- 使用 Operator SDK 構(gòu)建并生成 Operator 部署清單文件
3、安裝 Operator SDK
下載地址:https://github.com/operator-framework/operator-sdk/releasesoperator sdk 官方文檔:https://sdk.operatorframework.io/docs/installation/
4、Operator 簡單使用
【示例1】快速簡單使用
這里只是簡單的安裝部署使用,后面會(huì)單獨(dú)拿一篇文章來詳細(xì)介紹Operator 。
4)Kubernetes API 聚合層
- 使用聚合層(Aggregation Layer),用戶可以通過附加的 API 擴(kuò)展 Kubernetes, 而不局限于 Kubernetes 核心 API 提供的功能。這里的附加 API 可以是現(xiàn)成的解決方案,比如 metrics server, 或者你自己開發(fā)的 API。
- 聚合層不同于 定制資源(Custom Resources)。后者的目的是讓 kube-apiserver 能夠識(shí)別新的對(duì)象類別(Kind)。
- 聚合層在 kube-apiserver 進(jìn)程內(nèi)運(yùn)行。在擴(kuò)展資源注冊(cè)之前,聚合層不做任何事情。
- 要注冊(cè) API,你可以添加一個(gè) APIService 對(duì)象,用它來 “申領(lǐng)” Kubernetes API 中的 URL 路徑。自此以后,聚合層將把發(fā)給該 API 路徑的所有內(nèi)容(例如 /apis/myextension.mycompany.io/v1/…) 轉(zhuǎn)發(fā)到已注冊(cè)的 APIService。
5)聲明式 APIs
典型地,在聲明式 API 中:
- 你的 API 包含相對(duì)而言為數(shù)不多的、尺寸較小的對(duì)象(資源)。
- 對(duì)象定義了應(yīng)用或者基礎(chǔ)設(shè)施的配置信息。
- 對(duì)象更新操作頻率較低。
- 通常需要人來讀取或?qū)懭雽?duì)象。
- 對(duì)象的主要操作是 CRUD 風(fēng)格的(創(chuàng)建、讀取、更新和刪除)。
- 不需要跨對(duì)象的事務(wù)支持:API 對(duì)象代表的是期望狀態(tài)而非確切實(shí)際狀態(tài)。
命令式 API(Imperative API)與聲明式有所不同。以下跡象表明你的 API 可能不是聲明式的:
- 客戶端發(fā)出“做這個(gè)操作”的指令,之后在該操作結(jié)束時(shí)獲得同步響應(yīng)。
- 客戶端發(fā)出“做這個(gè)操作”的指令,并獲得一個(gè)操作 ID,之后需要檢查一個(gè) Operation(操作) 對(duì)象來判斷請(qǐng)求是否成功完成。
- 你會(huì)將你的 API 類比為遠(yuǎn)程過程調(diào)用(Remote Procedure Call,RPCs)。
- 直接存儲(chǔ)大量數(shù)據(jù);例如每個(gè)對(duì)象幾 kB,或者存儲(chǔ)上千個(gè)對(duì)象。
- 需要較高的訪問帶寬(長期保持每秒數(shù)十個(gè)請(qǐng)求)。
- 存儲(chǔ)有應(yīng)用來處理的最終用戶數(shù)據(jù)(如圖片、個(gè)人標(biāo)識(shí)信息(PII)等)或者其他大規(guī)模數(shù)據(jù)。
- 在對(duì)象上執(zhí)行的常規(guī)操作并非 CRUD 風(fēng)格。
6)添加定制資源
Kubernetes 提供了兩種方式供你向集群中添加定制資源:
- CRD 相對(duì)簡單,創(chuàng)建 CRD 可以不必編程。
- API 聚合 需要編程,但支持對(duì) API 行為進(jìn)行更多的控制,例如數(shù)據(jù)如何存儲(chǔ)以及在不同 API 版本間如何轉(zhuǎn)換等。
Kubernetes 提供這兩種選項(xiàng)以滿足不同用戶的需求,這樣就既不會(huì)犧牲易用性也不會(huì)犧牲靈活性。
- 聚合 API指的是一些下位的 API 服務(wù)器,運(yùn)行在主 API 服務(wù)器后面;主 API 服務(wù)器以代理的方式工作。這種組織形式稱作 API 聚合(API Aggregation,AA) 。對(duì)用戶而言,看起來僅僅是 Kubernetes API 被擴(kuò)展了。
- CRD 允許用戶創(chuàng)建新的資源類別同時(shí)又不必添加新的 API 服務(wù)器。使用 CRD 時(shí),你并不需要理解 API 聚合。
CRD | 聚合 API |
無需編程。用戶可選擇任何語言來實(shí)現(xiàn) CRD 控制器。 | 需要編程,并構(gòu)建可執(zhí)行文件和鏡像。 |
無需額外運(yùn)行服務(wù);CRD 由 API 服務(wù)器處理。 | 需要額外創(chuàng)建服務(wù),且該服務(wù)可能失效。 |
一旦 CRD 被創(chuàng)建,不需要持續(xù)提供支持。Kubernetes 主控節(jié)點(diǎn)升級(jí)過程中自動(dòng)會(huì)帶入缺陷修復(fù)。 | 可能需要周期性地從上游提取缺陷修復(fù)并更新聚合 API 服務(wù)器。 |
無需處理 API 的多個(gè)版本;例如,當(dāng)你控制資源的客戶端時(shí),你可以更新它使之與 API 同步。 | 你需要處理 API 的多個(gè)版本;例如,在開發(fā)打算與很多人共享的擴(kuò)展時(shí)。 |
僅支持 CRUD 操作,例如 "logs" 或 "exec"的操作是不支持的。 | 支持 CRUD 之外的操作。 |
7)訪問定制資源
Kubernetes 客戶端庫可用來訪問定制資源。并非所有客戶端庫都支持定制資源。Go 和 Python 客戶端庫是支持的。
當(dāng)你添加了新的定制資源后,可以用如下方式之一訪問它們:
- kubectl
- Kubernetes 動(dòng)態(tài)客戶端(DynamicClient),可以對(duì)任意Kubernetes資源進(jìn)行RESTFful操作,包括CRD自定義資源。
- 你所編寫的 REST 客戶端
- 使用 Kubernetes 客戶端生成工具 所生成的客戶端。生成客戶端的工作有些難度,不過某些項(xiàng)目可能會(huì)隨著 CRD 或 聚合 API 一起提供一個(gè)客戶端
三、CRD 示例演示
1)創(chuàng)建 CRD (定制資源)
當(dāng)你創(chuàng)建新的 CustomResourceDefinition(CRD)時(shí),Kubernetes API 服務(wù)器會(huì)為你所指定的每個(gè)版本生成一個(gè)新的 RESTful 資源路徑?;?CRD 對(duì)象所創(chuàng)建的自定義資源可以是名字空間作用域的,也可以是集群作用域的, 取決于 CRD 對(duì)象 spec.scope 字段的設(shè)置。
執(zhí)行創(chuàng)建
這樣一個(gè)新的受名字空間約束的 RESTful API 端點(diǎn)會(huì)被創(chuàng)建在:
對(duì)象的 kind 將是來自你上面創(chuàng)建時(shí) 所用的 spec 中指定的 CronTab。
Kubernetes(k8s)API 的 操作可以參考我之前的文章:Kubernetes(k8s)API Server詳解
2)創(chuàng)建定制對(duì)象(定制控制器)
在創(chuàng)建了 CustomResourceDefinition 對(duì)象之后,你可以創(chuàng)建定制對(duì)象(?Custom Objects)。定制對(duì)象可以包含定制字段。這些字段可以包含任意的 JSON 數(shù)據(jù)。在下面的例子中,在類別為 CronTab 的定制對(duì)象中,設(shè)置了cronSpec 和 image 定制字段。類別 CronTab 來自你在上面所創(chuàng)建的 CRD 的規(guī)約。
并執(zhí)行創(chuàng)建命令:
你就可以使用 kubectl 來管理你的 CronTab 對(duì)象了。例如:
3)刪除 CustomResourceDefinition
當(dāng)你刪除某 CustomResourceDefinition 時(shí),服務(wù)器會(huì)卸載其 RESTful API 端點(diǎn),并刪除服務(wù)器上存儲(chǔ)的所有定制對(duì)象。