operator是coreos 公司工程师在2016年提出,就是可以根据应用独有的领域逻辑编写的自定义控制器。
k8s的资源类型实现都要满足俩个条件:
上面这种资源设计方式叫做“声明式API”
operator就是采用上面的模式实现,主要组成有:模型抽象-CRD、具体业务逻辑动作的处理-controller。
对于使用者来说,提交了定义好的CRD对象来描述期望的状态之后,无需关注处理过程,关注结果即可,过程由controller处理。
CRD(costom resource definition): 自定义资源
controller:控制器
group/version: api组 api版本
Kind/resouce: api类型 kind的实例
GVK: 定义一种资源的方式,通过GVK的信息(group/version/kind)确定一个具体资源类型GVR。
GVR: 实例化GVK定义的资源类型,体现在restful api 交互上
GVK和GVR的转换:GVR通过rest mapper映射到对应的GVK
api资源路径格式:/api/apps/v1/namespace/$namespace/job
“api/apps” : 组
“v1”: 版本
“job”: 资源
简单来说,就是控制器,控制k8s的资源实体。
kubernetes官方在2016年八月把k8s资源操作相关核心源码抽离出来,组成了一个新的项目,client-go。
client-go是k8s集群资源操作的编程式交互客户端库,通过与api server进行交互完成资源操作。
client-go主要用于内置、自定义资源的增删查改操作,通过client-go提供的能力,就可以实现controller的能力,所以学习client-go,对我们理解controller很重要。
.
├── CHANGELOG.md
├── CONTRIBUTING.md
├── INSTALL.md
├── LICENSE
├── OWNERS
├── README.md
├── SECURITY_CONTACTS
├── applyconfigurations
├── code-of-conduct.md
├── discovery # 包含discovery客户端,用于发现api server 支持的资源信息
├── doc.go
├── dynamic # 包含dynamic 客户端,用户对自定义k8s资源执行通过操作
├── examples #client-go使用示例
├── go.mod
├── go.sum
├── informers # 包含各种资源的informer实现
├── kubernetes #包含k8s内置资源的clientset
├── kubernetes_test
├── listers #提供监听服务
├── metadata
├── openapi
├── pkg
├── plugin
├── rest
├── restmapper
├── scale
├── testing
├── third_party
├── tools #与util一起提供常用工具,便于编写controller
├── transport #提供安全连接功能
└── util
client共支持4中与api server交互的客户端逻辑。如下
client-go主要用于k8s控制其中,包括内置控制器(kube-controller-manager)和CRD控制器。client提供了编写自定义controller所使用的各种机制,如下
list-watch机制
reflector:使用list-watch 方法监听指定类型的资源对象,通过list获取所有实例的resouceversion,并监听在这个版本后面所有的变化,并把收到的event用反射机制处理为监控的实体对象,即把GVK转为go type
deltafifo:上面得到的event及它对应的实体对象组合成为增量delt。
localStore:通过event类型,创建和更新本地缓存,并建立索引提供快速查找的能力indexer,可以减少api server压力。
workqueue:deltafifo同步完localstore后,会把这个event pop到内部的controller的回调函数resourehandler,进行简单的过滤工作,最后吧变更的对象放入workqueue中,供worker控制循环处理。
Worker:控制循环,work执行真正的业务逻辑,通过对比状态进行动作处理
kubebuilder是一个用go语言构建kubernetes apis的框架,通过这一套编程框架,可以便捷的使用crd构建api、controller和admission webhook,实现对k8s自定义资源的扩展。
Kubebuilder Scaffolds是实现这个脚手架最核心的逻辑,它借助 API Scaffolder对象模块,实现了 CRD的 Template和 Controller的核心代码块。
用户主要关注Userdefined 模块,需要根据实际场景,设计 CRD的结构定义,当然这里的 CRD的数量可以有多个。
用户还需要实现 Reconcile的逻辑。这里,首先了解 Reconcile的含义,用户自定义了CRD结构,而在 Kubernetes集群中,想要实现这样的 CRD 结构定义,Reconcile 需要协调逻辑。举例来说,假设用户定义了 MysqlCluster{Name:demo,Num:3} 这样的结构体,而希望在系统中创建MySQL的集群,而构造 MySQL 集群的构造过程,就是 Reconcile过程做的工作。
运行环境,用户自定义的部分能工作的前提是要有一个 Kubernetes集群,即架构中最下面的部分,它负责安装 CRD及运行 Controller。
controller runtime负责运行controller,包含了schema、manager、client、cache等核心模块。
{
"apiVersion":"demo1.example.org/v1","kind":"Demo",
"metadata":{
...
}
通过这个 GoType,能够正确地获取 GVR的信息,从而提供给 Controller, 获取期望的状态,即协调的逻辑。
manager,controller总控,负责初始化一些公共模块以及controller运行管理。
在Controller Runtime中Controller最依赖的除了Scheme之外,还包括 Manager 的初始化、安装和启动工作。Manager 的初始化依赖 Controller Runtime库初始化 Manager对象,包括 Client、Cache 等模块的生成工作。然后调用Client就可以实现对CRD的“增、删、改、查”,而查询的逻辑是通过本地的Cache 模块实现的。这里的Cache 负责监听CRD 的变化,它是通过监听Scheme,从而收集所有与 Controller有关的GVR 资源,并创建对应的监听器,从而实现当监听到Kubernetes集群中的CRD发生变化触发 Controller的协调进程Reconcile工作。
Kuberbuilder工具生成的内容还包括 Finalizer,它用于处理 Kubernetes资源的预删除逻辑,保障资源被删除后能够从 Cache中读取到,清理相关的其他资源;
OwnerReference用于清理资源时, 对于任何一个对象, 若它的 OwnerReference字段值为待删除对象,则这个对象也会被清理,支持对象的变更,也会触发 Owner对象的Controller 的协调过程。
Index 用于提供资源的缓存,提升客户端资源的查询效率。
.
├── api ## 这里定义了 sample 的结构体 GVK,以及所需的 deepcopy 实现
│ └── v1
│ ├── groupversion_info.go
│ ├── sample_types.go
│ └── zz_generated.deepcopy.go
├── bin
│ └── manager ## controller 编译后的 二进制文件
├── config ## 包含了我们在使用 crd 是可能需要的 yml 文件,包括rbac、controller的deployment 等
│ ├── certmanager
│ ├── crd
│ ├── default
│ ├── manager
│ ├── prometheus
│ ├── rbac
│ ├── samples #crd资源类型的部署yaml
│ └── webhook
├── controllers ## 我们的controller 逻辑就放在这里
│ ├── sample_controller.go
│ └── suite_test.go
├── Dockerfile
├── go.mod
├── go.sum
├── hack
│ └── boilerplate.go.txt
├── main.go
├── Makefile #编译打包工具
└── PROJECT
CRD创建
manager 初始化
controller 初始化
client初始化
manager启动
Finalizers,是每种资源在声明周期结束时都会使用到的字段,属于k8s GC垃圾回收器,是一种删除拦截机制,可以执行一些预删除处理,需要在reconcile中实现。
运行逻辑:Finalizers字段不为空时,delete -> update,更新deletetimestamp 字段,之后,如果再次检测发现finalizers为空,k8s GC可以删除该资源。
**使用姿势:**创建对象时定义好finalizer字段,任意string,删除资源的时候,update deletiontimestamp字段,执行所有的pre-hook操作,然后将finalizes字段值为空
核心模块介绍
controller runtime,是对client-go的部分能力的封装,也重写了部分controller组件逻辑,和clientl-go是两个用途不同的项目。
manager
controller
client
cache
webhook
《云原生应用开发 Operator原理与实践》