概述

CRD(Custom Resource Definition) 本身是一种Kubernetes内置的资源类型,即自定义资源的定义,用于描述用户定义的资源是什么样子,CRD的相关概念:

  • CRD是 v1.7 +新增的无需改变代码 就可以扩展 Kubernetes API 的机制,用来管理自定义对象。它实际上是ThirdPartyResources(TPR) 的升级版本,而 TPR 已经在 v1.8 中删除

  • 从Kubernetes 的用户角度来看,所有东西都叫资源Resource,就是Yaml里的字段Kind的内容,例如Service、Deployment等

  • 除了常见内置资源之外,Kubernetes允许用户自定义资源Custom Resource,而CRD表示自定义资源的定义

  • 当你创建新的CustomResourceDefinition(CRD)时,Kubernetes API服务器会为你所指定的每个版本生成一个新的 RESTful 资源路径

  • 基于CRD对象所创建的自定义资源可以是名字空间作用域的,也可以是集群作用域的, 取决于CRD对象spec.scope字段的设置

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

DNS子域名

很多资源类型需要可以用作DNS子域名的名称,名称必须满足如下规则:

  • 不能超过253个字符

  • 只能包含小写字母、数字,以及 '-' 和 '.'

  • 必须以字母数字开头

  • 必须以字母数字结尾

CRD更多文档参考官方文档

image-xyob.png定制资源

定制资源(Custom Resource) 是对Kubernetes API的扩展

image-saqn.png定制资源和定制控制器

  • 资源(Resource)是 Kubernetes API 中的一个端点, 其中存储的是某个类别的API对象的一个集合,例如内置的Pod资源包含一组Pod对象

  • 定制资源(Custom Resource)是对Kubernetes API的扩展, 定制资源所代表的是对特定Kubernetes安装的一种定制,不过很多Kubernetes 核心功能现在都用定制资源来实现,这使得Kubernetes更加模块化

  • 定制资源可以通过动态注册的方式在运行中的集群内或出现或消失,集群管理员可以独立于集群更新定制资源

  • 一旦某定制资源被安装,用户可以使用kubectl来创建和访问其中的对象, 就像他们为Pod这种内置资源所做的一样

定制控制器

  • 定制资源本身而言,它只能用来存取结构化的数据,当你将定制资源与定制控制器(Custom Controller) 结合时, 定制资源就能够提供真正的声明式API(Declarative API)

  • Operator模式就是将定制资源定制控制器相结合的

Operator介绍

Kubernetes CRD Operator = kubernetes CRD + custom controller

  • Operator是由CoreOS开发的,用来扩展 Kubernetes API,特定的应用程序控制器,它用来创建、配置和管理复杂的有状态应用,如数据库、缓存和监控系统

  • Operator基于Kubernetes的资源和控制器概念之上构建,但同时又包含了应用程序特定的领域知识,创建Operator的关键是CRD(自定义资源)的设计

  • Operator是Kubernetes的扩展软件, 它利用定制资源管理应用及其组件。 Operator遵循Kubernetes的理念,特别是在控制器方面

  • Operator模式会封装你编写的(Kubernetes 本身提供功能以外的)任务自动化代码

  • Kubernetes的Operator模式概念允许你在不修改 Kubernetes自身代码的情况下, 通过为一个或多个自定义资源关联控制器来扩展集群的能力

  • Operator是Kubernetes API的客户端。Operator旨在为其管理的资源提供强大的自动化功能,因此它还需要一些额外的支持性代码

Operator Framework

Operator Framework同样也是CoreOS开源的一个用于快速开发Operator的工具包,该框架包含两个主要的部分:

  • Operator SDK——无需了解复杂的Kubernetes API特性,即可让你根据你自己的专业知识构建一个Operator应用

  • Operator Lifecycle Manager OLM——帮助你安装、更新和管理跨集群的运行中的所有Operator(以及他们的相关服务)

image-isln.pngOperator安装

Operator SDK提供以下工作流来开发一个新的Operator

  • 使用SDK创建一个新的Operator项目

  • 通过添加自定义资源(CRD)定义新的资源API

  • 指定使用SDK API来watch的资源

  • 定义Operator的协调(reconcile)逻辑

  • 使用Operator SDK构建并生成Operator部署清单文件

安装Operator SDK

下载地址 Operator SDK官方文档

[root@k8s01 ~]# wget https://github.com/operator-framework/operator-sdk/releases/download/v1.23.0/operator-sdk_linux_amd64
#添加可执行权限
[root@k8s01 ~]# chmod +x operator-sdk_linux_amd64
#添加软链
[root@k8s01 ~]# ln -s /opt/k8s/crd/Operator/operator-sdk_linux_amd64 /usr/local/bin/operator-sdk

Operator简单使用

[root@k8s01 ~]# operator-sdk init --domain=example.com --repo=github.com/example-inc/memcached-operator
#步骤二: 创建 API(operator-sdk create api --group cache --version v1 --kind Memcached --resource=true --controller=true)
[root@k8s01 ~]# operator-sdk create api --group cache --version v1 --kind Memcached --resource=true --controller=true
#步骤三: 构建镜像-需要本地存在 docker 环境(make docker-build IMG=liumiaocn/memcache:v1)
[root@k8s01 ~]# make docker-build IMG=liumiaocn/memcache:v1
#步骤四: 运行Operator-需要环境具备 K8s/K3s(make install && make deploy IMG=liumiaocn/memcache:v1)
[root@k8s01 ~]# make install && make deploy IMG=liumiaocn/memcache:v1
#步骤五:创建自定义资源
[root@k8s01 ~]# kubectl apply -f config/samples/cache_v1_memcached.yaml
#步骤六:删除CR和相关资源(kubectl delete -f config/samples/cache_v1_memcached.yaml)
[root@k8s01 ~]# kubectl delete -f config/samples/cache_v1_memcached.yaml

Kubernetes API聚合层

  • 使用聚合层(Aggregation Layer),用户可以通过附加的API扩展 Kubernetes, 而不局限于 Kubernetes 核心API提供的功能。 这里的附加API可以是现成的解决方案,比如 metrics server, 或者你自己开发的API

  • 聚合层不同于 定制资源(Custom Resources)。 后者的目的是让kube-apiserver能够识别新的对象类别(Kind)

  • 聚合层在kube-apiserver进程内运行,在扩展资源注册之前,聚合层不做任何事情

  • 要注册API,你可以添加一个APIService 对象,用它来"申领" Kubernetes API中的URL路径。 自此以后聚合层将把发给该 API 路径的所有内容(/apis/myextension.mycompany.io/v1/…) 转发到已注册的 APIService

声明式APIs

典型的在声明式API中:

  • API包含相对而言为数不多的、尺寸较小的对象(资源)

  • 对象定义了应用或者基础设施的配置信息

  • 对象更新操作频率较低

  • 通常需要人来读取或写入对象

  • 对象的主要操作是CRUD风格的(创建、读取、更新和删除)

  • 不需要跨对象的事务支持:API对象代表的是期望状态而非确切实际状态

命令式 API(Imperative API)与声明式有所不同,以下迹象表明你的 API 可能不是声明式的:

  • 客户端发出"做这个操作"的指令,之后在该操作结束时获得同步响应

  • 客户端发出"做这个操作"的指令,并获得一个操作ID,之后需要检查一个Operation(操作) 对象来判断请求是否成功完成

  • 你会将你的API类比为远程过程调用(Remote Procedure Call,RPCs)

  • 直接存储大量数据;例如每个对象几 kB,或者存储上千个对象

  • 需要较高的访问带宽(长期保持每秒数十个请求)

  • 存储有应用来处理的最终用户数据(如图片、个人标识信息(PII)等)或者其他大规模数据

  • 在对象上执行的常规操作并非CRUD风格

添加定制资源

Kubernetes提供了两种方式供你向集群中添加定制资源:

  • CRD相对简单,创建CRD可以不必编程

  • API聚合需要编程,但支持对API行为进行更多的控制,例如数据如何存储以及在不同API版本间如何转换等

Kubernetes提供这两种选项以满足不同用户的需求,这样就既不会牺牲易用性也不会牺牲灵活性

  • 聚合API指的是一些下位的API服务器,运行在主API服务器后面;主API服务器以代理的方式工作。这种组织形式称作API聚合(API Aggregation,AA),对用户而言看起来仅仅是Kubernetes API被扩展了

  • CRD允许用户创建新的资源类别同时又不必添加新的API服务器, 使用CRD时你并不需要理解API聚合

CRD

聚合API

无需编程,用户可选择任何语言来实现CRD控制器

需要编程,并构建可执行文件和镜像

无需额外运行服务,CRD由API服务器处理

需要额外创建服务,且该服务可能失效

一旦CRD被创建,不需要持续提供支持,Kubernetes主控节点升级过程中自动会带入缺陷修复

可能需要周期性地从上游提取缺陷修复并更新聚合 API服务器

无需处理API的多个版本,例如当你控制资源的客户端时,你可以更新它使之与API同步

你需要处理API的多个版本,例如在开发打算与很多人共享的扩展时

仅支持CRUD操作,例如 "logs" 或 "exec"的操作是不支持的

支持 CRUD 之外的操作

访问定制资源

Kubernetes客户端库可用来访问定制资源,并非所有客户端库都支持定制资源。Go和Python客户端库是支持的

当你添加了新的定制资源后,可以用如下方式之一访问它们

  • kubectl

  • Kubernetes动态客户端(DynamicClient),可以对任意Kubernetes资源进行RESTFful操作,包括CRD自定义资源

  • 编写的REST客户端

  • 使用Kubernetes 客户端生成工具所生成的客户端,生成客户端的工作有些难度,不过某些项目可能会随着 CRD或聚合API一起提供一个客户端

CRD示例

创建CRD(定制资源)

当你创建新的CustomResourceDefinition(CRD)时,Kubernetes API服务器会为你所指定的每个版本生成一个新的RESTful资源路径。 基于CRD对象所创建的自定义资源可以是名字空间作用域的,也可以是集群作用域的, 取决于CRD对象spec.scope字段的设置

[root@k8s01 ~]# cat > resourcedefinition.yaml << EOF
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  #名字必需与下面的spec字段匹配,并且格式为'<名称的复数形式>.<组名>'
  name: crontabs.stable.example.com
spec:
  #组名称,用于REST API: /apis/<组>/<版本>
  group: stable.example.com
  #列举此CustomResourceDefinition所支持的版本
  versions:
    - name: v1
      #每个版本都可以通过served标志来独立启用或禁止
      served: true
      #其中一个且只有一个版本必需被标记为存储版本
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                image:
                  type: string
                replicas:
                  type: integer
  #可以是Namespaced或Cluster
  scope: Namespaced
  names:
    #名称的复数形式,用于URL:/apis/<组>/<版本>/<名称的复数形式>
    plural: crontabs
    #名称的单数形式,作为命令行使用时和显示时的别名
    singular: crontab
    #kind通常是单数形式的驼峰命名(CamelCased)形式。你的资源清单会使用这一形式
    kind: CronTab
    #shortNames允许你在命令行使用较短的字符串来匹配资源
    shortNames:
    - ct
EOF

执行创建

[root@k8s01 ~]# kubectl apply -f resourcedefinition.yaml
customresourcedefinition.apiextensions.k8s.io/crontabs.stable.example.com created

这样一个新的受名字空间约束的RESTful API 端点会被创建在

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

对象的kind将是来自你上面创建时 所用的spec中指定的 CronTab

[root@k8s01 ~]# kubectl get --raw /apis/stable.example.com/v1/
{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"stable.example.com/v1","resources":[{"name":"crontabs","singularName":"crontab","namespaced":true,"kind":"CronTab","verbs":["delete","deletecollection","get","list","patch","create","update","watch"],"shortNames":["ct"],"storageVersionHash":"EdX2FP+L0js="}]}
[root@k8s01 ~]# kubectl get --raw /apis/stable.example.com/v1/|python -m json.tool
{
    "apiVersion": "v1",
    "groupVersion": "stable.example.com/v1",
    "kind": "APIResourceList",
    "resources": [
        {
            "kind": "CronTab",
            "name": "crontabs",
            "namespaced": true,
            "shortNames": [
                "ct"
            ],
            "singularName": "crontab",
            "storageVersionHash": "EdX2FP+L0js=",
            "verbs": [
                "delete",
                "deletecollection",
                "get",
                "list",
                "patch",
                "create",
                "update",
                "watch"
            ]
        }
    ]
}

创建定制对象(定制控制器)

在创建了CustomResourceDefinition对象之后,你可以创建定制对象(Custom Objects),定制对象可以包含定制字段,这些字段可以包含任意的JSON数据,在下面的例子中在类别为CronTab的定制对象中,设置了cronSpec和image定制字段,类别CronTab来自你在上面所创建的CRD的规约

[root@k8s01 ~]# cat >my-crontab.yaml<<EOF
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image
EOF

执行创建命令

[root@k8s01 ~]# kubectl apply -f my-crontab.yaml
crontab.stable.example.com/my-new-cron-object created

你就可以使用kubectl来管理你的CronTab对象了例如:

[root@k8s01 ~]# kubectl get ct -o yaml
apiVersion: v1
items:
- apiVersion: stable.example.com/v1
  kind: CronTab
  metadata:
    annotations:
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"stable.example.com/v1","kind":"CronTab","metadata":{"annotations":{},"name":"my-new-cron-object","namespace":"default"},"spec":{"cronSpec":"* * * * */5","image":"my-awesome-cron-image"}}
    creationTimestamp: "2023-06-25T07:09:27Z"
    generation: 1
    managedFields:
    - apiVersion: stable.example.com/v1
      fieldsType: FieldsV1
      fieldsV1:
        f:metadata:
          f:annotations:
            .: {}
            f:kubectl.kubernetes.io/last-applied-configuration: {}
        f:spec:
          .: {}
          f:cronSpec: {}
          f:image: {}
      manager: kubectl-client-side-apply
      operation: Update
      time: "2023-06-25T07:09:27Z"
    name: my-new-cron-object
    namespace: default
    resourceVersion: "51213757"
    selfLink: /apis/stable.example.com/v1/namespaces/default/crontabs/my-new-cron-object
    uid: 5094d58b-ddd1-445e-a2a3-8a43bf47eb3f
  spec:
    cronSpec: '* * * * */5'
    image: my-awesome-cron-image
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

删除CustomResourceDefinition

当你删除某CustomResourceDefinition时,服务器会卸载其RESTful API端点,并删除服务器上存储的所有定制对象

[root@k8s01 ~]# kubectl delete -f resourcedefinition.yaml
customresourcedefinition.apiextensions.k8s.io "crontabs.stable.example.com" deleted
[root@k8s01 ~]# kubectl get crontabs
Error from server (NotFound): Unable to list "stable.example.com/v1, Resource=crontabs": the server could not find the requested resource (get crontabs.stable.example.com)

文章作者: 鲜花的主人
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 爱吃可爱多
Kubernetes Kubernetes
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝