关注“Go语言中文网”公众号,回复关键词“入门”,即可下载从零入门 K8s 系列文章 PPT。
导读:本文将从实践出发,结合案例来说明,如何借助 Operator 开发框架来扩展 Kubernetes API。内容主要分为三个部分:首先会简单介绍一下 Operator 相关的知识;然后会介绍 Operator 开发框架并结合案例来详细说明整个开发过程;最后会结合案例的工作流程来重新说明 Operator 是如何工作的。
operator 概述
1. 基本概念
CRD (Custom Resource Definition): 允许用户自定义 Kubernetes 资源,是一个类型;
CR (Custom Resourse): CRD 的一个具体实例;
webhook: 它本质上是一种 HTTP 回调,会注册到 apiserver 上。在 apiserver 特定事件发生时,会查询已注册的 webhook,并把相应的消息转发过去。
工作队列:controller 的核心组件。它会监控集群内的资源变化,并把相关的对象,包括它的动作与 key,例如 Pod 的一个 Create 动作,作为一个事件存储于该队列中;
controller: 它会循环地处理上述工作队列,按照各自的逻辑把集群状态向预期状态推动。不同的 controller 处理的类型不同,比如 replicaset controller 关注的是副本数,会处理一些 Pod 相关的事件;
operator: operator 是描述、部署和管理 kubernetes 应用的一套机制,从实现上来说,可以将其理解为 CRD 配合可选的 webhook 与 controller 来实现用户业务逻辑,即 operator = CRD + webhook + controller。
2. 常见的 operator 工作模式
用户创建一个自定义资源 (CRD);
apiserver 根据自己注册的一个 pass 列表,把该 CRD 的请求转发给 webhook;
webhook 一般会完成该 CRD 的缺省值设定和参数检验。webhook 处理完之后,相应的 CR 会被写入数据库,返回给用户;
与此同时,controller 会在后台监测该自定义资源,按照业务逻辑,处理与该自定义资源相关联的特殊操作;
上述处理一般会引起集群内的状态变化,controller 会监测这些关联的变化,把这些变化记录到 CRD 的状态中。
operator framework 实战
1. operator framework 概述
2. kuberbuildere 实战
Step 1: 初始化
操作:新建一个 gitlab 项目,运行 "kubebuilder init --domain=kruise.io"。
参数解读:domain 指定了后续注册 CRD 对象的 Group 域名。
效果解读:拉取依赖代码库、生成代码框架、生成 Makefile/Dockerfile 等工具文件。
Step 2: 创建 API
group 加上之前的 domian 即此 CRD 的 Group: apps.kruise.io;
version 一般分三种,按社区标准;
v1alpha1: 此 api 不稳定,CRD 可能废弃、字段可能随时调整,不要依赖;
v1beta1: api 已稳定,会保证向后兼容,特性可能会调整;
v1: api 和特性都已稳定;
kind: 此 CRD 的类型,类似于社区原生的 Service 的概念;
namespaced: 此 CRD 是全局唯一还是 namespace 唯一,类似 node 和 Pod。
Step 3: 填充 CRD
调整注释
填充字段
genclient:nonNamespaced: 生成非 namespace 对象;
kubebuilder:subresource:status: 生成 status 子资源;
kubebuilder:printcolumn:name="MATCHED",type='integer',JSONPath=".status.matchedPods",description="xxx": kubectl get sidecarset: 后续展示相关。
Step 4: 生成 webhook 框架
生成 mutating webhook,运行:
生成 validating webhook,运行:
group/kind 描述需要处理的资源对象;
type 描述需要生成哪种类型的框架;
operations 描述关注资源对象的哪些操作。
Step 5: 填充 webhook
pkg/webhook/default_server/sidecarset/mutating/xxx_handler.go pkg/webhook/default_server/sidecarset/validating/xxx_handler.go pkg/webhook/default_server/pod/mutating/xxx_handler.go
是否需要注入 K8s client:取决于除了传入的 CRD 以外是否还需要其它资源。在本实战中,不仅要关注 SidecarSet,同时还要注入 Pod,因此需要注入 K8s client;
填充 webhook 的关键方法:即 mutatingSidecarSetFn 或 validatingSidecarSetFn。由于待操作资源对象指针已经传入,因此直接调整该对象属性即可完成 hook 的工作。
Step 6: 填充 controller
修改权限注释。框架会自动生成形如 //+kuberbuilder:rbac;groups=apps,resources=deployments/status,verbs=get;update;path 的注释,我们可以按照自己的需求修改,该注释最终会生成 rbac 规则;
增加入队逻辑。缺省的代码框架会填充 CRD 本身的入队逻辑(如 SidecarSet 对象的增删改都会加入工作队列),如果需要关联资源对象的触发机制(如 SidecarSet 也需关注 Pod 的变化),则需手工新增它的入队逻辑;
填充业务逻辑。修改 Reconcile 函数,循环处理工作队列。Reconcile 函数主要完成「根据 Spec 完成业务逻辑」和「将业务逻辑结果反馈回 status」两部分。需要注意的是,如果 Reconcile 函数出错返回 err,默认会重新入队。
SidecarSet 的工作流程
用户创建一个 SidecarSet;
webhook 收到该 SidecarSet 之后,会进行缺省值设置和配置项校验。这两个操作完成之后,会完成真正的入库,并返回给用户;
用户创建一个 Pod;
webhook 会拿回对应的 SidecarSet,并从中取出 container 注入 Pod 中,因此 Pod 在实际入库时就已带有了刚刚的 sidecar;
controller 在后台不停地轮询,查看集群的状态变化。第 4 步中的注入会触发 SidecarSet 的入队,controller 就会令 SidecarSet 的 UpdatedPods 加 1。
本文总结
Operator 是 CRD 配合 可选的 webhook 和 controller,在 Kubernetes 体系下扩展用户业务逻辑的一套机制; kubebuilder 是社区认可度很高的一种官方、标准化 Operator 框架; 按照上文实战步骤,填充用户自定义代码,就可以很方便的实现一个 Operator。
推荐阅读