https://kubernetes.io/zh/docs/concepts/extend-kubernetes/api-extension/custom-resources/

https://staight.github.io/2019/10/08/Kubernetes-CRD%E7%AE%80%E4%BB%8B/

Kubernetes 提供了两种方式供你向集群中添加定制资源:
  • CRD 相对简单,创建 CRD 可以不必编程。
  • API 聚合 需要编程,但支持对 API 行为进行更多的控制,例如数据如何存储以及在不同 API 版本间如何转换等。

1、CRD概述

CRD的全称为CustomResourceDefinitions,即自定义资源。k8s拥有一些内置的资源,比如说Pod,Deployment,ReplicaSet等等,而CRD则提供了一种方式,使用户可以自定义新的资源,以扩展k8s的功能。 使用CRD可以在不修改k8s源代码的基础上方便的扩展k8s的功能,比如腾讯云TKE使用CRD:logcollectors.ccs.cloud.tencent.com以添加日志收集服务,而Istio也大量使用到了CRD。 值得一提的是,另一种扩展k8s的方式是apiservice,通过API:metrics.k8s.io自定义HPA是其最典型的应用。

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

CRD 使得你不必编写自己的 API 服务器来处理定制资源,不过其背后实现的通用性也意味着 你所获得的灵活性要比 API 服务器聚合少很多。 可以使用kubectl api-resources命令查看集群中已定义的资源:
  1. kubectl api-resources
从如上输出中可以略窥一二,CRD至少包括如下属性:
  • NAME:CRD的复数名称
  • SHORTNAMES:cli中使用的资源简称
  • APIGROUP:API所使用的组名称
  • NAMESPACED:是否具有namespace属性
  • KIND:资源文件需要,用以识别资源
另外,CRD提供了定义资源的方式,不过想要让其具有实际意义还需控制器的配合。k8s的kube-controller-manager组件提供了多种内置控制器,比如说:cronjobdaemonsetdeploymentnamespace等等,它们监听资源的创建/更新/删除,且做出相应的动作。而对于CRD来说,也可以编写相应的控制器来完成对应的功能。
  1. # crd-test.yml
  2. apiVersion: apiextensions.k8s.io/v1beta1
  3. kind: CustomResourceDefinition
  4. metadata:
  5. # 名称必须符合如下格式:<plural>.<group>
  6. name: crontabs.staight.k8s.io
  7. spec:
  8. # 组名,表示使用该API: /apis/<group>/<version>
  9. group: staight.k8s.io
  10. # version列表,表示该CRD支持的版本
  11. versions:
  12. - name: v1
  13. # 开启/关闭该API
  14. served: true
  15. # 有且只能有一个版本要将storage设置为true
  16. storage: true
  17. # Namespaced/Cluster,表示该CRD是命名空间属性还是集群属性
  18. scope: Namespaced
  19. names:
  20. # API中使用的名称:/apis/<group>/<version>/<plural>
  21. plural: crontabs
  22. # 单数名称,cli中使用
  23. singular: crontab
  24. # 往往是首字母大写的单数名称,资源文件中需要用到
  25. kind: CronTab
  26. # cli中的简称
  27. shortNames:
  28. - ct
  29. # 阻止无法识别的字段,集群版本1.15以上才可使用
  30. preserveUnknownFields: false
  31. # 创建资源文件时需验证的字段
  32. validation:
  33. openAPIV3Schema:
  34. type: object
  35. properties:
  36. spec:
  37. type: object
  38. properties:
  39. cronSpec:
  40. type: string
  41. image:
  42. type: string
  43. replicas:
  44. type: integer

1.1 使用前提

在k8s中CRD本身也是资源,大于1.7.0版本的集群可以使用piextensions.k8s.io/v1beta1API访问CRD,大于1.16.0版本则可以使用apiextensions.k8s.io/v1API。

1.2 创建CRD实例

  1. # crd-test.yml
  2. apiVersion: apiextensions.k8s.io/v1
  3. kind: CustomResourceDefinition
  4. metadata:
  5. # 名称必须符合如下格式:<plural>.<group>
  6. name: crontabs.samplecontroller.k8s.io
  7. annotations:
  8. "api-approved.kubernetes.io": "unapproved, experimental-only; please get an approval from Kubernetes API reviewers if you're trying to develop a CRD in the *.k8s.io or *.kubernetes.io groups"
  9. spec:
  10. group: samplecontroller.k8s.io
  11. names:
  12. kind: Crontab # 往往是首字母大写的单数名称,资源文件中需要用到
  13. plural: crontabs # API中使用的名称:/apis/<group>/<version>/<plural>
  14. singular: crontab # 单数名称,cli中使用
  15. shortNames: # cli中的简称
  16. - ct
  17. scope: Namespaced # Namespaced/Cluster,表示该CRD是命令空间属性还是集群属性
  18. # version列表,表示该CRD支持的版本
  19. preserveUnknownFields: false # 阻止无法识别的字段,集群版本1.15以上才可使用
  20. versions:
  21. - name: v1alpha1
  22. served: true # 开启/关闭该API
  23. storage: true # 有且只能有一个版本要将storage设置为true
  24. # 创建资源文件时需验证的字段
  25. schema:
  26. openAPIV3Schema:
  27. type: object
  28. properties:
  29. spec:
  30. type: object
  31. properties:
  32. cronSpec:
  33. type: string
  34. image:
  35. type: string
  36. replicas:
  37. type: integer
  1. kubectl create -f crd-test.yaml
  2. customresourcedefinition.apiextensions.k8s.io/crontabs.samplecontroller.k8s.io created
CRD创建完成。可以通过URL:https://IP:6443/apis/crontabs.samplecontroller.k8s.io/v1/namespaces/default/crontabs访问到crontab资源。

1.3 查看创建的CRD

  1. kubectl get crd crontabs.samplecontroller.k8s.io
  2. NAME CREATED AT
  3. crontabs.samplecontroller.k8s.io 2021-12-30T01:50:50Z

1.4 创建自定义资源对象

在创建CRD之后,即可创建其资源的对象了。资源文件示例:
  1. # crontab.yml
  2. apiVersion: "samplecontroller.k8s.io/v1alpha1"
  3. kind: CronTab
  4. metadata:
  5. name: new-crontab
  6. namespace: default
  7. spec:
  8. cronSpec: "* * * * *"
  9. image: new-image
注意spec中的字段应符合CRD的要求,创建它:
  1. kubectl create -f crontab.yaml
  2. crontab.samplecontroller.k8s.io/new-crontab created
接着即可看到该对象:
  1. kubectl get ct
  2. NAME AGE
  3. new-crontab 6s

2、API 服务聚合

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

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