Black lives matter.
We stand in solidarity with the Black community.
Racism is unacceptable.
It conflicts with the core values of the Kubernetes project and our community does not tolerate it.
We stand in solidarity with the Black community.
Racism is unacceptable.
It conflicts with the core values of the Kubernetes project and our community does not tolerate it.
本页介绍了如何添加版本信息到 CustomResourceDefinitions,如何表示 CustomResourceDefinitions 的稳定水平或者用 API 之间的表征的转换提高您的 API 到一个新的版本。它还描述了如何将对象从一个版本升级到另一个版本。
你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:
要获知版本信息,请输入kubectl version
.
apiextensions.k8s.io/v1
的1.16.0或更高版本,apiextensions.k8s.io/v1beta1
的1.11.0或更高版本。Kubernetes v1.18 [stable]
CustomResourceDefinition API 提供了用于引入和升级的工作流程到 CustomResourceDefinition 的新版本。
创建 CustomResourceDefinition 时,会在 CustomResourceDefinition spec.versions
列表设置适当的稳定级和版本号。例如v1beta1
表示第一个版本尚未稳定。所有自定义资源对象将首先存储在这个版本
创建 CustomResourceDefinition 后,客户端可以开始使用 v1beta1 API。
稍后可能需要添加新版本,例如 v1。
增加一个新版本:
apiVersion
字段有变更。served:true
的 spec.versions 列表。另外,设置spec.conversion
字段
到所选的转换策略。如果使用转换 Webhook,请配置spec.conversion.webhookClientConfig
来调用 webhook。添加新版本后,客户端可以逐步迁移到新版本。对于某些客户而言,在使用旧版本的同时支持其他人使用新版本。
将存储的对象迁移到新版本:
对于客户来说,在将对象升级到新的存储版本之前,期间和之后使用旧版本和新版本都是安全的。
删除旧版本:
spec.versions
列表中将旧版本的 served 设置为 false。如果任何客户端仍然意外地使用他们可能开始报告的旧版本尝试访问旧版本的自定义资源对象时出错。
如果发生这种情况,请切换回在旧版本上使用served:true
,然后迁移其他客户使用新版本,然后重复此步骤。spec.versions
列表中,确认新版本的stored
已设置为true
。status.storedVersions
。spec.versions
列表中删除旧版本。CustomResourceDefinition API 的versions
字段可用于支持您自定义资源的多个版本已经开发的。版本可以具有不同的架构,并且转换 Webhooks 可以在版本之间转换自定义资源。
在适用的情况下,Webhook 转换应遵循 Kubernetes API。
注意: Inapiextensions.k8s.io/v1beta1
, there was aversion
field instead ofversions
. Theversion
field is deprecated and optional, but if it is not empty, it must match the first item in theversions
field.
此示例显示了两个版本的 CustomResourceDefinition。第一个例子,假设所有的版本共享相同的模式而它们之间没有转换。YAML 中的评论提供了更多背景信息。
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# 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
# A schema is required
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
# The conversion section is introduced in Kubernetes 1.13+ with a default value of
# None conversion (strategy sub-field set to None).
conversion:
# None conversion assumes the same schema for all versions and only sets the apiVersion
# field of custom resources to the proper value
strategy: None
# 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
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# 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
- name: v1
served: true
storage: false
validation:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
# The conversion section is introduced in Kubernetes 1.13+ with a default value of
# None conversion (strategy sub-field set to None).
conversion:
# None conversion assumes the same schema for all versions and only sets the apiVersion
# field of custom resources to the proper value
strategy: None
# 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
你可以将 CustomResourceDefinition 存储在 YAML 文件中,然后使用kubectl apply
来创建它。
kubectl apply -f my-versioned-crontab.yaml
在创建之后,apiserver 开始在 HTTP REST 端点上为每个启用的版本提供服务。在上面的示例中,API 版本可以在/apis/example.com/v1beta1
和 /apis/example.com/v1
中获得。
不考虑 CustomResourceDefinition 中版本被定义的顺序,kubectl 使用具有最高优先级的版本作为访问对象的默认版本。 通过解析 name 字段确定优先级来决定版本号,稳定性(GA,Beta,或者 Alpha),以及该稳定性水平内的序列。
用于对版本进行排序的算法被设计成与 Kubernetes 项目对 Kubernetes 版本进行排序的方式相同。
版本以v
开头跟一个数字,一个可选的beta
或者 alpha
命名,和一个可选的附加的数字型的版本信息。
从广义上讲,版本字符串可能看起来像v2
或者v2beta1
。
使用以下算法对版本进行排序:
beta
或 alpha
跟随第一数字部分,它们按顺序排序,在没有beta
或 alpha
后缀(假定为 GA 版本)的等效字符串后面。beta
或alpha
之后,那么这些数字也是从最大到最小排序。foo1
在 foo10
上方排序。这与遵循 Kubernetes 版本模式的条目的数字部分排序不同。如果查看以下排序版本列表可以明白:
- v10
- v2
- v1
- v11beta2
- v10beta3
- v3beta1
- v12alpha1
- v11alpha2
- foo1
- foo10
对于 指定多个版本 中的示例,版本排序顺序为v1
,后跟着v1beta1
。
这导致了 kubectl 命令使用v1
作为默认版本,除非提供对象指定版本。
注意: Webhook 转换在 Kubernetes 1.13 中作为 alpha 功能引入。要使用它,应启用CustomResourceWebhookConversion
功能。请参阅 feature gate 文档以获得更多信息。
上面的例子在版本之间有一个 None 转换,它只在转换时设置apiVersion
字段而不改变对象的其余部分。apiserver 还支持在需要转换时调用外部服务的 webhook 转换。例如:
为了涵盖所有这些情况并通过 API 服务优化转换,转换对象可能包含多个对象,以便最大限度地减少外部调用。webhook 应该独立执行这些转换。
请参考 自定义资源转换 webhook 服务 的实施,这在 Kubernetes e2e 测试中得到验证。webhook 处理由 apiserver 发送的ConversionReview
请求,并发送回包含在ConversionResponse
中的转换结果。请注意,请求包含需要独立转换不改变对象顺序的自定义资源列表。示例服务器的组织方式使其可以重用于其他转换。大多数常见代码都位于 框架文件 中,只留下 示例 用于实施不同的转换。
用于部署转换 webhook 的文档与 准入webhook示例服务。
下一节的假设是转换 webhook 服务器部署到default
命名空间中名为example-conversion-webhook-server
的服务器上,并在路径/crdconvert
上提供流量。
注意: 当 webhook 服务器作为一个部署到 Kubernetes 集群中的服务器时,它必须通过端口443上的服务器公开(服务器本身可以有一个任意端口,但是服务器对象应该将它映射到端口443)。 如果为服务器使用不同的端口,则 apiserver 和 webhook 服务器之间的通信可能会失败。
通过修改spec
中的conversion
部分,可以扩展None
转换示例来使用转换 webhook。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# 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
# Each version can define it's own schema when there is no top-level
# schema is defined.
schema:
openAPIV3Schema:
type: object
properties:
hostPort:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
conversion:
# a Webhook strategy instruct API server to call an external webhook for any conversion between custom resources.
strategy: Webhook
# webhook is required when strategy is `Webhook` and it configures the webhook endpoint to be called by API server.
webhook:
# conversionReviewVersions indicates what ConversionReview versions are understood/preferred by the webhook.
# The first version in the list understood by the API server is sent to the webhook.
# The webhook must respond with a ConversionReview object in the same version it received.
conversionReviewVersions: ["v1","v1beta1"]
clientConfig:
service:
namespace: default
name: example-conversion-webhook-server
path: /crdconvert
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
# 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
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# prunes object fields that are not specified in OpenAPI schemas below.
preserveUnknownFields: false
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# 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
# Each version can define it's own schema when there is no top-level
# schema is defined.
schema:
openAPIV3Schema:
type: object
properties:
hostPort:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
conversion:
# a Webhook strategy instruct API server to call an external webhook for any conversion between custom resources.
strategy: Webhook
# webhookClientConfig is required when strategy is `Webhook` and it configures the webhook endpoint to be called by API server.
webhookClientConfig:
service:
namespace: default
name: example-conversion-webhook-server
path: /crdconvert
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
# 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
您可以将 CustomResourceDefinition 保存在 YAML 文件中,然后使用kubectl apply
来应用它。
kubectl apply -f my-versioned-crontab-with-conversion.yaml
在应用新更改之前,请确保转换服务器已启动并正在运行。
apiserver 一旦确定请求应发送到转换 webhook,它需要知道如何调用 webhook。这是在webhookClientConfig
中指定的 webhook 配置。
转换 webhook 可以通过调用 URL 或服务,并且可以选择包含自定义 CA 包,以用于验证 TLS 连接。
url 以标准 URL 形式给出 webhook 的位置(scheme://host:port/path
)。
host
不应引用集群中运行的服务;采用通过指定service
字段来提供服务引用。
host
可以通过某些 apiserver 中的外部 DNS 进行解析(即kube-apiserver
无法解析集群内 DNS 违反分层规则)。主机也可以是 IP 地址。
请注意,除非您非常小心在所有主机上运行此 Webhook,否则 localhost 或 127.0.0.1 用作主机是风险很大的,运行一个 apiserver 可能需要对此进行调用 webhook。这样的安装很可能是不可移植的,即不容易出现在新集群中。
方案必须为https
:URL 必须以https://
开头。
尝试使用用户或基本身份验证,例如不允许使用user:password@
。片段(#...
)和查询参数(?...
)也不允许。
这是配置为调用 URL 的转换 Webhook 的示例(并且期望使用系统信任根来验证 TLS 证书,因此不指定 caBundle):
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
clientConfig:
url: "https://my-webhook.example.com:9443/my-webhook-path"
...
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhookClientConfig:
url: "https://my-webhook.example.com:9443/my-webhook-path"
...
webhookClientConfig
内部的service
段是对转换 webhook 服务的引用。如果 Webhook 在集群中运行,则应使用service
而不是url
。
服务名称空间和名称是必需的。端口是可选的,默认为 443。该路径是可选的,默认为/
。
这是一个配置为在端口1234
上调用服务的 Webhook 的示例在子路径/my-path
下,并针对 ServerName 验证 TLS 连接
使用自定义 CA 捆绑包的my-service-name.my-service-namespace.svc
。
apiVersion: apiextensions.k8s.io/v1b
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: my-service-namespace
name: my-service-name
path: /my-path
port: 1234
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhookClientConfig:
service:
namespace: my-service-namespace
name: my-service-name
path: /my-path
port: 1234
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...
向 Webhooks 发送 POST 请求,请求的内容类型为:application/json,与 APIapitensions.k8s.io API 组中的 ConversionReview API 对象一起使用序列化为 JSON 作为主体。
Webhooks 可以指定他们接受的ConversionReview
对象的版本在其 CustomResourceDefinition 中使用conversionReviewVersions
字段:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
conversionReviewVersions: ["v1", "v1beta1"]
...
创建时,conversionReviewVersions
是必填字段apiextensions.k8s.io/v1
自定义资源定义。
需要 Webhooks 支持至少一个ConversionReview
当前和以前的 apiserver 可以理解的版本。
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
conversionReviewVersions: ["v1", "v1beta1"]
...
如果未指定conversionReviewVersions
,则创建时的默认值 apiextensions.k8s.io/v1beta1 自定义资源定义为 v1beta1。
API servers send the first ConversionReview
version in the conversionReviewVersions
list they support.
If none of the versions in the list are supported by the API server, the custom resource definition will not be allowed to be created.
If an API server encounters a conversion webhook configuration that was previously created and does not support any of the ConversionReview
versions the API server knows how to send, attempts to call to the webhook will fail.
此示例显示了包含在ConversionReview
对象中的数据请求将CronTab
对象转换为example.com/v1
:
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"request": {
# Random uid uniquely identifying this conversion call
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
# The API group and version the objects should be converted to
"desiredAPIVersion": "example.com/v1",
# The list of objects to convert.
# May contain one or more objects, in one or more versions.
"objects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"hostPort": "localhost:1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"hostPort": "example.com:2345"
}
]
}
}
{
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"request": {
# Random uid uniquely identifying this conversion call
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
# The API group and version the objects should be converted to
"desiredAPIVersion": "example.com/v1",
# The list of objects to convert.
# May contain one or more objects, in one or more versions.
"objects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"hostPort": "localhost:1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"hostPort": "example.com:2345"
}
]
}
}
Webhooks 响应是以 200 HTTP 状态代码,Content-Type:application/json
,和包含 ConversionReview 对象的主体(与发送的版本相同),
带有response
节的序列,并序列化为 JSON。
如果转换成功,则 Webhook 应该返回包含以下字段的response
节:
uid
,从发送到 webhook 的request.uid
复制而来result
,设置为{"status":"Success"}}
convertedObjects
,包含来自request.objects
的所有对象,转换为request.desiredVersion
Webhook 的最简单成功响应示例:
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"response": {
# must match <request.uid>
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
"result": {
"status": "Success"
},
# Objects must match the order of request.objects, and have apiVersion set to <request.desiredAPIVersion>.
# kind, metadata.uid, metadata.name, and metadata.namespace fields must not be changed by the webhook.
# metadata.labels and metadata.annotations fields may be changed by the webhook.
# All other changes to metadata fields by the webhook are ignored.
"convertedObjects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"host": "localhost",
"port": "1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"host": "example.com",
"port": "2345"
}
]
}
}
{
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"response": {
# must match <request.uid>
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
"result": {
"status": "Failed"
},
# Objects must match the order of request.objects, and have apiVersion set to <request.desiredAPIVersion>.
# kind, metadata.uid, metadata.name, and metadata.namespace fields must not be changed by the webhook.
# metadata.labels and metadata.annotations fields may be changed by the webhook.
# All other changes to metadata fields by the webhook are ignored.
"convertedObjects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"host": "localhost",
"port": "1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"host": "example.com",
"port": "2345"
}
]
}
}
如果转换失败,则 Webhook 应该返回包含以下字段的response
节:
*uid
,从发送到 webhook 的request.uid
复制而来
*result
,设置为{"status":"Failed"}
警告:转换失败会破坏对自定义资源的读写访问,包括更新或删除资源的能力。转换失败应尽可能避免使用,并且不应用于强制验证 约束(改用验证模式 或 Webhook admission)。
来自 Webhook 的响应示例,指示转换请求失败,并带有可选消息:
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"response": {
"uid": "<value from request.uid>",
"result": {
"status": "Failed",
"message": "hostPort could not be parsed into a separate host and port"
}
}
}
{
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"response": {
"uid": "<value from request.uid>",
"result": {
"status": "Failed",
"message": "hostPort could not be parsed into a separate host and port"
}
}
}
写入对象时,它将保留在写入时指定为存储版本的版本中。如果存储版本发生变化,现有对象永远不会自动转换。然而,新创建或更新的对象将在新的存储版本中编写。对象可能已在不再被服务的版本中编写。
当读取对象时,将版本指定为路径的一部分。
如果指定的版本与对象的持久版本不同,Kubernetes 会在您请求的版本里将对象返还给您,但是在提供请求时,持久化对象既不会在磁盘上更改,也不会以任何方式进行转换(除了更改apiVersion
字符串)。您可以在当前提供的任何版本中请求对象。
如果您更新了一个现有对象,它将在现在的存储版本中被重写。 这是对象可以从一个版本改到另一个版本的唯一办法。
为了说明这一点,请考虑以下假设的一系列事件:
v1beta1
。
它保存在版本v1beta1
的存储中。v1
添加到 CustomResourceDefinition 中,并将其指定为存储版本。v1beta1
中读取您的对象,然后您再次在版本v1
中读取对象。
除了 apiVersion 字段之外,两个返回的对象都是相同的。v1
的存储中。
您现在有两个对象,其中一个位于v1beta1
,另一个位于v1
。v1
中,因为那是当前的存储版本。API 服务在状态字段storedVersions
中记录曾被标记为存储版本的每个版本。
对象可能已被保留在任何曾被指定为存储版本的版本中。
从未成为存储版本的版本的存储中不能存在任何对象。
弃用版本并删除支持时,请设计存储升级过程。
以下是从v1beta1
升级到v1
的示例过程。
v1
设置为 CustomResourceDefinition 文件中的存储,并使用 kubectl 应用它。
storedVersions
现在是v1beta1、 v1
。v1
。storedVersions
字段中删除v1beta1
来更新 CustomResourceDefinitionStatus
。