任务

Edit This Page

CustomResourceDefinitions 的版本

本页介绍了如何添加版本信息到CustomResourceDefinitions,如何表示 CustomResourceDefinitions 的稳定水平或者用 API 之间的表征的转换提高您的 API 到一个新的版本。它还描述了如何将对象从一个版本升级到另一个版本。

准备开始

你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

为了检查版本, 输入 kubectl version.

概览

CustomResourceDefinition API 支持您使用versions字段来开发多个版本的自定义资源。 版本可以有不同的模式与转换 webhook 在版本之间转换自定义资源。 Webhook 转换应遵循适用的Kubernetes API 约定。 具体来说,请参阅 API 更改文档以获取一组有用的问题和建议。

Note: 早期的迭代包括 version 字段而不是versionsversion 字段已弃用且可选,但如果它不为空,则必须必配versions 字段中的第一项。

指定多个版本

此示例显示了两个版本的 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
  - name: v1
    served: true
    storage: false
  # 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

在创建之后,API 服务器开始在 HTTP REST 端点上为每个启用的版本提供服务。在上面的示例中,API 版本可以在/apis/example.com/v1beta1/apis/example.com/v1中获得。

版本优先级

不考虑 CustomResourceDefinition 中版本被定义的顺序,kubectl 使用具有最高优先级的版本作为访问对象的默认版本。 通过解析_name_字段确定优先级来决定版本号,稳定性(GA, Beta, 或者 Alpha),以及该稳定性水平内的序列。

用于对版本进行排序的算法被设计成与 Kubernetes 项目对 Kubernetes 版本进行排序的方式相同。 版本以v开头跟一个数字,一个可选的beta 或者 alpha命名,和一个可选的附加的数字型的版本信息。 从广义上讲,版本字符串可能看起来像v2或者v2beta1。 使用以下算法对版本进行排序:

如果查看以下排序版本列表可以明白:

- v10
- v2
- v1
- v11beta2
- v10beta3
- v3beta1
- v12alpha1
- v11alpha2
- foo1
- foo10

对于 指定多个版本中的示例,版本排序顺序为v1,后跟着v1beta1。 这导致了 kubectl 命令使用v1作为默认版本,除非提供对象指定版本。

Webhook 转换

Note: Webhook 转换在 Kubernetes 1.13中作为 alpha 功能引入。要使用它,应启用CustomResourceWebhookConversion功能。 请参阅 feature gate 文档以获得更多信息。

上面的例子在版本之间有一个 None 转换,它只在转换时设置apiVersion字段而不改变对象的其余部分。API 服务器还支持在需要转换时调用外部服务的 webhook 转换。例如:

为了涵盖所有这些情况并通过 API 服务器优化转换,转换对象可能包含多个对象,以便最大限度地减少外部调用。webhook 应该独立执行这些转换。

编写一个 webhook 服务器的转换

请参考自定义资源转换 webhook 服务器的实施,这在Kubernetes e2e测试中得到验证。 webhook 处理由 API 服务器发送的ConversionReview请求,并发送回包含在ConversionResponse中的转换结果。 请注意,请求包含需要独立转换不改变对象顺序的自定义资源列表。 示例服务器的组织方式使其可以重用于其他转换。 大多数常见代码都位于框架文件中,只留下一个功能用于实施不同的转换。

Note: 示例转换 webhook 服务器留下ClientAuth字段empty,默认为NoClientCert。 这意味着 webhook 服务器没有验证客户端的身份,据称是 API 服务器。 如果您需要相互 TLS 或者其他方式来验证客户端,请参阅如何验证 API 服务器

部署转换 webhook 服务器

用于部署转换 webhook 的文档与准入 webhook 示例服务。 下一节的假设是转换 webhook 服务器部署到default命名空间中名为example-conversion-webhook-server的服务器上,并在路径/crdconvert上提供流量。

Note: 当 webhook 服务器作为一个部署到 Kubernetes 集群中的服务器时,它必须通过端口443上的服务器公开(服务器本身可以有一个任意端口,但是服务器对象应该将它映射到端口443)。 如果为服务器使用不同的端口,则 API 服务器和 webhook 服务器之间的通信可能会失败。

配置 CustomResourceDefinition 以使用转换 webhook

通过修改spec中的conversion部分,可以扩展None转换示例来使用转换 webhook。

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
    # Each version can define it's own schema when there is no top-level
    # schema is defined.
    schema:
      openAPIV3Schema:
        properties:
          hostPort:
            type: string
  - name: v1
    served: true
    storage: false
    schema:
      openAPIV3Schema:
        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 configure the webhook endpoint to be
    # called by API server.
    webhookClientConfig:
      service:
        namespace: default
        name: example-conversion-webhook-server
        # path is the url the API server will call. It should match what the webhook is serving at. The default is '/'.
        path: /crdconvert
      caBundle: <pem encoded ca cert that signs the server cert used by the webhook>
  # 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
Note: 当使用 clientConfig.service时,服务器证书必须对<svc_name>.<svc_namespace>.svc有效。

您可以将 CustomResourceDefinition 保存在 YAML 文件中,然后使用kubectl apply来应用它。

kubectl apply -f my-versioned-crontab-with-conversion.yaml

在应用新更改之前,请确保转换服务器已启动并正在运行。

编写、读取和更新版本化的 CustomResourceDefinition 对象

写入对象时,它将保留在写入时指定为存储版本的版本中。 如果存储版本发生变化,现有对象永远不会自动转换。 然而,新创建或更新的对象将在新的存储版本中编写。 对象可能已在不再被服务的版本中编写。

当读取对象时,将版本指定为路径的一部分。 如果指定的版本与对象的持久版本不同, Kubernetes 会在您请求的版本里将对象返还给您,但是在提供请求时,持久化对象既不会在磁盘上更改,也不会以任何方式进行转换(除了更改apiVersion字符串)。 您可以在当前提供的任何版本中请求对象。

如果您更新了一个现有对象,它将在现在的存储版本中被重写。 这是对象可以从一个版本改到另一个版本的唯一办法。

为了说明这一点,请考虑以下假设的一系列事件:

  1. 存储版本是v1beta1。 它保存在版本v1beta1的存储中。
  2. 您将版本v1添加到 CustomResourceDefinition 中,并将其指定为存储版本。
  3. 您在版本v1beta1中读取您的对象,然后您再次在版本v1中读取对象。 除了 apiVersion 字段之外,两个返回的对象都是相同的。
  4. 您创建一个新对象。 它存储在版本v1的存储中。 您现在有两个对象,其中一个位于v1beta1,另一个位于v1
  5. 您更新第一个对象。 它现在保存在版本v1中,因为那是当前的存储版本。

以前的存储版本

API 服务器在状态字段storedVersions中记录曾被标记为存储版本的每个版本。 对象可能已被保留在任何曾被指定为存储版本的版本中。 从未成为存储版本的版本的存储中不能存在任何对象。

将现有对象升级到新的存储版本

弃用版本并删除支持时,请设计存储升级过程。 以下是从v1beta1升级到v1的示例过程。

  1. v1设置为 CustomResourceDefinition 文件中的存储,并使用 kubectl 应用它。 storedVersions现在是v1beta1、 v1
  2. 编写升级过程以列出所有现有对象并使用相同内容编写它们。 这会强制后端在当前存储版本中写入对象,即v1
  3. 通过从storedVersions字段中删除v1beta1来更新 CustomResourceDefinitionStatus

反馈