使用 CustomResourceDefinitions 擴充套件 Kubernetes API
本頁面展示瞭如何透過建立 CustomResourceDefinition 將自定義資源安裝到 Kubernetes API 中。
準備工作
你需要一個 Kubernetes 叢集,並且 kubectl 命令列工具必須配置為與你的叢集通訊。建議在至少有兩個不是控制平面主機的節點上執行本教程。如果你還沒有叢集,你可以使用 minikube 建立一個,或者使用這些 Kubernetes 遊樂場之一。
你的 Kubernetes 伺服器版本必須是 1.16 或更高。要檢查版本,請輸入 kubectl version
。
建立 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,它將從空狀態開始。
指定結構化模式
CustomResources 將結構化資料儲存在自定義欄位中(除了 API 伺服器隱式驗證的內建欄位 apiVersion
、kind
和 metadata
)。透過 OpenAPI v3.0 驗證,可以指定一個模式,該模式在建立和更新期間進行驗證,有關此模式的詳細資訊和限制,請參見下文。
對於 apiextensions.k8s.io/v1
,CustomResourceDefinitions 必須定義結構化模式。在 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。與諸如 ConfigMap 等原生 Kubernetes 資源一樣,如果你指定了 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
已被修剪。
此示例透過新增 --validate=false
命令列選項來關閉客戶端驗證,以演示 API 伺服器的行為。由於 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
欄位被修剪,但外部的一切都沒有被修剪。
整型或字串
模式中帶有 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
被展開為上面所示的兩種模式之一。
原始擴充套件
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 多個版本以及將物件從一個版本遷移到另一個版本的更多資訊,請參閱 Custom resource definition versioning。
高階主題
終結器
終結器(Finalizers) 允許控制器實現非同步預刪除鉤子。自定義物件支援與內建物件類似的終結器。
你可以像這樣向自定義物件新增終結器
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
finalizers:
- stable.example.com/finalizer
自定義終結器的識別符號由域名、正斜槓和終結器名稱組成。任何控制器都可以將終結器新增到任何物件的終結器列表中。
對具有終結器物件進行的第一次刪除請求會為 metadata.deletionTimestamp
欄位設定一個值,但不會刪除它。一旦設定了此值,finalizers
列表中的條目只能被移除。在任何終結器仍然存在的情況下,也無法強制刪除物件。
當設定了 metadata.deletionTimestamp
欄位後,監視物件的控制器會執行它們處理的所有終結器,並在完成後將終結器從列表中移除。每個控制器都有責任從列表中移除其終結器。
metadata.deletionGracePeriodSeconds
的值控制輪詢更新的間隔。
一旦終結器列表為空,即所有終結器都已執行完畢,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
擴充套件可用於使用 通用表示式語言 (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.33 [stable]
(預設啟用:true)如果你使用的是低於 v1.30 的 Kubernetes 版本,則需要顯式啟用 CRDValidationRatcheting
功能門 才能使用此行為,然後此行為將應用於叢集中的所有 CustomResourceDefinition。
如果你啟用了功能門,Kubernetes 會為 CustomResourceDefinitions 實現 驗證棘輪機制。API 伺服器願意接受對更新後無效的資源的更新,前提是資源中未能透過驗證的每個部分在更新操作中都沒有更改。換句話說,資源中任何仍然無效的無效部分都必須已經是錯誤的。你不能使用此機制來更新有效資源使其變為無效。
此功能允許 CRD 作者在某些條件下自信地向 OpenAPIV3 模式新增新的驗證。使用者可以安全地更新到新模式,而無需增加物件的版本或破壞工作流。
儘管 CRD 的 OpenAPIV3 模式中放置的大多數驗證都支援棘輪機制,但也有一些例外。以下 OpenAPIV3 模式驗證在 Kubernetes 1.34 的實現中不支援棘輪機制,如果違反,將像往常一樣繼續丟擲錯誤:
量詞
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-list-map-keys
因更改列表模式的對映鍵而產生的錯誤將不會被棘輪化。required
因更改必填欄位列表而產生的錯誤將不會被棘輪化。properties
新增/刪除/修改屬性名稱不會被棘輪化,但如果屬性名稱保持不變,則對每個屬性的模式和子模式中的驗證進行更改可能會被棘輪化。additionalProperties
移除以前指定的additionalProperties
驗證將不會被棘輪化。metadata
來自 Kubernetes 對物件metadata
的內建驗證的錯誤不會被棘輪化(例如物件名稱或標籤值中的字元)。如果你為自定義資源的元資料指定了自己額外的規則,則該額外驗證將被棘輪化。
驗證規則
Kubernetes v1.29 [stable]
驗證規則使用 通用表示式語言 (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)) | 驗證兩個 listSet 是否不相交 |
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 中是否存在且僅存在一次 |
交叉引用: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
如果規則的作用域是一個具有額外屬性(即對映)的物件,則可以透過
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) |
string | self.startsWith('kube') |
apiVersion
、kind
、metadata.name
和 metadata.generateName
始終可從物件的根和任何帶有 x-kubernetes-embedded-resource
註釋的物件訪問。其他元資料屬性不可訪問。
透過 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 RESERVED 關鍵字 |
注意:CEL RESERVED 關鍵字需要與要轉義的精確屬性名稱匹配(例如,單詞 sprint 中的 int 不會被轉義)。
轉義示例
屬性名稱 | 帶轉義屬性名稱的規則 |
---|---|
名稱空間 | self.__namespace__ > 0 |
x-prop | self.x__dash__prop > 0 |
redact__d | self.redact__underscores__d > 0 |
string | 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' with Properties | 物件 / "訊息型別" |
'object' with AdditionalProperties | 對映 |
'object' with x-kubernetes-embedded-type | 物件 / "訊息型別",'apiVersion'、'kind'、'metadata.name' 和 'metadata.generateName' 隱式包含在模式中 |
'object' with x-kubernetes-preserve-unknown-fields | 物件 / "訊息型別",未知欄位在 CEL 表示式中不可訪問 |
x-kubernetes-int-or-string | 動態物件,可以是整數或字串,type(value) 可用於檢查型別 |
'array | list |
'array' with x-kubernetes-list-type=map | 具有基於對映的相等性和唯一鍵保證的列表 |
'array' with x-kubernetes-list-type=set | 具有基於集合的相等性和唯一條目保證的列表 |
'boolean' | 布林值 |
'number' (所有格式) | 雙精度浮點數 |
'integer' (所有格式) | 整數 (64) |
'null' | null 型別 |
'string' | string |
'string' with format=byte (base64 編碼) | 位元組 |
'string' with format=date | 時間戳 (google.protobuf.Timestamp) |
'string' with format=datetime | 時間戳 (google.protobuf.Timestamp) |
'string' with format=duration | 持續時間 (google.protobuf.Duration) |
交叉引用: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
,返回的錯誤將正確引用欄位 x
的位置。
fieldPath
值必須是相對 JSON 路徑,其作用域為模式中 x-kubernetes-validations
擴充套件的位置。此外,它應該引用模式中已存在的欄位。例如,當驗證檢查對映 testMap
下的特定屬性 foo
時,你可以將 fieldPath
設定為 ".testMap.foo"
或 .testMap['foo']'
。如果驗證需要檢查兩個列表中唯一的屬性,則 fieldPath
可以設定為任一列表。例如,它可以設定為 .testList1
或 .testList2
。目前它支援子操作以引用現有欄位。有關更多資訊,請參閱 Kubernetes 中的 JSONPath 支援。fieldPath
欄位不支援按數字索引陣列。
設定 fieldPath
是可選的。
optionalOldSelf
欄位
Kubernetes v1.33 [stable]
(預設啟用:true)如果你的叢集未啟用 CRD 驗證棘輪機制,則 CustomResourceDefinition API 不包含此欄位,嘗試設定它可能會導致錯誤。
optionalOldSelf
欄位是一個布林欄位,它改變了下面描述的 過渡規則 的行為。通常,如果無法確定 oldSelf
(在物件建立期間或在更新中引入新值時),則過渡規則將不會評估。
如果 optionalOldSelf
設定為 true,則過渡規則將始終被評估,並且 oldSelf
的型別將更改為 CEL Optional
型別。
optionalOldSelf
在模式作者希望透過比 預設的基於等價的行為 提供更多控制工具來對新值引入新的(通常更嚴格的)約束,同時仍然允許使用舊的驗證來“祖父”或棘輪化舊值的情況下非常有用。
使用示例
CEL | 描述 |
---|---|
self.foo == "foo" || (oldSelf.hasValue() && oldSelf.value().foo != "foo") | 棘輪規則。一旦值設定為“foo”,它必須保持為 foo。但如果它在引入“foo”約束之前存在,則可以使用任何值 |
[oldSelf.orValue(""), self].all(x, ["OldCase1", "OldCase2"].exists(case, x == case)) || ["NewCase1", "NewCase2"].exists(case, self == case) || ["NewCase"].has(self) | “如果 oldSelf 使用了被刪除的列舉案例,則對這些案例進行棘輪驗證” |
oldSelf.optMap(o, o.size()).orValue(0) < 4 || self.size() >= 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
) 不一定可以在現有物件和對同一物件的後續更新之間進行關聯。
如果模式節點包含無法應用的過渡規則(例如,“舊 Self 不能在模式中不可關聯的部分中使用 path”),則會在 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
欄位的預設值除外),並且必須根據提供的模式進行驗證。例如,在上面的示例中,spec
欄位的預設值 {"replicas": "foo", "badger": 1}
將無效,因為 badger
是一個未知欄位,並且 replicas
不是字串。
x-kubernetes-embedded-resources: true
節點的 metadata
欄位(或覆蓋 metadata
的預設值的一部分)的預設值在 CustomResourceDefinition 建立期間不會被修剪,而是在請求處理期間透過修剪步驟進行修剪。
預設值和可空性
對於未指定 nullable 標誌或將其設定為 false
的欄位,null 值將在預設值發生之前被修剪。如果存在預設值,它將被應用。當 nullable 為 true
時,null 值將被保留並且不會被預設設定。
例如,給定下面的 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
具有 null 值的物件
spec:
foo: null
bar: null
baz: null
導致
spec:
foo: "default"
bar: null
其中 foo
被修剪並預設設定,因為該欄位不可為空,bar
由於 nullable: true
而保留 null 值,而 baz
被修剪,因為該欄位不可為空且沒有預設值。
在 OpenAPI 中釋出驗證模式
CustomResourceDefinition OpenAPI v3 驗證模式,如果它們是 結構化的 且 啟用修剪,則會作為 OpenAPI v3 和 OpenAPI v2 從 Kubernetes API 伺服器釋出。建議使用 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
JSONPath 表示。對
/status
子資源的PUT
請求接受一個自定義資源物件,並忽略除了狀態節之外的所有更改。對
/status
子資源的PUT
請求僅驗證自定義資源的狀態節。對自定義資源的
PUT
/POST
/PATCH
請求忽略狀態節的更改。除了對
.metadata
或.status
的更改外,.metadata.generation
值將針對所有更改遞增。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
列出屬於該類別的資源。
以下示例在 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
下一步
閱讀有關 自定義資源 的內容。