19. Kubernetes API编程范式

本文由 CNCF + Alibaba 云原生技术公开课 整理而来

需求来源

在 Kubernetes 里面, API 编程范式也就是 Custom Resources Definition(CRD)CRD,其实指的就是用户自定义资源。

为什么会有用户自定义资源问题呢?

随着 Kubernetes 使用的越来越多,用户自定义资源的需求也会越来越多。而 Kubernetes 提供的聚合各个子资源的功能,已经不能满足日益增长的广泛需求了。用户希望提供一种用户自定义的资源,把各个子资源全部聚合起来。但 Kubernetes 原生资源的扩展和使用比较复杂,因此诞生了用户自定义资源这么一个功能。


示例

  • CRD 的一个实例:

CRD 功能是在 Kubernetes 1.7 版本被引入的,用户可以根据自己的需求添加自定义的 Kubernetes 对象资源。值得注意的是,这里用户自己添加的 Kubernetes 对象资源都是 native 的、都是一等公民,和 Kubernetes 中自带的、原生的那些 PodDeployment 是同样的对象资源。在 Kubernetes 的 API Server 看来,它们都是存在于 etcd 中的一等资源。

同时,自定义资源和原生内置的资源一样,都可以用 kubectl 来去创建、查看,也享有 RBAC、安全功能。用户可以开发自定义控制器来感知或者操作自定义资源的变化。

一个简单的 CRD 定义:

apiVersion: apiextension.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

文件解析:

apiVersion: apiextension.k8s.io/v1beta1     表示 CRD 当前所属的组是 apiextension.k8s.io,版本是 v1beta1

kind        表示 Kubernetes 资源类型是 CRD

metadata    表示 CRD 的元数据,元数据通常包含 name,name 建议遵循 顶级域名.xxx.APIGroup 这样的格式规范

spec    表示 CRD 的期望状态,group 表示 CRD 的 api 组;version 表示 CRD 的 api 版本;names 指定 CRD 的 kind 和 plural(昵称,用于简化长度);
        scope 表示 CRD 是否被 namespace 管理。如 ClusterRoleBinding 是 Cluster 级别的;Pod、Deployment 可以被创建到不同的命名空间里,它们的 scope 就是 Namespaced 的

上面定义的 CRD 的一个实例:

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

文件解析:

apiVersion: samplecontroller.k8s.io/v1alpha1        表示 Foo 当前所属的组是 samplecontroller.k8s.io,版本是 v1alpha1

kind        表示 Kubernetes 资源类型是 Foo

metadata    表示 Foo 的元数据,元数据通常包含 name、namespace 等

spec    表示 Foo 的期望状态,可以在 spec 中根据自己的需求定义一些内容,遵循 key:value 格式
  • 带有校验的 CRD

一个包含校验的 CRD 定义:

apiVersion: apiextension.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
  validation:
    openAPIV3Schema:
      properties:
        spec:
          properties:
            replicas:
              type: integer
              minimum: 1
              maximum: 10
和不包含校验的 CRD 相比,多了 .spec.validation 字段,用于校验。

首先是一个 openAPIV3Schema 的定义,spec 中则定义了有哪些资源,以 replicas 为例,这里将 replicas 定义为一个 integer 的资源,最小值为 1,最大值是 10。

那么,当再次使用这个 CRD 的时候,如果给出的 replicas 不是 int 值,或者去写一个 -1 或大于 10 的值,这个 CRD 对象就不会被提交到 API Server,API Server 会直接报错,告诉不满足所定义的参数条件。
  • 带有状态字段的 CRD

一个包含状态的 CRD 定义:

apiVersion: apiextension.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
  subresources:
    status: {
    
    }
状态实际上是一个自定义资源的子资源,它的好处在于,对该字段的更新并不会触发 Deployment 或 Pod 的重新部署。

对于某些 Deployment 和 Pod,只要修改了某些 spec,它就会重新创建一个新的 Deployment 或者 Pod 出来。

但是状态资源并不会被重新创建,它只是用来回应当前 Pod 的整个状态。上面的 CRD 声明中它的子资源的状态非常简单,就是一个 key:value 的格式。在 "{}" 里写什么,都是自定义的。

架构设计

  • 控制器概览:

只定义一个 CRD 其实没有什么作用,它只会被 API Server 简单地计入到 etcd 中。如何依据这个 CRD 定义的资源和 Schema 来做一些复杂的操作,则是由 Controller 来实现的。

Controller 其实是 Kubernetes 提供的一种可插拔式的方法来扩展或者控制声明式的 Kubernetes 资源。它是 Kubernetes 的大脑,负责大部分资源的控制操作。以 Deployment 为例,它就是通过 kube-Controller-Manager 来部署的。

比如说声明一个 Deploymentreplicas、有 2 个 Pod,那么 Kube-Controller-Manager 在观察 etcd 时接收到了该请求之后,就会去创建两个对应的 Pod 的副本,并且它会去实时地观察着这些 Pod 的状态,如果这些 Pod 发生变化了、回滚了、失败了、重启了等等,它都会去做一些对应的操作。

所以 Controller 才是控制整个 Kubernetes 资源最终表现出来的状态的大脑。用户声明完成 CRD 之后,也需要创建一个控制器来完成对应的目标。比如之前的 Foo,它希望去创建一个 Deploymentreplicas 为 1,这就需要创建一个控制器用于创建对应的 Deployment 才能真正实现 CRD 的功能。

  • 控制器工作流程:

在这里插入图片描述

Kube-Controller-Manager 为例,左侧是一个 Informer,它的机制就是通过去 watch Kube-ApiServer,而 Kube-ApiServer 会去监督所有 etcd 中资源的创建、更新与删除。Informer 主要有两个方法:ListFuncWatchFunc

ListFunc 就是像 kuberctl get pods 这类操作,把当前所有的资源都列出来;WatchFunc 会和 Kube-ApiServer 建立一个长链接,一旦有一个新的对象提交上去之后,apiserver 就会反向推送回来,告诉 Informer 有一个新的对象创建或者更新等操作。

Informer 接收到了对象的需求之后,就会调用对应的函数(比如 AddFunc, UpdateFunc, DeleteFunc),并将其按照 key 值的格式放到一个队列中去,key 值的命名规则就是 namespace/namename 就是对应的资源的名字。比如在 defaultnamespace 中创建一个 foo 类型的资源,那么它的 key 值就是 default/example-fooController 从队列中拿到一个对象之后,就会去做相应的操作。

在这里插入图片描述

首先,通过 Kube-ApiServer 来推送事件,比如 Added, Updated, Deleted;然后进入到 ControllerListAndWatch() 循环中;ListAndWatch 中有一个先入先出的队列,在操作的时候就将其 Pop() 出来;然后去找对应的 Handler,Handler 会将其交给对应的函数(比如 Add(), Update(), Delete())。

一个函数一般会有多个 Worker。多个 Worker 的意思是说比如同时有好几个对象进来,那么这个 Controller 可能会同时启动 5 个、10 个这样的 Worker 来并行地执行,每个 Worker 可以处理不同的对象实例。

工作完成之后,即把对应的对象创建出来之后,就把这个 key 丢掉,代表已经处理完成。如果处理过程中有什么问题,就直接报错,打印出一个事件来,再把这个 key 重新放回到队列中,下一个 Worker 就可以接收过来继续进行相同的处理。

  • 总结:

CRDCustom Resources Definition 的缩写,也就是用户自定义资源,用户可以使用这个功能扩展自己的 Kubernetes 原生资源信息;

CRD 和普通的 Kubernetes 资源一样,都可以受 RBAC 权限控制,并且支持 status 状态字段;

CRD-controller 也就是 CRD 控制器,能够实现用户自行编写,并且解析 CRD 并把它变成用户期望的状态。


猜你喜欢

转载自blog.csdn.net/miss1181248983/article/details/112997339
今日推荐