嘉宾 | 郑大禹 整理 | ClaireWang
出品 | CSDN云原生
2022年5月17日,在CSDN云原生系列在线峰会第5期"DevOps峰会"上,阿里云弹性技术专家郑大禹对构建阿里云产品的技术进行了解密,并分享了在构建运维编排产品中的云上实践。
运维编排服务(Operation Orchestration Service,简称OOS)是阿里云的免费的云上自动化运维平台,提供运维任务的管理和执行功能。
简单来说,OOS就是通过模板编排的方式,将ECS、RDS等基础云产品所提供的原子能力组合成用户的实际运维场景。
为了实现各类产品能力,OOS被划分为4个部分,分别是:API接入层、工作流引擎、中间件、应用支撑服务。
API接入层:负责运维任务的输入,健全流控和运维任务参数的校验工作。
工作流引擎:承担大批量的运维任务执行,负责模板任务的分解、原子API的编排执行并提供并发处理、错误处理等功能。API接入层和工作流引擎通过MS消息队列来完成通信工作。
中间件:如数据库缓存、消息队列等,中间件周围构建了许多监控以及运维方案。
应用支撑服务:包括线上运维监控、应用稳定性监控及业务报表等。
适用于OOS的产品架构一般具有以下四类特点:
云产品故障容忍较低
业务存在明显的高峰和低谷
产品的稳定性要求高
完全构建在阿里云公有云平台上,最大化利用云上技术红利和最佳实践
针对前面所提到的运维编排服务的特点,我们也遇到了一些挑战。
如何自动化管理云资源——多地域大规模云资源管理
多地域大规模云资源部署和管理是一个非常大的挑战。多地域资源的初始化、应用的部署升级、应用配置的变更本身就是一个比较繁琐的过程。如果变更过程中遗漏了某些地域,会造成应用的故障。
而OOS服务又由多个应用组成,且每个部分的管理需求也不一样,这使得如何管理成为一个挑战。比如API接入层对应用的可用性要求比较高,而工作流引擎部分需要应用有比较好的弹性,应用支撑服务对可靠性要求及在线服务要求可能又会比较低,这些都需要单独配置。
如何构建云上弹性服务——应对大流量及突发流量
随着编排服务的用户越来越多,执行的任务越来越多,这要求应用具有更好的弹性,从而能够应对不断发展的大流量和突发流量。
如何提升服务的可靠性——及时发现线上问题
因为应用稳定性要求比较高,所以我们需要尽力提高服务的可靠性,及时发现和处理线上出现的潜在问题。比如一个任务失败了,用户会在一分钟之内感受到,如果此时我们的应用能够在线上10秒钟内发现执行异常,并且通过重试或者补偿机制来完成此任务,这样就能使服务的可靠性得到大幅提升。因此如何及时发现线上的问题也是一个需要解决的关键点。
下面针对这三大挑战,分享一下我们的实战经验和解决之道。
多地域大规模云资源管理场景
针对多地域的单元化部署,阿里云有30+地域,较一般公有云用户痛点更加突出。
在云资源部署过程中,每一个地域需要部署一套同构的云资源。以OOS为例,云资源包含数十个资源实例,整个资源的配置过程相当复杂,原始手工配置耗时长且容易出错。
在运维过程中,每个地域需要执行一套相同的运维操作,与云资源的部署类似,过程比较复杂,执行时间长且容易出错。
在应用变更时,除了前面这些痛点之外,应用变更还需要适配各种数据库的客户端、缓存应用的变更,也较为复杂。
在大规模应用资源的分组管理方面,因为整个服务被分成三个应用即API接入层、工作流引擎和支撑服务。每一个分组对应用的管理要求不一样,运维时要根据不同的维度来选择性运维,比如只升级一个API接入层,或者只变更API接入层的一个配置。
标准化资源交付
多地域部署同构云资源的构建过程中,我们也遇到了多方面挑战。
云上资源多地域、多类型分布。整个部署过程是多地域多资源类型的部署,传统的手工交互方式很难完成。
快速稳定的交付资源。以OOS某个地域的主要资源示意为例,其中不光包含了大量的ECS服务器,还包括中间件如MIS、RDS、Redis、SLS及其相关配置,还包括所有云资源的监控和告警配置,每种云资源都有对应的监控Matrix。整套系统若采用手动配置,大约需要一周时间,由于配置较为复杂繁琐且容易出错,还需不断调试,这就会造成整套云资源不能快速交付。
快速复制资源到新地域。阿里云还在不断增加新地域,所以如何将这样一套系统原封不动地复制到一个新地域是十分棘手的问题。需要在部署的过程中不断对比两边的配置是否一致,这就会给部署过程造成很大的麻烦。
在实践过程中,我们借鉴了Infrastructure as Code的思想,运用ROS资源编排,将整套OOS的云资源配置模板化,让整个部署过程标准化、流程化。借助ROS的能力,使云资源快速、稳定地交付,大大降低了配置过程的出错概率。
另外,在部署新地域的场景下,将资源地域相关的配置抽取成参数,这样在配置新地域时可以使用相同的ROS模板,只需要填写地域相关的参数,将之前一周左右的部署流程缩短为两个小时。
自动化运维管理
运维场景复杂,与部署类似,整个运维过程是多地域多资源类型,非单一云产品单一功能。
运维操作需多次执行,通常需要进行大批量操作,并且对执行速度有相应的要求。
这时,有人可能会想通过运维脚本来做。
通过脚本确实可以做到自动化,但技术门槛高,需要熟悉对应的脚本语言和云产品的API。其次针对公司内的一些合规要求,脚本执行难以做审计,必须再配合一些专业的审计工具,无形中又提升了门槛。
在实践过程中,我们采用云原生的自动化编排即OOS,将整个运维操作为代码管理起来(Operation as Code),运用OOS将多种常用的运维操作标准化、流程化。
如下图所示,整个运维过程可以同时应用到多个地域、多次执行,能够轻松查看到每个地域每台服务器的执行结果。结合OOS的定时告警等触发功能,能够让运维操作自动化起来。同时由于OOS是阿里云上的云产品,使用阿里云的Open API,所有操作都可以通过Action Trail来审计,能够轻松满足公司的合规要求。
多地域同构数据库管理
之前已经提到,多地域应用配置的变更也是一大挑战。应用除了代码和资源的部分之外,还有很多配置项,最典型的就是数据库的表结构以及数据。
以最典型的数据库为例,作为一个多地域部署的应用,在运维编排账号下,每个地域都有一个独立的数据库实例。这就提高了数据库的运维要求:
一是要求所有地域的数据库表要同构变更,如果某个地域遗漏,其表的结构就与其他地域不同,在升级完新版本的代码后可能会造成故障。
二是新地域数据库需要同步之前所有的数据库变更。随着业务规模的变大,部署地域的增多,手工维护的方式越来越难以维继,数据库变更的可复制性变得越来越重要。
于是,我们在实践中把这种方式切换为通过云上产品DMS对数据库结构进行管理。
通过DMS统一管理线上地域的数据库结构,每次变更时各个地域同步执行没有遗漏,大大降低了出错概率。
新增的地域开服也不需要手工操作,只需要同步一个已有地域的数据库结构,将新增地域也统一纳入DMS管理就即可。在改为DMS统一管理之后,数据库的变更再也没有出现过任何问题,有效减少了变更的出错概率。
多维度视角管理云资源
在大量的云资源中,不同的应用模块特点不一,所以不同的资源需要更加精细化的管理。
以前面所述的运维编排应用为例,Open API接入层对应用的吞吐性要求较高;工作流引擎层对延迟要求不高,但要求应用有比较好的弹性,能够及时根据线上任务进行快速扩缩容;支撑服务层流量比较小,稳定性要求相较于线上系统要求稍低。
资源杂乱无章,需要分类——分组
若不按分组配置,而是按最高的计算需求来配置的话,会增加不必要的成本。因此配置需要根据应用的特点来进行,同时分组也能够实现精细化地管控访问权限。
精细化的访问权限需要控制——分权
我们将整个云资源分为生产环境和预发环境两类。因为研发人员需要进行上线之前的测试工作,所以所有人都需要对预发环境进行访问。而生产环境只有负责线上环境部署和运维的人员才能访问,这样配置能够避免用户的误操作。
精细化的成本控制——分账
精细化的管理可以分析资源的成本做分账,可以多维度查看如预发环境和生产环境的成本,以及每个应用的成本。
因此,在实践的过程中,首先将资源划分为预发环境和生产环境两个部分,再针对每个环境做不同的RAM权限策略的配置,来达到不同用户分权的效果。其次,每个环境又划分了多个应用如Open API工作流引擎和支撑系统,不同的应用特点不一,其中包含的实例类型数量以及配置都是不相同的。
应对大流量以及突发流量场景
随着运维编排用户的增加、请求流量变大、任务数量越来越多,需要应用具有更好的弹性来应对不断发展的大流量请求。
其次,运维业务也会面临突发流量请求,因为某些业务负载与时间或者某些事件呈现相关性。突发性流量请求在时间上存在周期性和不规律性特点,有明显的高峰和低谷,例如工作日是一个高峰,双十一秒杀也会出现高峰。
这就要求构建的应用需要具有高弹性,能够及时处理这些突发的大规模运维任务,在没有任务的低峰时段,能够快速缩容,降低资源成本。
基于计算负载动态扩缩容
下图是OOS某台服务器的CPU使用率采样示例,可以看到这些峰值存在以下特点。
第一,CPU的利用率在峰值上会比较高。
第二,峰值一般持续时间比较短,只有十几二十分钟,针对大批量任务,例如同时管理数千甚至上万台ECS实例时,峰值可能会持续数个小时。
这样就会造成峰值时的计算资源不足,工作流引擎执行量过大,任务的延迟加大(延迟最大会达到十几分钟甚至半个小时)。
传统的云下应用在解决这个问题时,由于云下的资源没有很好的弹性,必须预估出峰值的流量,最后按最大的峰值来预先配置好机器。
当然云上资源也可以采用这样的方案,但这势必造成一个问题:没有真正利用起来云上资源的弹性。
云上产品主要优势就是计算资源的弹性,可以按需的配置和付费,因为峰值往往只是一个相对较小的时间段,长期按峰值配置必然造成成本增加及资源浪费。而预先人工针对负载进行扩容这种方法,对类似于双十一这种可预测的负担稍有成效,但对于不可预测的随机负载来说,人工控制往往很不及时。
如下图所示,针对云下这种按峰值超配的资源方式,虽然能够满足资源的需求,但成本浪费其实是巨大的。
人工扩缩容的方式能够减少浪费,但因为对随机负载的扩充容操作并不及时,会存在时而紧张时而浪费的情况,在资源紧张时会给用户带来不佳体验。而使用基于计算负载的自动伸缩功能,能够更贴合用户的计算需求,减少浪费。
因此在实践过程中,我们采用基于弹性伸缩的产品,以及对工作流引擎计算资源弹性要求比较高的应用进行配置,使其能够根据资源的监控指标如CPU内存的利用率进行动态扩缩容。
基于弹性伸缩的扩缩容方案,OOS成功地将某个地域固定的十台服务器缩减为常备两台服务器。
基于负载动态扩缩容的方式,统计显示每月扩缩容达300余次,节省了约80%的成本。
另外采用该方案还需要注意的是,为了保证新扩容出来的应用为最新版本,每次做完应用的升级后,需要更新对应的弹性伸缩配置,可以通过更新ECS镜像或者User data的方式实现。如果没有对应更新伸缩配置,新扩容出来的机器依旧是老版本的应用,这样会造成线上出现问题。
大容量数据库管理
上面讲到计算资源的弹性,但并不是所有资源都有ECS服务器这样的弹性,比如数据库RDS实例,随着业务的发展,逐渐也有可能会变成应用的瓶颈。
首先业务数据一定会随着业务的发展逐渐积累,而且会越来越多。其次当单表的数据积累到数千万甚至上亿条时,一些日常的业务数据库运维操作也会对线上业务的可用性造成伤害。
下面举两个十分常见的数据库运维场景,在较小数据量的情况下,这些场景直接操作,并没有什么危害。但当数据库积累数据过多时,情况就全然不同。
一个是业务表结构的日常变更,如添加新列,这在业务发展的过程中都是一些常规的操作。
另外一个是数据库的管理操作,如历史数据的定时清理和归档,这也是一些常规的操作。
添加新列的操作会造成锁表,在数据量较小时,该操作只耗时几毫秒甚至几十毫秒,线上的请求只要等变更完毕之后执行即可,并不会对线上的应用造成太大的影响。而当数据量过多时,该操作耗时将增加到几秒甚至几分钟,会造成应用在此时间段内的不可用。
当然我们也可以将这些会造成锁表的操作放在运维窗口中进行停服操作,但随着现在应用的可用性要求越来越高,能停服的时间窗口是比较少的,而这些变更其实是业务发展中很常见的操作,每周甚至每天都要执行,不可能都放在运维窗口来进行。
因此,我们利用DMS提供的云原生的数据库管理能力,对这些大表应用进行无锁变更。基于运维编排的应用特点,我们采用了binlog gh-ost方案。采用这个方案主要是因为需要对变更时数据库的负载进行比较精确的控制,保证数据库不会因为大表的无锁变更使数据库过载,进而影响线上的应用。
而在历史数据清理场景中,DMS也提供了解决方案,DMS可以将单个的SQL拆分成多个批次执行,降低单个批次内操作的数据量,从而降低每次锁表的时间和范围,减少锁表对线上应用的影响。
及时发现线上问题
因为应用对稳定性要求比较高,所以必须尽力提高服务的可靠性。因此如何及时发现线上出现的问题,也是一个关键点。在这里我们将所有的问题分为两类。
1. 云资源工作不正常。这时应用或者还能正常工作,或者已经不能正常工作。不管如何,这时都是线上存在一些潜在的问题。比如CPU内存磁盘等计算资源不足、ECS实例潜在的宕机风险等问题,都需要我们自动或手动进行及时处理。
资源不足的问题,可以通过弹性伸缩来自动的处理。
数据库或中间件的问题。以数据库为例,它也可能会出现计算资源不足的问题,但由于数据库不像ECS服务器容易水平扩展,所以需要根据分析采取扩展只读服务实例,或者是升级数据库配置等方案。数据库还有一个潜在的问题,即慢查询问题。这些慢查询不一定会马上造成应用工作的不正常,但会有潜在的隐患。可以利用RDS提供的工具,来将这些问题及时的告警,手动或自动的分析处理慢查询问题。
2. 另一大类的问题是应用工作不正常,这时资源可能已经报警或者资源并没有什么问题。
我们需要重点关注的是应用逻辑的缺陷,这时一般都会写入错误日志。
另外还要关注相关的Metrics,如API整体的耗时、平均耗时异常增高。
最后还有一些内部业务逻辑的Metrics,这也是业务相关的一个监控点。
云资源监控
针对云资源工作不正常的问题,监控的配置也需要根据应用的特点来划分,不能所有的资源共用一套监控配置。
以OOS为例,API接入层用户对耗时十分敏感,几秒钟内请求没有返回,用户就会感知上报这个问题,因此需要设置相对较低的CPU告警阈值,以触发后续的自动扩容操作。
Engine层相对来说对延迟的容忍度较高,在一分钟内执行完成任务即可,超过一分钟可能用户才会感知,这样就可以把告警以及扩容的阈值设置得高一些。而应用支撑服务基本没有弹性的需求,就只需要配置告警,而不需要配置动态扩缩容。
除了要支持常见的计算资源,包括CPU、内存、磁盘之外,还要支持丰富的中间件资源监控数据,如慢查询数据、连接数数据。
我们需要监控系统支持完善的告警通知功能,能够根据告警的级别及时通知到用户。
告警能够及时触发线上自动化的运维处理,包括通过告警触发弹性伸缩或是OOS能够形成运维场景的闭环,它达到真正的无人值守。
在实践中我们采用云监控作为资源监控,不仅可以和应用的标签分组无缝打通,针对不同的应用分组设定特定的告警规则,还能够支持中间件资源的特定指标。
此外,针对告警进行了分级,比如说慢查询等一般告警只需要钉钉通知即可,对于宕机等比较重要的告警,通过手机短信的方式来进行通知。此外针对有弹性需求的应用,通过弹性伸缩的配置创建对应的告警来触发伸缩活动,自动化处理线上突发的计算资源不足的问题,以上就是我们解决资源问题的方案。
应用监控
对于应用相关的监控,一是要构建不同级别的应用日志,针对不同级别的告警采用不同级别的方式。比如关键的错误日志,可能每条错误都需要告警,而优先级较低的Warning日志,一段时间内比较频繁或者是有异常比例的升高时才需要告警。
在实践的过程中,我们将应用的接入日志、Info日志、Error日志以及Profiling日志都做好分级,在告警中主要关注是应用的错误日志,只需要通过SLS把将要关注的错误日志告警提取出来,以方便后续人工或者自动的及时处理。
另外针对一些复杂的调用链路场景,我们也会采用Traces数据来做错误以及性能的分析。
最后我们还会在应用中生成一些Profiling的数据,专门用于构建业务和性能分析的报表,比如每天执行的任务分析、任务执行效率的分析报表等。
本文主要分享了云上构建应用的三个大问题。
如何自动化管理云资源。因为云上的应用天然具有多地域多资源的属性,使得我们必须基于云原生的方式做标准化的资源交付、多维度的云资源分组,从而方便后续资源自动化运维的管理。
构建云上的弹性服务。应用需要构建为云上的弹性服务,充分利用云上资源弹性的优势。不然即使应用上云,却没有享受到云上的技术红利,其实是得不偿失的。
提高服务的可靠性。因为应用对稳定性的要求较高,因此利用资源以及应用的可观测性作为开发人员及时发现和解决线上问题的方法,能够帮助我们大幅提高服务的可靠性。
聚焦云原生新技术、新实践,帮助开发者群体赢在开发范式转移的新时代。欢迎关注CSDN云原生CSDN云原生微信公众号~