PingCode DevOps 团队:企业CICD流水线可能会遇到的问题及解法

CICD 流水线是指一系列自动化的构建、测试和部署步骤,用于将应用程序从开发到生产环境的过程。在 CICD 流水线中,每个步骤都是自动化的,并且在完成后会触发下一个步骤的执行。

CICD 的价值

CICD 流水线可以帮助团队更快地交付产品,减少手动错误,并提高软件质量。通过自动化构建、测试和部署过程,团队可以更快地检测和修复错误,并更快地将新功能推向市场。

CICD 工具链

通常由8个部分组成

  • 源代码管理:用于存储和管理应用程序代码的工具,代码管理是 CICD 工具链的基础,提供了代码的版本控制、协作和管理功能,例如 GitLab、GitHub、Bitbucket 等。
  • 构建工具:将源代码编译成可执行文件或软件包的工具,例如 Maven、Gradle、Webpack 等。
  • 测试工具:自动化执行测试用例并生成测试报告的工具,例如 JUnit、Selenium 等。
  • 镜像构建:构建和管理容器镜像的工具,例如 Docker、Kaniko 等。
  • 制品管理:存放业务镜像的仓库,在应用部署时需要拉取。例如:Harbor、Registry、云厂商私有仓库等。
  • 监控工具:用于监控流水线运行过程中的状态,如资源占用、负载情况,为流水线性能优化提供数据基础。例如:Prometheus、Grafana、EFK 。
  • 部署工具:用于将代码构建完成的制品发布到目标环境中,例如 Jenkins、GitLab CI、Travis CI 等。
  • 自动化工具:用于代替分散脚本执行各种自动化类操作,使执行流程更加清晰有序。例如:Ansible、Puppet 等。

CICD 的演进历史

从CI/CD发展历史来说可以大致分为以下几个阶段:

1、人工发布阶段:开发或运维人员通常需要手动构建和部署应用程序。这种方法非常耗时且容易出错,因为它需要手动执行多个步骤,并且容易遗漏某些步骤。

2、脚本发布阶段:我们称之为“半自动化”阶段,人工手动操作的步骤严重困扰了开发和运维人员,过于耗时耗力以及手动执行具有一定的不可靠性存在。于是开始寻求用脚本来替代一部分人工操作,如 shell、python 脚本,但长此以往依然消耗开发运维人员大量时间成本,发布不够规范依然在持续

3、自动化发布阶段: 为了进一步规范发布流程,规避人为操作所带来的风险,提高发布效率,多数公司开始构建自己的 CI/CD 发布系统,这样的好处是无需人工介入,脚本内容不易被篡改。

4、智能化发布阶段:人工智能大数据时代,一些优秀的公司已经开启智能化 CI/CD 系统,通过引入数据分析、智能预测手段,进一步优化发布流程、提高发布效率。

在这四个阶段中,每个阶段都是在前一个阶段的基础上发展而来的,并且每个阶段都可以提供更高效、更可靠和更安全的软件交付过程。

进入自动化时代以后,CI/CD 效率虽得到了大幅提升,但架构的维护过程中依然会遇到各种各样的问题需要解决,下面我将介绍大多数企业在整个维护过程中可能会遇到的流水线问题以及优化方案。

企业CICD流水线可能会遇到的问题

Jenkins 当属业内持续集成老大哥,有着丰富的插件,适用于大型流水线方案的建设以及大多数场景,受到不少企业用户的追捧,所以本文主要基于 Jenkins 建设的流水线方案为核心从运维角度来讲述可能存在的瓶颈及优化点。

1、Jenkins Master 与 Worker 共用宿主机带来的失联问题

有些企业为了方便部署以及尽可能的节省服务器资源选择 Jenkins Master 与 Worker 共用宿主机,当流水线数量较少或 stage 耗费资源较少时无明显感知。随着项目越来越多,流水线数量的也随之增多,这种架构开始出现瓶颈,多个 Job 并行构建占用资源较多导致系统负载增高,Master 与Worker 之间的通信也会受到干扰,重连超时导致 Job 最终失败。

建议优化方案:

  • Jenkins Master 与 Worker 分离部署,可以允许Worker有短暂的高负载波动,不至于拖垮所有流水线
  • Jenkins Master 优化连接时间相关参数
  • Worker 主机负载高优化
    • kubelet 配置系统资源预留,保障系统进程的稳定性
    • kubelet 限制 maxPods 来硬性控制并行构建数,超出限制会进入队列等待
    • Jenkinsfile 中 PodTemplate 部分容器增加 resourceLimitCpu 参数限制最大使用CPU额度
      • 这一点是防止某个Pod无限制使用资源导致卡死

2、代码依赖缓存拉取的问题

默认走官方源拉取依赖多多少少会遇到网络稳定性问题,导致Job的构建成功率降低,影响产品交付效率。

推荐优化方案:

  • maven
    • 推荐 nexus 私服
  • npm
    • 使用淘宝源
    • 使用阿里云私有仓库,可以有效解决私有包的权限问题
  • 缓存目录映射宿主机实现持久化,减少每次拉取的网络消耗

3、Docker 构建业务镜像体积大,耗时长

对于小型项目优化的必要性不大,大型项目的弊端较明显。

建议优化方案:

  • 养成良好编写 Dockerfile 的习惯,合并多 RUN 步骤,减少 layer 层级
  • 注意 ADD/COPY 的用法,禁止使用先 COPY 后解压操作,对于大型碎文件目录建议归档为 tar 包后使用 ADD 上传(大量碎文件会影响性能)
  • Dockerfile 使用多阶段构建,最终镜像打包只引用构建产物
  • 使用 .dockerignore 来忽略 docker build 时不需要加载的文件或目录,节省构建时间
  • 基础镜像的选型很重要,根据所属项目依赖来确定满足需求最小基础镜像

4、镜像推送拉取慢

包含运行时镜像、打包基础镜像、业务镜像等

建议优化方案:

  • 无论是公共镜像还是私有镜像尽量都使用私有仓库走内网传输,避免使用官方仓库。
    • 常见私有仓库:
      • 阿里云云效私有仓库
      • AWS ECR
      • Harbor
      • Registry
      • 等…
  • 流水线宿主机本地长期保留常用镜像

5、代码打 Tag 后 Jenkins 拉取版本有误

开发打 Tag 后触发 Jenkins 流水线,流水线访问仓储获取 Tag 代码,但偶尔会遇到流水线获取到的Tag与预期不符,引发网站访问报错

建议优化方案:

  • 这可能是一个 bug,偶然出现
  • 可以使用独立部署 webhook 服务来主动触发 Jenkins 的方式彻底解决

6、Jenkinsfile 文件多,管理难

一般 Jenkinsfile、Dockerfile 等文件都会存在在业务仓储内,如果企业仓储较多,而 Jenkinsfile 又不能共用的情况下就会面临统一管理的问题。

建议优化方案:

  • 简化版
    • 只需要将各仓储相关文件转移至统一仓储,Jenkins 先拉取管理仓储,再在 stage 中拉取业务代码来实现,不必合并所有Jenkins的内容
    • 优势:
      • 不依赖额外插件,属于轻量型
      • 与业务解耦
    • 劣势:
      • 统一修改较耗时
  • 复杂版(推荐,但不建议代码逻辑过于复杂化)
    • 基于 Global Pipeline Libraries 插件做代码整合,通用部分提取到单独文件复用
      • 官方文档: https://www.jenkins.io/doc/book/pipeline/shared-libraries/ 
    • 优势:
      • 复用部分一处修改生效全局,减少代码量
      • 节省一定的时间成本
    • 劣势:
      • 复用部分的修改需要慎重,尽量使用判断
      • 需要一定的 Groovy 代码基础

7、多条流水线并行构建的问题

当 Worker 节点为固定时,资源少会导致流水线排队,整体效率低,资源多可以满足高峰期的并行构建需求,但空闲时间又会浪费成本。

建议优化方案:

  • 使用云厂商的 Serverless 产品按需付费,只对Pod资源限制
  • 使用云厂商的 Autoscheduling 功能来实现主机级别的扩缩容(需要依赖云厂商K8S产品)
  • 编写工具根据业务实际场景实现动态调整Worker节点的配置大小

8、流水线拥堵问题,与第7条不冲突

上一条提到的并行构建指的是正常的构建需求,是建立在流水线拥堵优化之后的结论之上,如:单个 CD Job 的并行构建显然是不合理的,却需要多耗费几倍的资源。

建议优化方案:

  • CD 流水线开启「不允许并行构建」以及「Abort previous builds」,每个Job只保留最新的构建进程
  • CI 流水线需要测试每个 PR 的代码,所以可以开启「不允许并行构建」,无需开启「Abort previous builds」
  • 当系统资源较充足时, CI 可以关闭 「不允许并行构建」,但需要注意的是共用缓存映射所带来的潜在冲突问题
  • 主机负载高可能导致 Job Pod 运行状态失联,未及时被 K8S 回收,建议设置定时检测脚本来按需清理

9、Jenkins Master磁盘占用率高、运行缓慢卡顿

大概有几方面原因:构建日志保留过多、服务日志未定时清理、主机资源匮乏、JVM 限制参数不合理等。

建议优化方案:

  • 按构建天数或个数进行日志保留
  • 服务日志设置定时清理或调整日志级别
  • 根据监控判断资源合理需求
  • JVM 参数配置调整测试,得出合理值
  • 对于分支构建的 Job 关闭 Tag 拉取,以及开启浅克隆

10、Jenkins 批量新增、修改 Job 信息麻烦

少量的流水线直接通过界面编辑即可,几十上百条甚至更多以后修改配置会很麻烦。

建议优化方案

  • 使用 Python、Go 等语言编写统一管理工具
  • 合并可能通用的流水线,如:单条流水线发布多个项目,是一对多的关系

总结:

以上分享的是较常见可能影响流水线交付效率的因素以及建议解决方案,PingCode DevOps 团队充分借鉴了以上部分方案进行专项优化,流水线交付效率得到了质的提升。CICD 流水线优化是一个经久不衰的话题,我相信流水线的高效稳定和便于管理是每个企业共同追求的目标,实现形式可以是多种多样,适合自身场景的方案就是好的方案,现阶段我们依然在为进一步优化流水线做努力,追求极致,没有最好,只有更好!

你可能感兴趣的:(pingcode,devops,运维)