写点什么

Kubernetes Operator 测试面面观

  • 2020-03-02
  • 本文字数:3549 字

    阅读完需:约 12 分钟

Kubernetes Operator 测试面面观

软件测试是一门工程技术,更是一门艺术。维护良好、质量过硬的测试用例不仅能大幅提高开发者的工作幸福感,也是企业对外提供优质软件服务的重要基础。在这篇文章中,才云工程师 gaocegege 将分享团队在 Kubernetes Operator 测试方案上的一些心得。


本文将介绍一些比较成熟的 Kubernetes Operator 测试方案与方法,分析目前对 Kubernetes Operator 进行测试的最佳实践。

单元测试

首先,让我们把镜头对准单元测试。单元测试又称模块测试,它是针对程序模块(软件设计的最小单位)进行正确性检验的测试工作,也被视为是软件质量的第一道保障。


Kubernetes 的做法


在 tf-operator 中,我们采取了跟 Kubernetes 内置的 controller 类似的测试方案(例子可见 job_controller_test.go)。


如下面的代码所示,我们通过 Fake KubeConfig 创建了 Fake Clienset 和 Informer。之后,我们利用 Indexer,将测试的数据注入到 Informer 的 Cache 中,同时把 Informer 的 Sync 状态置为 AlwaysReady。最后,我们用到了 Fake PodControl 和 ServiceControl,这一操作使得我们不会真正在 Kubernetes 中创建对象,而是只进行一个记录。



随后,我们将状态更新的函数也 Fake 掉,将其赋值到内存的一个对象中,以便在后续的测试中进行状态比对。通过手动调用 SyncTFJob,我们可以利用之前自己手动构造的 Cache 进行状态的 Sync。


最后,就是根据构造对象和实际更新后对象的比对,来判断 Operator 在 Sync 的过程中是否达到了期望状态。



这一方法利用了 Kubernetes 的一些机制,绕过了对 Kubernetes API Server 和其他组件的依赖,直接利用 Informer 针对 Operator 的代码逻辑进行测试,可以测试单次 Sync 过程中,Operator 的工作是否符合预期。


etcd-operator 的做法


etcd-operator 是问世最久的 Operator 之一,Operator 这一模式也是由 CoreOS 提出的,了解 etcd-operator 有助于我们以史为镜。


目前 etcd-operator 在实现中仍没有像主流的 Operator 一样,采用 Work Queue 的方式来避免阻塞问题,而是在 Informer 中直接进行处理,而它的处理逻辑则被统一写成了:



因此,在做单元测试时,这种方法相对容易些,可以直接构造 Event 对象来进行测试。


Kubebuilder-generated Operator 的做法


严格意义上,Kubebuilder 的测试有别于传统单元测试,它背后依赖的是 “sigs.k8s.io/controller-runtime/pkg/envtest”.Environment。


在运行时,它会启动一个真正的 API Server 和 etcd,随后把 CRD 注册到 Scheme 中并把 Operator 运行起来。但值得注意的是,它不会启动 Controller Manager,这也意味着来自 API Server 的关于 Kubernetes 资源的事件不会真正被处理。


相比其他测试方法,它有许多比较明显的不同。首先,它需要运行一个真正的 API Server 和 etcd 来做对象存储。这就意味着在测试时可以使用真正的 Clientset 对 API Server 进行各种请求。



其次,它会运行一个真正的 Operator,而不只是通过手动调用 Sync 过程的方式进行测试。如下方代码所示,inner 这一对象就是真正的 Operator 的逻辑,而这一函数对其进行了再次封装,利用一个没有缓冲的 Channel 对其进行了执行的控制。



根据 Golang 的内存模型,不带缓冲的 Channel 的接收操作 happens-before 相应 Channel 的发送操作完成。利用这一特性,在同一个测试用例中,测试的对象可以被多次 Sync,每次 Sync 的状态都可以被检查。如果需要检查其中的 reconcile.Result 的值,如 Requeue 等,也可以改动这部分的逻辑来扩展。


这样做的优势是可以在单个测试中多次 Sync,并且依赖真实的 API Server,直接简单地利用 Clientset 进行操作。而它的劣势也在于依赖真实的 API Server,由于有些 CI 系统对多进程支持不好,真正在持续集成环境下运行时会有各种各样的问题。

端到端测试

端到端测试是利用真实的外部组件,将系统当做黑盒,站在终端用户的角度进行的测试。这里的“真实的组件”指的是 Kubernetes 还有一些外部依赖。相比单元测试,端到端测试需要依赖一个真实的 Kubernetes 集群,同时由于其黑盒属性,我们就有了更多不同选型。


Kubernetes 的做法


首先介绍下 Kubernetes 自身 Controller 的 e2e 测试是如何做的。


Kubernetes 的端到端测试依赖一个关键的抽象,也就是 Framework。Framework 负责把需要的 Client 创建好,同时,它也会为测试创建一个 Namespace。


当前的测试用例会在这个 Namespace 下运行,因此它从设计上就避免了并行测试可能引起的冲突,是一个非常有价值的特性。这也使得 Kubernetes 的测试用例可以并行地运行。


其实 Kubernetes 的端到端测试有许多值得学习的地方,包括其整体的原则、哲学、设计和实现。限于篇幅原因,这里不过多介绍。


Operator-SDK generated Operator 的做法


Operator-SDK 的做法和 etcd-operator 的做法类似,和 Kubernetes 的做法也有异曲同工之妙,相当于是基于 Kubernetes 社区的实现做了一个新的抽象和改写。


首先它需要设置 Main Entry:



这一函数会根据传入的 Kubeconfig、ProjectRoot 等参数,创建出 CRD 和 Operator。Operator 可以运行在集群外,也可以以 Pod 的方式运行在集群内。


随后,集群就可以进行测试了。我们可以完全把它当做黑盒,把 Clientset 当做 kubectl,将端到端的黑盒测试自动化。不过这里值得一提的是,这一方式不能通过 go test 直接进行测试。因为在 MainEntry 中,它会依赖一些参数,而这些参数会涉及一些预处理的逻辑。


举个例子,Operator-SDK 会把 Operator 所有的 YAML 文件合并成一个 YAML,然后再把这一临时的 YAML 文件的路径作为参数传递给后续的命令。


因此 Operator-SDK 是利用 operator-sdk test local 这一命令先进行预处理,然后再把处理好的参数传递给 go test 命令的。这一方式对用户并不是那么友好,必须依赖 operator-sdk 才能发起测试。但它默认支持一个用例一个 Namespace,与 Kubernetes 测试时的行为类似。


Kubebuilder-generated Operator 的做法


由于 Kubebuilder 生成的测试原本就依赖一个真实的 API Server 和 etcd,所以我们只要再创建出其他 Kubernetes 的组件就可以了。


但是,如果已经有正在运行的 Kubernetes 集群,那么我们就可以利用 UseExistingCluster,通过运行的集群进行测试。


相比前几种方式,这种方法可以真正检查所有资源的状态。而之前的方法只有 API Server 的运行中,是做不到对状态的检查的,因为事件不会被 Kubernetes Controller Manager 处理,因此状态更新无法进行。


tf-operator 的做法


因为端到端测试是黑盒测试,只要能够利用 Kubernetes 的 API 进行请求就可以完成,因此 tf-operator 的端到端测试是用 Python 实现的。


其实不只是端到端测试,tf-operator 的构建也不是用 Make 或者 Bazel 做的,而是用 Python 实现的,它们其实都是历史遗留问题。


不过这也证明了,只要能够解决集群部署、CRD 以及 Operator 的安装,用什么语言都可以做 Operator 的端到端测试。

总结

除了以上内容,Operator 的单元测试还存在多种不同的实现方案,本文只是基于才云内部实践,列举了几种较为主流且高效的方法。


对于单元测试,Kubernetes 和 tf-operator 的做法能够细粒度地构造测试用例,同时检查 Sync 的过程可否满足期望。


etcd-operator 的做法为单元测试提供了一种新思路,通过对 Operator 进行更高层次的抽象,针对高层次的抽象进行单元测试,我们可以避免手动利用 Indexer 构造测试场景。


kubebuilder 生成 Operator 实现的测试并不是传统意义上的单元测试。它利用了真实的 API Server,在测试时可以利用 Client 获取真实的资源。但由于没有 Controller 的支持,所以对于不少需要依赖一些 Kubernetes 自身资源状态来更新自己状态的 CRD 而言,没办法进行状态的检查。这一问题在前面的方法中不存在。


而对于端到端测试,我列举的所有方案基本都是利用 Client 来对已经创建好的集群进行端到端的黑盒测试,它们的区别主要在于运行集群的方式。


Kubernetes 和 Operator-SDK 的做法利用 Framework 这一抽象来部署集群环境。


而 Operator-SDK 由于需要部署 CRD 和 Operator,因此基于 Kubernetes 原本的理念做了一些修改,支持从本地或者利用 Deployment 的方式部署 Operator 以便测试。


kubebuilder 采用了类似单元测试的方法,利用 controller-runtime 提供的抽象和能力,在运行时注册 CRD,在测试代码中运行 Operator 的逻辑,依赖已经部署好的标准的 Kubernetes 集群进行端到端测试。但它在默认情况下,没有每个测试使用一个 Namespace 的支持,需要用户自行实现这样的逻辑。


不同的测试选型适合于不同的 Operator,在测试时,大家可以根据 Operator 的特点来确定具体的测试方案。目前来看,社区并没有一个 One for all 的方案。


本文转载自才云 Caicloud 公众号。


原文链接:https://mp.weixin.qq.com/s/_vCZucfzlsKIzElxKnCDcQ


2020-03-02 17:471041

评论

发布
暂无评论
发现更多内容

喜讯 | 拍乐云荣登2020「年度最具投资价值创新企业TOP20」榜单

拍乐云Pano

音视频 拍乐云

投行工作的本质 | 读《投行职业进阶指南:从新手到合伙人》

邓瑞恒Ryan

读书笔记 投资 金融 投行 职业第二曲线

Gemini双子新约交易所系统软件APP开发

系统开发

第八周大作业

小兵

DolphinDB与Aliyun HybridDB for PostgreSQL在金融数据集上的比较

DolphinDB

postgresql 阿里云 时序数据库 DolphinDB 数据库开发

构建一张音视频全球大网究竟需要多少个节点?Pano Backbone技术探秘

拍乐云Pano

音视频 RTC 拍乐云

看到Mybatis源码就感到烦躁,怎么办?

田维常

mybatis

第八周总结

小兵

12.3大数据计算框架MapReduce-编程框架

张荣召

深入浅出理解视频编解码技术

拍乐云Pano

音视频 RTC 拍乐云 视频编解码 视频算法

【涂鸦物联网足迹】物联网常见通信协议

IoT云工坊

物联网 HTTP 通信协议 mqtt coap

云原生体系下的技海浮沉与理论探索

阿里巴巴云原生

Serverless 容器 微服务 云原生 k8s

巨头们为什么要开源自己的技术?解析科技企业对软件开源的态度

Marilyn

开源 敏捷开发

探究神秘的SpringMVC,寻找遗失的web.xml踪迹

996小迁

Java 编程 程序员 架构 面试

12.6大数据仓库Hive

张荣召

12.7作业

张荣召

12.5大数据集群资源管理系统Yarn

张荣召

从物理空间到数字世界,数字孪生打造智能化基础设施

华为云开发者联盟

IoT 智能 数字

区块链应用落地,物流供应链平台搭建

t13823115967

区块链应用

H3C核心交换机故障处理通用流程

GaussDB(DWS)应用实践丨负载管理与作业排队处理方法

华为云开发者联盟

数据 负载 GaussDB

我看技术人的成长路径

阿里巴巴云原生

开发者 云原生 技术人 自我思考 职场成长

公安大数据分析系统开发,情报研判系统搭建

t13823115967

智慧公安

云小课 | 需求任务还未分解,该咋整!项目管理Scrum项目工作分解的心酸谁能知?

华为云开发者联盟

项目管理 敏捷 devcloud

Norvarm波场链系统开发方案丨Norvarm波场源码功能

系统开发咨询1357O98O718

Norvarm波场链系统开发

忒棒了!阿里P8大牛用这份技术点直接带你玩转高可用服务架构

比伯

Java 编程 架构 互联网 程序人生

北京天源迪科与重庆邮电大学移通学院成功签约

DT极客

ICT芯矿链挖矿矿机系统开发平台丨ICT芯矿链源码案例

系统开发咨询1357O98O718

ICT芯矿链矿机系统开发

《微信小程序开发入门与实践》.pdf

田维常

快来!开源一份阿里微服务指导手册:SpringBoot+SpringCloud+消息中间件

Java架构追梦

Java 架构 面试 微服务

12.4大数据计算框架MapReduce-架构

张荣召

Kubernetes Operator 测试面面观_文化 & 方法_才云科技_InfoQ精选文章