k8s

k8s CRD详解

简介

k8s中的 CRD(Custom Resource Definition)是一种强大的功能,允许用户通过定义自己的资源来扩展 k8s API。这意味着用户可以创建自定义的资源类型,这些资源类型与 k8s 内置的资源(如 Pods、Deployments 等)具有相同的 API 风格。CRD 为 k8s 生态系统的扩展和自定义提供了极大的灵活性。

  • 自定义资源(Custom Resource):用户定义的资源类型,可以通过 k8s API 进行管理。自定义资源的实例被 k8s 存储在 etcd 中,并可以通过 k8s API 访问。
  • 自定义资源定义(Custom Resource Definition):定义自定义资源的 YAML 文件。它告诉 k8s 如何理解这个新资源的结构,包括资源的名称、版本、字段等。

官方文档:https://kubernetes.io/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources/

创建CRD

官方文档:https://kubernetes.io/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/

即编写一个 CRD 定义文件,k8s API 服务器会为你所指定的每个版本生成一个新的 RESTful 资源路径。 基于 CRD 对象所创建的自定义资源可以是 namespace 作用域的,也可以是集群作用域的, 取决于 CRD 对象 spec.scope 字段的设置。

与其它的内置对象一样,删除名字空间也将删除该名字空间中的所有自定义对象。 CRD 本身是无 namespace 的,可在所有 namespace 中访问。

下面是一个crontab CRD示例的yaml文件:

cat crd.yaml

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  # 名字必需与下面的 spec 字段匹配,格式为 <plural>.<group>
  name: crontabs.stable.example.com
spec:
  # 组名称,用于 REST API:  /apis/<group>/<version>
  group: stable.example.com
  # 列举此 CustomResourceDefinition 所支持的版本
  versions:
    - name: v1
      # 每个版本都可以通过 served 服务标志启用/禁用
      served: true
      # 有且仅有一个版本被标记为存储版本。
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                image:
                  type: string
                replicas:
                  type: integer
  # 可以是 Namespaced 或 Cluster
  scope: Namespaced
  names:
    # URL中使用的复数名称: /apis/<group>/<version>/<plural>
    plural: crontabs
    # 名称的单数形式,作为命令行使用时和显示时的别名
    singular: crontab
    # kind 通常是单数形式的驼峰命名(CamelCased)形式。你的资源清单会使用这一形式。
    kind: CronTab
    # shortNames 允许你在命令行使用较短的字符串来匹配资源
    shortNames:
    - ct
k apply -f crd.yaml

这样一个新的受namespace约束的 RESTful API 端点会被创建在:/apis/stable.example.com/v1/namespaces/*/crontabs/...,此端点 URL 自此可以用来创建和管理定制对象。对象的 kind 将是来自你上面创建时 所用的 spec 中指定的 CronTab。

查看CRD

k get crontab/ct

file

创建自定义对象

在创建了 CRD 对象之后,你可以创建自定义对象(Custom Objects)。自定义对象可以包含自定义字段。这些字段可以包含任意的 JSON 数据。

cat my-crontab.yaml

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image
k apply -f my-crontab.yaml
k get ct

file

删除CRD

k delete -f crd.yaml
k get ct

file

设置结构化模式

CRD 对象在定制字段中保存结构化的数据,这些字段和内置的字段 apiVersion、kind 和 metadata 等一起存储,不过内置的字段都会被 API 服务器隐式完成合法性检查。有了 OpenAPI v3.0 检查 能力之后,你可以设置一个模式(Schema),在创建和更新定制对象时,这一模式会被用来对对象内容进行合法性检查。

在 apiextensions.k8s.io/v1 版本中,CustomResourceDefinition 的这一结构化模式 定义是必需的。 在 CustomResourceDefinition 的 beta 版本中,结构化模式定义是可选的。

结构化模式本身是一个 OpenAPI v3.0 验证模式,其中:

  1. 为对象根(root)设置一个非空的 type 值(藉由 OpenAPI 中的 type),对每个 object 节点的每个字段(藉由 OpenAPI 中的 properties 或 additionalProperties)以及 array 节点的每个条目(藉由 OpenAPI 中的 items)也要设置非空的 type 值, 除非:
    • 节点包含属性 x-kubernetes-int-or-string: true
    • 节点包含属性 x-kubernetes-preserve-unknown-fields: true
  2. 对于 object 的每个字段或 array 中的每个条目,如果其定义中包含 allOf、anyOf、oneOf 或 not,则模式也要指定这些逻辑组合之外的字段或条目(试比较例 1 和例 2)。
  3. 在 allOf、anyOf、oneOf 或 not 上下文内不设置 description、type、default、 additionalProperties 或者 nullable。此规则的例外是 x-kubernetes-int-or-string 的两种模式。
  4. 如果 metadata 被设置,则只允许对 metadata.namemetadata.generateName 设置约束。

如果违反了结构化模式规则,CRD 的 NonStructural 状况中会包含报告信息。

字段剪裁

CRD 在 etcd 中保存经过合法性检查的资源数据。如果你指定了 API 服务器所无法识别的字段,则该未知字段会在保存资源之前被 剪裁(Pruned) 掉(删除)。

--validate=false 命令行选项可以关闭客户端的合法性检查以展示 API 服务器的行为, 因为 OpenAPI 合法性检查模式也会发布到 客户端,kubectl 也会检查未知的字段并在对象被发送到 API 服务器之前就拒绝它们。

控制剪裁

默认情况下,定制资源的所有版本中的所有未规定的字段都会被剪裁掉。 通过在结构化的 OpenAPI v3 检查模式定义中为特定字段的子树添加 x-kubernetes-preserve-unknown-fields: true 属性, 可以选择不对其执行剪裁操作。

type: object
properties:
  json:
    x-kubernetes-preserve-unknown-fields: true

字段 json 可以保存任何 JSON 值,其中内容不会被剪裁掉。你也可以部分地指定允许的 JSON 数据格式通过这样设置,JSON 中只能设置 object 类型的值。对于所指定的每个属性(或 additionalProperties),剪裁会再次被启用。

RawExtension

RawExtensions(就像在 k8s.io/apimachinery 项目中 runtime.RawExtension 所定义的那样) 可以保存完整的 Kubernetes 对象,也就是,其中会包含 apiVersion 和 kind 字段。

设置了 x-kubernetes-embedded-resource: true 之后,apiVersion、kind 和 metadata 都是隐式设定并隐式完成合法性验证。

Finalizers

Finalizer 能够让控制器实现异步的删除前(Pre-delete)回调。 与内置对象类似,定制对象也支持 Finalizer。

你可以像下面一样为定制对象添加 Finalizer:

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  finalizers:
  - stable.example.com/finalizer

自定义 Finalizer 的标识符包含一个域名、一个正向斜线和 finalizer 的名称。 任何控制器都可以在任何对象的 finalizer 列表中添加新的 finalizer。删除逻辑和其他资源一样。

合法性检查

定制资源是通过 OpenAPI v3 模式定义 来执行合法性检查的,当启用验证规则特性时,通过 x-kubernetes-validations 验证, 你可以通过使用准入控制 Webhook 来添加额外的合法性检查逻辑。

此外,对模式定义存在以下限制:

  • definitions,dependencies,deprecated,discriminator,id,patternProperties,readOnly,writeOnly,xml,$ref 字段不可设置
  • 字段 uniqueItems 不可设置为 true
  • 字段 additionalProperties 不可设置为 false
  • 字段 additionalProperties 与 properties 互斥,不可同时使用

当验证规则特性被启用并且 CustomResourceDefinition 模式是一个结构化的模式定义时, x-kubernetes-validations 扩展可以使用通用表达式语言 (CEL)表达式来验证定制资源。

也可以通过修改apiserver的配置来关闭检查。--feature-gates=CustomResourceValidationExpressions=false

file

在下面的例子中, CRD 对定制对象的spec.cronSpecspec.replicas字段执行合法性检查:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.stable.example.com
spec:
  group: stable.example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        # openAPIV3Schema 是验证自定义对象的模式。
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                  pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
                image:
                  type: string
                replicas:
                  type: integer
                  minimum: 1
                  maximum: 10
  scope: Namespaced
  names:
    plural: crontabs
    singular: crontab
    kind: CronTab
    shortNames:
    - ct

修改my-crontab.yaml,并创建,会提示对象无效。

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * *"
  image: my-awesome-cron-image
  replicas: 15

修改为合法的yaml,创建成功。

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image
  replicas: 5

file

添加额外的打印列

kubectl 工具依赖服务器端的输出格式化。你的集群的 API 服务器决定 kubectl get 命令要显示的列有哪些。 你可以为 CRD 定制这些要打印的列。 下面的例子添加了 Spec、Replicas 和 Age 列:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.stable.example.com
spec:
  group: stable.example.com
  scope: Namespaced
  names:
    plural: crontabs
    singular: crontab
    kind: CronTab
    shortNames:
    - ct
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              cronSpec:
                type: string
              image:
                type: string
              replicas:
                type: integer
    additionalPrinterColumns:
    - name: Spec
      type: string
      description: The cron spec defining the interval a CronJob is run
      jsonPath: .spec.cronSpec
    - name: Replicas
      type: integer
      description: The number of jobs launched by the CronJob
      jsonPath: .spec.replicas
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp

输出中包含了 NAME、SPEC、REPLICAS 和 AGE 列。

file

子资源

定制资源支持 /status/scale 子资源。通过在 CRD 中定义 status 和 scale, 可以有选择地启用这些子资源。下面的例子同时启用了两者。

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.stable.example.com
spec:
  group: stable.example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                image:
                  type: string
                replicas:
                  type: integer
            status:
              type: object
              properties:
                replicas:
                  type: integer
                labelSelector:
                  type: string
      # subresources 描述定制资源的子资源
      subresources:
        # status 启用 status 子资源
        status: {}
        # scale 启用 scale 子资源
        scale:
          # specReplicasPath 定义定制资源中对应 scale.spec.replicas 的 JSON 路径
          specReplicasPath: .spec.replicas
          # statusReplicasPath 定义定制资源中对应 scale.status.replicas 的 JSON 路径 
          statusReplicasPath: .status.replicas
          # labelSelectorPath  定义定制资源中对应 scale.status.selector 的 JSON 路径 
          labelSelectorPath: .status.labelSelector
  scope: Namespaced
  names:
    plural: crontabs
    singular: crontab
    kind: CronTab
    shortNames:
    - ct

再使用下面的yaml创建自定义对象。

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image
  replicas: 3

然后会创建新的、命名空间作用域的 RESTful API 端点:/apis/stable.example.com/v1/namespaces/*/crontabs/status/apis/stable.example.com/v1/namespaces/*/crontabs/scale

定制资源可以使用 kubectl scale 命令来扩缩其规模。

kubectl scale --replicas=5 crontabs/my-new-cron-object
kubectl get crontabs my-new-cron-object -o jsonpath='{.spec.replicas}'
=

file

分类

分类(Categories)是定制资源所归属的分组资源列表(例如,all)。 你可以使用 kubectl get <分类名称> 来列举属于某分类的所有资源。

下面的示例在 CRD 中将 ctab 添加到分类列表中, 并展示了如何使用 kubectl get ctab 来输出定制资源:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.stable.example.com
spec:
  group: stable.example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                image:
                  type: string
                replicas:
                  type: integer
  scope: Namespaced
  names:
    plural: crontabs
    singular: crontab
    kind: CronTab
    shortNames:
    - ct
    # categories 是定制资源所归属的分类资源列表
    categories:
    - ctab

file

分类: k8s
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部
0
希望看到您的想法,请您发表评论x