系统成功率99.99%+,美团CI/CD流水线引擎演进实践( 三 )


进一步分析 , 串行调度主要是为了避免资源竞争问题 , 获得相对最优的资源 。 这对于流水线场景(作业量大于资源量且都是短时作业) , 资源最优解不是强诉求 。 并且 , 资源量的并发度相对作业量更可控 , 根据作业执行快慢不同 , 我们通过主动拉取作业的方式 , 控制拉取的数量和频率 , 从而有效降低了资源竞争的情况 。
最终 , 我们在设计上采取了调度决策与资源分配分离的模式:调度决策:负责计算出可以调度的作业 , 提交决策 , 等待合适的资源来执行 。 该模块具体水平扩展 , 分担调度决策的压力 。 资源分配:负责维护作业与资源的关系 , 通过主动拉取作业的方式 , 资源可以向任意的实例拉取作业 , 取消了原先串行分配资源的单点限制 。
在这种模式下 , 作业调度、资源分配都具备水平扩展能力 , 拥有更高的性能和系统可用性 。 也利于作业调度的逻辑能够独立演进 , 便于开发、测试以及灰度上线 。
2)引入资源池管理模式 , 实现资源的灵活分配
考虑到不是所有资源都由引擎管理 , 我们引入资源池的概念来屏蔽不同资源方式的差异 , 每个资源池代表一类资源的集合 , 不同资源池的资源管理方式可以是多样化的 。 通过该方式 , 我们将资源分配的问题简化为作业与资源池的匹配问题 , 根据作业的实际情况 , 合理设置不同的资源池大小 , 并配合监控手段对资源池进行动态调整 。
在具体措施上 , 我们选择“标签”的方式建立作业与资源池的匹配关系 , 通过从作业与资源两个维度来满足上述条件 。 在作业端 , 作业基于标签属性拆分到不同的作业队列 , 并引入优先级概念 , 保证每个队列中作业按优先级高低被拉取到 , 避免在积压时 , 高优作业排在后面无法被及时处理 , 阻塞业务研发流程 。 在资源端 , 结合资源的实际场景 , 提供三种不同的资源池管理方式 , 以解决不同资源类型的配额和利用率问题 。
a.预置的公共资源 , 这部分资源会提前在资源池上扩容出来 , 主要应对业务高频使用的且对时间敏感的组件作业 。 在资源配额和利用率上 , 根据资源池的历史情况和实时监控 , 动态调整不同资源池的大小 。
b.按需使用的资源 , 主要针对公共资源环境不满足的情况 , 业务需要自定义资源环境 , 考虑到这部分作业的体量不大 , 直接采用实时扩容的方式 , 相比预置资源的方式 , 可以获得更好的资源利用率 。
c.外部平台的资源 , 这些资源的管理平台方比我们更有经验 , 平台方通过控制向引擎拉取作业的频率和数量 , 自行管理作业的吞吐情况 。
3)引入组件的分层设计 , 满足工具差异化需求
为了保持工具接入的自由度 , 引擎提供了作业维度最基本的操作接口(拉取作业、查询作业状态、上报作业结果) , 不同工具可以根据作业接口形式实现定制化的组件开发 。
组件开发主要涉及①实现业务逻辑和②确定交付方式两部分工作 , 而与引擎的系统交互相对是标准的 。 我们根据组件执行过程进行分层设计 , 拆分出业务逻辑、系统交互与执行资源三层 。 在向引擎屏蔽工具实现细节的同时 , 可以更好地满足多样化的接入场景 。 系统交互层 , 该层相对组件开发者是透明的 , 根据引擎提供的接口制定统一的流程交互标准 , 以向引擎屏蔽不同组件的实现差异 。 执行资源层 , 主要解决工具运行方式的差异化 , 通过支持多种组件交付形式(如镜像、插件安装、独立服务)满足工具与引擎的不同集成方式 。 业务逻辑层 , 针对业务不同的开发场景 , 采用多种适配器的选择 , 来满足业务不同的开发诉求 。