定制资源

    资源(Resource)Kubernetes API 中的一个端点, 其中存储的是某个类别的 的一个集合。 例如内置的 pods 资源包含一组 Pod 对象。

    定制资源(Custom Resource) 是对 Kubernetes API 的扩展,不一定在默认的 Kubernetes 安装中就可用。定制资源所代表的是对特定 Kubernetes 安装的一种定制。 不过,很多 Kubernetes 核心功能现在都用定制资源来实现,这使得 Kubernetes 更加模块化。

    定制资源可以通过动态注册的方式在运行中的集群内或出现或消失,集群管理员可以独立于集群 更新定制资源。一旦某定制资源被安装,用户可以使用 kubectl 来创建和访问其中的对象,就像他们为 pods 这种内置资源所做的一样。

    定制控制器

    就定制资源本身而言,它只能用来存取结构化的数据。 当你将定制资源与 定制控制器(Custom Controller) 相结合时,定制资源就能够 提供真正的 声明式 API(Declarative API)

    使用声明式 API, 你可以 声明 或者设定你的资源的期望状态,并尝试让 Kubernetes 对象的当前状态 同步到其期望状态。控制器负责将结构化的数据解释为用户所期望状态的记录,并 持续地维护该状态。

    你可以在一个运行中的集群上部署和更新定制控制器,这类操作与集群的生命周期无关。 定制控制器可以用于任何类别的资源,不过它们与定制资源结合起来时最为有效。 就是将定制资源 与定制控制器相结合的。你可以使用定制控制器来将特定于某应用的领域知识组织 起来,以编码的形式构造对 Kubernetes API 的扩展。

    我是否应该向我的 Kubernetes 集群添加定制资源?

    在创建新的 API 时,请考虑是 还是让你的 API 独立运行。

    典型地,在声明式 API 中:

    • 你的 API 包含相对而言为数不多的、尺寸较小的对象(资源)。
    • 对象定义了应用或者基础设施的配置信息。
    • 对象更新操作频率较低。
    • 通常需要人来读取或写入对象。
    • 对象的主要操作是 CRUD 风格的(创建、读取、更新和删除)。
    • 不需要跨对象的事务支持:API 对象代表的是期望状态而非确切实际状态。

    命令式 API(Imperative API)与声明式有所不同。 以下迹象表明你的 API 可能不是声明式的:

    • 客户端发出“做这个操作”的指令,之后在该操作结束时获得同步响应。
    • 客户端发出“做这个操作”的指令,并获得一个操作 ID,之后需要检查一个 Operation(操作) 对象来判断请求是否成功完成。
    • 你会将你的 API 类比为远程过程调用(Remote Procedure Call,RPCs)。
    • 直接存储大量数据;例如每个对象几 kB,或者存储上千个对象。
    • 需要较高的访问带宽(长期保持每秒数十个请求)。
    • 存储有应用来处理的最终用户数据(如图片、个人标识信息(PII)等)或者其他大规模数据。
    • 在对象上执行的常规操作并非 CRUD 风格。
    • API 不太容易用对象来建模。
    • 你决定使用操作 ID 或者操作对象来表现悬决的操作。

    如果满足以下条件之一,应该使用 ConfigMap:

    • 存在一个已有的、文档完备的配置文件格式约定,例如 mysql.cnfpom.xml
    • 你希望将整个配置文件放到某 configMap 中的一个主键下面。
    • 文件的使用者期望以 Pod 内文件或者 Pod 内环境变量的形式来使用文件数据, 而不是通过 Kubernetes API。
    • 你希望当文件被更新时通过类似 Deployment 之类的资源完成滚动更新操作。

    说明: 请使用 Secret 来保存敏感数据。 Secret 类似于 configMap,但更为安全。

    如果以下条件中大多数都被满足,你应该使用定制资源(CRD 或者 聚合 API):

    • 你希望使用 Kubernetes 客户端库和 CLI 来创建和更改新的资源。
    • 你希望 kubectl 能够直接支持你的资源;例如,kubectl get my-object object-name
    • 你希望构造新的自动化机制,监测新对象上的更新事件,并对其他对象执行 CRUD 操作,或者监测后者更新前者。
    • 你希望编写自动化组件来处理对对象的更新。
    • 你希望使用 Kubernetes API 对诸如 、.status.metadata 等字段的约定。
    • 你希望对象是对一组受控资源的抽象,或者对其他资源的归纳提炼。

    添加定制资源

    • CRD 相对简单,创建 CRD 可以不必编程。
    • API 聚合 需要编程,但支持对 API 行为进行更多的控制,例如数据如何存储以及在不同 API 版本间如何转换等。

    Kubernetes 提供这两种选项以满足不同用户的需求,这样就既不会牺牲易用性也不会牺牲灵活性。

    聚合 API 指的是一些下位的 API 服务器,运行在主 API 服务器后面;主 API 服务器以代理的方式工作。这种组织形式称作 。 对用户而言,看起来仅仅是 Kubernetes API 被扩展了。

    CRD 允许用户创建新的资源类别同时又不必添加新的 API 服务器。 使用 CRD 时,你并不需要理解 API 聚合。

    无论以哪种方式安装定制资源,新的资源都会被当做定制资源,以便与内置的 Kubernetes 资源(如 Pods)相区分。

    CustomResourceDefinitions

    API 资源允许你定义定制资源。 定义 CRD 对象的操作会使用你所设定的名字和模式定义(Schema)创建一个新的定制资源, Kubernetes API 负责为你的定制资源提供存储和访问服务。 CRD 对象的名称必须是合法的 DNS 子域名

    CRD 使得你不必编写自己的 API 服务器来处理定制资源,不过其背后实现的通用性也意味着 你所获得的灵活性要比 少很多。

    关于如何注册新的定制资源、使用新资源类别的实例以及如何使用控制器来处理事件, 相关的例子可参见定制控制器示例

    通常,Kubernetes API 中的每个资源都需要处理 REST 请求和管理对象持久性存储的代码。 Kubernetes API 主服务器能够处理诸如 podsservices 这些内置资源,也可以 按通用的方式通过 来处理定制资源。

    聚合层(Aggregation Layer) 使得你可以通过编写和部署你自己的 API 服务器来为定制资源提供特殊的实现。 主 API 服务器将针对你要处理的定制资源的请求全部委托给你自己的 API 服务器来处理,同时将这些资源 提供给其所有客户端。

    选择添加定制资源的方法

    CRD 更为易用;聚合 API 则更为灵活。请选择最符合你的需要的方法。

    通常,如何存在以下情况,CRD 可能更合适:

    • 定制资源的字段不多;
    • 你在组织内部使用该资源或者在一个小规模的开源项目中使用该资源,而不是 在商业产品中使用。

    比较易用性

    CRD 比聚合 API 更容易创建

    公共特性

    与在 Kubernetes 平台之外实现定制资源相比, 无论是通过 CRD 还是通过聚合 API 来创建定制资源,你都会获得很多 API 特性:

    准备安装定制资源

    在向你的集群添加定制资源之前,有些事情需要搞清楚。

    尽管添加新的 CRD 不会自动带来新的失效点(Point of Failure),例如导致第三方代码被在 API 服务器上运行, 类似 Helm Charts 这种软件包或者其他安装包通常在提供 CRD 的同时还包含带有第三方 代码的 Deployment,负责实现新的定制资源的业务逻辑。

    安装聚合 API 服务器时,也总会牵涉到运行一个新的 Deployment。

    存储

    定制资源和 ConfigMap 一样也会消耗存储空间。创建过多的定制资源可能会导致 API 服务器上的存储空间超载。

    聚合 API 服务器可以使用主 API 服务器的同一存储。如果是这样,你也要注意 此警告。

    CRD 通常与 API 服务器上的内置资源一样使用相同的身份认证、鉴权授权 和审计日志机制。

    如果你使用 RBAC 来执行鉴权授权,大多数 RBAC 角色都会授权对新资源的访问 (除了 cluster-admin 角色以及使用通配符规则创建的其他角色)。 你要显式地为新资源的访问授权。CRD 和聚合 API 通常在交付时会包含 针对所添加的类别的新的角色定义。

    聚合 API 服务器可能会使用主 API 服务器相同的身份认证、鉴权授权和审计 机制,也可能不会。

    Kubernetes 客户端库可用来访问定制资源。 并非所有客户端库都支持定制资源。GoPython 客户端库是支持的。

    当你添加了新的定制资源后,可以用如下方式之一访问它们:

    • Kubernetes 动态客户端
    • 你所编写的 REST 客户端
    • 使用 所生成的客户端。生成客户端的工作有些难度,不过某些项目可能会随着 CRD 或 聚合 API 一起提供一个客户端

    接下来

    • 了解如何