自定义资源

自定义资源是 Kubernetes API 的扩展。此页面讨论何时将自定义资源添加到您的 Kubernetes 集群,以及何时使用独立服务。它描述了添加自定义资源的两种方法以及如何在它们之间进行选择。

自定义资源

资源Kubernetes API 中的一个端点,它存储特定类型的API 对象 集合;例如,内置的pod 资源包含一组 Pod 对象。

自定义资源是 Kubernetes API 的扩展,它不一定在默认的 Kubernetes 安装中可用。它代表了特定 Kubernetes 安装的定制。但是,现在许多核心 Kubernetes 功能都是使用自定义资源构建的,这使得 Kubernetes 更加模块化。

自定义资源可以通过动态注册在运行的集群中出现和消失,并且集群管理员可以独立于集群本身更新自定义资源。安装自定义资源后,用户可以使用kubectl创建和访问其对象,就像他们对Pod 等内置资源那样。

自定义控制器

自定义资源本身可以让您存储和检索结构化数据。当您将自定义资源与自定义控制器结合使用时,自定义资源提供了一个真正的声明式 API

Kubernetes 的声明式 API 强制执行职责分离。您声明资源的期望状态。Kubernetes 控制器使 Kubernetes 对象的当前状态与您声明的期望状态保持同步。这与命令式 API 相反,在命令式 API 中,您指示服务器要做什么。

您可以在运行的集群上独立于集群的生命周期部署和更新自定义控制器。自定义控制器可以与任何类型的资源一起工作,但与自定义资源结合使用时特别有效。 运算符模式 结合了自定义资源和自定义控制器。您可以使用自定义控制器将特定应用程序的领域知识编码到 Kubernetes API 的扩展中。

我应该将自定义资源添加到我的 Kubernetes 集群中吗?

创建新 API 时,请考虑是否将您的 API 与 Kubernetes 集群 API 聚合,或者让您的 API 独立存在。

如果以下情况,请考虑 API 聚合如果以下情况,请首选独立 API
您的 API 是 声明式 的。您的 API 不符合 声明式 模型。
您希望您的新类型可以使用 kubectl 读取和写入。kubectl 支持不是必需的
您希望在 Kubernetes UI(例如仪表板)中查看您的新类型,与内置类型并列。Kubernetes UI 支持不是必需的。
您正在开发一个新的 API。您已经有一个程序为您的 API 提供服务,并且运行良好。
您愿意接受 Kubernetes 对 REST 资源路径的格式限制,例如 API 组和命名空间。(参见API 概述。)您需要拥有特定的 REST 路径才能与已定义的 REST API 兼容。
您的资源自然地限定在集群或集群的命名空间中。集群或命名空间限定资源不适合;您需要控制资源路径的细节。
您希望重用 Kubernetes API 支持功能您不需要这些功能。

声明式 API

在声明式 API 中,通常

  • 您的 API 由数量相对较少的、大小相对较小的对象(资源)组成。
  • 这些对象定义了应用程序或基础设施的配置。
  • 这些对象更新的频率相对较低。
  • 人类通常需要读取和写入这些对象。
  • 对对象的主要操作是 CRUD 式的(创建、读取、更新和删除)。
  • 跨对象的事务不是必需的:API 表示期望状态,而不是精确状态。

命令式 API 不是声明式的。以下迹象表明您的 API 可能不是声明式的

  • 客户端说“执行此操作”,然后在完成后收到同步响应。
  • 客户端说“执行此操作”,然后收到一个操作 ID,并且必须检查一个单独的操作对象以确定请求的完成。
  • 您谈论远程过程调用(RPC)。
  • 直接存储大量数据;例如,> 每个对象 > 几个 kB,或 > 数千个对象。
  • 需要高带宽访问(每秒 10 多次请求)。
  • 存储最终用户数据(例如图像、PII 等)或应用程序处理的其他大规模数据。
  • 对对象的主要操作不是 CRUD 式的。
  • API 难以建模为对象。
  • 您选择使用操作 ID 或操作对象来表示挂起的操作。

我应该使用 ConfigMap 还是自定义资源?

如果以下任何一项适用,请使用 ConfigMap

  • 存在现有的、有良好文档记录的配置文件格式,例如 mysql.cnfpom.xml
  • 您希望将整个配置放入 ConfigMap 的一个键中。
  • 配置文件的主要用途是让集群上的 Pod 中运行的程序使用该文件来配置自身。
  • 文件的使用者更喜欢通过 Pod 中的文件或 Pod 中的环境变量来使用文件,而不是 Kubernetes API。
  • 您希望在更新文件时通过 Deployment 等执行滚动更新。

如果以下大多数情况适用,请使用自定义资源(CRD 或聚合 API)

  • 您希望使用 Kubernetes 客户端库和 CLI 来创建和更新新的资源。
  • 您希望从 kubectl 获得顶级支持;例如,kubectl get my-object object-name
  • 您希望构建新的自动化,它会监视新对象上的更新,然后对其他对象执行 CRUD 操作,反之亦然。
  • 您希望编写处理对象更新的自动化。
  • 您希望使用 Kubernetes API 约定,如 .spec.status.metadata
  • 您希望该对象成为受控资源集合的抽象,或其他资源的汇总。

添加自定义资源

Kubernetes 提供两种方法来将自定义资源添加到您的集群中

  • CRD 很简单,可以在没有任何编程的情况下创建。
  • API 聚合 需要编程,但允许更多地控制 API 行为,例如如何存储数据以及在 API 版本之间进行转换。

Kubernetes 提供了这两个选项来满足不同用户的需求,因此既不牺牲易用性也不牺牲灵活性。

聚合 API 是位于主 API 服务器后面的从属 API 服务器,主 API 服务器充当代理。这种安排称为API 聚合 (AA)。对于用户来说,Kubernetes API 似乎扩展了。

CRD 允许用户创建新类型的资源,而无需添加另一个 API 服务器。您不需要了解 API 聚合即可使用 CRD。

无论它们是如何安装的,这些新资源都被称为自定义资源,以区别于内置的 Kubernetes 资源(如 pod)。

CustomResourceDefinitions

CustomResourceDefinition API 资源允许您定义自定义资源。定义 CRD 对象会创建一个新的自定义资源,该资源具有您指定的名称和模式。Kubernetes API 为您的自定义资源提供服务并处理其存储。CRD 对象本身的名称必须是根据定义的资源名称及其 API 组得出的有效DNS 子域名;参见如何创建 CRD以了解更多详细信息。此外,由 CRD 定义其 kind/resource 的对象的名称也必须是有效的 DNS 子域名。

这使您无需编写自己的 API 服务器来处理自定义资源,但实现的通用性意味着您比使用API 服务器聚合 的灵活性要低。

请参考自定义控制器示例,了解如何注册新的自定义资源、使用新资源类型实例以及使用控制器来处理事件的示例。

API 服务器聚合

通常,Kubernetes API 中的每个资源都需要代码来处理 REST 请求并管理对象的持久存储。主 Kubernetes API 服务器处理pod服务等内置资源,还可以通过CRD 通用地处理自定义资源。

聚合层 允许您通过编写和部署自己的 API 服务器为自定义资源提供专门的实现。主 API 服务器将针对您处理的自定义资源的请求委托给您的 API 服务器,使其可供其所有客户端使用。

选择添加自定义资源的方法

CRD 更易于使用。聚合 API 更加灵活。选择最符合您需求的方法。

通常,CRD 非常适合以下情况

  • 您有少量字段
  • 您在公司内部使用该资源,或作为小型开源项目(而非商业产品)的一部分

比较易用性

CRD 比聚合 API 更易于创建。

CRD聚合 API
不需要编程。用户可以选择任何语言用于 CRD 控制器。需要编程并构建二进制文件和镜像。
无需运行额外的服务;CRD 由 API 服务器处理。一个额外的服务来创建,并且可能会失败。
CRD 创建后不再提供持续支持。任何错误修复都将在正常的 Kubernetes 主节点升级中解决。可能需要定期从上游获取错误修复并重建和更新聚合 API 服务器。
无需处理 API 的多个版本;例如,当您控制此资源的客户端时,您可以与 API 同步升级它。您需要处理 API 的多个版本;例如,在开发与世界共享的扩展时。

高级功能和灵活性

聚合 API 提供更高级的 API 功能和对其他功能(例如存储层)的定制。

功能描述CRD聚合 API
验证帮助用户防止错误并允许您独立于客户端发展 API。这些功能在有许多无法同时更新的客户端时最为有用。是的。大多数验证可以使用 CRD 中的 OpenAPI v3.0 验证 指定。 CRDValidationRatcheting 功能门允许忽略使用 OpenAPI 指定的失败验证,如果资源的失败部分未改变。任何其他验证都支持通过添加 验证 Webhook 来实现。是的,任意验证检查
默认值见上文是的,通过 OpenAPI v3.0 验证 default 关键字(在 1.17 中发布)或通过 变异 Webhook(尽管这在从 etcd 读取旧对象时不会运行)。是的
多版本允许通过两个 API 版本提供同一个对象。可以帮助简化 API 更改,例如重命名字段。如果您控制客户端版本,则不太重要。是的是的
自定义存储如果您需要具有不同性能模式的存储(例如,时间序列数据库而不是键值存储)或出于安全原因的隔离(例如,敏感信息的加密等)。是的
自定义业务逻辑在创建、读取、更新或删除对象时执行任意检查或操作是的,使用 Webhook是的
Scale 子资源允许像 HorizontalPodAutoscaler 和 PodDisruptionBudget 这样的系统与您的新资源交互是的是的
Status 子资源允许细粒度访问控制,其中用户写入 spec 部分,而控制器写入 status 部分。允许在自定义资源数据变异时递增对象代数(需要在资源中单独的 spec 和 status 部分)。是的是的
其他子资源添加除 CRUD 之外的其他操作,例如“日志”或“执行”。是的
strategic-merge-patch新的端点支持使用 Content-Type: application/strategic-merge-patch+json 的 PATCH。对于更新可能在本地和服务器上修改的对象很有用。有关更多信息,请参见 "使用 kubectl patch 就地更新 API 对象"是的
Protocol Buffers新的资源支持想要使用 Protocol Buffers 的客户端是的
OpenAPI 模式是否有一个可以从服务器动态获取的类型 OpenAPI(swagger)模式?用户是否通过确保仅设置允许的字段来免受拼写错误的字段名称的保护?类型是否强制执行(换句话说,不要将 int 放入 string 字段中)?是的,基于 OpenAPI v3.0 验证 模式(在 1.16 中发布)。是的
实例名称此扩展机制是否对以这种方式定义其种类/资源的对象名称施加任何约束?是的,此类对象的名称必须是有效的 DNS 子域名称。

常见功能

当您通过 CRD 或 AA 创建自定义资源时,与在 Kubernetes 平台之外实现它相比,您的 API 将获得许多功能

功能它做什么
CRUD新的端点通过 HTTP 和 kubectl 支持 CRUD 基本操作
观看新的端点通过 HTTP 支持 Kubernetes Watch 操作
发现kubectl 和仪表板这样的客户端会自动在您的资源上提供列表、显示和字段编辑操作
json-patch新的端点支持使用 Content-Type: application/json-patch+json 的 PATCH
merge-patch新的端点支持使用 Content-Type: application/merge-patch+json 的 PATCH
HTTPS新的端点使用 HTTPS
内置身份验证对扩展的访问使用核心 API 服务器(聚合层)进行身份验证
内置授权对扩展的访问可以重复使用核心 API 服务器使用的授权;例如,RBAC。
终结器阻止删除扩展资源,直到外部清理完成。
准入 Webhook在任何创建/更新/删除操作期间设置默认值并验证扩展资源。
UI/CLI 显示Kubectl、仪表板可以显示扩展资源。
未设置与空客户端可以区分未设置的字段和零值字段。
客户端库生成Kubernetes 提供通用客户端库,以及用于生成特定于类型的客户端库的工具。
标签和注释跨对象的通用元数据,工具知道如何编辑核心和自定义资源。

准备安装自定义资源

在将自定义资源添加到您的集群之前,需要注意几个方面。

第三方代码和新的故障点

虽然创建 CRD 不会自动添加任何新的故障点(例如,通过导致第三方代码在您的 API 服务器上运行),但包(例如,图表)或其他安装捆绑包通常包括 CRD 以及实现新自定义资源的业务逻辑的第三方代码的部署。

安装聚合 API 服务器总是涉及运行新的部署。

存储

自定义资源与 ConfigMap 以相同的方式消耗存储空间。创建过多的自定义资源可能会使 API 服务器的存储空间过载。

聚合 API 服务器可能使用与主 API 服务器相同的存储,在这种情况下,相同的警告适用。

身份验证、授权和审计

CRD 始终使用与 API 服务器的内置资源相同的身份验证、授权和审计日志记录。

如果您使用 RBAC 进行授权,大多数 RBAC 角色不会授予访问新资源的权限(除了 cluster-admin 角色或使用通配符规则创建的任何角色)。您需要显式授予访问新资源的权限。CRD 和聚合 API 通常与为它们添加的类型捆绑在一起提供新的角色定义。

聚合 API 服务器可能使用也可能不使用与主 API 服务器相同的身份验证、授权和审计。

访问自定义资源

Kubernetes 客户端库 可用于访问自定义资源。并非所有客户端库都支持自定义资源。GoPython 客户端库支持。

添加自定义资源后,您可以使用以下方法访问它

  • kubectl
  • Kubernetes 动态客户端。
  • 您编写的 REST 客户端。
  • 使用 Kubernetes 客户端生成工具 生成的客户端(生成一个是一个高级任务,但一些项目可能会与 CRD 或 AA 一起提供客户端)。

自定义资源字段选择器

字段选择器 允许客户端根据一个或多个资源字段的值来选择自定义资源。

所有自定义资源都支持 metadata.namemetadata.namespace 字段选择器。

CustomResourceDefinition 中声明的字段也可以与字段选择器一起使用,前提是它们包含在 CustomResourceDefinitionspec.versions[*].selectableFields 字段中。

自定义资源的可选择字段

功能状态: Kubernetes v1.31 [beta]

CustomResourceDefinitionspec.versions[*].selectableFields 字段可用于声明自定义资源中的哪些其他字段可用于具有 CustomResourceFieldSelectors 功能门 功能的字段选择器(此功能门从 Kubernetes v1.31 开始默认启用)。以下示例将 .spec.color.spec.size 字段添加为可选择字段。

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: shirts.stable.example.com
spec:
  group: stable.example.com
  scope: Namespaced
  names:
    plural: shirts
    singular: shirt
    kind: Shirt
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              color:
                type: string
              size:
                type: string
    selectableFields:
    - jsonPath: .spec.color
    - jsonPath: .spec.size
    additionalPrinterColumns:
    - jsonPath: .spec.color
      name: Color
      type: string
    - jsonPath: .spec.size
      name: Size
      type: string

然后可以使用字段选择器仅获取颜色为 blue 的资源

kubectl get shirts.stable.example.com --field-selector spec.color=blue

输出应该是

NAME       COLOR  SIZE
example1   blue   S
example2   blue   M

下一步

上次修改时间:2024 年 7 月 26 日下午 7:53 PST:KEP-4358:自定义资源字段选择器:提升到 Beta (#46980) (8f1e148864)