本文是 Kubernetes operator学习 系列第二篇,主要对 CRD 进行学习
1.CRD介绍
1.1.如何使用
在K8S系统扩展点中,开发者可以通过CRD(CustomResourceDefinition)来扩展K8S API,其功能主要由APIExtensionServer负责。使用CRD扩展资源分为三步:
- 注册自定义资源:开发者需要通过K8S提供的方式注册自定义资源,即通过CRD进行注册,注册之后,K8S就知道我们自定义资源的存在了,然后我们就可以像使用K8S内置资源一样使用自定义资源(CR)
- 使用自定义资源:像内置资源比如Pod一样声明资源,使用CR声明我们的资源信息
- 删除自定义资源:当我们不再需要时,可以删除自定义资源
1.2.如何注册自定义资源
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
1.3.使用自定义资源
-
待CRD创建完成之后,我们就可以使用它来创建我们的自定义资源了
-
其创建方式跟内置的资源如Pod这些是一样的,只是需要将
kind
、apiVersion
指定为我们CRD中声明的值 -
比如使用上面例子中的CRD定义资源:
apiVersion: "demos.example.com/v1" kind: Demo metadata: name: crd-demo spec: name: test
1.4.Finalizers
-
Finalizer 能够让控制器实现 异步 的删除前(Pre-delete)回调,优雅的删除 资源
- 我们创建的自定义资源对象,finalizers不为空,那么在资源对象被删除之前,会阻塞住,同时往这个资源中添加一个字段:
- 我们的自定义Controller检测到deletionTimestamp后,就知道资源即将被删除,进行一些回收操作,结束后清空资源的finalizers值,删除操作就会被唤醒,自定义资源对象才会被删除
- 我们创建的自定义资源对象,finalizers不为空,那么在资源对象被删除之前,会阻塞住,同时往这个资源中添加一个字段:
-
与内置对象类似,定制对象也支持 Finalizer
apiVersion: "example.com/v1" kind: Demo metadata: finalizers: - example.com/finalizer
1.5.合法性验证
-
比如:我们指定 自定义资源CR的 name,必须以test开头
-
那么如果创建一个name不以test开头的CR,就会报错
1.6.附加字段
-
在kubectl get cr的时候,打印的字段值。默认只打印:.metadata.name、age
-
其实还可以添加额外字段,打印别的信息,设置的是
spec.versions.additionalPrinterColumns
versions: additionalPrinterColumns: - name: Name type: string description: The name of resource jsonPath: .spec.name
-
如:我想把.spec.name打印出来,就添加一个additionalPrinterColumns项
1.7.子资源
- 默认情况下,自定义资源,输出yaml的时候,没有status,不可以被kubectl scale 命令操作,也无法被HPA等控制器自动伸缩
- kubernetes 的 CRD,提供了对status和scale子资源的支持
spec:
versions:
subresources:
# status 加上这句,就是启用了 status 子资源,获取的yaml中就会输出status了。而且url访问也可以使用/.../status
status: {}
# scale 启用 scale 子资源,可以使用kubectl scale 命令伸缩,也可以被HPA等控制器自动伸缩
scale:
# specReplicasPath 定义定制资源中对应 scale.spec.replicas 的 JSON 路径
specReplicasPath: .spec.replicas
1.8.设置默认值
- 使用default,可以给某些字段,设置默认值
versions: - schema: openAPIV3Schema: type: Object properties: spec: type: Object properties: name: type: string default: "demo"
1.9.多版本
- version是一个数组,可以定义多个
- 一般我们会先有一个alpha版本,然后一个beta版本,然后再是v1…
- Webhook实现不同版本之间的值的转换
...
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"
1.10.删除自定义资源
当我们不再需要时,可以像删除其他资源一样,删除我们的自定义资源。