K8s-CRD 实战

举报
kaliarch 发表于 2022/04/04 20:18:12 2022/04/04
【摘要】 一 概述 1.1 CRD简介Custom resources:是对K8S API的扩展,代表了一个特定的kubetnetes的定制化安装。在一个运行中的集群中,自定义资源可以动态注册到集群中。注册完毕以后,用户可以通过kubelet创建和访问这个自定义的对象,类似于操作pod一样。Custom controllers:Custom resources可以让用户简单的存储和获取结构化数据。只...

一 概述

1.1 CRD简介

Custom resources:是对K8S API的扩展,代表了一个特定的kubetnetes的定制化安装。在一个运行中的集群中,自定义资源可以动态注册到集群中。注册完毕以后,用户可以通过kubelet创建和访问这个自定义的对象,类似于操作pod一样。

Custom controllers:Custom resources可以让用户简单的存储和获取结构化数据。只有结合控制器才能变成一个真正的declarative API(被声明过的API)。控制器可以把资源更新成用户想要的状态,并且通过一系列操作维护和变更状态。定制化控制器是用户可以在运行中的集群内部署和更新的一个控制器,它独立于集群本身的生命周期。
定制化控制器可以和任何一种资源一起工作,当和定制化资源结合使用时尤其有效。

Operator模式 是一个customer controllers和Custom resources结合的例子。它可以允许开发者将特殊应用编码至kubernetes的扩展API内。

1.2 使用场景

其实crd在很多k8s周边开源项目中有使用,比如ingress-controller 、istio 、hpa和众多的operator。

如何添加一个Custom resources到我的kubernetes集群呢? kubernetes提供了两种方式将Custom resources添加到集群。

Custom Resource Definitions (CRDs):更易用、不需要编码。但是缺乏灵活性。
API Aggregation:需要编码,允许通过聚合层的方式提供更加定制化的实现。
本文重点讲解Custom Resource Definitions (CRD)的使用方法。

1.3 通俗讲解

  • 在k8s中,所有的东西都叫做资源(Resource), 也就是yaml中Kind字段
  • 除过K8s集群中常见的deployment这些资源外,kube允许用户自定义资源(Custom Resource),也就CR
  • CRD 其实并不是自定义资源,而是我们自定义资源的定义(来描述我们定义的资源是什么样子)
  • 对于一个CRD来讲,其本质就是一个 Open Api 的 schema,无论是k8s自由资源,还是用户自定义资源,都需要yaml来描述,但是如果保障yaml的规范性和合法性,就是schema来做,就是想集群注册一种新资源,并告知 ApiServer,这种资源怎么怎么被合法的定义。

二 架构

2.1 架构图

2.2 架构详解

当您创建一个新的 CustomResourceDefinition (CRD)时,Kubernetes API Server 将为您指定的每个版本创建一个新的 RESTful 资源路径。CRD 可以是命名空间的,也可以是集群范围的,这在 CRD 的范围字段中指定了。与现有的内置对象一样,删除名称空间将删除该名称空间中的所有自定义对象。Customresourcedefinition 本身是非命名空间的,对所有命名空间都可用。

三 实战

3.1 环境

3.2 自定义资源

3.2.1 crontabl_crd.yaml

  • 内容
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # 称必须与下面的spec字段匹配,格式为: <plural>.<group>
  name: crontabs.crd.test.com
spec:
  # 用于REST API的组名称: /apis/<group>/<version>
  group: crd.test.com
  versions:
  - name: v1
    # 每个版本都可以通过服务标志启用/禁用。
    served: true
    # 必须将一个且只有一个版本标记为存储版本。
    storage: true
  scope: Namespaced  # 指定crd资源作用范围在命名空间或集群
  names:
    # URL中使用的复数名称: /apis/<group>/<version>/<plural>
    plural: crontabs
    # 在CLI(shell界面输入的参数)上用作别名并用于显示的单数名称
    singular: crontab
    kind: CronTab
    # 短名称允许短字符串匹配CLI上的资源,意识就是能通过kubectl 在查看资源的时候使用该资源的简名称来获取。
    shortNames:
    - ct
  • 部署crd
[root@master concrd]# kubectl apply -f crontab_crd.yaml 
customresourcedefinition.apiextensions.k8s.io/crontabs.crd.test.com created
[root@master concrd]# kubectl get crd |grep crontab
crontabs.crd.test.com                             2021-05-19T06:42:02Z

然后在以下地方创建一个新的名称空间 RESTful API 端点:

/apis/stable.example.com/v1/namespaces/*/crontabs/...

3.2.2 test_crontab.yaml

  • 内容
apiVersion: crd.test.com/v1
kind: CronTab
metadata:
  name: my-test-crontab
spec:
  cronSpec: "* * * * */10"
  image: my-test-image
  replicas: 2
  • 部署
[root@master concrd]# kubectl apply -f test_crontabl.yaml 
crontab.crd.test.com/my-test-crontab created
[root@master concrd]# kubectl get ct
NAME              AGE
my-test-crontab   6s
[root@master concrd]# kubectl  get ct my-test-crontab -oyaml
apiVersion: crd.test.com/v1
kind: CronTab
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"crd.test.com/v1","kind":"CronTab","metadata":{"annotations":{},"name":"my-test-crontab","namespace":"default"},"spec":{"cronSpec":"* * * * */10","image":"my-test-image","replicas":2}}
  creationTimestamp: "2021-05-19T06:44:26Z"
  generation: 1
  name: my-test-crontab
  namespace: default
  resourceVersion: "67685692"
  selfLink: /apis/crd.test.com/v1/namespaces/default/crontabs/my-test-crontab
  uid: fc78e12d-6b0f-4dc5-b6a7-75459d333eef
spec:
  cronSpec: '* * * * */10'
  image: my-test-image
  replicas: 2

3.3 validations

validation这个验证是为了在创建好自定义资源后,通过该资源创建对象的时候,对象的字段中存在无效值,则创建该对象的请求将被拒绝,否则会被创建。我们可以在crd文件中添加“validation:”字段来添加相应的验证机制。

3.3.1 crontab_validations_crd.yaml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # 称必须与下面的spec字段匹配,格式为: <plural>.<group>
  name: crontabs.crd.test.com
spec:
  # 用于REST API的组名称: /apis/<group>/<version>
  group: crd.test.com
  versions:
  - name: v1
    # 每个版本都可以通过服务标志启用/禁用。
    served: true
    # 必须将一个且只有一个版本标记为存储版本。
    storage: true
  scope: Namespaced # 指定crd资源作用范围在命名空间或集群
  names:
    # URL中使用的复数名称: /apis/<group>/<version>/<plural>
    plural: crontabs
    # 在CLI(shell界面输入的参数)上用作别名并用于显示的单数名称
    singular: crontab
    kind: CronTab
    # 短名称允许短字符串匹配CLI上的资源,意识就是能通过kubectl 在查看资源的时候使用该资源的简名称来获取。
    shortNames:
    - ct
  validation:
    openAPIV3Schema:
      properties:
        spec:
          properties:
            cronSpec: #必须是字符串、符合正则规则
              type: string
              pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
            replicas: #设置副本数的限制
              type: integer
              minimum: 1
              maximum: 10

3.3.2 test_validations_crontab.yaml

apiVersion: crd.test.com/v1
kind: CronTab
metadata:
  name: my-test-crontab
spec:
  cronSpec: "* * * * */10"
  image: my-test-image
  replicas: 21
  • 测试不符合规范的replicase
[root@master concrd]# kubectl apply -f test_validation_crontab.yaml 
The CronTab "my-test-crontab" is invalid: spec.replicas: Invalid value: 10: spec.replicas in body should be less than or equal to 10

3.4 additionalPrinterColumns

从Kubernetes 1.11开始,kubectl使用服务器端打印。服务器决定由kubectl get命令显示哪些列即在我们获取一个内置资源的时候会显示出一些列表信息(比如:kubectl get nodes)。这里我们可以使用CustomResourceDefinition自定义这些列,当我们在查看自定义资源信息的时候显示出我们需要的列表信息。通过在crd文件中添加“additionalPrinterColumns:”字段,在该字段下声明需要打印列的的信息

3.4.1 crontab_crd_additionalPrinterColumns.yaml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # 称必须与下面的spec字段匹配,格式为: <plural>.<group>
  name: crontabs.crd.test.com
spec:
  # 用于REST API的组名称: /apis/<group>/<version>
  group: crd.test.com
  versions:
  - name: v1
    # 每个版本都可以通过服务标志启用/禁用。
    served: true
    # 必须将一个且只有一个版本标记为存储版本。
    storage: true
  scope: Namespaced # 指定crd资源作用范围在命名空间或集群
  names:
    # URL中使用的复数名称: /apis/<group>/<version>/<plural>
    plural: crontabs
    # 在CLI(shell界面输入的参数)上用作别名并用于显示的单数名称
    singular: crontab
    kind: CronTab
    # 短名称允许短字符串匹配CLI上的资源,意识就是能通过kubectl 在查看资源的时候使用该资源的简名称来获取。
    shortNames:
    - ct
  validation:
    openAPIV3Schema:
      properties:
        spec:
          properties:
            cronSpec: #必须是字符串、符合正则规则
              type: string
              pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
            replicas: #设置副本数的限制
              type: integer
              minimum: 1
              maximum: 10
  additionalPrinterColumns:
  - name: Replicas
    type: integer
    JSONPath: .spec.replicas
  - name: Age
    type: date
    JSONPath: .metadata.creationTimestamp

  • 部署
[root@master concrd]# kubectl apply -f crontab_crd_additionalPrinterColumns.yaml 
customresourcedefinition.apiextensions.k8s.io/crontabs.crd.test.com created
[root@master concrd]# kubectl get crd |grep crontab
crontabs.crd.test.com                             2021-05-19T06:42:02Z

3.4.2 test_additionalPrinterColumns_crontab.yml

  • 内容
apiVersion: crd.test.com/v1
kind: CronTab
metadata:
  name: my-test-crontab
spec:
  cronSpec: "* * * * */10"
  image: my-test-image
  replicas: 2


  • 查看
[root@master concrd]# kubectl  get ct
NAME              REPLICAS   AGE
my-test-crontab   2          178m

3.5 subresources

一般我们要是没有在自定义资源当中配置关于资源对象的伸缩和状态信息的一些相关配置的话,那么在当我们通过该自定义资源创建对象后,又想通过“kubectl scale”来弹性的扩展该对象的容器的时候就会无能为力。而CRD可以允许我们添加该方面的相关配置声明,从而达到我们可以对自定义资源对象的伸缩处理。添加“ subresources:”字段来声明状态和伸缩信息。

3.5.1 crontab_crd_subresources.yml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # 称必须与下面的spec字段匹配,格式为: <plural>.<group>
  name: crontabs.crd.test.com
spec:
  # 用于REST API的组名称: /apis/<group>/<version>
  group: crd.test.com
  versions:
  - name: v1
    # 每个版本都可以通过服务标志启用/禁用。
    served: true
    # 必须将一个且只有一个版本标记为存储版本。
    storage: true
  scope: Namespaced # 指定crd资源作用范围在命名空间或集群
  names:
    # URL中使用的复数名称: /apis/<group>/<version>/<plural>
    plural: crontabs
    # 在CLI(shell界面输入的参数)上用作别名并用于显示的单数名称
    singular: crontab
    kind: CronTab
    # 短名称允许短字符串匹配CLI上的资源,意识就是能通过kubectl 在查看资源的时候使用该资源的简名称来获取。
    shortNames:
    - ct
  validation:
    openAPIV3Schema:
      properties:
        spec:
          properties:
            cronSpec: #必须是字符串、符合正则规则
              type: string
              pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
            replicas: #设置副本数的限制
              type: integer
              minimum: 1
              maximum: 10
  additionalPrinterColumns:
  - name: Replicas
    type: integer
    JSONPath: .spec.replicas
  - name: Age
    type: date
    JSONPath: .metadata.creationTimestamp
  subresources:
    scale:
      specReplicasPath: .spec.replicas
      statusReplicasPath: .status.replicas

3.5.2 测试

[root@master concrd]# kubectl  apply -f crontab_crd_subresources.yml 
customresourcedefinition.apiextensions.k8s.io/crontabs.crd.test.com configured
[root@master concrd]# kubectl  get ct
NAME              REPLICAS   AGE
my-test-crontab   2          3h1m
[root@master concrd]# kubectl scale --replicas=5 crontabs/my-test-crontab
crontab.crd.test.com/my-test-crontab scaled
[root@master concrd]# kubectl  get ct
NAME              REPLICAS   AGE
my-test-crontab   5          3h1m

清理

  • 删除自定义资源
kubectl delete  ct my-test-crontab
  • 清理crd
kubectl delete crd crontabs.crd.test.com

四 注意事项

五 总结

功能上:CRD 使得 Kubernetes 已有的资源和能力变成了乐高积木,我们很轻松就可以利用这些积木拓展 Kubernetes 原生不具备的能力。

产品上:基于 Kubernetes 做的产品无法避免的需要让我们将产品术语向 Kube 术语靠拢,比如一个服务就是一个 Deployment,一个实例就是一个 Pod 之类。但是 CRD 允许我们自己基于产品创建概念(或者说资源),让 Kube 已有的资源为我们的概念服务,这可以使产品更专注与解决的场景,而不是如何思考如何将场景应用到 Kubernetes。

参考链接

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。