如何使用

在K8S系统扩展点中,开发者可以通过CRD(CustomResourceDefinition)来扩展K8S API,其功能主要由APIExtensionServer负责。使用CRD扩展资源分为三步:

  • 注册自定义资源:开发者需要通过K8S提供的方式注册自定义资源,即通过CRD进行注册,注册之后,K8S就知道我们自定义资源的存在了,然后我们就可以像使用K8S内置资源一样使用自定义资源(CR)
  • 使用自定义资源:像内置资源比如Pod一样声明资源,使用CR声明我们的资源信息
  • 删除自定义资源:当我们不再需要时,可以删除自定义资源

如何注册自定义资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# 强制规定:名字必须与下面的 spec 字段匹配,并且格式为 '<名称的复数形式>.<组名>'
name: demos.example.com
spec:
# 组名称,用于 REST API: /apis/<组>/<版本>
group: example.com
names:
# 名称的复数形式,用于 URL:/apis/<组>/<版本>/<名称的复数形式>
plural: demos
# 名称的单数形式,作为命令行使用时和显示时的别名
singular: demo
# kind 通常是单数形式的帕斯卡编码(PascalCased)形式。你的资源清单会使用这一形式。
kind: Demo
# shortNames 允许你在命令行使用较短的字符串来匹配资源
shortNames:
- dm
# 可以是 Namespaced命名空间范围内使用 或 Cluster集群范围内使用
scope: Namespaced
# 列举此 CustomResourceDefinition 所支持的版本,可以在不破坏现有客户端的情况下,对CRD定义的资源进行演进和升级
versions:
- name: v1
# 每个版本都可以通过 served 标志来独立启用或禁止,指示该版本的资源是否应该由API服务器提供服务
served: true
# 其中一个且只有一个版本必需被标记为存储版本(指示该版本的资源是否应该存储在etcd中)
storage: true
# 一个OpenAPI v3模式对象,用于定义该版本的资源的结构。该模式对象描述了该版本的资源的属性、类型和验证规则等信息
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
name:
type: string

使用自定义资源

  • 待CRD创建完成之后,我们就可以使用它来创建我们的自定义资源了

  • 其创建方式跟内置的资源如Pod这些是一样的,只是需要将kind、apiVersion指定为我们CRD中声明的值

  • 比如使用上面例子中的CRD定义资源:

    1
    2
    3
    4
    5
    6
    apiVersion: "demos.example.com/v1"
    kind: Demo
    metadata:
    name: crd-demo
    spec:
    name: test

Finalizers

  • Finalizer 能够让控制器实现 异步 的删除前(Pre-delete)回调,优雅的删除 资源

    • 我们创建的自定义资源对象,finalizers不为空,那么在资源对象被删除之前,会阻塞住,同时往这个资源中添加一个字段:
    • 我们的自定义Controller检测到deletionTimestamp后,就知道资源即将被删除,进行一些回收操作,结束后清空资源的finalizers值,删除操作就会被唤醒,自定义资源对象才会被删除
  • 与内置对象类似,定制对象也支持 Finalizer

    1
    2
    3
    4
    5
    apiVersion: "example.com/v1"
    kind: Demo
    metadata:
    finalizers:
    - example.com/finalizer

合法性验证

  • 比如:我们指定 自定义资源CR的 name,必须以test开头
  • 那么如果创建一个name不以test开头的CR,就会报错

附加字段

  • 在kubectl get cr的时候,打印的字段值。默认只打印:.metadata.name、age

  • 其实还可以添加额外字段,打印别的信息,设置的是 spec.versions.additionalPrinterColumns

    1
    2
    3
    4
    5
    6
    versions:
    additionalPrinterColumns:
    - name: Name
    type: string
    description: The name of resource
    jsonPath: .spec.name
  • 如:我想把.spec.name打印出来,就添加一个additionalPrinterColumns项

子资源

  • 默认情况下,自定义资源,输出yaml的时候,没有status,不可以被kubectl scale 命令操作,也无法被HPA等控制器自动伸缩
  • kubernetes 的 CRD,提供了对status和scale子资源的支持
    1
    2
    3
    4
    5
    6
    7
    8
    9
    spec:
    versions:
    subresources:
    # status 加上这句,就是启用了 status 子资源,获取的yaml中就会输出status了。而且url访问也可以使用/.../status
    status: {}
    # scale 启用 scale 子资源,可以使用kubectl scale 命令伸缩,也可以被HPA等控制器自动伸缩
    scale:
    # specReplicasPath 定义定制资源中对应 scale.spec.replicas 的 JSON 路径
    specReplicasPath: .spec.replicas

设置默认值

  • 使用default,可以给某些字段,设置默认值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    versions:
    - schema:
    openAPIV3Schema:
    type: Object
    properties:
    spec:
    type: Object
    properties:
    name:
    type: string
    default: "demo"

多版本

  • version是一个数组,可以定义多个
    • 一般我们会先有一个alpha版本,然后一个beta版本,然后再是v1…
    • Webhook实现不同版本之间的值的转换
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      ...
      versions:
      ...
      conversion:
      strategy: Webhook
      webhook:
      conversionReviewVersions: ["v1","v1beta1"]
      clientConfig:
      service:
      namespace: default
      name: example-conversion-webhook-server
      path: /crdconvert
      caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"

删除自定义资源

当我们不再需要时,可以像删除其他资源一样,删除我们的自定义资源。