Kubernetes CRD

一、Customer Resource

自定义资源是Kubernetes API的扩展,本文将讨什么时候应该向Kubernetes集群添加自定义资源以及何时使用独立服务。它描述了添加自定义资源的两种方法以及如何在它们之间进行选择。

1.1 自定义资源概述

资源就是Kubernetes API集合中的某个的对象。例如,内置pods资源包含Pod对象的集合。

自定义资源是扩展了Kubernetes API,但在默认的API集合中是不可用的,因为没有对应的controller处理业务逻辑。使用自定义资源,不仅可以解耦大多数的自研功能,还可用使得Kubernetes更加模块化。

自定义资源可以通过动态注册的方法,于正在running的集群中创建、删除和更新,并且与集群本身的资源是相互独立的。当自定义资源被创建,就可以通过kubectl创建和访问对象,和对内置资源的操作完全一致。

1.2 是否需要自定义资源

在创建新的API时,应该考虑与Kubernetes的API聚合,还是让API独立运行。

API聚合 API独立
声明式 非声明式
kubectl可读可写 不需要kubectl支持
接受k8s的REST限制 特定API路径
可限定为cluster或者namespace 不适用namespace
重用k8s API支持的功能 不需要这些功能

1.3 声明式API VS 命令式API

在声明式API,通过具有以下特性:

  • 对象颗粒度小
  • 基础结构的定义
  • 读写多,更新少,操作主要为CRUD
  • API表期望状态

命令式API,通过具有以下特性:

  • 同步响应
  • RPC调用
  • 大量数据存储(大对象或多对象)
  • 高带宽访问
  • 操作非CRUD
  • API不易抽象

二、Customer Resource Definition

Kubernetes提供了两种向集群添加自定义资源的方法:

  • 创建自定义API server并聚合到API中
  • CRDs

2.1 Customer Resource Definition介绍

通过CRD创建自定义资源,只要符合CRD结构体定义,均可以被Kubernetes所接收,以下是CRD的定义:

type CustomResourceDefinition struct {
    //Kind,APIVersion
	metav1.TypeMeta
    //metadata
	metav1.ObjectMeta
    //spec
	Spec CustomResourceDefinitionSpec
    //status
	Status CustomResourceDefinitionStatus
}

type CustomResourceDefinitionSpec struct {

	Group string

	Version string

    //Plural,Singular,ShortNames,Kind,ListKind,Categories
	Names CustomResourceDefinitionNames

    //cluster or namespace
	Scope ResourceScope

    //validation methods
	Validation *CustomResourceValidation

    //status,scale(spec.replicas,status.replicas,status.labelSelector)
	Subresources *CustomResourceSubresources

    //name,serve,storage
	Versions []CustomResourceDefinitionVersion

    //定义额外显示的列
	AdditionalPrinterColumns []CustomResourceColumnDefinition

    //不同版本之间的转换
	Conversion *CustomResourceConversion
}

type CustomResourceDefinitionStatus struct {

    //描述资源的当前状态,即status.conditions
	Conditions []CustomResourceDefinitionCondition
    //与spec.names类似,即status.acceptNames
	AcceptedNames CustomResourceDefinitionNames
	//资源曾经存在的版本,可在etcd中存储,供迁移用
	StoredVersions []string
}

2.2 CRD定义示例

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # 名称必须符合下面的格式:.
  name: clusterversions.paas
spec:
  # REST API使用的组名称:/apis//
  group: paas
  # REST API使用的版本号:/apis//
  versions:
  	- name: v1alpha1
  	  serve: true
  	  storage: true
  # Namespaced或Cluster
  scope: Cluster
  names:
    # URL中使用的复数名称: /apis///
    plural: clusterversions
    # CLI中使用的单数名称
    singular: clusterversion
    # CamelCased格式的单数类型。在清单文件中使用
    kind: ClusterVersion
    # CLI中使用的资源简称
    shortNames:
    - cv
  # 校验方法  
  validation:
    openAPIV3Schema:
      type: object
      properties:
        spec:
          type: object
          properties:
            #类型校验
            cronSpec:
              type: string
            image:
              type: string
            replicas:
              type: integer

2.3 Customer Controller

只定义资源,不实现资源控制器是没有任何意义的。自定义控制器能够完成业务逻辑,最主要是依赖client-go库的各个组件的交互。下图展示它们之间的关系:
Kubernetes CRD_第1张图片

通过图示,可以看到几个核心组件的交互流程,蓝色表示client-go,黄色是自定义controller,各组件作用介绍如下:

2.3.1 client-go组件

  • Reflector:reflector用来watch特定的k8s API资源。具体的实现是通过ListAndWatch的方法,watch可以是k8s内建的资源或者是自定义的资源。当reflector通过watch API接收到有关新资源实例存在的通知时,它使用相应的列表API获取新创建的对象,并将其放入watchHandler函数内的Delta FIFO队列中。
  • Informer:informer从Delta FIFO队列中弹出对象。执行此操作的功能是processLoop。base controller的作用是保存对象以供以后检索,并调用我们的控制器将对象传递给它。
  • Indexer:索引器提供对象的索引功能。典型的索引用例是基于对象标签创建索引。 Indexer可以根据多个索引函数维护索引。Indexer使用线程安全的数据存储来存储对象及其键。 在Store中定义了一个名为MetaNamespaceKeyFunc的默认函数,该函数生成对象的键作为该对象的namespace/name组合。

2.3.2 自定义controller组件

  • Informer reference:指的是Informer实例的引用,定义如何使用自定义资源对象。 自定义控制器代码需要创建对应的Informer。
  • Indexer reference:自定义控制器对Indexer实例的引用。自定义控制器需要创建对应的Indexer。
  • Resource Event Handlers:资源事件回调函数,当它想要将对象传递给控制器时,它将被调用。 编写这些函数的典型模式是获取调度对象的key,并将该key排入工作队列以进行进一步处理。
  • Work queue:任务队列。 编写资源事件处理程序函数以提取传递的对象的key并将其添加到任务队列。
  • Process Item:处理任务队列中对象的函数, 这些函数通常使用Indexer引用或Listing包装器来重试与该key对应的对象。

简单的说,整个处理流程大概为:Reflector通过检测 Kubernetes API来跟踪该扩展资源类型的变化,一旦发现有变化,就将该Object存储队列中,Informer循环取出该Object并将其存入Indexer进行检索,同时触发Callback回调函数,并将变更的Object Key信息放入到工作队列中,此时自定义Controller里面的Process Item就会获取工作队列里面的Key,并从Indexer中获取Key对应的Object,从而进行相关的业务处理。

三、sample-controller使用

3.1 资源创建

3.1.1 foo.crd.yaml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: foos.samplecontroller.k8s.io
spec:
  group: samplecontroller.k8s.io
  version: v1alpha1
  names:
    kind: Foo
    plural: foos
  scope: Namespaced

3.1.2 example.foo.yaml

apiVersion: samplecontroller.k8s.io/v1alpha1
kind: Foo
metadata:
  name: example-foo
  namespace: fst-manage
spec:
  deploymentName: example-foo
  replicas: 1
  namespace: fst-manage

3.2 sample-controller部署

3.2.1 编译

go build -o $GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/sample-controller .

3.2.2 启动

sudo ./sample-controller -kubeconfig=/opt/kube-agent/kubernetes/kubelet/kubeconfig

3.2.3 检查结果

kubectl get po -n fst-manage -o wide |grep foo
curl podId:80

你可能感兴趣的:(kubernetes)