您现在的位置是:首页 > 文章详情

如何基于Kubernetes开发自定义的Controller

日期:2018-12-13点击:408

继上次分享Kubernetes源码编译调试之后,一直想写些对scheduler,controller-manager,kubelete等组件的深入介绍,今天先介绍下Controller部分,在kubernetes内部提供了大量的controller,比如node controller,pod controller,endpoint controller等等。这些controller都是由controller-manager进行管理。每个Controller通过API Server提供的接口实时监控整个集群的每个资源对象的当前状态,当发生各种故障导致系统状态发生变化时,会尝试通过CRUD操作将系统状态修复到“期望状态”。

在kubernetes中一切皆资源,Kubernetes 1.7之后,提供了CRD(CustomResourceDefinitions)的自定义资源二次开发能力来扩展kubernetes API,通过此扩展,可以向kubernetes API中增加新类型,会比修改kubernetes的源代码或者是创建自定义的API server来的更加的简洁和容易,并且不会随着kuberntetes内核版本的升级,而出现需要代码重新merger的需要,以及兼容性方面的问题。这一功能特性的提供大大提升了kubernetes的扩展能力。


具体使用建议见:请参考Should I add a custom resource to my Kubernetes Cluster?

Kube – Controller的内部大致实现逻辑:

主要使用到 Informer和workqueue两个核心组件。Controller可以有一个或多个informer来跟踪某一个resource。Informter跟API server保持通讯获取资源的最新状态并更新到本地的cache中,一旦跟踪的资源有变化,informer就会调用callback。把关心的变更的Object放到workqueue里面。然后woker执行真正的业务逻辑,计算和比较workerqueue里items的当前状态和期望状态的差别,然后通过client-go向API server发送请求,直到驱动这个集群向用户要求的状态演化。

具体对client-go的使用,可参考《client-go的使用和源码分析》,在编写自定义的Controller的时候,需要大量使用client-go组件。上图中的蓝色部分全部是client-go已经包含的部分,不需要重新开发可以直接使用。红色的部分是自己的业务逻辑,需要自己开发。可见基于CRD开发一个自定义的资源管理API 来扩展kubernetes的底层能力还是非常简洁的。比如在kubernetes中目前还是没有办法可以做到通过pod直接查询到对应的service是谁。为了实现这个定制化的能力,为上层操作提供接口,就可以来扩展这个能力,写一个pod-service-controller。这个controller中提供两个informer,一个informer关注pod资源,一个informer关注service资源。把各自的变化情况通过回调的方式放到workerqueue中。然后在worker中并发的去处理queue中的item。整理出pod和service的映射关系。这样上层就可以直接通过该controller的RESTful API 查询到他们之间的映射关系。而不需要在上层哐哐的写一堆业务处理逻辑。

下面以sample-controller为例,来讲解开发自定义Controller的关键步骤和注意点。

1. 根据CRD的模板定义出自己的资源管理对象。比如crd.yaml文件

apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: #名称必须符合下面的格式:<plural>.<group> name: foos.samplecontroller.k8s.io spec: # REST API使用的组名称:/apis/<group>/<version> group: samplecontroller.k8s.io # REST API使用的版本号:/apis/<group>/<version> version: v1alpha1 names: # CamelCased格式的单数类型。在清单文件中使用 kind: Foo # URL中使用的复数名称: /apis/<group>/<version>/<plural> plural: foos # Namespaced或Cluster scope: Namespaced validation: openAPIV3Schema: properties: spec: properties: replicas: type: integer minimum: 1 maximum: 10

2. Kubectl create –f crd.yaml 执行完成后就创建了Foo这个资源对象。没有修改任何kubernetes内核代码,仅通过定义CustomResourceDefinition类型的yaml文件就可以直接创建新的资源对象,非常的简单和方便

一旦你创建CRD后,可以使用如下命令来验证CRD是否创建成功

kubectl get crd -o 'custom-columns=NAME:{.metadata.name},ESTABLISHED:{.status.conditions[?(@.type=="Established")].status}'

执行后输出如下:

NAME ESTABLISHED foos.samplecontroller.k8s.io True

3. 使用Foo这个新创建的类型,创建一个pod。

apiVersion: samplecontroller.k8s.io/v1alpha1 kind: Foo metadata: name: example-foo spec: deploymentName: example-foo replicas: 1 使用kubectl create f example-foo.yaml NAME READY STATUS RESTARTS AGE example-foo-86ccd54874-9ctfm 1/1 Running 0 3h

4. Foo类型的Pod对象创建成功后,结合上对Foo类型资源的控制才会让资源对象有意义。所以还需要开发一个自定义的Foo-Controller。

5. 定义一个Controller结构体

6. 构造出workqueue和Informer对象用于初始化Controller对象

7. 通过informer监控资源CRUD的操作的回调函数

8. 启动Controller

在run函数中在worker运行前,必须要等待状态的同步完成。使用go启动多个worker协程并发的从queue中一个个的获取待处理的Item。其中的runwoker是包含真正的业务逻辑的函数。

9.

以上便是一个完整的编写自定义Controller的完整过程。比如推荐大家一个比较好的Controller学习参考实现就是kubewatch,事件探测器。

https://github.com/bitnami-labs/kubewatch

本文转自kubernetes中文社区- 如何基于Kubernetes开发自定义的Controller

原文链接:https://yq.aliyun.com/articles/679422
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章