使用 CustomResourceDefinition 扩展 Kubernetes API
本页展示如何使用 CustomResourceDefinition 将 定制资源(Custom Resource) 安装到 Kubernetes API 上。
准备开始
你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:
您的 Kubernetes 服务器版本必须不低于版本 1.16. 要获知版本信息,请输入kubectl version
.
如果你在使用较老的、仍处于被支持范围的 Kubernetes 版本,请切换到该版本的 文档查看对于的集群而言有用的建议。
创建 CustomResourceDefinition
当你创建新的 CustomResourceDefinition(CRD)时,Kubernetes API 服务器会为你所
指定的每一个版本生成一个 RESTful 的 资源路径。CRD 可以是名字空间作用域的,也可以
是集群作用域的,取决于 CRD 的 scope
字段设置。和其他现有的内置对象一样,删除
一个名字空间时,该名字空间下的所有定制对象也会被删除。CustomResourceDefinition
本身是不受名字空间限制的,对所有名字空间可用。
例如,如果你将下面的 CustomResourceDefinition 保存到 resourcedefinition.yaml
文件:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# 名字必需与下面的 spec 字段匹配,并且格式为 '<名称的复数形式>.<组名>'
name: crontabs.stable.example.com
spec:
# 组名称,用于 REST API: /apis/<组>/<版本>
group: stable.example.com
# 列举此 CustomResourceDefinition 所支持的版本
versions:
- name: v1
# 每个版本都可以通过 served 标志来独立启用或禁止
served: true
# 其中一个且只有一个版本必需被标记为存储版本
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
# 可以是 Namespaced 或 Cluster
scope: Namespaced
names:
# 名称的复数形式,用于 URL:/apis/<组>/<版本>/<名称的复数形式>
plural: crontabs
# 名称的单数形式,作为命令行使用时和显示时的别名
singular: crontab
# kind 通常是单数形式的帕斯卡编码(PascalCased)形式。你的资源清单会使用这一形式。
kind: CronTab
# shortNames 允许你在命令行使用较短的字符串来匹配资源
shortNames:
- ct
之后创建它:
kubectl apply -f resourcedefinition.yaml
这样一个新的受名字空间约束的 RESTful API 端点会被创建在:
/apis/stable.example.com/v1/namespaces/*/crontabs/...
此端点 URL 自此可以用来创建和管理定制对象。对象的 kind
将是来自你上面创建时
所用的 spec 中指定的 CronTab
。
创建端点的操作可能需要几秒钟。你可以监测你的 CustomResourceDefinition 的
Established
状况变为 true,或者监测 API 服务器的发现信息等待你的资源出现在
那里。
创建定制对象
在创建了 CustomResourceDefinition 对象之后,你可以创建定制对象(Custom
Objects)。定制对象可以包含定制字段。这些字段可以包含任意的 JSON 数据。
在下面的例子中,在类别为 CrontTab
的定制对象中,设置了cronSpec
和 image
定制字段。类别 CronTab
来自你在上面所创建的 CRD 的规约。
如果你将下面的 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 中所定义的单数 形式或复数形式,也可以使用其短名称:
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 时,该 CRD 会是一个空的结构。
设置结构化的模式
CustomResource 对象在定制字段中保存结构化的数据,这些字段和内置的字段
apiVersion
、kind
和 metadata
等一起存储,不过内置的字段都会被 API
服务器隐式完成合法性检查。有了 OpenAPI v3.0 检查
能力之后,你可以设置一个模式(Schema),在创建和更新定制对象时,这一模式会被用来
对对象内容进行合法性检查。参阅下文了解这类模式的细节和局限性。
在 apiextensions.k8s.io/v1
版本中,CustomResourceDefinition 的这一结构化模式
定义是必需的。
在 CustomResourceDefinition 的 beta 版本中,结构化模式定义是可选的。
结构化模式本身是一个 OpenAPI v3.0 验证模式,其中:
- 为对象根(root)设置一个非空的 type 值(藉由 OpenAPI 中的
type
),对每个 object 节点的每个字段(藉由 OpenAPI 中的properties
或additionalProperties
)以及 array 节点的每个条目(藉由 OpenAPI 中的items
)也要设置非空的 type 值, 除非:- 节点包含属性
x-kubernetes-int-or-string: true
- 节点包含属性
x-kubernetes-preserve-unknown-fields: true
- 节点包含属性
- 对于 object 的每个字段或 array 中的每个条目,如果其定义中包含
allOf
、anyOf
、oneOf
或not
,则模式也要指定这些逻辑组合之外的字段或条目(试比较例 1 和例 2)。 - 在
allOf
、anyOf
、oneOf
或not
上下文内不设置description
、type
、default
、additionalProperties
或者nullable
。此规则的例外是x-kubernetes-int-or-string
的两种模式(见下文)。 - 如果
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"
不是一个结构化的模式,因为其中存在以下违例:
- 根节点缺失 type 设置(规则 1)
foo
的 type 缺失(规则 1)anyOf
中的bar
未在外部指定(规则 2)bar
的type
位于anyOf
中(规则 3)anyOf
中设置了description
(规则 3)metadata.finalizers
不可以被限制 (规则 4)
作为对比,下面的 YAML 所对应的模式则是结构化的:
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
状况中
会包含报告信息。
字段剪裁
CustomResourceDefinition 在集群的持久性存储 etcd 中保存经过合法性检查的资源数据。 就像原生的 Kubernetes 资源,例如 ConfigMap, 如果你指定了 API 服务器所无法识别的字段,则该未知字段会在保存资源之前 被 剪裁(Pruned) 掉(删除)。
从 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
通过这样设置,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(就像在
k8s.io/apimachinery
项目中 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
Finalizer 能够让控制器实现异步的删除前(Pre-delete)回调。 与内置对象类似,定制对象也支持 Finalizer。
你可以像下面一样为定制对象添加 Finalizer:
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
finalizers:
- stable.example.com/finalizer
自定义 Finalizer 的标识符包含一个域名、一个正向斜线和 finalizer 的名称。 任何控制器都可以在任何对象的 finalizer 列表中添加新的 finalizer。
对带有 Finalizer 的对象的第一个删除请求会为其 metadata.deletionTimestamp
设置一个值,但不会真的删除对象。一旦此值被设置,finalizers
列表中的表项
只能被移除。在列表中仍然包含 finalizer 时,无法强制删除对应的对象。
当 metadata.deletionTimestamp
字段被设置时,监视该对象的各个控制器会
执行它们所能处理的 finalizer,并在完成处理之后将其从列表中移除。
每个控制器负责将其 finalizer 从列表中删除。
metadata.deletionGracePeriodSeconds
的取值控制对更新的轮询周期。
一旦 finalizers 列表为空时,就意味着所有 finalizer 都被执行过, Kubernetes 会最终删除该资源,
合法性检查
定制资源是通过 OpenAPI v3 模式定义 来执行合法性检查的, 你可以通过使用准入控制 Webhook 来添加额外的合法性检查逻辑。
此外,对模式定义存在以下限制:
- 以下字段不可设置:
definitions
dependencies
deprecated
discriminator
id
patternProperties
readOnly
writeOnly
xml
$ref
- 字段
uniqueItems
不可设置为true
- 字段
additionalProperties
不可设置为false
- 字段
additionalProperties
与properties
互斥,不可同时使用
当设置默认值特性被启用时,可以设置字段 default
。
就 apiextensions.k8s.io/v1
组的 CustomResourceDefinitions,这一条件是满足的。
设置默认值的功能特性从 1.17 开始正式发布。该特性在 1.16 版本中处于
Beta 状态,要求 CustomResourceDefaulting
特性门控
被启用。对于大多数集群而言,Beta 状态的特性门控默认都是自动启用的。
关于对某些 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
并创建 CustomResourceDefinition:
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
设置默认值
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 是用来检查定制对象的模式定义
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
使用此 CRD 定义时,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 读取对象时,使用存储版本来设置默认值;
- 在 Mutating 准入控制插件执行非空的补丁操作时,基于准入 Webhook 对象 版本设置默认值。
从 etcd 中读取数据时所应用的默认值设置不会被写回到 etcd 中。 需要通过 API 执行更新请求才能将这种方式设置的默认值写回到 etcd。
默认值一定会被剪裁(除了 metadata
字段的默认值设置),且必须通过所提供
的模式定义的检查。
针对 x-kubernetes-embedded-resource: true
节点(或者包含 metadata
字段的结构的默认值)
的 metadata
字段的默认值设置不会在 CustomResourceDefinition 创建时被剪裁,
而是在处理请求的字段剪裁阶段被删除。
设置默认值和字段是否可为空(Nullable)
1.20 版本新增: 对于未设置其 nullable 标志的字段或者将该标志设置为
false
的字段,其空值(Null)会在设置默认值之前被剪裁掉。如果对应字段
存在默认值,则默认值会被赋予该字段。当 nullable
被设置为 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 v2 形式发布合法性检查模式
CustomResourceDefinition 的结构化的、 启用了剪裁的 OpenAPI v3 合法性检查模式 会在 Kubernetes API 服务器上作为 OpenAPI v2 规约 的一部分发布出来。
kubectl 命令行工具会基于所发布的模式定义来执行
客户端的合法性检查(kubectl create
和 kubectl apply
),为定制资源的模式定义
提供解释(kubectl explain
)。
所发布的模式还可被用于其他目的,例如生成客户端或者生成文档。
OpenAPI v3 合法性检查模式定义会被转换为 OpenAPI v2 模式定义,并出现在
OpenAPI v2 规范
的 definitions
和 paths
字段中。
在转换过程中会发生以下修改,目的是保持与 1.13 版本以前的 kubectl 工具兼容。 这些修改可以避免 kubectl 过于严格,以至于拒绝它无法理解的 OpenAPI 模式定义。 转换过程不会更改 CRD 中定义的合法性检查模式定义,因此不会影响到 API 服务器中 的合法性检查。
- 以下字段会被移除,因为它们在 OpenAPI v2 中不支持(在将来版本中将使用 OpenAPI v3,
因而不会有这些限制)
- 字段
allOf
、anyOf
、oneOf
和not
会被删除
- 字段
- 如果设置了
nullable: true
,我们会丢弃type
、nullable
、items
和properties
OpenAPI v2 无法表达 Nullable。为了避免 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
(优先级)字段。当前,优先级用来区分标准视图(Standard
View)和宽视图(Wide View)(使用 -o wide
标志)中显示的列:
- 优先级为
0
的列会在标准视图中显示。 - 优先级大于
0
的列只会在宽视图中显示。
类型
列的 type
字段可以是以下值之一
(比较 OpenAPI v3 数据类型):
integer
– 非浮点数字number
– 浮点数字string
– 字符串boolean
–true
或false
date
– 显示为以自此时间戳以来经过的时长
如果定制资源中的值与列中指定的类型不匹配,该值会被忽略。 你可以通过定制资源的合法性检查来确保取值类型是正确的。
格式
列的 format
字段可以是以下值之一:
int32
int64
float
double
byte
date
date-time
password
列的 format
字段控制 kubectl
打印对应取值时采用的风格。
子资源
定制资源支持 /status
和 /scale
子资源。
通过在 CustomResourceDefinition 中定义 status
和 scale
,
可以有选择地启用这些子资源。
Status 子资源
当启用了 status 子资源时,对应定制资源的 /status
子资源会被暴露出来。
- status 和 spec 内容分别用定制资源内的
.status
和.spec
JSON 路径来表达; - 对
/status
子资源的PUT
请求要求使用定制资源对象作为其输入,但会忽略 status 之外的所有内容。 - 对
/status
子资源的PUT
请求仅对定制资源的 status 内容进行合法性检查。 - 对定制资源的
PUT
、POST
、PATCH
请求会忽略 status 内容的改变。 - 对所有变更请求,除非改变是针对
.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 子资源
当启用了 scale 子资源时,定制资源的 /scale
子资源就被暴露出来。
针对 /scale
所发送的对象是 autoscaling/v1.Scale
。
为了启用 scale 子资源,CustomResourceDefinition 定义了以下字段:
-
specReplicasPath
指定定制资源内与scale.spec.replicas
对应的 JSON 路径。- 此字段为必需值。
- 只可以使用
.spec
下的 JSON 路径,只可使用带句点的路径。 - 如果定制资源的
specReplicasPath
下没有取值,则针对/scale
子资源执行 GET 操作时会返回错误。
-
statusReplicasPath
指定定制资源内与scale.status.replicas
对应的 JSON 路径。- 此字段为必需值。
- 只可以使用
.status
下的 JSON 路径,只可使用带句点的路径。 - 如果定制资源的
statusReplicasPath
下没有取值,则针对/scale
子资源的 副本个数状态值默认为 0。
-
labelSelectorPath
指定定制资源内与scale.status.selector
对应的 JSON 路径。- 此字段为可选值。
- 此字段必须设置才能使用 HPA。
- 只可以使用
.status
或.spec
下的 JSON 路径,只可使用带句点的路径。 - 如果定制资源的
labelSelectorPath
下没有取值,则针对/scale
子资源的 选择算符状态值默认为空字符串。 - 此 JSON 路径所指向的字段必须是一个字符串字段(而不是复合的选择算符结构), 其中包含标签选择算符串行化的字符串形式。
在下面的例子中,status
和 scale
子资源都被启用。
将此 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 描述定制资源的子资源
subresources:
# status 启用 status 子资源
status: {}
# scale 启用 scale 子资源
scale:
# specReplicasPath 定义定制资源中对应 scale.spec.replicas 的 JSON 路径
specReplicasPath: .spec.replicas
# statusReplicasPath 定义定制资源中对应 scale.status.replicas 的 JSON 路径
statusReplicasPath: .status.replicas
# labelSelectorPath 定义定制资源中对应 scale.status.selector 的 JSON 路径
labelSelectorPath: .status.labelSelector
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
之后创建此 CustomResourceDefinition:
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 来保护启用了 scale 子资源的定制资源。
分类
分类(Categories)是定制资源所归属的分组资源列表(例如,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 是定制资源所归属的分类资源列表
categories:
- all
之后创建此 CRD:
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
接下来
- 阅读了解定制资源
- 参阅 CustomResourceDefinition
- 参阅支持 CustomResourceDefinition 的多个版本