摘要
本文简单介绍了分布式全闪的基本架构,根据对存储架构的理解和软件自动化测试系统理论的研究,指出软件自动化系统需涉及的主要方面,为软件自动化测试系统实现奠定基础。根据软件测试需求(功能、可靠性、性能),列出自动化系统的各个模块,逐步细化、设计,实现能与测试流程融合的自动化测试框架。在此基础上,还提出了未来自动化测试系统后续的优化方向,让大家意识到软件自动化测试的合理应用是软件开发过程中降本增效的关键。
引言
·分布式存储是具有独特系统架构的数据存储技术,它可以聚合复数主流的服务器来完成单个节点无法完成的计算、存储任务,通过网络使用每台服务器上的磁盘空间,并将这些分散的存储资源构成一个虚拟的存储设备,真实数据分散在众多节点上。要设计出一个良好的分布式软件系统需要考虑很多因素,如可靠性、安全性、可扩展性、可定制化、可伸缩性、可维护性、用户体验等,架构设计的复杂性使得系统测试也至关重要。如果测试人员漫无目的的进行探索性测试,而不了解系统的内部原理,最终浪费了时间,却达不到理想的效果,所以我们要求测试人员必须从方案设计之初甚至是讨论需求的时候就和开发在一起讨论,测试需要比开发更加理解系统的设计原则。
·随着软件业的迅猛发展,软件测试也变得尤为重要。分布式系统测试从大的方面来看可分为三种,分别是可用性、性能、可靠性。可用性是指系统正常功能的响应、系统的扩展性和避免宕机的能力,是分布式存储最基本的能力;性能测试是分布式系统的关键,我们通常用IOPS、Throughput和Latency来测评一款存储系统,理想中的存储系统,可以满足任何业务需求;分布式存储天生包含大量的交互、依赖点,潜在问题极多,在生产环境中实际运行一个分布式系统,各种不可预期的突发事件是一定会发生的,任何一次处理不好都有可能导致业务停滞、性能低下,所以可靠性是分布式存储的基石,也是用户最关心的问题。
·分布式系统测试从执行的角度可以分为手工测试和自动化测试,在大数据时代,测试用例数量非常庞大,由于手工测试回归效率低、具有偶然性和不确定性、回归的覆盖率也不足,为了加快测试结果反馈,提升测试质量,设计一套自动化测试体系势在必行。
全闪分布式简介
FASS是大道云行( TaoCloud)面向IO密集型应用场景,完全自主研发的分布式全闪存储系统。它采用高性能的全闪存硬件平台,针对NVMe闪存介质设计了高效的分布式存储软件栈,FASS可将多个节点的SSD资源通过高速以太网或Infiniband网络组成高性能、高可用、易扩展的块存储资源池,并通过 iSCSI、iSER、NVMeoF存储接口对外提供超高性能的存储服务,可广泛应用于各类高性能需求场景。FASS架构的设计在本文不做具体分析,只做一个简单的介绍,主要可分为以下四个方面:
·****IO引擎 IO引擎负责解决数据在单机上存储,每一个IO引擎之间是隔离的,为实现CPU多核心的高效分配,FASS 软件绕开了操作系统的CPU调度器,用协程取代内核线程做任务调度。通过FASS专属的CPU调度和内存管理,基于微控制器实现高效的并发流水线作业,从根源上解决存储系统的性能问题。
·****一致性模型 FASS采用Raft like的共识算法,在算法的基础上做了很多工作,将这个复杂的问题划分为数个可以被独立解释、理解的子问题,减少需要考虑的状态数,使得算法更加清晰,减少不确定性,实现了顺序一致性。
·****存储接口 FASS存储集群支持标准的iSCSI、iSER、NVMeoF存储访问协议,可基于以太网或Infiniband网络,为业务应用场景提供高性能块存储服务。
·****元数据服务 元数据服务提供的功能一般包括:集群成员管理,数据寻址,副本分配,负载均衡,心跳,垃圾回收等等。为发挥出硬件的最大性能,FASS 通过多层元数据索引进行数据切片,高效定位与管理,主元数据服务管理数据到各个节点的映射关系,通过元数据查询可以迅速定位到数据的存储节点;同时每个节点上都维护有一份本地数据块索引,通过 K/V 数据库(redis)记录了本节点所有数据盘上Slice分布信息,并将其缓存在内存中,实现了远高于其他分布式存储系统的 I/O 性能。
IO路径图
各个ctl详细描述:
tgtctl:目标端控制器,转发IO请求到本节点内同一NUMA节点上的frctl并进行下一步IO处理
frctl:前端控制器,负责IO路径管理与选择,并将IO转发到bactl进行读写落盘
rangctl:子卷控制器,向mdctl查询并缓存子卷元数据信息,并负责子卷的数据分布管理,协调卷IO读写、修复、平衡等任务
mdctl:元数据控制器,运行KV数据库,提供元数据查询与持久化写入管理,其中一个mdctl充当master角色。
bactl:后端控制器,负载管理本地磁盘的数据读写,提供数据的写入和读取服务。
自动化测试
手工测试往往作为存储测试的起点,而软件测试的一个显著特点就是重复,重复的人工操作势必造成低效率和错误。自动化测试拥有更好的精确性和效率。自动化测试开发与软件开发过程从本质上来讲是一样的,经过对测试需求的分析,设计出自动化测试用例,从而搭建自动化测试的框架,通过设计与编写自动化脚本,保证软件的正确性。
定 / 义
·自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程
**原 / 则 **
·自动化测试用例的范围往往是核心业务流程或者重复执行率较高的。
·不是所有手工测试用例都可以使用自动化测试来实现的。
·测试用例一般需要回归原点,即故障隔离。
·不需要每个步骤都写预期结果。
·对合理的和不合理的输入数据都要进行测试。
·长期完整地保留所有的测试用例和测试文件。
**内 / 容 **
·****功能测试,针对验证整个存储系统的逻辑实现。功能测试是试图发现程序与其外部规格说明是否冲突的过程。外部规格说明是一份从最终用户的角度对程序行为的精确描述,测试时按照科学方法设计的测试用例执行测试,在优先保证测试用例执行完全的前提下,再根据对业务的了解和经验性的判断进行探索性测试。分布式存储中除了基本功能外,还包括一些高级特性,比如快照和Qos。
①集群配置的增删改查
②一些特性配置后是否生效
③快照的创建、删除、回滚、分离、克隆、保护
④集群异常情况下,能否正常对外提供服务和接口
·****可靠性测试,针对验证元数据服务和一致性协议的实现。分布式系统的一个重要问题就是数据的复制,但复制数据的同时也带来了一个难点,就是如何保持各个副本数据的一致性。在实际生产环境中,集群中的节点、网络、磁盘随时都会有问题,那么就可能会导致写入的数据出现乱序或者丢失,我们需要通过实验证明生产环境下的分布式系统在面对失控条件的时候依然具备较强的可观测性和故障恢复能力。首先需要一个或多个故障模型来触发分布式存储软件的一些特殊机制和策略(用于解决分布式存储中共性问题,如下),其次是客户端要实现一个工具来检查读写数据。
①模拟节点反复故障,导致集群不停选主,客户端请求超时
②模拟网络分区导致的脑裂
③模拟磁盘坏块导致的数据损坏
④模拟网络延时导致的包乱序
⑥系统时钟回跳自动Failover的影响
·****性能测试,主要针对验证IO引擎和接口协议的实现,和元数据的管理实现也有很大关系。性能指标主要包括IOPS、带宽、延时,可以展现小文件和大文件的处理能力。分布式存储的性能测试维度有很多,维度的不同一定会导致结果有很大差异,比如cpu核数的分配和绑定、客户端和卷的数量、存储接口协议、存储引擎选择等。除了集群正常情况下的性能结果,我们还需做一些额外的测试:
①集群修复时性能对比
②集群做均衡时性能对比
③快照后性能表现
目 / 的
·优化测试速度:可非常快速的运行上千条记录
·提高准确性、稳定性:可以不为外界因素干扰,准确运行测试用例
·确定性:能真实快速搭建测试环境,测试数据,重现缺陷
·提高工作效率:一边运行自动化测试,一边准备测试报告
·测试环境搭建:可以结合多种编程语言及技术协助搭建测试环境,防止手工测试重复劳动,如批处理技术
·提高技能:可提高测试人员技能,同时提高对测试的兴趣,防止对手工测试感觉枯燥
自动化体系设计
自动化体系的定义是为解决某些特定问题而约束边界、支撑整个问题解决方案、配套了一些解决问题的组件而构成的工具。它大概包括测试对象,测试组件,基础类和函数,工具类,测试数据,异常处理,测试日志,断言和测试报告等这些模块。在设计的时候,我们要尽可能的将这些模块有机的结合起来,将脚本能够有效的组织、连贯应用起来,提高测试脚本的可维护性和可读性。FASS内部测试体系由如下几个模块组成:
部 / 署 / 模 / 块
通常需要每次总是重复的手动敲入命令来实现测试环境的部署,对于这样的安装环境过程;看着是很着急的,甚至很容易出错的。所以部署模块通过python封装ansible库,来实现批量系统配置、集群程序部署、集群运行命令等功能。ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的。
功 / 能 / 模 / 块
它把软件对象当做一个黑盒子,不用考虑软件对象内部结构和处理过程,只需要按照产品规格文档的要求来验证。测试人员预先设计好每个小功能对应的测试用例来验证,测试用例主要内容包括:执行环境、执行步骤、预期结果。在分布式存储的领域,自动化会使用底层命令行、web管理平台API来分别做功能测试。测试项主要分为以下几个部分:
·合理正向功能、反向功能
·不合理正向功能、反向功能
·高级功能,快照、Qos配置等
·存储引擎:用户态/内核态配置
·存储接口:iscsi/iser/nvmf
可 / 靠 / 性 / 模 / 块
分布式存储中面临很多出错的可能性,比如机器宕机,网络分区,程序崩溃等等。要提供一个稳定可靠的分布式系统,必须能够保持健壮,即使在出现上述问题的时候也能尽可能保证提供服务,同时也要能保证正确性。为了验证可靠性,我们在测试中注入多种故障类型来验证一致性算法是否可行,可靠性模块主要包括两个故障模型和一个客户端验证工具组成:
·****静态故障模型--CT CT属于黑盒的故障模型,它不会关心集群内部状态,只管生成故障序列。模型有两个分支,分别为单节点和多节点,单节点是随机在集群选一个节点做故障注入,多节点是随机在集群中选多个节点做故障注入。故障主类型可分为:物理盘、网络、节点、服务、集群,每个主类型还会细分故障方法。主函数只需要调用故障生成器就可以,调用的时候需要指定fault number(m),然后接口返会回一个故障序列集合(C),主函数会依次执行集合里面的元素,且每个元素都可以loop多次,每个集合也可以loop多次。在模型里面,每一个用例都包含了完整的操作步骤(测试步骤都是预先设计好的),无论单节点还是多节点故障序列,它们之间都要做故障隔离。
·****动态故障模型--MBT 该模型属于灰盒故障模型,要求测试开发人员理解掌握存储内部实现原理,它会制定l两个行为之间的关系以及行为和分布式系统的关系(有限状态机),模型会根据被测系统的状态、之前设置的限制条件和策略来生成很多用例,每执行一次生成的用例会不同,测试结果受一系列操作的影响,可以产生不确定性,更有可能发现一些想不到的很深路径下的BUG。MBT模型里面的故障类型更加丰富,除了CT模型包含的,还包括模拟负载的增加、资源的耗尽、网络延迟和分区、上行或下行输入的大幅波动以及重试风暴、时间同步不正确、服务之间不正常的或者预料之外的组合调用、资源竞争条件、下游依赖故障。MBT模型大大提高了测试自动化水平,但也有一定的缺陷,如‘状态爆炸’,这对检验,评审和维护都增加了难度,也直接影响了测试自动化。该问题需要通过抽象和排除方法来减小测试规模,对生成故障序列做裁剪,降低测试难度。简单举了一个mbt里面的测试用例,如下图所示,A为leader,客户端写入w1到A,A->commit->apply,但B和C还没有commit,此时客户端r1是正常的,但如果在测试中模拟A掉线,再次r2,假设B通过选举成为leader,但B并未收到commit index,如果存储软件不做策略进行优化,B就不能正常返回w1的结果。
·****客户端一致性工具-Suproc 一致性模型给定一组规则规定相关的操作导致的状态转化,如果一个系统的操作历史在任何情况下都符合这个规则,那我们认为这个系统是符合这个一致性模型的。验证过程的时候,通常分为data centric和client centric两方面。data centric站在底层数据层面,以数据事实作为一致性判断的标准;client centric则是以用户的角度来看系统的一致性,用户层面不关心底层具体实现,只关心自己读取和写入的数据的一致性。Suproc便是一个为了用来验证客户端数据一致性的工具,它从用户视角来看,只关心数据最终是否会一致。详细设计如下所示:
性 / 能 / 模 / 块
封装开源客户端测试工具,比如fio、vdbench、perf等。
全方位的了解我们的软件系统,可分为这几个维度:接口协议、I/O驱动、客户端配置、读写类型、numjobs*qd,具体如下图所示。
测试前,要了解记录硬件信息,计算集群中所有盘的读写性能以及网卡的性能,判断是否有硬件瓶颈,并根据测试结果判断是否完全发挥了硬件的性能,如果没有,就进一步排查问题。
测 / 试 / 报 / 告
无论测试中途失败还是测试完成,都要经由特定媒介发送至管理员等相关责任人,邮件中需要包含一些重要信息:测试结果、测试环境信息、测试用例通过率和失败率。如果测试失败,发送邮件至开发人员,如果开发人员回复确认是问题,则会自动提交bug至gitlab相关项目下并指给该开发人员;如果没有开发人员回复,则下次测试会忽略这次失败的邮件提醒。
状 / 态 / 检 / 查
有专用线程来进行状态检查,每隔120s检查一次,一旦发现异常,即时通知相关测试人员。检查的内容主要有三点:
·集群是否产生core dump
·客户端Suproc是否异常
·命令行是否执行失败
流 / 程 / 图
自动化后续改进
本文所设计的自动化测试框架虽然达到了预期的效果,但还有较大的改进空间,需要进一步的实践论证。在未来的工作中,以下几个方面还可以进一步的深入讨论和研究:
持 / 续 / 集 / 成
持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。持续集成并不能消除Bug,而是让它们非常容易发现和改正。后续计划整合gitlab和测试框架,设计一个任务调度引擎,当开发每次提pr之前(premerge),便会自己触发测试,测试结果将以邮件的形式汇报给开发人员,如果测试通过则提交,后续发布给测试人员进行下一步的测试任务;反之开发自行调试,CircleCI。
业 / 务 / 场 / 景 / 测 / 试 / 自 / 动 / 化
·对接k8s csi接口
·对接oracle、mysql等数据库
·对接vmware、kvm等虚拟化平台测试
测 / 试 / web / 管 / 理 / 平 / 台
·灵活自定制测试流程、界面及业务规则
·中心测试用例库可视化
·多种测试结果实时分析报表
·测试配置文件灵活修改
·全面呈现测试任务的跟踪进展 (browsing、creating、modifying、deleting)
总结
本文简单介绍了分布式存储系统的设计,重点描述了自动化测试整体上的设计思路和实现,每个模块只是简单描述了一下,可靠性模块是测试框架的核心模块,这里我们先不展开做详细剖析,后续会根据它做一个专题分析,本文主要研究工作有以下几点:
·围绕分布式全闪(FASS)进行了分析和研究,了解了存储系统的核心组成:元数据、I/O引擎、一致性协议、存储接口。通过对它的了解,来进行测试分析和自动化的实现。
·为保证产品的完备性和质量,定义了自动化测试整体的原则、内容、目的。
·介绍了测试架构的模块组成以及模块之间如何协同工作,未来基于这个框架原型做哪些优化工作。