Kubernetes 定制資源

2022-05-27 09:37 更新

定制資源

資源(Resource) 是 Kubernetes API 中的一個端點, 其中存儲的是某個類別的 API 對象 的一個集合。 例如內置的 pods 資源包含一組 Pod 對象。

定制資源(Custom Resource) 是對 Kubernetes API 的擴展,不一定在默認的 Kubernetes 安裝中就可用。定制資源所代表的是對特定 Kubernetes 安裝的一種定制。 不過,很多 Kubernetes 核心功能現(xiàn)在都用定制資源來實現(xiàn),這使得 Kubernetes 更加模塊化。

定制資源可以通過動態(tài)注冊的方式在運行中的集群內或出現(xiàn)或消失,集群管理員可以獨立于集群 更新定制資源。一旦某定制資源被安裝,用戶可以使用 kubectl 來創(chuàng)建和訪問其中的對象,就像他們?yōu)?nbsp;pods 這種內置資源所做的一樣。

定制控制器 

就定制資源本身而言,它只能用來存取結構化的數(shù)據(jù)。 當你將定制資源與 定制控制器(Custom Controller) 相結合時,定制資源就能夠 提供真正的 聲明式 API(Declarative API)。

使用聲明式 API, 你可以 聲明 或者設定你的資源的期望狀態(tài),并嘗試讓 Kubernetes 對象的當前狀態(tài) 同步到其期望狀態(tài)??刂破髫撠煂⒔Y構化的數(shù)據(jù)解釋為用戶所期望狀態(tài)的記錄,并 持續(xù)地維護該狀態(tài)。

你可以在一個運行中的集群上部署和更新定制控制器,這類操作與集群的生命周期無關。 定制控制器可以用于任何類別的資源,不過它們與定制資源結合起來時最為有效。 Operator 模式就是將定制資源 與定制控制器相結合的。你可以使用定制控制器來將特定于某應用的領域知識組織 起來,以編碼的形式構造對 Kubernetes API 的擴展。

我是否應該向我的 Kubernetes 集群添加定制資源?

在創(chuàng)建新的 API 時,請考慮是 將你的 API 與 Kubernetes 集群 API 聚合起來 還是讓你的 API 獨立運行。

考慮 API 聚合的情況 優(yōu)選獨立 API 的情況
你的 API 是聲明式的。 你的 API 不符合聲明式模型。
你希望可以是使用 kubectl 來讀寫你的新資源類別。 不要求 kubectl 支持。
你希望在 Kubernetes UI (如儀表板)中和其他內置類別一起查看你的新資源類別。 不需要 Kubernetes UI 支持。
你在開發(fā)新的 API。 你已經(jīng)有一個提供 API 服務的程序并且工作良好。
你有意愿取接受 Kubernetes 對 REST 資源路徑所作的格式限制,例如 API 組和名字空間。(參閱 API 概述) 你需要使用一些特殊的 REST 路徑以便與已經(jīng)定義的 REST API 保持兼容。
你的資源可以自然地界定為集群作用域或集群中某個名字空間作用域。 集群作用域或名字空間作用域這種二分法很不合適;你需要對資源路徑的細節(jié)進行控制。
你希望復用 Kubernetes API 支持特性。 你不需要這類特性。

聲明式 APIs

典型地,在聲明式 API 中:

  • 你的 API 包含相對而言為數(shù)不多的、尺寸較小的對象(資源)。
  • 對象定義了應用或者基礎設施的配置信息。
  • 對象更新操作頻率較低。
  • 通常需要人來讀取或寫入對象。
  • 對象的主要操作是 CRUD 風格的(創(chuàng)建、讀取、更新和刪除)。
  • 不需要跨對象的事務支持:API 對象代表的是期望狀態(tài)而非確切實際狀態(tài)。

命令式 API(Imperative API)與聲明式有所不同。 以下跡象表明你的 API 可能不是聲明式的:

  • 客戶端發(fā)出“做這個操作”的指令,之后在該操作結束時獲得同步響應。
  • 客戶端發(fā)出“做這個操作”的指令,并獲得一個操作 ID,之后需要檢查一個 Operation(操作) 對象來判斷請求是否成功完成。
  • 你會將你的 API 類比為遠程過程調用(Remote Procedure Call,RPCs)。
  • 直接存儲大量數(shù)據(jù);例如每個對象幾 kB,或者存儲上千個對象。
  • 需要較高的訪問帶寬(長期保持每秒數(shù)十個請求)。
  • 存儲有應用來處理的最終用戶數(shù)據(jù)(如圖片、個人標識信息(PII)等)或者其他大規(guī)模數(shù)據(jù)。
  • 在對象上執(zhí)行的常規(guī)操作并非 CRUD 風格。
  • API 不太容易用對象來建模。
  • 你決定使用操作 ID 或者操作對象來表現(xiàn)懸決的操作。

我應該使用一個 ConfigMap 還是一個定制資源?

如果滿足以下條件之一,應該使用 ConfigMap:

  • 存在一個已有的、文檔完備的配置文件格式約定,例如 ?mysql.cnf? 或 ?pom.xml?。
  • 你希望將整個配置文件放到某 configMap 中的一個主鍵下面。
  • 配置文件的主要用途是針對運行在集群中 Pod 內的程序,供后者依據(jù)文件數(shù)據(jù)配置自身行為。
  • 文件的使用者期望以 Pod 內文件或者 Pod 內環(huán)境變量的形式來使用文件數(shù)據(jù), 而不是通過 Kubernetes API。
  • 你希望當文件被更新時通過類似 Deployment 之類的資源完成滾動更新操作。

Note: 請使用 Secret 來保存敏感數(shù)據(jù)。 Secret 類似于 configMap,但更為安全。

如果以下條件中大多數(shù)都被滿足,你應該使用定制資源(CRD 或者 聚合 API):

  • 你希望使用 Kubernetes 客戶端庫和 CLI 來創(chuàng)建和更改新的資源。
  • 你希望 ?kubectl ?能夠直接支持你的資源;例如,?kubectl get my-object object-name?。
  • 你希望構造新的自動化機制,監(jiān)測新對象上的更新事件,并對其他對象執(zhí)行 CRUD 操作,或者監(jiān)測后者更新前者。
  • 你希望編寫自動化組件來處理對對象的更新。
  • 你希望使用 Kubernetes API 對諸如 ?.spec?、?.status? 和 ?.metadata? 等字段的約定。
  • 你希望對象是對一組受控資源的抽象,或者對其他資源的歸納提煉。

添加定制資源 

Kubernetes 提供了兩種方式供你向集群中添加定制資源:

  • CRD 相對簡單,創(chuàng)建 CRD 可以不必編程。
  • API 聚合 需要編程,但支持對 API 行為進行更多的控制,例如數(shù)據(jù)如何存儲以及在不同 API 版本間如何轉換等。

Kubernetes 提供這兩種選項以滿足不同用戶的需求,這樣就既不會犧牲易用性也不會犧牲靈活性。

聚合 API 指的是一些下位的 API 服務器,運行在主 API 服務器后面;主 API 服務器以代理的方式工作。這種組織形式稱作 API 聚合(API Aggregation,AA) 。 對用戶而言,看起來僅僅是 Kubernetes API 被擴展了。

CRD 允許用戶創(chuàng)建新的資源類別同時又不必添加新的 API 服務器。 使用 CRD 時,你并不需要理解 API 聚合。

無論以哪種方式安裝定制資源,新的資源都會被當做定制資源,以便與內置的 Kubernetes 資源(如 Pods)相區(qū)分。

CustomResourceDefinitions

CustomResourceDefinition API 資源允許你定義定制資源。 定義 CRD 對象的操作會使用你所設定的名字和模式定義(Schema)創(chuàng)建一個新的定制資源, Kubernetes API 負責為你的定制資源提供存儲和訪問服務。 CRD 對象的名稱必須是合法的 DNS 子域名。

CRD 使得你不必編寫自己的 API 服務器來處理定制資源,不過其背后實現(xiàn)的通用性也意味著 你所獲得的靈活性要比 API 服務器聚合少很多。

關于如何注冊新的定制資源、使用新資源類別的實例以及如何使用控制器來處理事件, 相關的例子可參見定制控制器示例。

API 服務器聚合 

通常,Kubernetes API 中的每個資源都需要處理 REST 請求和管理對象持久性存儲的代碼。 Kubernetes API 主服務器能夠處理諸如 pods 和 services 這些內置資源,也可以 按通用的方式通過 CRD 來處理定制資源。

聚合層(Aggregation Layer) 使得你可以通過編寫和部署你自己的 API 服務器來為定制資源提供特殊的實現(xiàn)。 主 API 服務器將針對你要處理的定制資源的請求全部委托給你自己的 API 服務器來處理,同時將這些資源 提供給其所有客戶端。

選擇添加定制資源的方法 

CRD 更為易用;聚合 API 則更為靈活。請選擇最符合你的需要的方法。

通常,如何存在以下情況,CRD 可能更合適:

  • 定制資源的字段不多;
  • 你在組織內部使用該資源或者在一個小規(guī)模的開源項目中使用該資源,而不是 在商業(yè)產(chǎn)品中使用。

比較易用性 

CRD 比聚合 API 更容易創(chuàng)建

CRDs 聚合 API
無需編程。用戶可選擇任何語言來實現(xiàn) CRD 控制器。 需要使用 Go 來編程,并構建可執(zhí)行文件和鏡像。
無需額外運行服務;CRD 由 API 服務器處理。 需要額外創(chuàng)建服務,且該服務可能失效。
一旦 CRD 被創(chuàng)建,不需要持續(xù)提供支持。Kubernetes 主控節(jié)點升級過程中自動會帶入缺陷修復。 可能需要周期性地從上游提取缺陷修復并更新聚合 API 服務器。
無需處理 API 的多個版本;例如,當你控制資源的客戶端時,你可以更新它使之與 API 同步。 你需要處理 API 的多個版本;例如,在開發(fā)打算與很多人共享的擴展時。

高級特性與靈活性 

聚合 API 可提供更多的高級 API 特性,也可對其他特性實行定制;例如,對存儲層進行定制。

特性 描述 CRDs 聚合 API
合法性檢查 幫助用戶避免錯誤,允許你獨立于客戶端版本演化 API。這些特性對于由很多無法同時更新的客戶端的場合。 可以。大多數(shù)驗證可以使用 OpenAPI v3.0 合法性檢查 來設定。其他合法性檢查操作可以通過添加合法性檢查 Webhook來實現(xiàn)。 可以,可執(zhí)行任何合法性檢查。
默認值設置 同上 可以??赏ㄟ^ OpenAPI v3.0 合法性檢查的 default 關鍵詞(自 1.17 正式發(fā)布)或更改性(Mutating)Webhook來實現(xiàn)(不過從 etcd 中讀取老的對象時不會執(zhí)行這些 Webhook)。 可以。
多版本支持 允許通過兩個 API 版本同時提供同一對象??蓭椭喕愃谱侄胃@類 API 操作。如果你能控制客戶端版本,這一特性將不再重要。 可以。 可以。
定制存儲 支持使用具有不同性能模式的存儲(例如,要使用時間序列數(shù)據(jù)庫而不是鍵值存儲),或者因安全性原因對存儲進行隔離(例如對敏感信息執(zhí)行加密)。 不可以。 可以。
定制業(yè)務邏輯 在創(chuàng)建、讀取、更新或刪除對象時,執(zhí)行任意的檢查或操作。 可以。要使用 Webhook。 可以。
支持 scale 子資源 允許 HorizontalPodAutoscaler 和 PodDisruptionBudget 這類子系統(tǒng)與你的新資源交互。 可以。 可以。
支持 status 子資源 允許在用戶寫入 spec 部分而控制器寫入 status 部分時執(zhí)行細粒度的訪問控制。允許在對定制資源的數(shù)據(jù)進行更改時增加對象的代際(Generation);這需要資源對 spec 和 status 部分有明確劃分。 可以。 可以。
其他子資源 添加 CRUD 之外的操作,例如 "logs" 或 "exec"。 不可以。 可以。
strategic-merge-patch 新的端點要支持標記了 Content-Type: application/strategic-merge-patch+json 的 PATCH 操作。對于更新既可在本地更改也可在服務器端更改的對象而言是有用的。要了解更多信息,可參見使用 kubectl patch 來更新 API 對象。 不可以。 可以。
支持協(xié)議緩沖區(qū) 新的資源要支持想要使用協(xié)議緩沖區(qū)(Protocol Buffer)的客戶端。 不可以。 可以。
OpenAPI Schema 是否存在新資源類別的 OpenAPI(Swagger)Schema 可供動態(tài)從服務器上讀???是否存在機制確保只能設置被允許的字段以避免用戶犯字段拼寫錯誤?是否實施了字段類型檢查(換言之,不允許在 string 字段設置 int 值)? 可以,依據(jù) OpenAPI v3.0 合法性檢查 模式(1.16 中進入正式發(fā)布狀態(tài))。 可以。

公共特性 

與在 Kubernetes 平臺之外實現(xiàn)定制資源相比, 無論是通過 CRD 還是通過聚合 API 來創(chuàng)建定制資源,你都會獲得很多 API 特性:

功能特性 具體含義
CRUD 新的端點支持通過 HTTP 和 kubectl 發(fā)起的 CRUD 基本操作
監(jiān)測(Watch) 新的端點支持通過 HTTP 發(fā)起的 Kubernetes Watch 操作
發(fā)現(xiàn)(Discovery) 類似 kubectl 和儀表盤(Dashboard)這類客戶端能夠自動提供列舉、顯示、在字段級編輯你的資源的操作
json-patch 新的端點支持帶 Content-Type: application/json-patch+json 的 PATCH 操作
merge-patch 新的端點支持帶 Content-Type: application/merge-patch+json 的 PATCH 操作
HTTPS 新的端點使用 HTTPS
內置身份認證 對擴展的訪問會使用核心 API 服務器(聚合層)來執(zhí)行身份認證操作
內置鑒權授權 對擴展的訪問可以復用核心 API 服務器所使用的鑒權授權機制;例如,RBAC
Finalizers 在外部清除工作結束之前阻止擴展資源被刪除
準入 Webhooks 在創(chuàng)建、更新和刪除操作中對擴展資源設置默認值和執(zhí)行合法性檢查
UI/CLI 展示 kubectl 和儀表盤(Dashboard)可以顯示擴展資源
區(qū)分未設置值和空值 客戶端能夠區(qū)分哪些字段是未設置的,哪些字段的值是被顯式設置為零值的。
生成客戶端庫 Kubernetes 提供通用的客戶端庫,以及用來生成特定類別客戶端庫的工具
標簽和注解 提供涵蓋所有對象的公共元數(shù)據(jù)結構,且工具知曉如何編輯核心資源和定制資源的這些元數(shù)據(jù)

準備安裝定制資源

在向你的集群添加定制資源之前,有些事情需要搞清楚。

第三方代碼和新的失效點的問題

盡管添加新的 CRD 不會自動帶來新的失效點(Point of Failure),例如導致第三方代碼被在 API 服務器上運行, 類似 Helm Charts 這種軟件包或者其他安裝包通常在提供 CRD 的同時還包含帶有第三方 代碼的 Deployment,負責實現(xiàn)新的定制資源的業(yè)務邏輯。

安裝聚合 API 服務器時,也總會牽涉到運行一個新的 Deployment。

存儲 

定制資源和 ConfigMap 一樣也會消耗存儲空間。創(chuàng)建過多的定制資源可能會導致 API 服務器上的存儲空間超載。

聚合 API 服務器可以使用主 API 服務器的同一存儲。如果是這樣,你也要注意 此警告。

身份認證、鑒權授權以及審計

CRD 通常與 API 服務器上的內置資源一樣使用相同的身份認證、鑒權授權 和審計日志機制。

如果你使用 RBAC 來執(zhí)行鑒權授權,大多數(shù) RBAC 角色都會授權對新資源的訪問 (除了 cluster-admin 角色以及使用通配符規(guī)則創(chuàng)建的其他角色)。 你要顯式地為新資源的訪問授權。CRD 和聚合 API 通常在交付時會包含 針對所添加的類別的新的角色定義。

聚合 API 服務器可能會使用主 API 服務器相同的身份認證、鑒權授權和審計 機制,也可能不會。

訪問定制資源

Kubernetes 客戶端庫可用來訪問定制資源。 并非所有客戶端庫都支持定制資源。Go 和 Python 客戶端庫是支持的。

當你添加了新的定制資源后,可以用如下方式之一訪問它們:

  • ?kubectl ?
  • Kubernetes 動態(tài)客戶端
  • 你所編寫的 REST 客戶端
  • 使用 Kubernetes 客戶端生成工具 所生成的客戶端。生成客戶端的工作有些難度,不過某些項目可能會隨著 CRD 或 聚合 API 一起提供一個客戶端


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號