自定義資源

自定義資源 是 Kubernetes API 的擴充套件。本頁面討論何時向 Kubernetes 叢集新增自定義資源以及何時使用獨立的(Standalone)服務。它描述了新增自定義資源的兩種方法以及如何選擇它們。

自定義資源

資源Kubernetes API 中的一個端點,它儲存特定種類的 API 物件的集合;例如,內建的 pods 資源包含 Pod 物件的集合。

自定義資源是 Kubernetes API 的擴充套件,它不一定在預設的 Kubernetes 安裝中可用。它代表了特定 Kubernetes 安裝的定製。然而,許多核心 Kubernetes 功能現在都使用自定義資源構建,使 Kubernetes 更加模組化。

自定義資源可以透過動態註冊在執行中的叢集中出現和消失,並且叢集管理員可以獨立於叢集本身更新自定義資源。一旦安裝了自定義資源,使用者就可以使用 kubectl 建立和訪問其物件,就像他們對 Pods 等內建資源一樣。

自定義控制器

自定義資源本身允許你儲存和檢索結構化資料。當你將自定義資源與一個 自定義控制器 結合使用時,自定義資源就提供了一個真正的 宣告式 API

Kubernetes 宣告式 API 強制職責分離。你宣告資源的期望狀態。Kubernetes 控制器使 Kubernetes 物件的當前狀態與你宣告的期望狀態保持同步。這與命令式 API 相反,命令式 API 中你 指示 伺服器做什麼。

你可以在執行中的叢集上部署和更新自定義控制器,而獨立於叢集的生命週期。自定義控制器可以與任何型別的資源一起工作,但當它們與自定義資源結合使用時尤其有效。Operator 模式結合了自定義資源和自定義控制器。你可以使用自定義控制器將特定應用程式的領域知識編碼到 Kubernetes API 的擴充套件中。

我應該向我的 Kubernetes 叢集新增自定義資源嗎?

在建立新 API 時,考慮是 將你的 API 與 Kubernetes 叢集 API 聚合 還是讓你的 API 獨立執行。

如果出現以下情況,請考慮 API 聚合如果出現以下情況,請首選獨立 API
你的 API 是宣告式的你的 API 不符合宣告式模型。
你希望你的新型別可以使用 kubectl 進行讀寫。不需要 kubectl 支援。
你希望在 Kubernetes UI(例如儀表盤)中檢視你的新型別,就像內建型別一樣。不需要 Kubernetes UI 支援。
你正在開發一個新的 API。你已經有一個程式可以提供你的 API 並且執行良好。
你願意接受 Kubernetes 對 REST 資源路徑的格式限制,例如 API 組和名稱空間。(請參閱 API 概述。)你需要特定的 REST 路徑以與已定義的 REST API 相容。
你的資源自然地作用於叢集或叢集的名稱空間。叢集或名稱空間作用域的資源不適合;你需要控制資源路徑的細節。
你想要重用 Kubernetes API 支援功能你不需要這些功能。

宣告式 API

在宣告式 API 中,通常

  • 你的 API 由相對較少的、相對較小的物件(資源)組成。
  • 這些物件定義了應用程式或基礎設施的配置。
  • 這些物件更新頻率相對較低。
  • 人類通常需要讀寫這些物件。
  • 對物件的主要操作是 CRUD(建立、讀取、更新和刪除)。
  • 不需要跨物件事務:API 表示期望狀態,而不是精確狀態。

命令式 API 不是宣告式的。你的 API 可能不是宣告式的跡象包括

  • 客戶端說“執行此操作”,然後操作完成後立即收到同步響應。
  • 客戶端說“執行此操作”,然後收到一個操作 ID,並且必須檢查一個單獨的操作物件以確定請求是否完成。
  • 你談論遠端過程呼叫 (RPC)。
  • 直接儲存大量資料;例如,每個物件 > 幾 KB,或 > 數千個物件。
  • 需要高頻寬訪問(每秒 10 次請求持續不斷)。
  • 儲存應用程式處理的最終使用者資料(如影像、PII 等)或其他大規模資料。
  • 對物件的自然操作不是 CRUD 式的。
  • API 不容易建模為物件。
  • 你選擇用操作 ID 或操作物件來表示待處理的操作。

我應該使用 ConfigMap 還是自定義資源?

如果符合以下任何條件,請使用 ConfigMap

  • 存在一個已有的、文件完善的配置檔案格式,例如 mysql.cnfpom.xml
  • 你希望將整個配置放入 ConfigMap 的一個鍵中。
  • 配置檔案主要用於在叢集的 Pod 中執行的程式,以消費該檔案來配置自身。
  • 檔案的消費者更喜歡透過 Pod 中的檔案或 Pod 中的環境變數進行消費,而不是透過 Kubernetes API。
  • 你希望在檔案更新時透過 Deployment 等執行滾動更新。

如果以下大多數情況適用,請使用自定義資源(CRD 或聚合 API)

  • 你希望使用 Kubernetes 客戶端庫和 CLI 來建立和更新新資源。
  • 你希望 kubectl 提供頂級支援;例如,kubectl get my-object object-name
  • 你希望構建新的自動化,用於監視新物件的更新,然後對其他物件執行 CRUD 操作,反之亦然。
  • 你希望編寫處理物件更新的自動化。
  • 你希望使用 Kubernetes API 約定,例如 .spec.status.metadata
  • 你希望該物件是受控資源集合的抽象,或對其他資源的彙總。

新增自定義資源

Kubernetes 提供了兩種向叢集新增自定義資源的方式

  • CRD 簡單且無需任何程式設計即可建立。
  • API 聚合 需要程式設計,但允許對 API 行為(例如資料儲存方式和 API 版本之間的轉換)進行更多控制。

Kubernetes 提供這兩種選項以滿足不同使用者的需求,以便在易用性和靈活性方面都不受影響。

聚合 API 是主 API 伺服器後面的從屬 API 伺服器,主 API 伺服器充當代理。這種安排稱為 API 聚合 (AA)。對使用者而言,Kubernetes API 似乎得到了擴充套件。

CRD 允許使用者建立新的資源型別,而無需新增另一個 API 伺服器。你不需要了解 API 聚合即可使用 CRD。

無論如何安裝,新資源都被稱為自定義資源,以區別於內建的 Kubernetes 資源(如 Pod)。

CustomResourceDefinition

CustomResourceDefinition API 資源允許你定義自定義資源。定義 CRD 物件會建立具有你指定名稱和模式的新自定義資源。Kubernetes API 提供並處理自定義資源的儲存。CRD 物件本身的名稱必須是派生自定義的資源名稱及其 API 組的有效 DNS 子域名;有關更多詳細資訊,請參閱 如何建立 CRD。此外,由 CRD 定義其種類/資源的物件的名稱也必須是有效的 DNS 子域名。

這使你無需編寫自己的 API 伺服器來處理自定義資源,但實現的通用性意味著你的靈活性不如使用 API 伺服器聚合

請參閱自定義控制器示例,瞭解如何註冊新的自定義資源、使用新資源型別的例項以及使用控制器處理事件的示例。

API 伺服器聚合

通常,Kubernetes API 中的每個資源都需要處理 REST 請求和管理物件持久儲存的程式碼。主 Kubernetes API 伺服器處理 podsservices 等內建資源,還可以透過 CRD 泛型處理自定義資源。

聚合層 允許你透過編寫和部署自己的 API 伺服器,為自定義資源提供專門的實現。主 API 伺服器將請求委託給你的 API 伺服器,以處理你負責的自定義資源,使其對所有客戶端可用。

選擇新增自定義資源的方法

CRD 更易於使用。聚合 API 更靈活。選擇最符合你需求的方法。

通常,如果出現以下情況,CRD 是一個不錯的選擇

  • 你只有少數幾個欄位
  • 你正在公司內部使用該資源,或者作為小型開源專案的一部分使用(而不是商業產品)

易用性比較

CRD 比聚合 API 更容易建立。

CRD聚合 API
不需要程式設計。使用者可以選擇任何語言來編寫 CRD 控制器。需要程式設計和構建二進位制檔案和映象。
無需額外服務執行;CRD 由 API 伺服器處理。需要建立可能失敗的額外服務。
CRD 建立後無需持續支援。任何 Bug 修復都作為正常的 Kubernetes 主版本升級的一部分進行。可能需要定期從上游獲取 Bug 修復,並重建和更新聚合 API 伺服器。
無需處理 API 的多個版本;例如,當您控制此資源的客戶端時,可以與 API 同步升級它。你需要處理 API 的多個版本;例如,當你開發一個要與世界共享的擴充套件時。

高階功能和靈活性

聚合 API 提供更高階的 API 功能和對其他功能(例如儲存層)的自定義。

特性描述CRD聚合 API
驗證幫助使用者防止錯誤,並允許你獨立於客戶端演進你的 API。這些功能在許多客戶端無法同時更新時最有用。是。大多數驗證可以在 CRD 中使用 OpenAPI v3.0 驗證 來指定。CRDValidationRatcheting 功能門允許在資源失敗部分未更改的情況下,也可以忽略使用 OpenAPI 指定的失敗驗證。透過新增 Validating Webhook 支援任何其他驗證。是,任意驗證檢查
預設值見上文是的,可以透過 OpenAPI v3.0 驗證 default 關鍵字(1.17 GA),或者透過 Mutating Webhook(儘管當從 etcd 讀取舊物件時不會執行此操作)。
多版本控制允許透過兩個 API 版本提供相同的物件。可以幫助簡化 API 更改,例如欄位重新命名。如果您控制客戶端版本,則不那麼重要。
自定義儲存如果您需要不同效能模式的儲存(例如,時間序列資料庫而不是鍵值儲存)或為了安全進行隔離(例如,敏感資訊加密等)
自定義業務邏輯在建立、讀取、更新或刪除物件時執行任意檢查或操作是的,使用 Webhooks
擴縮子資源允許 HorizontalPodAutoscaler 和 PodDisruptionBudget 等系統與你的新資源互動
狀態子資源允許細粒度訪問控制,使用者可以編寫 spec 部分,控制器可以編寫 status 部分。允許在自定義資源資料變動時遞增物件 Generation(要求資源中包含獨立的 spec 和 status 部分)
其他子資源新增除了 CRUD 之外的操作,例如“logs”或“exec”。
戰略合併補丁新端點支援帶有 Content-Type: application/strategic-merge-patch+json 的 PATCH。對於更新可能在本地和伺服器上都已修改的物件很有用。更多資訊,請參閱 “使用 kubectl patch 就地更新 API 物件”
Protocol Buffers新資源支援想要使用 Protocol Buffers 的客戶端
OpenAPI Schema是否存在一個 OpenAPI (swagger) 模式,可以從伺服器動態獲取型別?是否透過確保只設置允許的欄位來保護使用者免於拼寫錯誤的欄位名?是否強制執行型別(換句話說,不要將 int 放入 string 欄位)?是,基於 OpenAPI v3.0 驗證 模式 (1.16 GA)。
例項名稱此擴充套件機制是否對以這種方式定義的種類/資源的物件名稱施加任何限制?是的,這類物件的名稱必須是有效的 DNS 子域名。

常見功能

與在 Kubernetes 平臺之外實現 API 相比,透過 CRD 或 AA 建立自定義資源,你的 API 可以獲得許多功能

特性作用
CRUD新端點支援透過 HTTP 和 kubectl 進行 CRUD 基本操作。
Watch新端點透過 HTTP 支援 Kubernetes Watch 操作。
發現kubectl 和儀表盤等客戶端會自動對你的資源提供列表、顯示和欄位編輯操作。
json-patch新端點支援帶有 Content-Type: application/json-patch+json 的 PATCH。
合併補丁新端點支援帶有 Content-Type: application/merge-patch+json 的 PATCH。
HTTPS新端點使用 HTTPS
內建認證訪問擴充套件使用核心 API 伺服器(聚合層)進行認證
內建授權訪問擴充套件可以重用核心 API 伺服器使用的授權;例如 RBAC。
終結器阻止刪除擴充套件資源,直到外部清理完成。
Admission Webhook在任何建立/更新/刪除操作期間設定預設值並驗證擴充套件資源。
UI/CLI 顯示Kubectl、儀表盤可以顯示擴充套件資源。
未設定與空值客戶端可以將未設定的欄位與零值欄位區分開來。
客戶端庫生成Kubernetes 提供通用客戶端庫,以及生成特定型別客戶端庫的工具。
標籤和註解工具知道如何為核心和自定義資源編輯的常見物件元資料。

準備安裝自定義資源

在向叢集新增自定義資源之前,有幾點需要注意。

第三方程式碼和新的故障點

雖然建立 CRD 不會自動新增任何新的故障點(例如,透過導致第三方程式碼在你的 API 伺服器上執行),但包(例如,Charts)或其他安裝包通常包括 CRD 以及實現新自定義資源業務邏輯的第三方程式碼的 Deployment。

安裝聚合 API 伺服器總是涉及執行新的 Deployment。

儲存

自定義資源會像 ConfigMap 一樣佔用儲存空間。建立過多的自定義資源可能會使 API 伺服器的儲存空間過載。

聚合 API 伺服器可能會使用與主 API 伺服器相同的儲存,在這種情況下,同樣的警告也適用。

身份認證、授權和審計

CRD 總是使用與 API 伺服器內建資源相同的身份認證、授權和審計日誌。

如果你使用 RBAC 進行授權,大多數 RBAC 角色將不會授予對新資源的訪問許可權(除了 cluster-admin 角色或任何使用萬用字元規則建立的角色)。你需要明確授予對新資源的訪問許可權。CRD 和聚合 API 通常捆綁了它們新增的型別的新角色定義。

聚合 API 伺服器可能會或可能不會使用與主 API 伺服器相同的身份認證、授權和審計。

訪問自定義資源

Kubernetes 客戶端庫 可用於訪問自定義資源。並非所有客戶端庫都支援自定義資源。GoPython 客戶端庫支援。

新增自定義資源後,你可以使用以下方式訪問它

  • kubectl
  • Kubernetes 動態客戶端。
  • 你編寫的 REST 客戶端。
  • 使用 Kubernetes 客戶端生成工具 生成的客戶端(生成客戶端是一項高階任務,但某些專案可能會隨 CRD 或 AA 提供客戶端)。

自定義資源欄位選擇器

欄位選擇器 允許客戶端根據一個或多個資源欄位的值選擇自定義資源。

所有自定義資源都支援 metadata.namemetadata.namespace 欄位選擇器。

CustomResourceDefinition 中宣告的欄位也可以與欄位選擇器一起使用,當它們包含在 CustomResourceDefinitionspec.versions[*].selectableFields 欄位中時。

自定義資源的可選欄位

特性狀態: Kubernetes v1.32 [stable] (預設啟用:true)

CustomResourceDefinitionspec.versions[*].selectableFields 欄位可用於宣告自定義資源中的哪些其他欄位可以在欄位選擇器中使用。

以下示例將 .spec.color.spec.size 欄位新增為可選欄位。

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: shirts.stable.example.com
spec:
  group: stable.example.com
  scope: Namespaced
  names:
    plural: shirts
    singular: shirt
    kind: Shirt
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              color:
                type: string
              size:
                type: string
    selectableFields:
    - jsonPath: .spec.color
    - jsonPath: .spec.size
    additionalPrinterColumns:
    - jsonPath: .spec.color
      name: Color
      type: string
    - jsonPath: .spec.size
      name: Size
      type: string

然後可以使用欄位選擇器僅獲取 colorblue 的資源

kubectl get shirts.stable.example.com --field-selector spec.color=blue

輸出應該是

NAME       COLOR  SIZE
example1   blue   S
example2   blue   M

下一步

最後修改於 2024 年 10 月 31 日太平洋標準時間上午 10:47:刪除穩定功能的欄位門資訊,為欄位選擇器文件新增詳細資訊 (2b996e4434)