透過 CustomResourceDefinitions 擴充 Kubernetes API
本頁說明如何透過建立 CustomResourceDefinition,將自訂資源安裝到 Kubernetes API 中。
開始之前
您需要有一個 Kubernetes 叢集,並且必須設定 kubectl 命令列工具以與您的叢集通訊。建議在至少有兩個節點且這些節點不充當控制平面主機的叢集上執行本教學課程。如果您還沒有叢集,可以使用 minikube 建立一個,或者您可以使用下列 Kubernetes 體驗環境之一
您的 Kubernetes 伺服器必須是 1.16 或更新版本。若要檢查版本,請輸入kubectl version
。如果您使用的是仍受支援的舊版 Kubernetes,請切換到該版本的文件,以查看與您的叢集相關的建議。建立 CustomResourceDefinition
當您建立新的 CustomResourceDefinition (CRD) 時,Kubernetes API 伺服器會為您指定的每個版本建立新的 RESTful 資源路徑。從 CRD 物件建立的自訂資源可以是命名空間範圍或叢集範圍,如 CRD 的 spec.scope
欄位中所指定。與現有的內建物件一樣,刪除命名空間會刪除該命名空間中的所有自訂物件。CustomResourceDefinition 本身是非命名空間範圍的,並且適用於所有命名空間。
例如,如果您將下列 CustomResourceDefinition 儲存到 resourcedefinition.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.stable.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: stable.example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
# either Namespaced or Cluster
scope: Namespaced
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular name to be used as an alias on the CLI and for display
singular: crontab
# kind is normally the CamelCased singular type. Your resource manifests use this.
kind: CronTab
# shortNames allow shorter string to match your resource on the CLI
shortNames:
- ct
並建立它
kubectl apply -f resourcedefinition.yaml
然後會在以下位置建立新的命名空間 RESTful API 端點
/apis/stable.example.com/v1/namespaces/*/crontabs/...
然後可以使用此端點 URL 來建立和管理自訂物件。這些物件的 kind
將會是您在上面建立的 CustomResourceDefinition 物件規格中的 CronTab
。
建立端點可能需要幾秒鐘。您可以監看 CustomResourceDefinition 的 Established
條件是否為 true,或監看 API 伺服器的探索資訊,以查看您的資源是否顯示。
建立自訂物件
建立 CustomResourceDefinition 物件後,您可以建立自訂物件。自訂物件可以包含自訂欄位。這些欄位可以包含任意 JSON。在以下範例中,cronSpec
和 image
自訂欄位在 CronTab
類型的自訂物件中設定。CronTab
類型來自您在上面建立的 CustomResourceDefinition 物件的規格。
如果您將下列 YAML 儲存到 my-crontab.yaml
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
並建立它
kubectl apply -f my-crontab.yaml
然後您可以使用 kubectl 管理您的 CronTab 物件。例如
kubectl get crontab
應該列印出像這樣的清單
NAME AGE
my-new-cron-object 6s
使用 kubectl 時,資源名稱不區分大小寫,您可以使用 CRD 中定義的單數或複數形式,以及任何簡短名稱。
您也可以檢視原始 YAML 資料
kubectl get ct -o yaml
您應該會看到它包含您用來建立它的 YAML 中的自訂 cronSpec
和 image
欄位
apiVersion: v1
items:
- apiVersion: stable.example.com/v1
kind: CronTab
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"stable.example.com/v1","kind":"CronTab","metadata":{"annotations":{},"name":"my-new-cron-object","namespace":"default"},"spec":{"cronSpec":"* * * * */5","image":"my-awesome-cron-image"}}
creationTimestamp: "2021-06-20T07:35:27Z"
generation: 1
name: my-new-cron-object
namespace: default
resourceVersion: "1326"
uid: 9aab1d66-628e-41bb-a422-57b8b3b1f5a9
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
kind: List
metadata:
resourceVersion: ""
selfLink: ""
刪除 CustomResourceDefinition
當您刪除 CustomResourceDefinition 時,伺服器將解除安裝 RESTful API 端點,並刪除其中儲存的所有自訂物件。
kubectl delete -f resourcedefinition.yaml
kubectl get crontabs
Error from server (NotFound): Unable to list {"stable.example.com" "v1" "crontabs"}: the server could not
find the requested resource (get crontabs.stable.example.com)
如果您稍後重新建立相同的 CustomResourceDefinition,它將從空白開始。
指定結構化綱要
CustomResource 會在自訂欄位中儲存結構化資料 (以及 API 伺服器隱含驗證的內建欄位 apiVersion
、kind
和 metadata
)。透過 OpenAPI v3.0 驗證,可以指定綱要,該綱要在建立和更新期間進行驗證,請比較下方以取得此類綱要的詳細資訊和限制。
使用 apiextensions.k8s.io/v1
,結構化綱要的定義對於 CustomResourceDefinition 是強制性的。在 CustomResourceDefinition 的 Beta 版本中,結構化綱要是選用的。
結構化綱要是 OpenAPI v3.0 驗證綱要,其
- 為根目錄、物件節點的每個指定欄位 (透過 OpenAPI 中的
properties
或additionalProperties
) 以及陣列節點中的每個項目 (透過 OpenAPI 中的items
) 指定非空類型 (透過 OpenAPI 中的type
),但下列情況除外:- 具有
x-kubernetes-int-or-string: true
的節點 - 具有
x-kubernetes-preserve-unknown-fields: true
的節點
- 具有
- 針對物件中的每個欄位以及陣列中的每個項目,這些項目指定於
allOf
、anyOf
、oneOf
或not
中的任何一個,綱要也會指定這些邏輯連接詞之外的欄位/項目(比較範例 1 和 2)。 - 不會在
allOf
、anyOf
、oneOf
或not
內設定description
、type
、default
、additionalProperties
、nullable
,但x-kubernetes-int-or-string: true
的兩種模式除外(見下文)。 - 如果指定了
metadata
,則僅允許對metadata.name
和metadata.generateName
進行限制。
非結構化範例 1
allOf:
- properties:
foo:
...
與規則 2 衝突。以下是正確的寫法
properties:
foo:
...
allOf:
- properties:
foo:
...
非結構化範例 2
allOf:
- items:
properties:
foo:
...
與規則 2 衝突。以下是正確的寫法
items:
properties:
foo:
...
allOf:
- items:
properties:
foo:
...
非結構化範例 3
properties:
foo:
pattern: "abc"
metadata:
type: object
properties:
name:
type: string
pattern: "^a"
finalizers:
type: array
items:
type: string
pattern: "my-finalizer"
anyOf:
- properties:
bar:
type: integer
minimum: 42
required: ["bar"]
description: "foo bar object"
由於以下違規行為,因此不是結構化綱要
- 根目錄的類型遺失(規則 1)。
foo
的類型遺失(規則 1)。anyOf
內部的bar
未在外部指定(規則 2)。bar
的type
位於anyOf
內部(規則 3)。- 描述設定在
anyOf
內部(規則 3)。 metadata.finalizers
可能未受限制(規則 4)。
相反地,以下對應的綱要是結構化的
type: object
description: "foo bar object"
properties:
foo:
type: string
pattern: "abc"
bar:
type: integer
metadata:
type: object
properties:
name:
type: string
pattern: "^a"
anyOf:
- properties:
bar:
minimum: 42
required: ["bar"]
結構化綱要規則的違規情況會在 CustomResourceDefinition 的 NonStructural
條件中報告。
欄位修剪
CustomResourceDefinitions 將驗證過的資源資料儲存在叢集的持久儲存區 etcd 中。與原生 Kubernetes 資源(例如 ConfigMap)一樣,如果您指定的欄位 API 伺服器無法辨識,則未知的欄位會在持久儲存之前被修剪(移除)。
從 apiextensions.k8s.io/v1beta1
轉換為 apiextensions.k8s.io/v1
的 CRD 可能缺少結構化綱要,且 spec.preserveUnknownFields
可能為 true
。
對於以 apiextensions.k8s.io/v1beta1
建立且 spec.preserveUnknownFields
設定為 true
的舊版 CustomResourceDefinition 物件,以下情況也適用
- 未啟用修剪。
- 您可以儲存任意資料。
為了與 apiextensions.k8s.io/v1
相容,請更新您的自訂資源定義以
- 使用結構化 OpenAPI 綱要。
- 將
spec.preserveUnknownFields
設定為false
。
如果您將下列 YAML 儲存到 my-crontab.yaml
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
someRandomField: 42
並建立它
kubectl create --validate=false -f my-crontab.yaml -o yaml
您的輸出會類似於
apiVersion: stable.example.com/v1
kind: CronTab
metadata:
creationTimestamp: 2017-05-31T12:56:35Z
generation: 1
name: my-new-cron-object
namespace: default
resourceVersion: "285"
uid: 9423255b-4600-11e7-af6a-28d2447dc82b
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
請注意,欄位 someRandomField
已被修剪。
此範例關閉了用戶端驗證,以示範 API 伺服器的行為,方法是加入 --validate=false
命令列選項。由於 OpenAPI 驗證綱要也會發布給用戶端,因此 kubectl
也會檢查未知的欄位,並在這些物件傳送至 API 伺服器之前就拒絕它們。
控制修剪
預設情況下,自訂資源的所有未指定欄位(跨所有版本)都會被修剪。但是,可以透過在 結構化 OpenAPI v3 驗證綱要中加入 x-kubernetes-preserve-unknown-fields: true
,選擇不針對特定欄位子樹進行修剪。
例如
type: object
properties:
json:
x-kubernetes-preserve-unknown-fields: true
欄位 json
可以儲存任何 JSON 值,而不會修剪任何內容。
您也可以部分指定允許的 JSON;例如
type: object
properties:
json:
x-kubernetes-preserve-unknown-fields: true
type: object
description: this is arbitrary JSON
透過這樣做,僅允許 object
類型的值。
針對每個指定的屬性(或 additionalProperties
),再次啟用修剪
type: object
properties:
json:
x-kubernetes-preserve-unknown-fields: true
type: object
properties:
spec:
type: object
properties:
foo:
type: string
bar:
type: string
透過這樣做,值
json:
spec:
foo: abc
bar: def
something: x
status:
something: x
會修剪為
json:
spec:
foo: abc
bar: def
status:
something: x
這表示指定 spec
物件中的 something
欄位會被修剪,但外部的所有內容則不會。
IntOrString
具有 x-kubernetes-int-or-string: true
的綱要中的節點會從規則 1 中排除,因此以下是結構化的
type: object
properties:
foo:
x-kubernetes-int-or-string: true
這些節點也部分從規則 3 中排除,因為允許以下兩種模式(完全相同,附加欄位的順序沒有變化)
x-kubernetes-int-or-string: true
anyOf:
- type: integer
- type: string
...
以及
x-kubernetes-int-or-string: true
allOf:
- anyOf:
- type: integer
- type: string
- ... # zero or more
...
透過其中一種規格,整數和字串都可以驗證。
在 發布驗證綱要中,x-kubernetes-int-or-string: true
會展開為上面顯示的兩種模式之一。
RawExtension
RawExtensions(如 runtime.RawExtension
中)包含完整的 Kubernetes 物件,即具有 apiVersion
和 kind
欄位。
可以透過設定 x-kubernetes-embedded-resource: true
來指定這些嵌入式物件(完全沒有限制或部分指定)。例如
type: object
properties:
foo:
x-kubernetes-embedded-resource: true
x-kubernetes-preserve-unknown-fields: true
在這裡,欄位 foo
保留完整的物件,例如
foo:
apiVersion: v1
kind: Pod
spec:
...
由於 x-kubernetes-preserve-unknown-fields: true
是與此一起指定的,因此不會修剪任何內容。但是,x-kubernetes-preserve-unknown-fields: true
的使用是選用的。
透過 x-kubernetes-embedded-resource: true
,apiVersion
、kind
和 metadata
會隱含地指定和驗證。
提供 CRD 的多個版本
請參閱 自訂資源定義版本控制,以取得關於提供 CustomResourceDefinition 的多個版本以及將您的物件從一個版本移轉到另一個版本的更多資訊。
進階主題
定案器
Finalizers 允許控制器實作非同步的預先刪除掛鉤。自訂物件支援類似於內建物件的 finalizers。
您可以像這樣將 finalizer 新增至自訂物件
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
finalizers:
- stable.example.com/finalizer
自訂 finalizers 的識別碼包含網域名稱、正斜線和 finalizer 的名稱。任何控制器都可以將 finalizer 新增至任何物件的 finalizers 清單。
對具有 finalizers 的物件的第一個刪除請求會設定 metadata.deletionTimestamp
欄位的值,但不會刪除它。一旦設定此值,finalizers
清單中的項目就只能移除。在任何 finalizers 存在的情況下,也不可能強制刪除物件。
當設定 metadata.deletionTimestamp
欄位時,監看物件的控制器會執行它們處理的任何 finalizers,並在完成後從清單中移除 finalizer。每個控制器都有責任從清單中移除其 finalizer。
metadata.deletionGracePeriodSeconds
的值控制輪詢更新之間的時間間隔。
一旦 finalizers 清單為空,表示所有 finalizers 都已執行,資源就會被 Kubernetes 刪除。
驗證
自訂資源會透過 OpenAPI v3.0 綱要、啟用 驗證規則功能時的 x-kubernetes-validations 來驗證,而且您可以使用 准入 Webhook 新增額外的驗證。
此外,以下限制適用於綱要
這些欄位無法設定
definitions
,dependencies
,deprecated
,discriminator
,id
,patternProperties
,readOnly
,writeOnly
,xml
,$ref
.
欄位
uniqueItems
無法設定為true
。欄位
additionalProperties
無法設定為false
。欄位
additionalProperties
與properties
互斥。
當啟用 驗證規則功能且 CustomResourceDefinition 綱要是 結構化綱要時,x-kubernetes-validations
擴充功能可用於使用 Common Expression Language (CEL) 表達式來驗證自訂資源。
請參閱 結構化綱要章節,以了解其他限制和 CustomResourceDefinition 功能。
綱要定義於 CustomResourceDefinition 中。在以下範例中,CustomResourceDefinition 將以下驗證套用至自訂物件
spec.cronSpec
必須是字串,且必須採用規則運算式所描述的形式。spec.replicas
必須是整數,且最小值必須為 1,最大值必須為 10。
將 CustomResourceDefinition 儲存至 resourcedefinition.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
# openAPIV3Schema is the schema for validating custom objects.
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
並建立它
kubectl apply -f resourcedefinition.yaml
如果種類為 CronTab 的自訂物件的欄位中存在無效值,則會拒絕建立自訂物件的請求。在以下範例中,自訂物件包含具有無效值的欄位
spec.cronSpec
與規則運算式不符。spec.replicas
大於 10。
如果您將下列 YAML 儲存到 my-crontab.yaml
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * *"
image: my-awesome-cron-image
replicas: 15
並嘗試建立它
kubectl apply -f my-crontab.yaml
然後您會收到錯誤
The CronTab "my-new-cron-object" is invalid: []: Invalid value: map[string]interface {}{"apiVersion":"stable.example.com/v1", "kind":"CronTab", "metadata":map[string]interface {}{"name":"my-new-cron-object", "namespace":"default", "deletionTimestamp":interface {}(nil), "deletionGracePeriodSeconds":(*int64)(nil), "creationTimestamp":"2017-09-05T05:20:07Z", "uid":"e14d79e7-91f9-11e7-a598-f0761cb232d1", "clusterName":""}, "spec":map[string]interface {}{"cronSpec":"* * * *", "image":"my-awesome-cron-image", "replicas":15}}:
validation failure list:
spec.cronSpec in body should match '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
spec.replicas in body should be less than or equal to 10
如果欄位包含有效值,則會接受物件建立請求。
將以下 YAML 儲存至 my-crontab.yaml
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 5
並建立它
kubectl apply -f my-crontab.yaml
crontab "my-new-cron-object" created
驗證棘輪效應
Kubernetes v1.30 [beta]
(預設啟用:true)如果您使用的 Kubernetes 版本早於 v1.30,您需要明確啟用 CRDValidationRatcheting
功能閘道,才能使用此行為,然後此行為會套用至您叢集中的所有 CustomResourceDefinitions。
如果您啟用了功能閘道,Kubernetes 會為 CustomResourceDefinitions 實作驗證棘輪效應。API 伺服器願意接受對更新後無效的資源進行更新,前提是資源中未通過驗證的每個部分都未被更新操作變更。換句話說,資源的任何無效部分保持無效,則必須已經是錯誤的。您無法使用此機制來更新有效的資源,使其變為無效。
此功能允許 CRD 的作者在特定條件下放心地將新的驗證新增至 OpenAPIV3 綱要。使用者可以安全地更新到新的綱要,而無需提高物件的版本或中斷工作流程。
雖然 CRD 的 OpenAPIV3 綱要中放置的大多數驗證都支援棘輪效應,但也有一些例外情況。在 Kubernetes 1.32 的實作中,以下 OpenAPIV3 綱要驗證不受棘輪效應支援,如果違反,將繼續像平常一樣拋出錯誤
量詞
allOf
oneOf
anyOf
not
- 這些欄位之一的後代中的任何驗證
x-kubernetes-validations
對於 Kubernetes 1.28,CRD 驗證規則會被棘輪效應忽略。從 Kubernetes 1.29 的 Alpha 2 開始,只有當x-kubernetes-validations
不參照oldSelf
時,才會進行棘輪效應。轉換規則永遠不會進行棘輪效應:只有不使用
oldSelf
的規則引發的錯誤,在其值未變更的情況下才會自動進行棘輪效應。若要為 CEL 表達式撰寫自訂棘輪效應邏輯,請查看 optionalOldSelf。
x-kubernetes-list-type
由於變更子綱要的清單類型而產生的錯誤將不會進行棘輪效應。例如,將set
新增至具有重複項目的清單將始終導致錯誤。x-kubernetes-map-keys
由於變更清單綱要的對應金鑰而產生的錯誤將不會進行棘輪效應。required
由於變更必要欄位清單而產生的錯誤將不會進行棘輪效應。properties
新增/移除/修改屬性的名稱不會進行棘輪效應,但如果屬性的名稱保持不變,則變更每個屬性綱要和子綱要中的驗證可能會進行棘輪效應。additionalProperties
移除先前指定的additionalProperties
驗證將不會進行棘輪效應。metadata
來自 Kubernetes 內建物件metadata
驗證的錯誤不會進行棘輪效應(例如物件名稱或標籤值中的字元)。如果您為自訂資源的 metadata 指定自己的額外規則,則該額外驗證將會進行棘輪效應。
驗證規則
Kubernetes v1.29 [stable]
驗證規則使用 Common Expression Language (CEL) 來驗證自訂資源值。驗證規則使用 x-kubernetes-validations
擴充功能包含在 CustomResourceDefinition 綱要中。
規則的作用域設定為綱要中 x-kubernetes-validations
擴充功能的位置。而 CEL 表達式中的 self
變數會繫結至作用域值。
所有驗證規則的作用域都設定為目前的物件:不支援跨物件或具狀態的驗證規則。
例如
...
openAPIV3Schema:
type: object
properties:
spec:
type: object
x-kubernetes-validations:
- rule: "self.minReplicas <= self.replicas"
message: "replicas should be greater than or equal to minReplicas."
- rule: "self.replicas <= self.maxReplicas"
message: "replicas should be smaller than or equal to maxReplicas."
properties:
...
minReplicas:
type: integer
replicas:
type: integer
maxReplicas:
type: integer
required:
- minReplicas
- replicas
- maxReplicas
將拒絕建立此自訂資源的請求
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
minReplicas: 0
replicas: 20
maxReplicas: 10
並傳回以下回應
The CronTab "my-new-cron-object" is invalid:
* spec: Invalid value: map[string]interface {}{"maxReplicas":10, "minReplicas":0, "replicas":20}: replicas should be smaller than or equal to maxReplicas.
x-kubernetes-validations
可以有多個規則。x-kubernetes-validations
下的 rule
代表將由 CEL 評估的表達式。message
代表驗證失敗時顯示的訊息。如果未設定訊息,則以上回應將為
The CronTab "my-new-cron-object" is invalid:
* spec: Invalid value: map[string]interface {}{"maxReplicas":10, "minReplicas":0, "replicas":20}: failed rule: self.replicas <= self.maxReplicas
注意
您可以在 CEL Playground 中快速測試 CEL 表達式。驗證規則會在建立/更新 CRD 時編譯。如果驗證規則編譯失敗,則 CRD 建立/更新的請求將會失敗。編譯過程也包含類型檢查。
編譯失敗
no_matching_overload
:此函數沒有適用於引數類型的多載。例如,針對整數類型欄位的規則(例如
self == true
)將會產生錯誤Invalid value: apiextensions.ValidationRule{Rule:"self == true", Message:""}: compilation failed: ERROR: \<input>:1:6: found no matching overload for '_==_' applied to '(int, bool)'
no_such_field
:不包含所需的欄位。例如,針對不存在欄位的規則(例如
self.nonExistingField > 0
)將傳回以下錯誤Invalid value: apiextensions.ValidationRule{Rule:"self.nonExistingField > 0", Message:""}: compilation failed: ERROR: \<input>:1:5: undefined field 'nonExistingField'
invalid argument
:巨集引數無效。例如,規則(例如
has(self)
)將傳回錯誤Invalid value: apiextensions.ValidationRule{Rule:"has(self)", Message:""}: compilation failed: ERROR: <input>:1:4: invalid argument to has() macro
驗證規則範例
規則 | 目的 |
---|---|
self.minReplicas <= self.replicas && self.replicas <= self.maxReplicas | 驗證定義副本的三個欄位的順序是否正確 |
'Available' in self.stateCounts | 驗證具有 'Available' 金鑰的項目是否存在於對應中 |
(size(self.list1) == 0) != (size(self.list2) == 0) | 驗證兩個清單中只有一個是非空的,但不是兩個都是 |
!('MY_KEY' in self.map1) || self['MY_KEY'].matches('^[a-zA-Z]*$') | 驗證對應中特定金鑰的值(如果它在對應中) |
self.envars.filter(e, e.name == 'MY_ENV').all(e, e.value.matches('^[a-zA-Z]*$') | 驗證金鑰欄位 'name' 為 'MY_ENV' 的 listMap 項目的 'value' 欄位 |
has(self.expired) && self.created + self.ttl < self.expired | 驗證 'expired' 日期是否在 'create' 日期加上 'ttl' 期間之後 |
self.health.startsWith('ok') | 驗證 'health' 字串欄位是否具有前綴 'ok' |
self.widgets.exists(w, w.key == 'x' && w.foo < 10) | 驗證具有金鑰 'x' 的 listMap 項目的 'foo' 屬性是否小於 10 |
type(self) == string ? self == '100%' : self == 1000 | 驗證 int-or-string 欄位的整數和字串案例 |
self.metadata.name.startsWith(self.prefix) | 驗證物件的名稱是否具有另一個欄位值的前綴 |
self.set1.all(e, !(e in self.set2)) | 驗證兩個 listSets 是否不相交 |
size(self.names) == size(self.details) && self.names.all(n, n in self.details) | 驗證 'details' 對應是否以 'names' listSet 中的項目作為金鑰 |
size(self.clusters.filter(c, c.name == self.primary)) == 1 | 驗證 'primary' 屬性在 'clusters' listMap 中是否只有一個出現次數 |
Xref: CEL 上支援的評估
如果規則的作用域設定為資源的根目錄,則它可能會選取在 CRD 的 OpenAPIv3 綱要中宣告的任何欄位,以及
apiVersion
、kind
、metadata.name
和metadata.generateName
。這包括在同一個表達式中選取spec
和status
中的欄位... openAPIV3Schema: type: object x-kubernetes-validations: - rule: "self.status.availableReplicas >= self.spec.minReplicas" properties: spec: type: object properties: minReplicas: type: integer ... status: type: object properties: availableReplicas: type: integer
如果規則的作用域設定為具有屬性的物件,則物件的可存取屬性可以透過
self.field
進行欄位選取,並且可以透過has(self.field)
檢查欄位的存在。在 CEL 表達式中,Null 值欄位會被視為不存在的欄位。... openAPIV3Schema: type: object properties: spec: type: object x-kubernetes-validations: - rule: "has(self.foo)" properties: ... foo: type: integer
如果規則的作用域設定為具有 additionalProperties 的物件(即對應),則對應的值可以透過
self[mapKey]
存取,可以透過mapKey in self
檢查對應的包含關係,並且可以透過 CEL 巨集和函數(例如self.all(...)
)存取對應的所有項目。... openAPIV3Schema: type: object properties: spec: type: object x-kubernetes-validations: - rule: "self['xyz'].foo > 0" additionalProperties: ... type: object properties: foo: type: integer
如果規則的作用域設定為陣列,則陣列的元素可以透過
self[i]
以及巨集和函數存取。... openAPIV3Schema: type: object properties: ... foo: type: array x-kubernetes-validations: - rule: "size(self) == 1" items: type: string
如果規則的作用域設定為純量,則
self
會繫結至純量值。... openAPIV3Schema: type: object properties: spec: type: object properties: ... foo: type: integer x-kubernetes-validations: - rule: "self > 0"
範例
欄位規則的作用域類型 | 規則範例 |
---|---|
根物件 | self.status.actual <= self.spec.maxDesired |
物件的對應 | self.components['Widget'].priority < 10 |
整數清單 | self.values.all(value, value >= 0 && value < 100) |
字串 | self.startsWith('kube') |
apiVersion
、kind
、metadata.name
和 metadata.generateName
始終可以從物件的根目錄以及任何 x-kubernetes-embedded-resource
註解的物件存取。無法存取其他 metadata 屬性。
透過 x-kubernetes-preserve-unknown-fields
保留在自訂資源中的未知資料在 CEL 表達式中無法存取。這包括
透過具有
x-kubernetes-preserve-unknown-fields
的物件綱要保留的未知欄位值。屬性綱要是「未知類型」的物件屬性。「未知類型」以遞迴方式定義為
- 沒有類型且 x-kubernetes-preserve-unknown-fields 設定為 true 的綱要
- 項目綱要是「未知類型」的陣列
- additionalProperties 綱要是「未知類型」的物件
只有 [a-zA-Z_.-/][a-zA-Z0-9_.-/]*
形式的屬性名稱可以存取。當在表達式中存取時,可存取的屬性名稱會根據以下規則逸出
逸出序列 | 等效的屬性名稱 |
---|---|
__underscores__ | __ |
__dot__ | . |
__dash__ | - |
__slash__ | / |
__{keyword}__ | CEL 保留關鍵字 |
注意:CEL 保留關鍵字需要與確切的屬性名稱相符才能逸出(例如,單字 sprint 中的 int 不會逸出)。
逸出範例
屬性名稱 | 具有逸出屬性名稱的規則 |
---|---|
namespace | self.__namespace__ > 0 |
x-prop | self.x__dash__prop > 0 |
redact__d | self.redact__underscores__d > 0 |
字串 | self.startsWith('kube') |
對於 x-kubernetes-list-type
為 set
或 map
的陣列,等式會忽略元素順序,即 [1, 2] == [2, 1]
。對於具有 x-kubernetes-list-type 的陣列,串連會使用清單類型的語意
set
:X + Y
執行聯集,其中保留X
中所有元素的陣列位置,並附加Y
中不相交的元素,同時保留其部分順序。map
:X + Y
執行合併,其中保留X
中所有金鑰的陣列位置,但當X
和Y
的金鑰集相交時,這些值會被Y
中的值覆寫。具有不相交金鑰的Y
中的元素會被附加,同時保留其部分順序。
以下是 OpenAPIv3 和 CEL 類型之間的宣告類型對應
OpenAPIv3 類型 | CEL 類型 |
---|---|
具有屬性的 'object' | 物件 /「訊息類型」 |
具有 AdditionalProperties 的 'object' | 對應 |
具有 x-kubernetes-embedded-type 的 'object' | 物件 /「訊息類型」,'apiVersion'、'kind'、'metadata.name' 和 'metadata.generateName' 隱含地包含在綱要中 |
具有 x-kubernetes-preserve-unknown-fields 的 'object' | 物件 /「訊息類型」,未知欄位在 CEL 表達式中不可存取 |
x-kubernetes-int-or-string | 動態物件,可以是整數或字串,type(value) 可以用於檢查類型 |
'array' | 清單 |
具有 x-kubernetes-list-type=map 的 'array' | 具有基於對應的等式和唯一金鑰保證的清單 |
具有 x-kubernetes-list-type=set 的 'array' | 具有基於集合的等式和唯一項目保證的清單 |
'boolean' | 布林值 |
'number'(所有格式) | 雙精度浮點數 |
'integer'(所有格式) | 整數 (64) |
'null' | null_type |
'string' | 字串 |
'string',格式為 byte (base64 編碼) | 位元組 |
'string',格式為 date | 時間戳記 (google.protobuf.Timestamp) |
'string',格式為 datetime | 時間戳記 (google.protobuf.Timestamp) |
'string',格式為 duration | 持續時間 (google.protobuf.Duration) |
xref: CEL 類型、OpenAPI 類型、Kubernetes 結構化綱要。
messageExpression 欄位
與 message
欄位類似,後者定義了驗證規則失敗時報告的字串,messageExpression
允許您使用 CEL 表達式來建構訊息字串。這允許您在驗證失敗訊息中插入更具描述性的資訊。messageExpression
必須評估字串,並且可以使用與 rule
欄位相同的變數。例如
x-kubernetes-validations:
- rule: "self.x <= self.maxLimit"
messageExpression: '"x exceeded max limit of " + string(self.maxLimit)'
請記住,CEL 字串串連(+
運算子)不會自動轉換為字串。如果您有非字串純量,請使用 string(<value>)
函數將純量轉換為字串,如以上範例所示。
messageExpression
必須評估為字串,這會在寫入 CRD 時進行檢查。請注意,可以在同一個規則上設定 message
和 messageExpression
,如果兩者都存在,則會使用 messageExpression
。但是,如果 messageExpression
評估為錯誤,則會改為使用 message
中定義的字串,並且會記錄 messageExpression
錯誤。如果 messageExpression
中定義的 CEL 表達式產生空字串或包含換行符號的字串,也會發生此回退。
如果滿足上述條件之一,且未設定 message
,則會改為使用預設的驗證失敗訊息。
messageExpression
是 CEL 表達式,因此 驗證函數的資源使用中列出的限制適用。如果在 messageExpression
執行期間由於資源限制而停止評估,則不會執行進一步的驗證規則。
設定 messageExpression
是選用的。
message
欄位
如果您想要設定靜態訊息,您可以提供 message
而不是 messageExpression
。如果驗證失敗,message
的值會用作不透明的錯誤字串。
設定 message
是選用的。
reason
欄位
您可以在 validation
中新增機器可讀的驗證失敗原因,以便在請求未通過此驗證規則時傳回。
例如
x-kubernetes-validations:
- rule: "self.x <= self.maxLimit"
reason: "FieldValueInvalid"
傳回給呼叫者的 HTTP 狀態碼將與第一個失敗的驗證規則的原因相符。目前支援的原因為:「FieldValueInvalid」、「FieldValueForbidden」、「FieldValueRequired」、「FieldValueDuplicate」。如果未設定或原因不明,則預設使用「FieldValueInvalid」。
設定 reason
是選用的。
fieldPath
欄位
您可以指定驗證失敗時傳回的欄位路徑。
例如
x-kubernetes-validations:
- rule: "self.foo.test.x <= self.maxLimit"
fieldPath: ".foo.test.x"
在以上範例中,驗證檢查欄位 x
的值應小於 maxLimit
的值。如果未指定 fieldPath
,則當驗證失敗時,fieldPath 將預設為 self
的作用域位置。如果指定了 fieldPath
,則傳回的錯誤將使 fieldPath
正確參照欄位 x
的位置。
fieldPath
值必須是相對於此綱要中 x-kubernetes-validations 擴充功能位置的 JSON 路徑。此外,它應參照綱要內的現有欄位。例如,當驗證檢查對應 testMap
下的特定屬性 foo
時,您可以將 fieldPath
設定為 ".testMap.foo"
或 .testMap['foo']'
。如果驗證需要檢查兩個清單中的唯一屬性,則 fieldPath 可以設定為其中一個清單。例如,它可以設定為 .testList1
或 .testList2
。它支援子操作以參照目前的現有欄位。請參閱 Kubernetes 中的 JSONPath 支援以取得更多資訊。fieldPath
欄位不支援以數字方式索引陣列。
設定 fieldPath
是選用的。
optionalOldSelf
欄位
Kubernetes v1.30 [beta]
(預設啟用:true)如果您的叢集未啟用 CRD 驗證棘輪效應,則 CustomResourceDefinition API 不包含此欄位,嘗試設定它可能會導致錯誤。
optionalOldSelf
欄位是一個布林值欄位,它會改變以下描述的 轉換規則的行為。通常,如果無法確定 oldSelf
,則轉換規則將不會評估:在物件建立期間或在更新中引入新值時。
如果 optionalOldSelf
設定為 true,則轉換規則將始終被評估,並且 oldSelf
的類型將變更為 CEL Optional
類型。
在綱要作者希望使用比 預設的基於等式的行為提供的更具控制力的工具來對新值引入更新、通常更嚴格的限制,同時仍然允許使用較舊的驗證來「祖父化」或棘輪化舊值的情況下,optionalOldSelf
非常有用。
使用範例
CEL | 描述 |
---|---|
`self.foo == "foo" | |
[oldSelf.orValue(""), self].all(x, ["OldCase1", "OldCase2"].exists(case, x == case)) | |
oldSelf.optMap(o, o.size()).orValue(0) < 4 |
驗證函數
可用的函數包括
轉換規則
包含參照識別碼 oldSelf
的表達式的規則會隱含地被視為轉換規則。轉換規則允許綱要作者防止兩個原本有效的狀態之間的特定轉換。例如
type: string
enum: ["low", "medium", "high"]
x-kubernetes-validations:
- rule: "!(self == 'high' && oldSelf == 'low') && !(self == 'low' && oldSelf == 'high')"
message: cannot transition directly between 'low' and 'high'
與其他規則不同,轉換規則僅適用於符合以下條件的操作
該操作更新現有的物件。轉換規則永遠不適用於建立操作。
舊值和新值都存在。仍然可以透過在父節點上放置轉換規則來檢查值是否已新增或移除。轉換規則永遠不適用於自訂資源建立。當放置在選用欄位上時,轉換規則將不適用於設定或取消設定欄位的更新操作。
轉換規則驗證的綱要節點的路徑必須解析為可在舊物件和新物件之間比較的節點。例如,清單項目及其後代 (
spec.foo[10].bar
) 不一定可以在現有物件和稍後對同一物件的更新之間建立關聯。
如果綱要節點包含永遠無法套用的轉換規則(例如「oldSelf 無法在路徑內綱要的不可關聯部分上使用」),則會在 CRD 寫入時產生錯誤。
轉換規則僅允許在綱要的可關聯部分上使用。如果所有 array
父綱要的類型都是 x-kubernetes-list-type=map
,則綱要的一部分是可關聯的;任何 set
或 atomic
陣列父綱要都會使 self
與 oldSelf
之間的明確關聯變得不可能。
以下是一些轉換規則的範例
使用案例 | 規則 |
---|---|
不可變性 | self.foo == oldSelf.foo |
防止指派後修改/移除 | oldSelf != 'bar' || self == 'bar' 或 !has(oldSelf.field) || has(self.field) |
僅附加集合 | self.all(element, element in oldSelf) |
如果先前的值是 X,則新值只能是 A 或 B,不能是 Y 或 Z | oldSelf != 'X' || self in ['A', 'B'] |
單調(非遞減)計數器 | self >= oldSelf |
驗證函數的資源使用
當您建立或更新使用驗證規則的 CustomResourceDefinition 時,API 伺服器會檢查執行這些驗證規則可能產生的影響。如果評估某個規則的執行成本過高,則 API 伺服器會拒絕建立或更新操作,並傳回錯誤訊息。在執行階段也使用類似的系統來觀察解譯器採取的動作。如果解譯器執行的指令過多,則會停止規則的執行,並產生錯誤。每個 CustomResourceDefinition 也被允許一定量的資源來完成執行其所有驗證規則。如果在建立時評估其規則的總和超過該限制,則也會發生驗證錯誤。
如果您僅指定始終花費相同時間量的規則,而與其輸入的大小無關,則您不太可能遇到驗證資源預算的問題。例如,斷言 self.foo == 1
的規則本身沒有任何在驗證資源預算群組上被拒絕的風險。但是,如果 foo
是字串,並且您定義了驗證規則 self.foo.contains("someString")
,則該規則的執行時間會根據 foo
的長度而變長。另一個範例是,如果 foo
是陣列,並且您指定了驗證規則 self.foo.all(x, x > 5)
。成本系統始終假設最壞情況,如果未給出 foo
長度的限制,並且這將發生在任何可以迭代的內容(清單、對應等)上。
因此,最佳做法是針對驗證規則中將處理的任何內容,透過 maxItems
、maxProperties
和 maxLength
設定限制,以防止成本評估期間發生驗證錯誤。例如,給定具有一個規則的此綱要
openAPIV3Schema:
type: object
properties:
foo:
type: array
items:
type: string
x-kubernetes-validations:
- rule: "self.all(x, x.contains('a string'))"
然後 API 伺服器會基於驗證預算理由拒絕此規則,並產生錯誤
spec.validation.openAPIV3Schema.properties[spec].properties[foo].x-kubernetes-validations[0].rule: Forbidden:
CEL rule exceeded budget by more than 100x (try simplifying the rule, or adding maxItems, maxProperties, and
maxLength where arrays, maps, and strings are used)
拒絕發生是因為 self.all
意味著在 foo
中的每個字串上呼叫 contains()
,這反過來會檢查給定的字串,以查看它是否包含 'a string'
。在沒有限制的情況下,這是一個非常昂貴的規則。
如果您未指定任何驗證限制,則此規則的估計成本將超過每個規則的成本限制。但是,如果您在適當的位置新增限制,則規則將被允許
openAPIV3Schema:
type: object
properties:
foo:
type: array
maxItems: 25
items:
type: string
maxLength: 10
x-kubernetes-validations:
- rule: "self.all(x, x.contains('a string'))"
成本評估系統除了規則本身的估計成本外,還會考慮規則將被執行的次數。例如,以下規則將具有與先前範例相同的估計成本(儘管規則現在定義在個別陣列項目上)
openAPIV3Schema:
type: object
properties:
foo:
type: array
maxItems: 25
items:
type: string
x-kubernetes-validations:
- rule: "self.contains('a string'))"
maxLength: 10
如果清單內的清單具有使用 self.all
的驗證規則,則這比具有相同規則的非巢狀清單要昂貴得多。在非巢狀清單上可能允許的規則可能需要在兩個巢狀清單上設定較低的限制才能被允許。例如,即使沒有設定限制,以下規則也是允許的
openAPIV3Schema:
type: object
properties:
foo:
type: array
items:
type: integer
x-kubernetes-validations:
- rule: "self.all(x, x == 5)"
但是,以下綱要(新增了巢狀陣列)上的相同規則會產生驗證錯誤
openAPIV3Schema:
type: object
properties:
foo:
type: array
items:
type: array
items:
type: integer
x-kubernetes-validations:
- rule: "self.all(x, x == 5)"
這是因為 foo
的每個項目本身都是一個陣列,並且每個子陣列反過來都會呼叫 self.all
。如果使用驗證規則,請盡可能避免巢狀清單和對應。
預設值
注意
若要使用預設值,您的 CustomResourceDefinition 必須使用 API 版本apiextensions.k8s.io/v1
。預設值允許在 OpenAPI v3 驗證綱要中指定預設值
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
# openAPIV3Schema is the schema for validating custom objects.
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
default: "5 0 * * *"
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
default: 1
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
透過這樣做,cronSpec
和 replicas
都會預設為
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
image: my-awesome-cron-image
導致
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "5 0 * * *"
image: my-awesome-cron-image
replicas: 1
預設值會發生在物件上
- 在使用請求版本預設值向 API 伺服器發出的請求中,
- 在從 etcd 讀取時,使用儲存版本預設值,
- 在使用具有非空修補程式的變更准入外掛程式之後,使用准入 Webhook 物件版本預設值。
從 etcd 讀取資料時套用的預設值不會自動寫回 etcd。需要透過 API 發出更新請求,才能將這些預設值持久儲存回 etcd。
預設值必須經過修剪(metadata 欄位的預設值除外),並且必須根據提供的結構描述進行驗證。
針對 x-kubernetes-embedded-resources: true
節點的 metadata
欄位(或涵蓋 metadata
的預設值部分)的預設值,在 CustomResourceDefinition 建立期間不會進行修剪,而是在處理請求期間透過修剪步驟進行修剪。
預設值設定與可空值 (Nullable)
對於未指定可空值標記或給定 false
值的欄位,其空值將在預設值設定之前被修剪。如果存在預設值,則將會套用。當可空值為 true
時,空值將會被保留,且不會設定預設值。
例如,給定以下 OpenAPI 結構描述
type: object
properties:
spec:
type: object
properties:
foo:
type: string
nullable: false
default: "default"
bar:
type: string
nullable: true
baz:
type: string
建立一個物件,其中 foo
、bar
和 baz
的值為空值
spec:
foo: null
bar: null
baz: null
導致
spec:
foo: "default"
bar: null
foo
因為欄位不可空值而被修剪並設定預設值,bar
因為 nullable: true
而保留空值,而 baz
因為欄位不可空值且沒有預設值而被修剪。
在 OpenAPI 中發布驗證結構描述
CustomResourceDefinition OpenAPI v3 驗證結構描述,這些結構描述是 結構化 的,並且 啟用修剪,會從 Kubernetes API 伺服器發布為 OpenAPI v3 和 OpenAPI v2。建議使用 OpenAPI v3 文件,因為它是 CustomResourceDefinition OpenAPI v3 驗證結構描述的無損表示,而 OpenAPI v2 則表示有損轉換。
kubectl 命令列工具會使用已發布的結構描述來執行用戶端驗證 (kubectl create
和 kubectl apply
)、結構描述說明 (kubectl explain
) 在自訂資源上。已發布的結構描述也可以用於其他目的,例如用戶端產生或文件編寫。
與 OpenAPI V2 的相容性
為了與 OpenAPI V2 相容,OpenAPI v3 驗證結構描述會對 OpenAPI v2 結構描述執行有損轉換。該結構描述會顯示在 OpenAPI v2 規格 中的 definitions
和 paths
欄位中。
在轉換期間會套用以下修改,以保持與先前 1.13 版本中 kubectl 的回溯相容性。這些修改可防止 kubectl 過於嚴格,並拒絕其無法理解的有效 OpenAPI 結構描述。轉換不會修改 CRD 中定義的驗證結構描述,因此不會影響 API 伺服器中的 驗證。
以下欄位由於 OpenAPI v2 不支援而被移除。
- 欄位
allOf
、anyOf
、oneOf
和not
已移除
- 欄位
如果設定了
nullable: true
,我們會捨棄type
、nullable
、items
和properties
,因為 OpenAPI v2 無法表達可空值。為了避免 kubectl 拒絕良好的物件,這是必要的。
額外的印表機欄位
kubectl 工具依賴伺服器端輸出格式設定。您叢集的 API 伺服器決定 kubectl get
命令顯示哪些欄位。您可以為 CustomResourceDefinition 自訂這些欄位。以下範例新增了 Spec
、Replicas
和 Age
欄位。
將 CustomResourceDefinition 儲存至 resourcedefinition.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
additionalPrinterColumns:
- name: Spec
type: string
description: The cron spec defining the interval a CronJob is run
jsonPath: .spec.cronSpec
- name: Replicas
type: integer
description: The number of jobs launched by the CronJob
jsonPath: .spec.replicas
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
建立 CustomResourceDefinition
kubectl apply -f resourcedefinition.yaml
使用前一節的 my-crontab.yaml
建立一個執行個體。
調用伺服器端列印
kubectl get crontab my-new-cron-object
請注意輸出中的 NAME
、SPEC
、REPLICAS
和 AGE
欄位
NAME SPEC REPLICAS AGE
my-new-cron-object * * * * * 1 7s
注意
NAME
欄位是隱含的,不需要在 CustomResourceDefinition 中定義。優先順序
每個欄位都包含 priority
欄位。目前,優先順序區分在標準視圖或寬視圖(使用 -o wide
旗標)中顯示的欄位。
- 優先順序為
0
的欄位會在標準視圖中顯示。 - 優先順序大於
0
的欄位僅在寬視圖中顯示。
類型
欄位的 type
欄位可以是以下任何一種(比較 OpenAPI v3 資料類型)
integer
– 非浮點數number
– 浮點數string
– 字串boolean
–true
或false
date
– 以自此時間戳記以來的時間差方式呈現。
如果 CustomResource 內的值與為欄位指定的類型不符,則會省略該值。使用 CustomResource 驗證來確保值類型正確。
格式
欄位的 format
欄位可以是以下任何一種
int32
int64
float
雙精度浮點數
byte
date
date-time
password
欄位的 format
控制 kubectl
列印值時使用的樣式。
欄位選擇器
欄位選擇器 讓用戶端可以根據一個或多個資源欄位的值來選擇自訂資源。
所有自訂資源都支援 metadata.name
和 metadata.namespace
欄位選擇器。
在 CustomResourceDefinition 中宣告的欄位,如果包含在 CustomResourceDefinition 的 spec.versions[*].selectableFields
欄位中,也可以與欄位選擇器一起使用。
自訂資源的可選欄位
Kubernetes v1.32 [stable]
(預設啟用:true)CustomResourceDefinition 的 spec.versions[*].selectableFields
欄位可用於宣告自訂資源中的哪些其他欄位可以與 CustomResourceFieldSelectors
功能閘道 的功能一起用於欄位選擇器(此功能閘道自 Kubernetes v1.31 起預設啟用)。以下範例將 .spec.color
和 .spec.size
欄位新增為可選欄位。
將 CustomResourceDefinition 儲存到 shirt-resource-definition.yaml
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
建立 CustomResourceDefinition
kubectl apply -f https://k8s.io/examples/customresourcedefinition/shirt-resource-definition.yaml
透過編輯 shirt-resources.yaml
定義一些襯衫;例如
---
apiVersion: stable.example.com/v1
kind: Shirt
metadata:
name: example1
spec:
color: blue
size: S
---
apiVersion: stable.example.com/v1
kind: Shirt
metadata:
name: example2
spec:
color: blue
size: M
---
apiVersion: stable.example.com/v1
kind: Shirt
metadata:
name: example3
spec:
color: green
size: M
建立自訂資源
kubectl apply -f https://k8s.io/examples/customresourcedefinition/shirt-resources.yaml
取得所有資源
kubectl get shirts.stable.example.com
輸出為
NAME COLOR SIZE
example1 blue S
example2 blue M
example3 green M
提取藍色襯衫(檢索 color
為 blue
的襯衫)
kubectl get shirts.stable.example.com --field-selector spec.color=blue
應輸出
NAME COLOR SIZE
example1 blue S
example2 blue M
僅取得 color
為 green
且 size
為 M
的資源
kubectl get shirts.stable.example.com --field-selector spec.color=green,spec.size=M
應輸出
NAME COLOR SIZE
example2 blue M
子資源
自訂資源支援 /status
和 /scale
子資源。
狀態和規模子資源可以選擇性地透過在 CustomResourceDefinition 中定義它們來啟用。
狀態子資源
當啟用狀態子資源時,會公開自訂資源的 /status
子資源。
狀態和規格段落分別由自訂資源內的
.status
和.spec
JSONPaths 表示。對
/status
子資源的PUT
請求會取得自訂資源物件,並忽略對狀態段落以外任何內容的變更。對
/status
子資源的PUT
請求僅驗證自訂資源的狀態段落。對自訂資源的
PUT
/POST
/PATCH
請求會忽略對狀態段落的變更。.metadata.generation
值會針對所有變更遞增,但對.metadata
或.status
的變更除外。僅允許以下建構在 CRD OpenAPI 驗證結構描述的根目錄中
description
example
exclusiveMaximum
exclusiveMinimum
externalDocs
format
items
maximum
maxItems
maxLength
minimum
minItems
minLength
multipleOf
pattern
properties
required
title
type
uniqueItems
規模子資源
當啟用規模子資源時,會公開自訂資源的 /scale
子資源。autoscaling/v1.Scale
物件會作為 /scale
的酬載傳送。
若要啟用規模子資源,請在 CustomResourceDefinition 中定義以下欄位。
specReplicasPath
定義自訂資源內對應於scale.spec.replicas
的 JSONPath。- 這是必要的值。
- 僅允許
.spec
下且使用點符號的 JSONPath。 - 如果自訂資源中的
specReplicasPath
下沒有值,則/scale
子資源將在 GET 時傳回錯誤。
statusReplicasPath
定義自訂資源內對應於scale.status.replicas
的 JSONPath。- 這是必要的值。
- 僅允許
.status
下且使用點符號的 JSONPath。 - 如果自訂資源中的
statusReplicasPath
下沒有值,則/scale
子資源中的狀態副本值將預設為 0。
labelSelectorPath
定義自訂資源內對應於Scale.Status.Selector
的 JSONPath。- 這是選用值。
- 必須設定此值才能與 HPA 和 VPA 搭配使用。
- 僅允許
.status
或.spec
下且使用點符號的 JSONPath。 - 如果自訂資源中的
labelSelectorPath
下沒有值,則/scale
子資源中的狀態選擇器值將預設為空字串。 - 此 JSON 路徑指向的欄位必須是字串欄位(而非複雜的選擇器結構),其中包含字串形式的序列化標籤選擇器。
在以下範例中,狀態和規模子資源都已啟用。
將 CustomResourceDefinition 儲存至 resourcedefinition.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
status:
type: object
properties:
replicas:
type: integer
labelSelector:
type: string
# subresources describes the subresources for custom resources.
subresources:
# status enables the status subresource.
status: {}
# scale enables the scale subresource.
scale:
# specReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Spec.Replicas.
specReplicasPath: .spec.replicas
# statusReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Replicas.
statusReplicasPath: .status.replicas
# labelSelectorPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Selector.
labelSelectorPath: .status.labelSelector
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
並建立它
kubectl apply -f resourcedefinition.yaml
在建立 CustomResourceDefinition 物件之後,您可以建立自訂物件。
如果您將下列 YAML 儲存到 my-crontab.yaml
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 3
並建立它
kubectl apply -f my-crontab.yaml
然後會在以下位置建立新的命名空間 RESTful API 端點
/apis/stable.example.com/v1/namespaces/*/crontabs/status
以及
/apis/stable.example.com/v1/namespaces/*/crontabs/scale
可以使用 kubectl scale
命令來擴展自訂資源的規模。例如,以下命令將上面建立的自訂資源的 .spec.replicas
設定為 5
kubectl scale --replicas=5 crontabs/my-new-cron-object
crontabs "my-new-cron-object" scaled
kubectl get crontabs my-new-cron-object -o jsonpath='{.spec.replicas}'
5
您可以使用 PodDisruptionBudget 來保護已啟用規模子資源的自訂資源。
類別
類別是自訂資源所屬的群組資源清單(例如 all
)。您可以使用 kubectl get <category-name>
列出屬於該類別的資源。
以下範例在 CustomResourceDefinition 的類別清單中新增了 all
,並說明如何使用 kubectl get all
輸出自訂資源。
將以下 CustomResourceDefinition 儲存到 resourcedefinition.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
# categories is a list of grouped resources the custom resource belongs to.
categories:
- all
並建立它
kubectl apply -f resourcedefinition.yaml
在建立 CustomResourceDefinition 物件之後,您可以建立自訂物件。
將以下 YAML 儲存至 my-crontab.yaml
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
並建立它
kubectl apply -f my-crontab.yaml
您可以在使用 kubectl get
時指定類別
kubectl get all
它將包含種類為 CronTab
的自訂資源
NAME AGE
crontabs/my-new-cron-object 3s
下一步
閱讀關於 自訂資源 的內容。