1.介绍

Kubernetes提供了CRD(CustomResourceDefinitions)自定义资源的功能,同样可以根据group+version进行资源管理。
CRD本质上只是用来存储结构化的数据,配合自定义的Controller,基本上可以实现对基于K8S功能的任意扩展。只有配合Controller才能实现对CRD中state的响应与处理。
本文介绍CRD的用法,以及使用kubectl如何进行控制。使用的是Kubernetes 1.10版本。

2.说明以及示例

a.CRD定义文件

下面是一个CRD定义文件示例resourcedefinition.yaml。里面对各项进行了简单说明

  1. # apiVersion+kind唯一定位到k8s中一种类型。
  2. apiVersion: apiextensions.k8s.io/v1beta1
  3. kind: CustomResourceDefinition
  4. metadata:
  5. # 必须匹配格式 <plural>.<group>
  6. name: crontabs.stable.huanxin.com
  7. spec:
  8. # group与version名用于REST API: /apis/<group>/<version>
  9. group: stable.huanxin.com
  10. version: v1
  11. # 可取值Namespaced 或者 Cluster
  12. scope: Namespaced
  13. names:
  14. # 用在/apis/<group>/<version>/<plural>中的复数形式<plural>
  15. plural: crontabs
  16. # 单数形式用作CLI以及展示
  17. singular: crontab
  18. # Kind表示定义的CRD的类型名,驼峰式的,resource manifests会使用这个名字。
  19. kind: CronTab
  20. # 缩写。这里ct就能表示crontabs.stable.huanxin.com
  21. shortNames:
  22. - ct

b.创建CRD定义

# kubectl create -f resourcedefinition.yaml
customresourcedefinition.apiextensions.k8s.io/crontabs.stable.huanxin.com created`        `

这样对应的api访问路径为
/apis/stable.huanxin.com/v1/namespaces/*/crontabs/
此路径可以用来创建与管理自定义对象,这些对象创建的使用指定kind为CronTab即可。

注: CRD定义里面并没有说明此CRD里面的定义细节,有哪些Label,哪些Spec项等。相当于只是定义好了group+version+kind,后续具体结构如何,完全自行定义,只要对应的controller能够相应处理接口。

c.创建CRD对象

对象配置文件crontab1.yaml

apiVersion: "stable.huanxin.com/v1"
kind: CronTab
metadata:
  name: crontab1
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image

然后执行命令

# kubectl create -f crontab1.yaml
crontab.stable.huanxin.com/crontab1 created

# kubectl get crontabs.stable.huanxin.com
NAME       CREATED AT
crontab1   37s

注意:CRD对象只是一份数据而已,并未创建其他实体。

d.删除CRD对象

# kubectl delete crontabs crontab1
crontab.stable.huanxin.com "crontab1" deleted

e.删除CRD定义

# kubectl delete -f resourcedefinition.yaml
customresourcedefinition.apiextensions.k8s.io "crontabs.stable.huanxin.com" deleted
# kubectl get crontabs
No resources found.
Error from server (NotFound): Unable to list {"stable.huanxin.com" "v1" "crontabs"}: the server could not find the requested resource (get crontabs.stable.huanxin.com)

可以看到crontabs已经没有对象也没有定义了。
不过有个疑惑,平台怎么知道crontabs找的是{“stable.huanxin.com” “v1” “crontabs”}?

3.其他用法

a.Finalizers

Finalizers允许实现一个异步的pre-delete hook。例如
编辑crontab1对象,加上

# kubectl edit crontabs crontab1 -o json
...
metadata:
  finalizers:  //下面是任意字符串列表,用于便于controller进行控制
  - finalizer.stable.huanxin.com 
...

这样的对象,如果要删除,会分成两个步骤:

  • 步骤1)发起delete,对应对象仅仅是设置了一个metadata.deletionTimestamp属性,而没有真正删除。
(session1)# kubectl delete crontabs crontab1
crontab.stable.huanxin.com "crontab1" deleted
..<卡住等待>

这时候另起一个shell可以查到对象信息

(session2)# kubectl describe ct
Name:         crontab1
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  stable.huanxin.com/v1
Kind:         CronTab
Metadata:
  Cluster Name:
  Creation Timestamp:             2018-11-30T07:23:55Z
  Deletion Grace Period Seconds:  0
  Deletion Timestamp:             2018-11-30T07:29:28Z
  Finalizers:
    finalizer.stable.huanxin.com
  Generation:        2
  Resource Version:  28542
  Self Link:         /apis/stable.huanxin.com/v1/namespaces/default/crontabs/crontab1
  UID:               e5844d5d-f470-11e8-bac7-02420ba6b342
Spec:
  Cron Spec:  * * * * */5
  Image:      my-awesome-cron-image
Events:       <none>
  • 步骤2)上一个步骤触发watch的controller做动作,做完动作后清理掉“finalizers:”下的字符串。
# kubectl edit crontabs crontab1 -o json
<删除掉 finalizer.stable.huanxin.com 这一行>

保存后步骤1)中(session1)中动作结束,完成了删除动作。
注: 如果finalizers中指定了多个字符串,则会等所有字符串都处理完才真正删除对象。(以polling update requests 的方式通知多个controller处理?)

b.Validation

CRD对象创建时对属性进行约束,例如spec下增加

validation:
   # openAPIV3Schema is the schema for validating custom objects.
    openAPIV3Schema:
      properties:
        spec:
          properties:
            cronSpec:
              type: string
              pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
            replicas:
              type: integer
              minimum: 1
              maximum: 10

测试:

# cat crontab2.yaml
apiVersion: "stable.huanxin.com/v1"
kind: CronTab
metadata:
  name: crontab2
spec:
  cronSpec: "* *  * */5"
  image: my-awesome-cron-image

# kubectl create -f crontab2.yaml
The CronTab "crontab2" is invalid: []: Invalid value: map[string]interface {}{"spec":map[string]interface {}{"image":"my-awesome-cron-image", "cronSpec":"* *  * */5"}, "apiVersion":"stable.huanxin.com/v1", "kind":"CronTab", "metadata":map[string]interface {}{"selfLink":"", "clusterName":"", "name":"crontab2", "namespace":"default", "generation":1, "creationTimestamp":"2018-11-30T07:55:47Z", "uid":"592cfb95-f475-11e8-bac7-02420ba6b342"}}: validation failure list:
spec.cronSpec in body should match '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'

报错是符合预期的。

c.Subresources

CRD自定义资源支持/status/scale这些子资源,这块还处于alpha,后续发展可能不兼容,暂不介绍,有需要看文档。

关于CRD与自定义Controller,后续再做介绍。

参考