1437 lines
57 KiB
Markdown
1437 lines
57 KiB
Markdown
---
|
||
title: CustomResourceDefinition 的版本
|
||
content_type: task
|
||
weight: 30
|
||
min-kubernetes-server-version: v1.16
|
||
---
|
||
<!--
|
||
title: Versions in CustomResourceDefinitions
|
||
reviewers:
|
||
- sttts
|
||
- liggitt
|
||
content_type: task
|
||
weight: 30
|
||
min-kubernetes-server-version: v1.16
|
||
-->
|
||
|
||
<!-- overview -->
|
||
<!--
|
||
This page explains how to add versioning information to
|
||
[CustomResourceDefinitions](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#customresourcedefinition-v1beta1-apiextensions), to indicate the stability
|
||
level of your CustomResourceDefinitions or advance your API to a new version with conversion between API representations. It also describes how to upgrade an object from one version to another.
|
||
-->
|
||
本页介绍如何添加版本信息到
|
||
[CustomResourceDefinitions](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#customresourcedefinition-v1beta1-apiextensions)。
|
||
目的是标明 CustomResourceDefinitions 的稳定级别或者服务于 API 升级。
|
||
API 升级时需要在不同 API 表示形式之间进行转换。
|
||
本页还描述如何将对象从一个版本升级到另一个版本。
|
||
|
||
## {{% heading "prerequisites" %}}
|
||
|
||
{{< include "task-tutorial-prereqs.md" >}}
|
||
|
||
<!--
|
||
You should have a initial understanding of [custom resources](/docs/concepts/extend-kubernetes/api-extension/custom-resources/).
|
||
-->
|
||
你应该对[定制资源](/zh/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
|
||
有一些初步了解。
|
||
|
||
{{< version-check >}}
|
||
|
||
<!-- steps -->
|
||
|
||
<!--
|
||
## Overview
|
||
|
||
The CustomResourceDefinition API provides a workflow for introducing and upgrading
|
||
to new versions of a CustomResourceDefinition.
|
||
|
||
When a CustomResourceDefinition is created, the first version is set in the
|
||
CustomResourceDefinition `spec.versions` list to an appropriate stability level
|
||
and a version number. For example `v1beta1` would indicate that the first
|
||
version is not yet stable. All custom resource objects will initially be stored
|
||
at this version.
|
||
|
||
Once the CustomResourceDefinition is created, clients may begin using the
|
||
`v1beta1` API.
|
||
|
||
Later it might be necessary to add new version such as `v1`.
|
||
-->
|
||
## 概览
|
||
|
||
CustomResourceDefinition API 提供了用于引入和升级的工作流程到 CustomResourceDefinition
|
||
的新版本。
|
||
|
||
创建 CustomResourceDefinition 时,会在 CustomResourceDefinition `spec.versions`
|
||
列表设置适当的稳定级别和版本号。例如,`v1beta1` 表示第一个版本尚未稳定。
|
||
所有定制资源对象将首先用这个版本保存。
|
||
|
||
创建 CustomResourceDefinition 后,客户端可以开始使用 `v1beta1` API。
|
||
|
||
稍后可能需要添加新版本,例如 `v1`。
|
||
|
||
<!--
|
||
Adding a new version:
|
||
|
||
1. Pick a conversion strategy. Since custom resource objects need to be able to
|
||
be served at both versions, that means they will sometimes be served at a
|
||
different version than their storage version. In order for this to be
|
||
possible, the custom resource objects must sometimes be converted between the
|
||
version they are stored at and the version they are served at. If the
|
||
conversion involves schema changes and requires custom logic, a conversion
|
||
webhook should be used. If there are no schema changes, the default `None`
|
||
conversion strategy may be used and only the `apiVersion` field will be
|
||
modified when serving different versions.
|
||
2. If using conversion webhooks, create and deploy the conversion webhook. See
|
||
the [Webhook conversion](#webhook-conversion) for more details.
|
||
3. Update the CustomResourceDefinition to include the new version in the
|
||
`spec.versions` list with `served:true`. Also, set `spec.conversion` field
|
||
to the selected conversion strategy. If using a conversion webhook, configure
|
||
`spec.conversion.webhookClientConfig` field to call the webhook.
|
||
-->
|
||
添加新版本:
|
||
|
||
1. 选择一种转化策略。由于定制资源对象需要能够两种版本都可用,
|
||
这意味着它们有时会以与存储版本不同的版本来提供服务。为了能够做到这一点,
|
||
有时必须在它们存储的版本和提供的版本之间进行转换。如果转换涉及模式变更,
|
||
并且需要自定义逻辑,则应该使用 Webhook 来完成。如果没有模式变更,
|
||
则可使用默认的 `None` 转换策略,为不同版本提供服务时只有 `apiVersion` 字段
|
||
会被改变。
|
||
2. 如果使用转换 Webhook,请创建并部署转换 Webhook。更多详细信息请参见
|
||
[Webhook conversion](#webhook-conversion)。
|
||
3. 更新 CustomResourceDefinition,将新版本设置为 `served:true`,加入到
|
||
`spec.versions` 列表。另外,还要设置 `spec.conversion` 字段
|
||
为所选的转换策略。如果使用转换 Webhook,请配置
|
||
`spec.conversion.webhookClientConfig` 来调用 Webhook。
|
||
|
||
<!--
|
||
Once the new version is added, clients may incrementally migrate to the new
|
||
version. It is perfectly safe for some clients to use the old version while
|
||
others use the new version.
|
||
|
||
Migrate stored objects to the new version:
|
||
-->
|
||
添加新版本后,客户端可以逐步迁移到新版本。让某些客户使用旧版本的同时
|
||
支持其他人使用新版本是相当安全的。
|
||
|
||
将存储的对象迁移到新版本:
|
||
|
||
<!--
|
||
1. See the [upgrade existing objects to a new stored version](#upgrade-existing-objects-to-a-new-stored-version) section.
|
||
|
||
It is safe for clients to use both the old and new version before, during and
|
||
after upgrading the objects to a new stored version.
|
||
-->
|
||
|
||
1. 请参阅[将现有对象升级到新的存储版本](#upgrade-existing-objects-to-a-new-stored-version)节。
|
||
|
||
对于客户来说,在将对象升级到新的存储版本之前、期间和之后使用旧版本和新版本都是安全的。
|
||
|
||
<!--
|
||
Removing an old version:
|
||
|
||
1. Ensure all clients are fully migrated to the new version. The kube-apiserver
|
||
logs can be reviewed to help identify any clients that are still accessing via
|
||
the old version.
|
||
1. Set `served` to `false` for the old version in the `spec.versions` list. If
|
||
any clients are still unexpectedly using the old version they may begin reporting
|
||
errors attempting to access the custom resource objects at the old version.
|
||
If this occurs, switch back to using `served:true` on the old version, migrate the
|
||
remaining clients to the new version and repeat this step.
|
||
1. Ensure the [upgrade of existing objects to the new stored version](#upgrade-existing-objects-to-a-new-stored-version) step has been completed.
|
||
1. Verify that the `storage` is set to `true` for the new version in the `spec.versions` list in the CustomResourceDefinition.
|
||
1. Verify that the old version is no longer listed in the CustomResourceDefinition `status.storedVersions`.
|
||
1. Remove the old version from the CustomResourceDefinition `spec.versions` list.
|
||
1. Drop conversion support for the old version in conversion webhooks.
|
||
-->
|
||
删除旧版本:
|
||
|
||
1. 确保所有客户端都已完全迁移到新版本。
|
||
可以查看 kube-apiserver 的日志以识别仍通过旧版本进行访问的所有客户端。
|
||
1. 在 `spec.versions` 列表中将旧版本的 `served` 设置为 `false`。
|
||
如果仍有客户端意外地使用旧版本,他们可能开始会报告采用旧版本尝试访
|
||
定制资源的错误消息。
|
||
如果发生这种情况,请将旧版本的`served:true` 恢复,然后迁移余下的客户端
|
||
使用新版本,然后重复此步骤。
|
||
1. 确保已完成[将现有对象升级到新存储版本](#upgrade-existing-objects-to-a-new-stored-version)
|
||
的步骤。
|
||
1. 在 CustomResourceDefinition 的 `spec.versions` 列表中,确认新版本的
|
||
`storage` 已被设置为 `true`。
|
||
2. 确认旧版本不在 CustomResourceDefinition `status.storedVersions` 中。
|
||
1. 从 CustomResourceDefinition `spec.versions` 列表中删除旧版本。
|
||
1. 在转换 Webhooks 中放弃对旧版本的转换支持。
|
||
|
||
<!--
|
||
## Specify multiple versions
|
||
|
||
The CustomResourceDefinition API `versions` field can be used to support multiple versions of custom resources that you
|
||
have developed. Versions can have different schemas, and conversion webhooks can convert custom resources between versions.
|
||
Webhook conversions should follow the [Kubernetes API conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md) wherever applicable.
|
||
Specifically, See the [API change documentation](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md) for a set of useful gotchas and suggestions.
|
||
-->
|
||
## 指定多个版本 {#specify-multiple-versions}
|
||
|
||
CustomResourceDefinition API 的 `versions` 字段可用于支持你所开发的
|
||
定制资源的多个版本。版本可以具有不同的模式,并且转换 Webhooks
|
||
可以在多个版本之间转换定制资源。
|
||
在适当的情况下,Webhook 转换应遵循
|
||
[Kubernetes API 约定](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md)。
|
||
尤其是,请查阅
|
||
[API 变更文档](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md)
|
||
以了解一些有用的常见错误和建议。
|
||
|
||
<!--
|
||
In `apiextensions.k8s.io/v1beta1`, there was a `version` field instead of `versions`. The
|
||
`version` field is deprecated and optional, but if it is not empty, it must
|
||
match the first item in the `versions` field.
|
||
-->
|
||
{{< note >}}
|
||
在 `apiextensions.k8s.io/v1beta1` 版本中曾经有一个 `version` 字段,
|
||
名字不叫做 `versions`。该 `version` 字段已经被废弃,成为可选项。
|
||
不过如果该字段不是空,则必须与 `versions` 字段中的第一个条目匹配。
|
||
{{< /note >}}
|
||
|
||
<!--
|
||
This example shows a CustomResourceDefinition with two versions. For the first
|
||
example, the assumption is all versions share the same schema with no conversion
|
||
between them. The comments in the YAML provide more context.
|
||
-->
|
||
下面的示例显示了两个版本的 CustomResourceDefinition。
|
||
第一个例子中假设所有的版本使用相同的模式而它们之间没有转换。
|
||
YAML 中的注释提供了更多背景信息。
|
||
|
||
{{< tabs name="CustomResourceDefinition_versioning_example_1" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
|
||
```yaml
|
||
apiVersion: apiextensions.k8s.io/v1
|
||
kind: CustomResourceDefinition
|
||
metadata:
|
||
# name 必须匹配后面 spec 中的字段,且使用格式 <plural>.<group>
|
||
name: crontabs.example.com
|
||
spec:
|
||
# 组名,用于 REST API: /apis/<group>/<version>
|
||
group: example.com
|
||
# 此 CustomResourceDefinition 所支持的版本列表
|
||
versions:
|
||
- name: v1beta1
|
||
# 每个 version 可以通过 served 标志启用或禁止
|
||
served: true
|
||
# 有且只能有一个 version 必须被标记为存储版本
|
||
storage: true
|
||
# schema 是必需字段
|
||
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
|
||
# conversion 节是 Kubernetes 1.13+ 版本引入的,其默认值为无转换,即
|
||
# strategy 子字段设置为 None。
|
||
conversion:
|
||
# None 转换假定所有版本采用相同的模式定义,仅仅将定制资源的 apiVersion
|
||
# 设置为合适的值.
|
||
strategy: None
|
||
# 可以是 Namespaced 或 Cluster
|
||
scope: Namespaced
|
||
names:
|
||
# 名称的复数形式,用于 URL: /apis/<group>/<version>/<plural>
|
||
plural: crontabs
|
||
# 名称的单数形式,用于在命令行接口和显示时作为其别名
|
||
singular: crontab
|
||
# kind 通常是驼峰编码(CamelCased)的单数形式,用于资源清单中
|
||
kind: CronTab
|
||
# shortNames 允许你在命令行接口中使用更短的字符串来匹配你的资源
|
||
shortNames:
|
||
- ct
|
||
```
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
|
||
```yaml
|
||
# 在 v1.16 中被弃用以推荐使用 apiextensions.k8s.io/v1
|
||
apiVersion: apiextensions.k8s.io/v1beta1
|
||
kind: CustomResourceDefinition
|
||
metadata:
|
||
# name 必须匹配后面 spec 中的字段,且使用格式 <plural>.<group>
|
||
name: crontabs.example.com
|
||
spec:
|
||
# 组名,用于 REST API: /apis/<group>/<version>
|
||
group: example.com
|
||
# 此 CustomResourceDefinition 所支持的版本列表
|
||
versions:
|
||
- name: v1beta1
|
||
# 每个 version 可以通过 served 标志启用或禁止
|
||
served: true
|
||
# 有且只能有一个 version 必须被标记为存储版本
|
||
storage: true
|
||
- name: v1
|
||
served: true
|
||
storage: false
|
||
validation:
|
||
openAPIV3Schema:
|
||
type: object
|
||
properties:
|
||
host:
|
||
type: string
|
||
port:
|
||
type: string
|
||
# conversion 节是 Kubernetes 1.13+ 版本引入的,其默认值为无转换,即
|
||
# strategy 子字段设置为 None。
|
||
conversion:
|
||
# None 转换假定所有版本采用相同的模式定义,仅仅将定制资源的 apiVersion
|
||
# 设置为合适的值.
|
||
strategy: None
|
||
# 可以是 Namespaced 或 Cluster
|
||
scope: Namespaced
|
||
names:
|
||
# 名称的复数形式,用于 URL: /apis/<group>/<version>/<plural>
|
||
plural: crontabs
|
||
# 名称的单数形式,用于在命令行接口和显示时作为其别名
|
||
singular: crontab
|
||
# kind 通常是大驼峰编码(PascalCased)的单数形式,用于资源清单中
|
||
kind: CronTab
|
||
# shortNames 允许你在命令行接口中使用更短的字符串来匹配你的资源
|
||
shortNames:
|
||
- ct
|
||
```
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
<!--
|
||
You can save the CustomResourceDefinition in a YAML file, then use
|
||
`kubectl apply` to create it.
|
||
-->
|
||
你可以将 CustomResourceDefinition 存储在 YAML 文件中,然后使用
|
||
`kubectl apply` 来创建它。
|
||
|
||
```shell
|
||
kubectl apply -f my-versioned-crontab.yaml
|
||
```
|
||
|
||
<!--
|
||
After creation, the API server starts to serve each enabled version at an HTTP
|
||
REST endpoint. In the above example, the API versions are available at
|
||
`/apis/example.com/v1beta1` and `/apis/example.com/v1`.
|
||
-->
|
||
在创建之后,API 服务器开始在 HTTP REST 端点上为每个已启用的版本提供服务。
|
||
在上面的示例中,API 版本可以在 `/apis/example.com/v1beta1` 和
|
||
`/apis/example.com/v1` 处获得。
|
||
|
||
<!--
|
||
### Version priority
|
||
|
||
Regardless of the order in which versions are defined in a
|
||
CustomResourceDefinition, the version with the highest priority is used by
|
||
kubectl as the default version to access objects. The priority is determined
|
||
by parsing the _name_ field to determine the version number, the stability
|
||
(GA, Beta, or Alpha), and the sequence within that stability level.
|
||
-->
|
||
### 版本优先级
|
||
|
||
不考虑 CustomResourceDefinition 中版本被定义的顺序,kubectl 使用
|
||
具有最高优先级的版本作为访问对象的默认版本。
|
||
通过解析 _name_ 字段确定优先级来决定版本号,稳定性(GA、Beta 或 Alpha)
|
||
级别及该稳定性级别内的序列。
|
||
|
||
<!--
|
||
The algorithm used for sorting the versions is designed to sort versions in the
|
||
same way that the Kubernetes project sorts Kubernetes versions. Versions start with a
|
||
`v` followed by a number, an optional `beta` or `alpha` designation, and
|
||
optional additional numeric versioning information. Broadly, a version string might look
|
||
like `v2` or `v2beta1`. Versions are sorted using the following algorithm:
|
||
-->
|
||
用于对版本进行排序的算法在设计上与 Kubernetes 项目对 Kubernetes 版本进行排序的方式相同。
|
||
版本以 `v` 开头跟一个数字,一个可选的 `beta` 或者 `alpha` 和一个可选的附加数字
|
||
作为版本信息。
|
||
从广义上讲,版本字符串可能看起来像 `v2` 或者 `v2beta1`。
|
||
使用以下算法对版本进行排序:
|
||
|
||
<!--
|
||
- Entries that follow Kubernetes version patterns are sorted before those that
|
||
do not.
|
||
- For entries that follow Kubernetes version patterns, the numeric portions of
|
||
the version string is sorted largest to smallest.
|
||
- If the strings `beta` or `alpha` follow the first numeric portion, they sorted
|
||
in that order, after the equivalent string without the `beta` or `alpha`
|
||
suffix (which is presumed to be the GA version).
|
||
- If another number follows the `beta`, or `alpha`, those numbers are also
|
||
sorted from largest to smallest.
|
||
- Strings that don't fit the above format are sorted alphabetically and the
|
||
numeric portions are not treated specially. Notice that in the example below,
|
||
`foo1` is sorted above `foo10`. This is different from the sorting of the
|
||
numeric portion of entries that do follow the Kubernetes version patterns.
|
||
-->
|
||
- 遵循 Kubernetes 版本模式的条目在不符合条件的条目之前进行排序。
|
||
- 对于遵循 Kubernetes 版本模式的条目,版本字符串的数字部分从最大到最小排序。
|
||
- 如果第一个数字后面有字符串 `beta` 或 `alpha`,它们首先按去掉 `beta` 或
|
||
`alpha` 之后的版本号排序(相当于 GA 版本),之后按 `beta` 先、`alpha` 后的顺序排序,
|
||
- 如果 `beta` 或 `alpha` 之后还有另一个数字,那么也会针对这些数字
|
||
从大到小排序。
|
||
- 不符合上述格式的字符串按字母顺序排序,数字部分不经过特殊处理。
|
||
请注意,在下面的示例中,`foo1` 排在 `foo10` 之前。
|
||
这与遵循 Kubernetes 版本模式的条目的数字部分排序不同。
|
||
|
||
<!--
|
||
This might make sense if you look at the following sorted version list:
|
||
-->
|
||
如果查看以下版本排序列表,这些规则就容易懂了:
|
||
|
||
```none
|
||
- v10
|
||
- v2
|
||
- v1
|
||
- v11beta2
|
||
- v10beta3
|
||
- v3beta1
|
||
- v12alpha1
|
||
- v11alpha2
|
||
- foo1
|
||
- foo10
|
||
```
|
||
|
||
<!--
|
||
For the example in [Specify multiple versions](#specify-multiple-versions), the
|
||
version sort order is `v1`, followed by `v1beta1`. This causes the kubectl
|
||
command to use `v1` as the default version unless the provided object specifies
|
||
the version.
|
||
-->
|
||
对于[指定多个版本](#specify-multiple-versions)中的示例,版本排序顺序为
|
||
`v1`,后跟着 `v1beta1`。
|
||
这导致了 kubectl 命令使用 `v1` 作为默认版本,除非所提供的对象指定了版本。
|
||
|
||
<!--
|
||
### Version deprecation
|
||
-->
|
||
### 版本废弃
|
||
|
||
{{< feature-state state="stable" for_k8s_version="v1.19" >}}
|
||
|
||
<!--
|
||
Starting in v1.19, a CustomResourceDefinition can indicate a particular version of the resource it defines is deprecated.
|
||
When API requests to a deprecated version of that resource are made, a warning message is returned in the API response as a header.
|
||
The warning message for each deprecated version of the resource can be customized if desired.
|
||
-->
|
||
从 v1.19 开始,CustomResourceDefinition 可用来标明所定义的资源的特定版本
|
||
被废弃。当发起对已废弃的版本的 API 请求时,会在 API 响应中以 HTTP 头部
|
||
的形式返回警告消息。
|
||
如果需要,可以对资源的每个废弃版本定制该警告消息。
|
||
|
||
<!--
|
||
A customized warning message should indicate the deprecated API group, version, and kind,
|
||
and should indicate what API group, version, and kind should be used instead, if applicable.
|
||
-->
|
||
定制的警告消息应该标明废弃的 API 组、版本和类别(kind),并且应该标明
|
||
应该使用(如果有的话)哪个 API 组、版本和类别作为替代。
|
||
|
||
{{< tabs name="CustomResourceDefinition_versioning_deprecated" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
|
||
```yaml
|
||
apiVersion: apiextensions.k8s.io/v1
|
||
kind: CustomResourceDefinition
|
||
name: crontabs.example.com
|
||
spec:
|
||
group: example.com
|
||
names:
|
||
plural: crontabs
|
||
singular: crontab
|
||
kind: CronTab
|
||
scope: Namespaced
|
||
versions:
|
||
- name: v1alpha1
|
||
served: true
|
||
# 此属性标明此定制资源的 v1alpha1 版本已被弃用。
|
||
# 发给此版本的 API 请求会在服务器响应中收到警告消息头。
|
||
deprecated: true
|
||
# 此属性设置用来覆盖返回给发送 v1alpha1 API 请求的客户端的默认警告信息。
|
||
deprecationWarning: "example.com/v1alpha1 CronTab is deprecated; see http://example.com/v1alpha1-v1 for instructions to migrate to example.com/v1 CronTab"
|
||
schema: ...
|
||
- name: v1beta1
|
||
served: true
|
||
# 此属性标明该定制资源的 v1beta1 版本已被弃用。
|
||
# 发给此版本的 API 请求会在服务器响应中收到警告消息头。
|
||
# 针对此版本的请求所返回的是默认的警告消息。
|
||
deprecated: true
|
||
schema: ...
|
||
- name: v1
|
||
served: true
|
||
storage: true
|
||
schema: ...
|
||
```
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
```yaml
|
||
# 在 v1.16 中弃用以推荐使用 apiextensions.k8s.io/v1
|
||
apiVersion: apiextensions.k8s.io/v1beta1
|
||
kind: CustomResourceDefinition
|
||
metadata:
|
||
name: crontabs.example.com
|
||
spec:
|
||
group: example.com
|
||
names:
|
||
plural: crontabs
|
||
singular: crontab
|
||
kind: CronTab
|
||
scope: Namespaced
|
||
validation: ...
|
||
versions:
|
||
- name: v1alpha1
|
||
served: true
|
||
# 此属性标明此定制资源的 v1alpha1 版本已被弃用。
|
||
# 发给此版本的 API 请求会在服务器响应中收到警告消息头。
|
||
deprecated: true
|
||
# 此属性设置用来覆盖返回给发送 v1alpha1 API 请求的客户端的默认警告信息。
|
||
deprecationWarning: "example.com/v1alpha1 CronTab is deprecated; see http://example.com/v1alpha1-v1 for instructions to migrate to example.com/v1 CronTab"
|
||
- name: v1beta1
|
||
served: true
|
||
# 此属性标明该定制资源的 v1beta1 版本已被弃用。
|
||
# 发给此版本的 API 请求会在服务器响应中收到警告消息头。
|
||
# 针对此版本的请求所返回的是默认的警告消息。
|
||
deprecated: true
|
||
- name: v1
|
||
served: true
|
||
storage: true
|
||
```
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
|
||
<!--
|
||
## Webhook conversion
|
||
|
||
Webhook conversion is available as beta since 1.15, and as alpha since Kubernetes 1.13. The
|
||
`CustomResourceWebhookConversion` feature should be enabled. Please refer to the [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) documentation for more information.
|
||
-->
|
||
## Webhook 转换 {#webhook-conversion}
|
||
|
||
{{< feature-state state="stable" for_k8s_version="v1.16" >}}
|
||
|
||
{{< note >}}
|
||
Webhook 转换在 Kubernetes 1.13 版本引入,在 Kubernetes 1.15 中成为 Beta 功能。
|
||
要使用此功能,应启用 `CustomResourceWebhookConversion` 特性。
|
||
在大多数集群上,这类 Beta 特性应该是自动启用的。
|
||
请参阅[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)
|
||
文档以获得更多信息。
|
||
{{< /note >}}
|
||
|
||
<!--
|
||
The above example has a None conversion between versions which only sets the `apiVersion` field
|
||
on conversion and does not change the rest of the object. The API server also supports webhook
|
||
conversions that call an external service in case a conversion is required. For example when:
|
||
-->
|
||
上面的例子在版本之间有一个 None 转换,它只在转换时设置 `apiVersion` 字段
|
||
而不改变对象的其余部分。API 服务器还支持在需要转换时调用外部服务的 webhook 转换。
|
||
例如:
|
||
|
||
<!--
|
||
* custom resource is requested in a different version than stored version.
|
||
* Watch is created in one version but the changed object is stored in another version.
|
||
* custom resource PUT request is in a different version than storage version.
|
||
-->
|
||
* 定制资源的请求版本与其存储版本不同。
|
||
* 使用某版本创建了 Watch 请求,但所更改对象以另一版本存储。
|
||
* 定制资源的 PUT 请求所针对版本与存储版本不同。
|
||
|
||
<!--
|
||
To cover all of these cases and to optimize conversion by the API server,
|
||
the conversion requests may contain multiple objects in order to minimize the external calls.
|
||
The webhook should perform these conversions independently.
|
||
-->
|
||
为了涵盖所有这些情况并优化 API 服务器所作的转换,转换请求可以包含多个对象,
|
||
以便减少外部调用。Webhook 应该独立执行各个转换。
|
||
|
||
<!--
|
||
### Write a conversion webhook server
|
||
|
||
Please refer to the implementation of the [custom resource conversion webhook
|
||
server](https://github.com/kubernetes/kubernetes/tree/v1.15.0/test/images/crd-conversion-webhook/main.go)
|
||
that is validated in a Kubernetes e2e test. The webhook handles the
|
||
`ConversionReview` requests sent by the API servers, and sends back conversion
|
||
results wrapped in `ConversionResponse`. Note that the request
|
||
contains a list of custom resources that need to be converted independently without
|
||
changing the order of objects.
|
||
The example server is organized in a way to be reused for other conversions.
|
||
Most of the common code are located in the
|
||
[framework file](https://github.com/kubernetes/kubernetes/tree/v1.15.0/test/images/crd-conversion-webhook/converter/framework.go)
|
||
that leaves only
|
||
[one function](https://github.com/kubernetes/kubernetes/blob/v1.15.0/test/images/crd-conversion-webhook/converter/example_converter.go#L29-L80)
|
||
to be implemented for different conversions.
|
||
-->
|
||
### 编写一个转换 Webhook 服务器
|
||
|
||
请参考[定制资源转换 Webhook 服务器](https://github.com/kubernetes/kubernetes/tree/v1.15.0/test/images/crd-conversion-webhook/main.go)
|
||
的实现;该实现在 Kubernetes e2e 测试中得到验证。
|
||
Webhook 处理由 API 服务器发送的 `ConversionReview` 请求,并在
|
||
`ConversionResponse` 中封装发回转换结果。
|
||
请注意,请求包含需要独立转换的定制资源列表,这些对象在被转换之后不能改变其
|
||
在列表中的顺序。该示例服务器的组织方式使其可以复用于其他转换。
|
||
大多数常见代码都位于
|
||
[framework 文件](https://github.com/kubernetes/kubernetes/tree/v1.15.0/test/images/crd-conversion-webhook/converter/framework.go)
|
||
中,只留下
|
||
[一个函数](https://github.com/kubernetes/kubernetes/blob/v1.13.0/test/images/crd-conversion-webhook/converter/example_converter.go#L29-L80)
|
||
用于实现不同的转换。
|
||
|
||
<!--
|
||
The example conversion webhook server leaves the `ClientAuth` field
|
||
[empty](https://github.com/kubernetes/kubernetes/tree/v1.13.0/test/images/crd-conversion-webhook/config.go#L47-L48),
|
||
which defaults to `NoClientCert`. This means that the webhook server does not
|
||
authenticate the identity of the clients, supposedly API servers. If you need
|
||
mutual TLS or other ways to authenticate the clients, see
|
||
how to [authenticate API servers](/docs/reference/access-authn-authz/extensible-admission-controllers/#authenticate-apiservers).
|
||
-->
|
||
{{< note >}}
|
||
转换 Webhook 服务器示例中将 `ClientAuth` 字段设置为
|
||
[空](https://github.com/kubernetes/kubernetes/tree/v1.13.0/test/images/crd-conversion-webhook/config.go#L47-L48),
|
||
默认为 `NoClientCert`。
|
||
这意味着 webhook 服务器没有验证客户端(也就是 API 服务器)的身份。
|
||
如果你需要双向 TLS 或者其他方式来验证客户端,请参阅如何
|
||
[验证 API 服务](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/#authenticate-apiservers)。
|
||
{{< /note >}}
|
||
|
||
<!--
|
||
#### Permissible mutations
|
||
|
||
A conversion webhook must not mutate anything inside of `metadata` of the converted object
|
||
other than `labels` and `annotations`.
|
||
Attempted changes to `name`, `UID` and `namespace` are rejected and fail the request
|
||
which caused the conversion. All other changes are ignored.
|
||
-->
|
||
#### 被允许的变更
|
||
|
||
转换 Webhook 不可以更改被转换对象的 `metadata` 中除 `labels` 和 `annotations`
|
||
之外的任何属性。
|
||
尝试更改 `name`、`UID` 和 `namespace` 时都会导致引起转换的请求失败。
|
||
所有其他变更都被忽略。
|
||
|
||
<!--
|
||
### Deploy the conversion webhook service
|
||
|
||
Documentation for deploying the conversion webhook is the same as for the [admission webhook example service](/docs/reference/access-authn-authz/extensible-admission-controllers/#deploy_the_admission_webhook_service).
|
||
The assumption for next sections is that the conversion webhook server is deployed to a service named `example-conversion-webhook-server` in `default` namespace and serving traffic on path `/crdconvert`.
|
||
-->
|
||
### 部署转换 Webhook 服务
|
||
|
||
用于部署转换 webhook 的文档与
|
||
[准入 Webhook 服务示例](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/#deploy_the_admission_webhook_service)相同。
|
||
这里的假设是转换 Webhook 服务器被部署为 `default` 名字空间中名为
|
||
`example-conversion-webhook-server` 的服务,并在路径 `/crdconvert`
|
||
上处理请求。
|
||
|
||
<!--
|
||
When the webhook server is deployed into the Kubernetes cluster as a
|
||
service, it has to be exposed via a service on port 443 (The server
|
||
itself can have an arbitrary port but the service object should map it to port 443).
|
||
The communication between the API server and the webhook service may fail
|
||
if a different port is used for the service.
|
||
-->
|
||
{{< note >}}
|
||
当 Webhook 服务器作为一个服务被部署到 Kubernetes 集群中时,它必须
|
||
通过端口 443 公开其服务(服务器本身可以使用任意端口,但是服务对象
|
||
应该将它映射到端口 443)。
|
||
如果为服务器使用不同的端口,则 API 服务器和 Webhook 服务器之间的通信
|
||
可能会失败。
|
||
{{< /note >}}
|
||
|
||
<!--
|
||
### Configure CustomResourceDefinition to use conversion webhooks
|
||
|
||
The `None` conversion example can be extended to use the conversion webhook by modifying `conversion`
|
||
section of the `spec`:
|
||
-->
|
||
### 配置 CustomResourceDefinition 以使用转换 Webhook
|
||
|
||
通过修改 `spec` 中的 `conversion` 部分,可以扩展 `None` 转换示例来
|
||
使用转换 Webhook。
|
||
|
||
{{< tabs name="CustomResourceDefinition_versioning_example_2" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
```yaml
|
||
apiVersion: apiextensions.k8s.io/v1
|
||
kind: CustomResourceDefinition
|
||
metadata:
|
||
# name 必须匹配后面 spec 中的字段,且使用格式 <plural>.<group>
|
||
name: crontabs.example.com
|
||
spec:
|
||
# 组名,用于 REST API: /apis/<group>/<version>
|
||
group: example.com
|
||
# 此 CustomResourceDefinition 所支持的版本列表
|
||
versions:
|
||
- name: v1beta1
|
||
# 每个 version 可以通过 served 标志启用或禁止
|
||
served: true
|
||
# 有且只能有一个 version 必须被标记为存储版本
|
||
storage: true
|
||
# 当不存在顶级模式定义时,每个版本(version)可以定义其自身的模式
|
||
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:
|
||
# Webhook strategy 告诉 API 服务器调用外部 Webhook 来完成定制资源
|
||
# 之间的转换
|
||
strategy: Webhook
|
||
# 当 strategy 为 "Webhook" 时,webhook 属性是必需的
|
||
# 该属性配置将被 API 服务器调用的 Webhook 端点
|
||
webhook:
|
||
# conversionReviewVersions 标明 Webhook 所能理解或偏好使用的
|
||
# ConversionReview 对象版本。
|
||
# API 服务器所能理解的列表中的第一个版本会被发送到 Webhook
|
||
# Webhook 必须按所接收到的版本响应一个 ConversionReview 对象
|
||
conversionReviewVersions: ["v1","v1beta1"]
|
||
clientConfig:
|
||
service:
|
||
namespace: default
|
||
name: example-conversion-webhook-server
|
||
path: /crdconvert
|
||
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
|
||
# 可以是 Namespaced 或 Cluster
|
||
scope: Namespaced
|
||
names:
|
||
# 名称的复数形式,用于 URL: /apis/<group>/<version>/<plural>
|
||
plural: crontabs
|
||
# 名称的单数形式,用于在命令行接口和显示时作为其别名
|
||
singular: crontab
|
||
# kind 通常是驼峰编码(CamelCased)的单数形式,用于资源清单中
|
||
kind: CronTab
|
||
# shortNames 允许你在命令行接口中使用更短的字符串来匹配你的资源
|
||
shortNames:
|
||
- ct
|
||
```
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
```yaml
|
||
# 在 v1.16 中被弃用以推荐使用 apiextensions.k8s.io/v1
|
||
apiVersion: apiextensions.k8s.io/v1beta1
|
||
kind: CustomResourceDefinition
|
||
metadata:
|
||
# name 必须匹配后面 spec 中的字段,且使用格式 <plural>.<group>
|
||
name: crontabs.example.com
|
||
spec:
|
||
# 组名,用于 REST API: /apis/<group>/<version>
|
||
group: example.com
|
||
# 裁剪掉下面的 OpenAPI 模式中未曾定义的对象字段
|
||
preserveUnknownFields: false
|
||
# 此 CustomResourceDefinition 所支持的版本列表
|
||
versions:
|
||
- name: v1beta1
|
||
# 每个 version 可以通过 served 标志启用或禁止
|
||
served: true
|
||
# 有且只能有一个 version 必须被标记为存储版本
|
||
storage: true
|
||
# 当不存在顶级模式定义时,每个版本(version)可以定义其自身的模式
|
||
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:
|
||
# Webhook strategy 告诉 API 服务器调用外部 Webhook 来完成定制资源
|
||
strategy: Webhook
|
||
# 当 strategy 为 "Webhook" 时,webhookClientConfig 属性是必需的
|
||
# 该属性配置将被 API 服务器调用的 Webhook 端点
|
||
webhookClientConfig:
|
||
service:
|
||
namespace: default
|
||
name: example-conversion-webhook-server
|
||
path: /crdconvert
|
||
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
|
||
# 可以是 Namespaced 或 Cluster
|
||
scope: Namespaced
|
||
names:
|
||
# 名称的复数形式,用于 URL: /apis/<group>/<version>/<plural>
|
||
plural: crontabs
|
||
# 名称的单数形式,用于在命令行接口和显示时作为其别名
|
||
singular: crontab
|
||
# kind 通常是驼峰编码(CamelCased)的单数形式,用于资源清单中
|
||
kind: CronTab
|
||
# shortNames 允许你在命令行接口中使用更短的字符串来匹配你的资源
|
||
shortNames:
|
||
- ct
|
||
```
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
<!--
|
||
You can save the CustomResourceDefinition in a YAML file, then use
|
||
`kubectl apply` to apply it.
|
||
-->
|
||
你可以将 CustomResourceDefinition 保存在 YAML 文件中,然后使用
|
||
`kubectl apply` 来应用它。
|
||
|
||
```shell
|
||
kubectl apply -f my-versioned-crontab-with-conversion.yaml
|
||
```
|
||
|
||
<!--
|
||
Make sure the conversion service is up and running before applying new changes.
|
||
-->
|
||
在应用新更改之前,请确保转换服务器已启动并正在运行。
|
||
|
||
<!--
|
||
### Contacting the webhook
|
||
|
||
Once the API server has determined a request should be sent to a conversion webhook,
|
||
it needs to know how to contact the webhook. This is specified in the `webhookClientConfig`
|
||
stanza of the webhook configuration.
|
||
|
||
Conversion webhooks can either be called via a URL or a service reference,
|
||
and can optionally include a custom CA bundle to use to verify the TLS connection.
|
||
-->
|
||
### 调用 Webhook
|
||
|
||
API 服务器一旦确定请求应发送到转换 Webhook,它需要知道如何调用 Webhook。
|
||
这是在 `webhookClientConfig` 中指定的 Webhook 配置。
|
||
|
||
转换 Webhook 可以通过 URL 或服务引用来调用,并且可以选择包含自定义 CA 包,
|
||
以用于验证 TLS 连接。
|
||
|
||
### URL
|
||
|
||
<!--
|
||
`url` gives the location of the webhook, in standard URL form
|
||
(`scheme://host:port/path`).
|
||
|
||
The `host` should not refer to a service running in the cluster; use
|
||
a service reference by specifying the `service` field instead.
|
||
The host might be resolved via external DNS in some apiservers
|
||
(i.e., `kube-apiserver` cannot resolve in-cluster DNS as that would
|
||
be a layering violation). `host` may also be an IP address.
|
||
|
||
Please note that using `localhost` or `127.0.0.1` as a `host` is
|
||
risky unless you take great care to run this webhook on all hosts
|
||
which run an apiserver which might need to make calls to this
|
||
webhook. Such installations are likely to be non-portable or not readily run in a new cluster.
|
||
-->
|
||
url 以标准 URL 形式给出 Webhook 的位置(`scheme://host:port/path`)。
|
||
`host` 不应引用集群中运行的服务,而应通过指定 `service` 字段来提供
|
||
服务引用。
|
||
在某些 API 服务器中,`host` 可以通过外部 DNS 进行解析(即
|
||
`kube-apiserver` 无法解析集群内 DNS,那样会违反分层规则)。
|
||
`host` 也可以是 IP 地址。
|
||
|
||
请注意,除非你非常小心地在所有运行着可能调用 Webhook 的 API 服务器的
|
||
主机上运行此 Webhook,否则将 `localhost` 或 `127.0.0.1` 用作 `host`
|
||
是风险很大的。这样的安装可能是不可移植的,或者不容易在一个新的集群中运行。
|
||
<!--
|
||
The scheme must be "https"; the URL must begin with "https://".
|
||
|
||
Attempting to use a user or basic auth e.g. "user:password@" is not allowed.
|
||
Fragments ("#...") and query parameters ("?...") are also not allowed.
|
||
|
||
Here is an example of a conversion webhook configured to call a URL
|
||
(and expects the TLS certificate to be verified using system trust roots, so does not specify a caBundle):
|
||
-->
|
||
HTTP 协议必须为 `https`;URL 必须以 `https://` 开头。
|
||
|
||
尝试使用用户或基本身份验证(例如,使用`user:password@`)是不允许的。
|
||
URL 片段(`#...`)和查询参数(`?...`)也是不允许的。
|
||
|
||
下面是为调用 URL 来执行转换 Webhook 的示例,其中期望使用系统信任根
|
||
来验证 TLS 证书,因此未指定 caBundle:
|
||
|
||
{{< tabs name="CustomResourceDefinition_versioning_example_3" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
```yaml
|
||
apiVersion: apiextensions.k8s.io/v1
|
||
kind: CustomResourceDefinition
|
||
...
|
||
spec:
|
||
...
|
||
conversion:
|
||
strategy: Webhook
|
||
webhook:
|
||
clientConfig:
|
||
url: "https://my-webhook.example.com:9443/my-webhook-path"
|
||
...
|
||
```
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
```yaml
|
||
# 在 v1.16 中已弃用以推荐使用 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"
|
||
...
|
||
```
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
<!--
|
||
### Service Reference
|
||
|
||
The `service` stanza inside `webhookClientConfig` is a reference to the service for a conversion webhook.
|
||
If the webhook is running within the cluster, then you should use `service` instead of `url`.
|
||
The service namespace and name are required. The port is optional and defaults to 443.
|
||
The path is optional and defaults to "/".
|
||
|
||
Here is an example of a webhook that is configured to call a service on port "1234"
|
||
at the subpath "/my-path", and to verify the TLS connection against the ServerName
|
||
`my-service-name.my-service-namespace.svc` using a custom CA bundle.
|
||
-->
|
||
### 服务引用
|
||
|
||
`webhookClientConfig` 内部的 `service` 段是对转换 Webhook 服务的引用。
|
||
如果 Webhook 在集群中运行,则应使用 `service` 而不是 `url`。
|
||
服务的名字空间和名称是必需的。端口是可选的,默认为 443。
|
||
路径是可选的,默认为`/`。
|
||
|
||
下面配置中,服务配置为在端口 `1234`、子路径 `/my-path` 上被调用。
|
||
例子中针对 ServerName `my-service-name.my-service-namespace.svc`,
|
||
使用自定义 CA 包验证 TLS 连接。
|
||
|
||
{{< tabs name="CustomResourceDefinition_versioning_example_4" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
```yaml
|
||
apiVersion: apiextensions.k8s.io/v1
|
||
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"
|
||
...
|
||
```
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
```yaml
|
||
# v1.16 中被弃用以推荐使用 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"
|
||
...
|
||
```
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
<!--
|
||
## Webhook request and response
|
||
|
||
### Request
|
||
|
||
Webhooks are sent a POST request, with `Content-Type: application/json`,
|
||
with a `ConversionReview` API object in the `apiextensions.k8s.io` API group
|
||
serialized to JSON as the body.
|
||
|
||
Webhooks can specify what versions of `ConversionReview` objects they accept
|
||
with the `conversionReviewVersions` field in their CustomResourceDefinition:
|
||
-->
|
||
## Webhook 请求和响应
|
||
|
||
### 请求
|
||
|
||
向 Webhooks 发起请求的动词是 POST,请求的 `Content-Type` 为 `application/json`。
|
||
请求的主题为 JSON 序列化形式的
|
||
apiextensions.k8s.io API 组的 ConversionReview API 对象。
|
||
|
||
Webhooks 可以在其 CustomResourceDefinition 中使用`conversionReviewVersions` 字段
|
||
设置它们接受的 `ConversionReview` 对象的版本:
|
||
|
||
{{< tabs name="conversionReviewVersions" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
```yaml
|
||
apiVersion: apiextensions.k8s.io/v1
|
||
kind: CustomResourceDefinition
|
||
...
|
||
spec:
|
||
...
|
||
conversion:
|
||
strategy: Webhook
|
||
webhook:
|
||
conversionReviewVersions: ["v1", "v1beta1"]
|
||
...
|
||
```
|
||
|
||
<!--
|
||
`conversionReviewVersions` is a required field when creating
|
||
`apiextensions.k8s.io/v1` custom resource definitions.
|
||
Webhooks are required to support at least one `ConversionReview`
|
||
version understood by the current and previous API server.
|
||
-->
|
||
创建 `apiextensions.k8s.io/v1` 版本的自定义资源定义时,
|
||
`conversionReviewVersions`是必填字段。
|
||
Webhooks 要求支持至少一个 `ConversionReview` 当前和以前的 API 服务器
|
||
可以理解的版本。
|
||
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
```yaml
|
||
# v1.16 已弃用以推荐使用 apiextensions.k8s.io/v1
|
||
apiVersion: apiextensions.k8s.io/v1beta1
|
||
kind: CustomResourceDefinition
|
||
...
|
||
spec:
|
||
...
|
||
conversion:
|
||
strategy: Webhook
|
||
conversionReviewVersions: ["v1", "v1beta1"]
|
||
...
|
||
```
|
||
<!--
|
||
If no `conversionReviewVersions` are specified, the default when creating
|
||
`apiextensions.k8s.io/v1beta1` custom resource definitions is `v1beta1`.
|
||
-->
|
||
创建 apiextensions.k8s.io/v1beta1 定制资源定义时若未指定
|
||
`conversionReviewVersions`,则默认值为 v1beta1。
|
||
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
<!--
|
||
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.
|
||
-->
|
||
API 服务器将 `conversionReviewVersions` 列表中他们所支持的第一个
|
||
`ConversionReview` 资源版本发送给 Webhook。
|
||
如果列表中的版本都不被 API 服务器支持,则无法创建自定义资源定义。
|
||
如果某 API 服务器遇到之前创建的转换 Webhook 配置,并且该配置不支持
|
||
API 服务器知道如何发送的任何 `ConversionReview` 版本,调用 Webhook
|
||
的尝试会失败。
|
||
|
||
<!--
|
||
This example shows the data contained in an `ConversionReview` object
|
||
for a request to convert `CronTab` objects to `example.com/v1`:
|
||
-->
|
||
下面的示例显示了包含在 `ConversionReview` 对象中的数据,
|
||
该请求意在将 `CronTab` 对象转换为 `example.com/v1`:
|
||
|
||
{{< tabs name="ConversionReview_request" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
```yaml
|
||
apiVersion: apiextensions.k8s.io/v1
|
||
kind: ConversionReview
|
||
request:
|
||
# 用来唯一标识此转换调用的随机 UID
|
||
uid: 705ab4f5-6393-11e8-b7cc-42010a800002
|
||
|
||
# 对象要转换到的目标 API 组和版本
|
||
desiredAPIVersion: example.com/v1
|
||
|
||
# 要转换的对象列表
|
||
# 其中可能包含一个或多个对象,版本可能相同也可能不同
|
||
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
|
||
```
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
```yaml
|
||
# v1.16 中已废弃以推荐使用 apiextensions.k8s.io/v1
|
||
apiVersion: apiextensions.k8s.io/v1beta1
|
||
kind: ConversionReview
|
||
request:
|
||
# 用来唯一标识此转换调用的随机 UID
|
||
uid: 705ab4f5-6393-11e8-b7cc-42010a800002
|
||
|
||
# 对象要转换到的目标 API 组和版本
|
||
desiredAPIVersion: example.com/v1
|
||
|
||
# 要转换的对象列表
|
||
# 其中可能包含一个或多个对象,版本可能相同也可能不同
|
||
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
|
||
```
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
<!--
|
||
### Response
|
||
|
||
Webhooks respond with a 200 HTTP status code, `Content-Type: application/json`,
|
||
and a body containing a `ConversionReview` object (in the same version they were sent),
|
||
with the `response` stanza populated, serialized to JSON.
|
||
|
||
If conversion succeeds, a webhook should return a `response` stanza containing the following fields:
|
||
* `uid`, copied from the `request.uid` sent to the webhook
|
||
* `result`, set to `{"status":"Success"}`
|
||
* `convertedObjects`, containing all of the objects from `request.objects`, converted to `request.desiredVersion`
|
||
|
||
Example of a minimal successful response from a webhook:
|
||
-->
|
||
### 响应
|
||
|
||
Webhooks 响应包含 200 HTTP 状态代码、`Content-Type: application/json`,
|
||
在主体中包含 JSON 序列化形式的数据,在 `response` 节中给出
|
||
ConversionReview 对象(与发送的版本相同)。
|
||
|
||
如果转换成功,则 Webhook 应该返回包含以下字段的 `response` 节:
|
||
|
||
* `uid`,从发送到 webhook 的 `request.uid` 复制而来
|
||
* `result`,设置为 `{"status":"Success"}}`
|
||
* `convertedObjects`,包含来自 `request.objects` 的所有对象,均已转换为
|
||
`request.desiredVersion`
|
||
|
||
Webhook 的最简单成功响应示例:
|
||
|
||
{{< tabs name="ConversionReview_response_success" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
```yaml
|
||
apiVersion: apiextensions.k8s.io/v1
|
||
kind: ConversionReview
|
||
response:
|
||
# 必须与 <request.uid> 匹配
|
||
uid: "705ab4f5-6393-11e8-b7cc-42010a800002"
|
||
result:
|
||
status: Success
|
||
# 这里的对象必须与 request.objects 中的对象顺序相同并且其 apiVersion
|
||
# 被设置为 <request.desiredAPIVersion>。
|
||
# kind、metadata.uid、metadata.name 和 metadata.namespace 等字段都不可
|
||
# 被 Webhook 修改。
|
||
# Webhook 可以更改 metadata.labels 和 metadata.annotations 字段值
|
||
# Webhook 对 metadata 中其他字段的更改都会被忽略
|
||
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"
|
||
```
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
```yaml
|
||
# v1.16 中已弃用以推荐使用 apiextensions.k8s.io/v1
|
||
apiVersion: apiextensions.k8s.io/v1beta1
|
||
kind: ConversionReview
|
||
response:
|
||
# 必须与 <request.uid> 匹配
|
||
uid: "705ab4f5-6393-11e8-b7cc-42010a800002"
|
||
result:
|
||
status: Failed
|
||
# 这里的对象必须与 request.objects 中的对象顺序相同并且其 apiVersion
|
||
# 被设置为 <request.desiredAPIVersion>。
|
||
# kind、metadata.uid、metadata.name 和 metadata.namespace 等字段都不可
|
||
# 被 Webhook 修改。
|
||
# Webhook 可以更改 metadata.labels 和 metadata.annotations 字段值
|
||
# Webhook 对 metadata 中其他字段的更改都会被忽略
|
||
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"
|
||
```
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
<!--
|
||
If conversion fails, a webhook should return a `response` stanza containing the following fields:
|
||
* `uid`, copied from the `request.uid` sent to the webhook
|
||
* `result`, set to `{"status":"Failed"}`
|
||
-->
|
||
如果转换失败,则 Webhook 应该返回包含以下字段的 `response` 节:
|
||
|
||
* `uid`,从发送到 Webhook 的 `request.uid` 复制而来
|
||
* `result`,设置为 `{"status": "Failed"}`
|
||
|
||
{{< warning >}}
|
||
<!--
|
||
Failing conversion can disrupt read and write access to the custom resources,
|
||
including the ability to update or delete the resources. Conversion failures
|
||
should be avoided whenever possible, and should not be used to enforce validation
|
||
constraints (use validation schemas or webhook admission instead).
|
||
-->
|
||
转换失败会破坏对定制资源的读写访问,包括更新或删除资源的能力。
|
||
转换失败应尽可能避免,并且不可用于实施合法性检查约束
|
||
(应改用验证模式或 Webhook 准入插件)。
|
||
{{< /warning >}}
|
||
|
||
<!--
|
||
Example of a response from a webhook indicating a conversion request failed, with an optional message:
|
||
-->
|
||
来自 Webhook 的响应示例,指示转换请求失败,并带有可选消息:
|
||
|
||
{{< tabs name="ConversionReview_response_failure" >}}
|
||
{{% tab name="apiextensions.k8s.io/v1" %}}
|
||
```yaml
|
||
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
|
||
```
|
||
{{% /tab %}}
|
||
{{% tab name="apiextensions.k8s.io/v1beta1" %}}
|
||
```yaml
|
||
# v1.16 中弃用以推荐使用 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
|
||
```
|
||
{{% /tab %}}
|
||
{{< /tabs >}}
|
||
|
||
<!--
|
||
## Writing, reading, and updating versioned CustomResourceDefinition objects
|
||
-->
|
||
## 编写、读取和更新版本化的 CustomResourceDefinition 对象
|
||
|
||
<!--
|
||
When an object is written, it is persisted at the version designated as the
|
||
storage version at the time of the write. If the storage version changes,
|
||
existing objects are never converted automatically. However, newly-created
|
||
or updated objects are written at the new storage version. It is possible for an
|
||
object to have been written at a version that is no longer served.
|
||
-->
|
||
写入对象时,将使用写入时指定的存储版本来存储。如果存储版本发生变化,
|
||
现有对象永远不会被自动转换。然而,新创建或被更新的对象将以新的存储版本写入。
|
||
对象写入的版本不再被支持是有可能的。
|
||
|
||
<!--
|
||
When you read an object, you specify the version as part of the path. If you
|
||
specify a version that is different from the object's persisted version,
|
||
Kubernetes returns the object to you at the version you requested, but the
|
||
persisted object is neither changed on disk, nor converted in any way
|
||
(other than changing the `apiVersion` string) while serving the request.
|
||
You can request an object at any version that is currently served.
|
||
-->
|
||
当读取对象时,作为路径的一部分,你需要指定版本。
|
||
如果所指定的版本与对象的持久版本不同,Kubernetes 会按所请求的版本将对象返回,
|
||
但是在满足服务请求时,被持久化的对象既不会在磁盘上更改,也不会以任何方式进行
|
||
转换(除了 `apiVersion` 字符串被更改之外)。你可以以当前提供的任何版本
|
||
来请求对象。
|
||
|
||
<!--
|
||
If you update an existing object, it is rewritten at the version that is
|
||
currently the storage version. This is the only way that objects can change from
|
||
one version to another.
|
||
-->
|
||
如果你更新一个现有对象,它将以当前的存储版本被重写。
|
||
这是可以将对象从一个版本改到另一个版本的唯一办法。
|
||
|
||
<!--
|
||
To illustrate this, consider the following hypothetical series of events:
|
||
-->
|
||
为了说明这一点,请考虑以下假设的一系列事件:
|
||
|
||
<!--
|
||
1. The storage version is `v1beta1`. You create an object. It is persisted in
|
||
storage at version `v1beta1`
|
||
2. You add version `v1` to your CustomResourceDefinition and designate it as
|
||
the storage version.
|
||
3. You read your object at version `v1beta1`, then you read the object again at
|
||
version `v1`. Both returned objects are identical except for the apiVersion
|
||
field.
|
||
4. You create a new object. It is persisted in storage at version `v1`. You now
|
||
have two objects, one of which is at `v1beta1`, and the other of which is at
|
||
`v1`.
|
||
5. You update the first object. It is now persisted at version `v1` since that
|
||
is the current storage version.
|
||
-->
|
||
1. 存储版本是 `v1beta1`。你创建一个对象。该对象以版本 `v1beta1` 存储。
|
||
2. 你将为 CustomResourceDefinition 添加版本 `v1`,并将其指定为存储版本。
|
||
3. 你使用版本 `v1beta1` 来读取你的对象,然后你再次用版本 `v1` 读取对象。
|
||
除了 apiVersion 字段之外,返回的两个对象是完全相同的。
|
||
4. 你创建一个新对象。对象以版本 `v1` 保存在存储中。
|
||
你现在有两个对象,其中一个是 `v1beta1`,另一个是 `v1`。
|
||
5. 你更新第一个对象。该对象现在以版本 `v1` 保存,因为 `v1` 是当前的存储版本。
|
||
|
||
<!--
|
||
### Previous storage versions
|
||
-->
|
||
### 以前的存储版本
|
||
|
||
<!--
|
||
The API server records each version which has ever been marked as the storage
|
||
version in the status field `storedVersions`. Objects may have been persisted
|
||
at any version that has ever been designated as a storage version. No objects
|
||
can exist in storage at a version that has never been a storage version.
|
||
-->
|
||
API 服务器在状态字段 `storedVersions` 中记录曾被标记为存储版本的每个版本。
|
||
对象可能以任何曾被指定为存储版本的版本保存。
|
||
存储中不会出现从未成为存储版本的版本的对象。
|
||
|
||
<!--
|
||
## Upgrade existing objects to a new stored version
|
||
-->
|
||
## 将现有对象升级到新的存储版本 {#upgrade-existing-objects-to-a-new-stored-version}
|
||
|
||
<!--
|
||
When deprecating versions and dropping support, devise a storage upgrade
|
||
procedure.
|
||
-->
|
||
弃用版本并删除其支持时,请设计存储升级过程。
|
||
|
||
<!--
|
||
*Option 1:* Use the Storage Version Migrator
|
||
|
||
1. Run the [storage Version migrator](https://github.com/kubernetes-sigs/kube-storage-version-migrator)
|
||
2. Remove the old version from the CustomResourceDefinition `status.storedVersions` field.
|
||
-->
|
||
|
||
*选项 1:* 使用存储版本迁移程序(Storage Version Migrator)
|
||
|
||
1. 运行[存储版本迁移程序](https://github.com/kubernetes-sigs/kube-storage-version-migrator)
|
||
2. 从 CustomResourceDefinition 的 `status.storedVersions` 字段中去掉
|
||
老的版本。
|
||
|
||
<!--
|
||
*Option 2:* Manually upgrade the existing objects to a new stored version
|
||
|
||
The following is an example procedure to upgrade from `v1beta1` to `v1`.
|
||
-->
|
||
*选项 2:* 手动将现有对象升级到新的存储版本
|
||
|
||
以下是从 `v1beta1` 升级到 `v1` 的示例过程。
|
||
|
||
<!--
|
||
1. Set `v1` as the storage in the CustomResourceDefinition file and apply it
|
||
using kubectl. The `storedVersions` is now `v1beta1, v1`.
|
||
2. Write an upgrade procedure to list all existing objects and write them with
|
||
the same content. This forces the backend to write objects in the current
|
||
storage version, which is `v1`.
|
||
3. Remove `v1beta1` from the CustomResourceDefinition `status.storedVersions` field.
|
||
-->
|
||
1. 在 CustomResourceDefinition 文件中将 `v1` 设置为存储版本,并使用 kubectl 应用它。
|
||
`storedVersions`现在是`v1beta1, v1`。
|
||
2. 编写升级过程以列出所有现有对象并使用相同内容将其写回存储。
|
||
这会强制后端使用当前存储版本(即 `v1`)写入对象。
|
||
3. 从 CustomResourceDefinition 的 `status.storedVersions` 字段中删除 `v1beta1`。
|
||
|
||
<!--
|
||
The `kubectl` tool currently cannot be used to edit or patch the `status` subresource on a CRD: see the [Kubectl Subresource Support KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2590-kubectl-subresource) for more details.
|
||
|
||
The easier way to patch the status subresource from the CLI is directly interacting with the API server using the `curl` tool, in this example:
|
||
-->
|
||
{{< note >}}
|
||
`kubectl` 工具目前不能用于编辑或修补 CRD 上的 `status` 子资源:请参阅
|
||
[kubectl Subresource Support KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2590-kubectl-subresource)
|
||
了解更多细节。
|
||
|
||
从 CLI 给 `status` 子资源打补丁的更简单的方法是使用 `curl` 工具直接与 API 服务器交互,示例:
|
||
```bash
|
||
kubectl proxy &
|
||
curl --header "Content-Type: application/json-patch+json" \
|
||
--request PATCH http://localhost:8001/apis/apiextensions.k8s.io/v1/customresourcedefinitions/<your CRD name here>/status \
|
||
--data '[{"op": "replace", "path": "/status/storedVersions", "value":["v1"]}]'
|
||
```
|
||
{{< /note >}} |