【阅读原文】戳:Moka:ACS容器计算服务助力CI/CD场景提效降本70%
前言
作为国内发展最快的HR SaaS厂商之一,Moka以“全员体验更好”为产品设计的核心理念,致力于为大中型企业提供“AI原生”的人力资源管理全模块解决方案。
Moka智能招聘管理系统:致力于通过完整的招聘生态体系,帮助企业提升招聘效能。覆盖社招、校招、内推、猎头管理等场景,让HR获得更高效的招聘体验、更便捷的协作体验,让管理者获得招聘数据洞见。让招聘降本增效的同时,树立企业在候选人心目中的专业形象。
智能人力资源管理系统Moka People:产品覆盖企业所需的组织人事、假期考勤、薪酬、绩效、审批等高频业务场景,打通从招聘到人力资源管理的全流程,为HR工作提效赋能;通过多维度数据洞见,助力管理者高效、科学决策;全生态对接,更加注重全员体验,是一款工作体验更愉悦的人力资源管理系统。
2020年开始,随着Moka的业务规模不断扩大,原有的传统架构已经不满足快速迭代、稳定性等需求,所以底层基建逐步从传统架构迁移到云原生架构。这里选用了阿里云的ACK产品家族,因此也获得了云原生很多优秀的能力,比如自动调度,自动修复,快速扩缩、水平扩展和负载均衡能力等。由于灵活的资源设置,相比于传统架构,能更好地控制资源使用率。
从2023年开始,受整体市场环境影响,降本增效成了大部分互联网公司的重要指标。与此同时我们也开始着手调研容器化场景提效降本方案。在2023年阿里云便开始孵化容器化Serverless产品ACS,Moka在ACS产品初期就与阿里云产品团队紧密联系产品需求及体验反馈,在今年年中ACS面向用户开放,同时我们快速引入该产品,在各个场景都进行了调研,并且取得了良好的效果。本文将着重分享我们使用ACS在CI/CD场景的最佳实践。
业务架构与痛点
流程说明:
目前使用的gitlab-runner部署在ACK集群(ops),底层节点池为多台高配服务器,月成本1w+。
在研发提交完代码后会自动触发一系列的任务,比如sonar检查,构建镜像,自动合并分支等等Job。
这些Job由部署在ACK中的runner生成一个Job类型资源,调度到后面的Node节点池上。
核心痛点:
• 白天Job并发量高时,拥塞严重,CPU使用率持续100%,或磁盘读写高,机器会夯死,构建会有毛刺情况。
• 单台服务器夯死,会导致所有运行中的Job失败,所有相关的Job要人为去重试,研发人员体验不好。
• 如果采用节点方式扩缩容,需要人肉维护Node节点:清理镜像缓存,排查Job失败原因,重启服务器等操作,维护成本高。
• 日忙夜闲,周末几乎闲置,资源使用不均衡,资源利用率不高。
方案设计
目前针对以上痛点,我们需要算力具有以下特点:
1. 按量使用Serverless方式,按量按需的使用算力;固定节点方式周末和晚上闲置,白天利用率不高存在64%的算力浪费。serverless这种方式在cicd场景比较适合。
2. 算力需要相互隔离,避免任务之间相互争抢和干扰,避免构建体验不好问题。
3. 迁移成本低。
通过对ACS产品的调研,该产品符合我们以上诉求;我们决定在ACK中使用ACS弹性容器算力来解决我们的问题,主要是因为ACS的以下优点。
- ACS特性 -
ACS可以直接在ACK中使用,通过virtual Node插件机制,容易上手
ACS算力精细,容器算力最小支持0.25 vCPU 0.5 GiB,以及算力质量可选default & best-effort(相对default价格低80%,比较适合构建这种时间较短任务)
ACS计费灵活,按需弹性申请使用,秒级按量付费,还有节省计划可用。
- 前置问题 -
关于ACS
ACS使用方式是否足够简单?接入Runner的配置是否支持?
pod的调度启动速度是否足够快?
构建速度是否会受影响?
关于内部
dind构建问题:
所有Job中,程序打包和镜像构建的Job为dind方式,目前是挂载Node节点的docker.sock文件。如果使用ACS,无Node节点概念,这里需要如何解决?
构建速度问题:
程序打包,镜像构建的Job是依赖于Node节点的镜像缓存,和宿主机目录缓存来实现构建加速,如果使用ACS,构建速度是否会下降?如何保证相同的构建速度?
实现步骤
一、配置ACS,并且安装gitlab-runner
首先在ACK中安装ACK Virtual Node,目前ECI和ACS都在此组件中控制,由于之前安装过,我们只需升级授权ACS即可。
安装好了之后我们就可以设置对应的runner了。
为了不影响原有的runner,使用Helm重新安装了一个带ACS标签的runner,更改values.yaml文件。
按照以下步骤修改:
1. 带ACS的标签。
2. 定义runner的资源配额,此处不需要太大资源,因为runner不真正执行Job。
3. 配置runner的标签,确保调度到ACS上,这里使用default算力,避免被资源抢占。
4. 配置让runner生成的Job也调度到ACS上。
这里设置的Job的标签,以及调度的pod使用的资源配额,算力为通用型best-effort,费用更加便宜。
此处注意:特权容器必须要打开privileged = true。
5、最后helm安装即可
helm upgrade --install --namespace gitlab-runner gitlab-runner -f values.yaml gitlab/gitlab-runner
然后就可以看到gitlab的runner列表中注册了一个ACS标签的runner。
二、dind之:适配ACS
原有配置:
runner的 values.yaml文件关于dind的配置为:
是通过直接挂载宿主机docker.sock文件来进行docker通讯。
.gitlab-ci.yaml文件关于镜像构建的写法为:
方式为直接在pod上运行一个docker容器来实现docker -t命令的镜像构建。
适配ACS配置:
经过测试需要做出以下修改,runner的values.yaml做出以下修改,并且更新runner组件即可。
.gitlab-ci.yaml需要做出以下修改
实现效果:
可以从runner中看到Job已经调度过来
从ACS后台可以看到Job也已经在运行
这里我们测试了一下耗时,从gitlab界面点击到runner开始调度Job,在5~8秒。Job从初始化运行起来,根据任务的不同,基本在6-10秒不等。速度相对于原有的方式有细微的提升,并且各个构建任务相互不受影响。
三、构建缓存:oss
经过测试,目前在ACS上Job的速度,除了构建的步骤,比如代码检测,安全检测等Job,时间相差无几。
构建的步骤主要是因为要从私有仓库下载文件,以及要读写磁盘,所以初期测试结果会比在Node上慢30s左右。
于是我们统一优化了之前的runner缓存配置,启用oss作为缓存层,每次构建都会去拉oss的缓存文件,构建完后上传。
runner的values.yaml做出以下修改
.gitlab-ci.yaml中指定cache的key定义,以及需要缓存的目录
则即可在触发的Job中看到对应的上传下载。
经测试运行一段时候后,发现ACS调度的Job与在Node节点调度的Job运行时间差不多,在某些情况下,反而更快,因为减少了资源抢占等问题。
关于CD的Job改造,这里就不赘述了,只要给Pod设置指定的Labels信息即可,使用起来非常简单方便。
最终的架构
目前替换了80%的Node节点池,直接使用ACS进行Job调度,避免闲时资源浪费,总体成本也有所下降。
业务价值
自从ACS上线后,已经支持了我们每日几千个Job的调度,之前的资源抢占问题,以及Job经常失败的问题已经基本解决了。最终我们保留了20%的机器作为备用节点,ACS同时也为我们的成本优化做出了巨大的贡献,费用相对于固定节点方式更加节约,使用起来更加方便。
后续计划我们将在开发测试环境,生产环境中逐步推广使用,加速完成我们降本增效的目标。
我们是阿里巴巴云计算和大数据技术幕后的核心技术输出者。
获取关于我们的更多信息~