K8S教程:使用kubebuilder开发简单的Operator
云原生技术通过方法论、工具集和最佳实践重塑着整个软件技术栈和生命周期,云原生对云计算服务方式与互联网架构进行整体性升级, 深刻改变着整个 IT 领域。云原生的核心是 kubernetes,围绕 kubernetes 构建满足自身需求的 PaaS 平台(应用中心)是绝大数企业的诉求, 但是不同企业自身场景往往存在一定的差异,Operator 是最常见 kubernetes 拓展方式。本片博文,我将会给大家理清 Operator 的来龙去脉, 同时介绍如何通过 kubebuilder 快速开发一个简单的 Operator。
Operator 诞生的背景
kubernetes 无法做到真正意义的开箱即用的,它与传统的 PaaS 平台不同,它仅仅只提供核心的基础设施功能,但是还无法满足用户的最终需求,这里用户主要指业务开发和业务运维, 比如说业务开发需要 CI/CD 工具实现 Devops 的功能,原生 kubernetes 是不提供支持的,但是我们可以通过tekton
这一个第三方工具实现 DevOps 相关功能, 这也正是 kubernetes 区别传统PaaS平台的真正强大之处,其提供完善的扩展机制以及基于此而发展出来的海量的第三方工具和丰富的生态。
Operator pattern
首先由 CoreOS 提出,通过结合 CRD 和 custom controller 将特定应用的运维知识转换为代码,实现应用运维的自动化和智能化。Operator 允许 kubernetes 来管理复杂的,有状态的分布式应用程序,并由 kubernetes 对其进行自动化管理,例如,etcd operator 能够创建并管理一组 etcd 集群, 定制化的 controller 组件了解这些资源,知道如何维护这些特定的应用。
随着 kubernetes 的功能越来越复杂,其需要管理的资源在高速增长,对应的 API 和 controller 的数量也愈发无法控制, kubernetes 变得很臃肿,很多不必要的 API 和功能将出现在每次安装的集群中。
为了解决这个问题,CRD 应运而生,CRD 由 TPR(Third Part Resource v1.2 版本引入)演化而来,v1.7 进入 beta,v1.8 进入稳定, 通过 CRD,kubernetes 可以动态的添加并管理资源。CRD 解决了结构化数据存储的问题,Controller 则用来跟踪这些资源, 保证资源的状态满足期望值。CRD+Controller=decalartive API
,声明式 API 设计是 kubernetes 重要的设计思想, 该设计保证能够动态扩展 kubernetes API,这种模式也正是 Operator pattern。
kubernetes 本身也在通过 CRD 添加新功能,我们有什么理由不使用呢?
使用场景总结及举例
CRD+custom controller 已经被广泛地使用,按使用场景可划分为以下两种:
- 通用型 controller: 这种场景和 kubernetes 内置的
apps controller
类似,主要解决特定通用类型应用的管理 - Operator: 该场景用于解决一个特定应用的自动化管理
通用型 controller 往往是 kubernetes 平台侧用户,如各大云厂商和 kubernetes 服务提供商,Operator 则是各种软件服务提供商, 他们设计时面向单一应用,很多开源的应用的 operator 可以在 operator hub 中获取。我列举一些示例供大家参考:
通用型 Controller
- 阿里的 cafedeploymentcontroller 解决金融场景下分布式应用特殊需求。
- oam-kubernetes-runtime 实现了 Application Model (OAM),以系统可持续的方式拓展 kubernetes
Operator
- etcd operator
- Prometheus operator
通用型Controller与kubernetes自带的几个controller类似,旨在解决一些通用的应用模型,而Operator则更加面向单个特定应用, 这两者没有本质的区别。
如何开发 CRD
作为kubernetes开发者,如何开发 CRD+Custom cntroller 呢?其实官方提供示例项目sample-controller供开发者参考,开发流程大致有以下几个过程:
- 初始化项目结构(可根据 sample controller 修改)
- 定义 CRD
- 生成代码
- 初始化 controller
- 实现 controller 具体逻辑
其中步骤 2,5 是核心业务逻辑,其余步骤完全可以通过自动生成的方式省略,到目前,社区有两个成熟的脚手架工具用于简化开发,一个是有 kube-sig 维护的 kubebuilder, 另一个是由 redhat 维护的 operator-sdk,这两个工具都是基于 controller-runtime 项目而实现,用户可自行选择,笔者用的是 kubebuilder。使用 kubebuilder 能够帮助我们节省以下工作:
如果你想要快速构建 CRD 和 Custom controller,脚手架工具是个不错的选择,如果是学习目的,建议结合 sample-controller 和 kubernetes controller 相关 源码。
kubebuilder 详解
kubebuilder 是一个帮助开发者快速开发 kubernetes API 的脚手架命令行工具,其依赖库 controller-tools 和 controller-runtime, controller-runtime 简化 kubernetes controller 的开发,并且对 kubernetes 的几个常用库进行了二次封装, 以简化开发者使用。controller-tool 主要功能是代码生成。下图是使用 kubebuilder 的工作流程图:
文章后面会结合一个简单示例来介绍开发流程。
“
kubebuilder 有非常良好的文档,包括一个从零开始的示例,您应该以文档为主。
”
使用 kubebuilder 开发一个 CRD
本次示例创建一个通用的Application
资源,Application 包含一个子资源 Deployment 以及一个 Count 资源, 每当 Application 进行被重新协调Reconcil,Count 会进行自增。
“
全部代码请参考代码仓
”
前提(你需要提前了解的)
- Golang 开发者,kubernetes 大量使用
Code Generate
这一功能来自动生成重复性代码 - 阅读 kubernetes controller 的代码
- 阅读 kubebuilder 的文档
- 了解 kustomize
开发步骤及主要代码展示
首先,根据你的开发环境安装 kubebuilder 工具,mac 下通过 homebrew 安装命令如下:
BASH
➜ ~ brew install kubebuilder
➜ ~ kubebuilder version
Version: version.Version{KubeBuilderVersion:"unknown", KubernetesVendor:"unknown", GitCommit:"$Format:%H$", BuildDate:"1970-01-01T00:00:00Z", GoOs:"unknown", GoArch:"unknown"}
安装完毕后,首先创建项目目录custom-controller
并使用go mod
初始化项目
BASH
➜ cd custom-controllers
➜ ls
➜ go mod init controllers.happyhack.io
接着,使用 kubebuilder 初始化项目,生成相关文件和目录,并创建 CRD 资源
BASH
# 使用kubebuilder初始化项目
➜ custom-controllers kubebuilder init --domain controller.daocloud.io --license apache2 --owner "Holder"
# 创建CRD资源
➜ custom-controllers kubebuilder create api --group controller --version v1 --kind Application
Create Resource [y/n]
y
Create Controller [y/n]
y
Writing scaffold for you to edit...
api/v1/application_types.go
controllers/application_controller.go
Running make:
$ make
/Users/donggang/Documents/Code/golang/bin/controller-gen object:headerFile="hack/huilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go build -o bin/manager main.go
到目前,该项目就已经能够运行了,不过我们需要添加我们自己业务代码,主要包括修改 CRD 定义和添加 controller 逻辑两部分。首先修改 API 资源定义即 CRD 定义,Application 包含一个 Deployment,我们可以参考 kubernetes Deployment 与 Pod 这两个类型之间的关系设计 Application 和 Deployment, Deployment 通过字段spec.template
来描述如何创建 Pod,DeploymentTemplateSpec
描述了该如何创建 Deployment,
GOLANG
// PodTemplateSpec describes the data a deployment should have when created from a template
type DeploymentTemplateSpec struct {// Standard object's metadata.// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata// +optionalmetav1.ObjectMeta `json:"metadata,omitempty"`// Specification of the desired behavior of the pod.// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-statusSpec v12.DeploymentSpec `json:"spec,omitempty"`
}
API 描述定义完成了,接下来需要我们来进行具体业务逻辑实现了,编写具体 controller 实现,首先我们简单梳理 controller 的主要逻辑
- 当一个 application 被创建时,需要创建对应的 deployment,当 application 被删除或更新时,对应 Deployment 也需要被删除或更新
- 当 application 对应的子资源 deployment 被其他客户端删除或更新时,controller 需要重建或恢复它
- 最后一步更新 application 的 status,这里即 count 加 1
我们在方法func(r *ApplicationReconciler) Reconcile(req ctrl.Request)(ctrl.Result,error)
实现相关逻辑, 当然当业务逻辑比较复杂时,可以拆分为多个方法。
GOLANG
func (r *ApplicationReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {ctx := context.Background()log := r.Log.WithValues("application", req.NamespacedName)var app controllerv1.Applicationif err := r.Get(ctx, req.NamespacedName, &app); err != nil {log.Error(err, "unable to fetch app")return ctrl.Result{}, client.IgnoreNotFound(err)}selector, err := metav1.LabelSelectorAsSelector(app.Spec.Selector)if err != nil {log.Error(err, "unable to convert label selector")return ctrl.Result{}, err}var deploys v12.DeploymentListif err := r.List(ctx, &deploys, client.InNamespace(req.Namespace), client.MatchingLabelsSelector{Selector: selector}); err != nil {if errors.IsNotFound(err) {deploy, err := r.constructDeploymentForApplication(&app)if err != nil {log.Error(err, "unable to construct deployment")return ctrl.Result{RequeueAfter: time.Second * 1,}, err}if err = r.Create(ctx, deploy); err != nil {return ctrl.Result{RequeueAfter: time.Second * 1}, err}}}...
}
完成Reconcile
方法后,我们可以修改config目录的示例yaml,来进行本地测试了。
官方开发自定义 Controller 的指导
kubernetes开箱自带了多个controller,这些controller在我们开发时具有非常重要的参考价值,同时社区也总结了的 controller 开发所需要遵循十一条原则, 但是请大家结合实际场景灵活运用这些原则:
img
总结及展望
本文简单介绍了 CRD 以及如何使用脚手架工具 kubebuilder 帮助我们开发自定义 controller,当然这个 controller 示例的逻辑比较简单, 在实际场景中,我们会遇到很多的挑战,比如controller 的逻辑会比较复杂、需要通过多个controller等。作为kubernetes开发者, Controller开发是一项必不可少的技能。
参考链接:https://blog.happyhack.io/2020/10/12/kubernetes-crd-day1/
K8S教程:使用kubebuilder开发简单的Operator相关推荐
- 微信小程序云开发简单入门教程
文章目录 ###开场白: 云开发顾名思义 就是后端开发,应该是微信上周才推出的开放能力,现在这让我想起了以前的leancloud,和更早的bmob了,而leancloud一早就开始支持微信小程序开发了 ...
- 2022 最新 Android 基础教程,从开发入门到项目实战【b站动脑学院】学习笔记——第三章:简单控件
第 3 章 简单控件 本章介绍了App开发常见的几类简单控件的用法,主要包括:显示文字的文本视图.容纳视图的常用布局.响应点击的按钮控件.显示图片的图像视图等.然后结合本章所学的知识,演示了一个实战项 ...
- 【前端实例代码】Html5+css3创建拟物风格昏昏欲睡的云朵动画网页效果~前端开发网页设计基础入门教程~适合初学者~超简单~
b站视频演示效果: [前端实例代码]Html5+css3创建拟物风格昏昏欲睡的云朵动画网页效果!前端开发网页设计基础入门教程!适合初学者~超简单~ 效果图: 完整代码: <!DOCTYPE ht ...
- python微信公众号开发教程_python微信公众号开发简单流程实现
本文为大家分享了python微信公众号开发的简单过程,供大家参考,具体内容如下 网上有很多微信公众号的开发教程,但是都是好几年前的了,而且很多都是抄袭其他人的,内容几乎一模一样.真的无语了.只好自己总 ...
- 【Python小案例教程1】Python开发简单记事本
####前言: 本文是使用Python,结合Tkinter开发简单记事本. ####基本环境配置: Python版本:2.7 编辑器:pycharm ####实现效果: ####主要思路: 我们可以看 ...
- k8s教程(Volume篇)-PV详解
文章目录 01 引言 02 PV详解 2.1 示例配置详解 2.1.1 存储容量 (Capacity) 2.1.2 存储卷模式 (Volume Modes) 2.1.3 访问模式 (Access Mo ...
- openlayers地图旋转_OpenLayers教程二:实现简单的地图显示
本文衔接上一篇文章:不睡觉的怪叔叔:OpenLayers教程二:实现简单的地图显示zhuanlan.zhihu.com 经过上一篇文章对OpenLayers的简单了解以后,现在让我们来实现一个简单的 ...
- 好程序员Web前端教程分享JavaScript开发技巧
好程序员Web前端教程分享JavaScript开发技巧,相信知道Web前端的小伙伴都熟悉,Javascript的很多扩展的特性是的它变得更加的犀利,同时也给予程序员机会创建更漂亮并且更让用户喜欢的网站 ...
- 视频教程-红孩儿网狐Cocos经典棋牌开发教程-手游开发
红孩儿网狐Cocos经典棋牌开发教程 中国早期游戏程序员,2003年起从事游戏程序开发,负责开发过多款游戏项目,曾担任大型端游<无限世界>自研引擎技术负责人,2012年起关注Cocos引擎 ...
最新文章
- 1035等差数列末项计算
- ROS知识【12】:用户的功能包覆盖系统功能包
- 属于PHP语言结构的是,PHP语言结构
- python期末设计作品_期末作品检查
- 关于安装TortoiseSVN.msi 报错2203错误
- 英特尔商用攻略升级:企业如何趟平信息化建设这条路?
- 【图像配准】基于灰度的模板匹配算法(一):MAD、SAD、SSD、MSD、NCC、SSDA、SATD算法...
- ADB工具安装及常用命令
- ShellServiceObjectDelayLoad注册表键值作用
- PyTorch代码学习-ImageNET训练
- iOS IPv6测试环境搭建及服务器ipv6测试
- Python RSA PKCS#1 转 PKCS#8
- 在线工具:将图片透明化
- is_file php 绕过,文件上传之绕过
- c语言 计算子网掩码位数,子网数、主机数与子网掩码的关系
- 汉诺塔(C语言实现)
- 解决蓝牙鼠标和电脑连接出现卡顿的情况
- 有趣的数据结构算法12——利用递归解决八皇后问题
- CKEDITOR获取内容
- OFBIZ分享:如何让OFBIZ使用中文界面
热门文章
- java http 状态_Java HTTP连接似乎保持打开状态
- 数据竞赛:记录3天进入比赛Top3%的全过程
- 【论文解读】用Dropout思想做特征选择保证效果,还兼顾了线上性能?
- 群友福利 | 55 本《AI 嵌入式系统: 算法优化与实现》免费送
- 【数据竞赛】DoubleEnsemble--专治硬样本的神奇集成技术。
- 【NLP】情感分析:BERT vs Catboost
- 【Python基础】Python 炫技操作:推导式的五种写法
- 【论文解读】AAAI21最佳论文Informer:效果远超Transformer的长序列预测神器!
- 【算法漫画】什么是红黑树?(下篇)
- 推荐一些动作识别数据集