在软件开发的世界中,时间就是一切。持续集成/持续部署流水线可以加快过程,但有时正是流水线导致过程变慢,这听起来有点讽刺意味。最近一段时间,这正是我遇到的问题,我们使用Jenkins流水线时,每个构建的时间长达难以控制的41分钟。
我决心消除这种低效,分析、优化并改造了我们的工作流程,将时间从惊人的41分钟缩短到8分钟——整整5倍的提升!在这篇文章中,我会分享我遇到的问题、采取的解决办法以及一些可以用来大幅提升你工作流程效率的策略。
问题我们的CI/CD流水线涉及了前后端的以下任务:
- 代码检出(Checkout)
- 静态代码分析:ESLint,SonarQube
- 单元测试
- 构建并推送Docker镜像
- 预发布环境部署
- 手动审批和生产部署
乍一看,管道挺结实的,但还是暴露了一些问题:
- 臃肿的Docker构建上下文
在构建镜像时发送到Docker的所有文件已经增长到1.5GB,并且构建时间变得非常长。 - 重复安装依赖项
流水线中的每个阶段都必须从头开始重新安装npm依赖项,造成了不必要的延迟。 - 糟糕的Docker镜像管理
即使没有发生任何更改,Docker镜像也被重建并推送到仓库。 - 无法并行执行
同样,所有任务,如代码静态检查或测试,都是依次执行的。 - 手动部署步骤
由于需要手动更新AWS ECS任务定义,后端的部署耗时且容易出错。
这是我实现管道流程5倍优化效果的方法。
减小 Docker 构建上下文的大小Docker 构建上下文过大,是因为未筛选的项目目录导致的。我们可以使用 .dockerignore
文件来排除一些不必要的文件,比如 node_modules
、logs
等。
重要文件 : .dockerignore
node_modules # 存放项目依赖的模块
*.log # 项目日志文件
dist # 项目构建输出的文件夹
coverage # 测试覆盖率报告
test-results # 测试结果文件夹
影响如下:
将构建上下文大小从1.5GB减少到大约10MB,传输时间从30分钟减少到不到1分钟。
每一个阶段都用了 npm install
。我把它改成了 npm ci
,确保可重现性,并且在 Jenkins 里启用了缓存。
命令更新通知 :
npm ci --cache ~/.npm
运行这个命令来安装依赖,使用指定的缓存目录 ~/.npm
.
影响:
将依赖安装耗时从每个步骤的3到4分钟减少到了不到20秒。
之前,构建流程会无条件地重建和推送Docker镜像。我增加了逻辑,用于比较本地和远程镜像的哈希值,只有在镜像发生变化时才推送。
更新后的逻辑:
def remoteImageHash = sh(returnStdout: true, script: "docker inspect --format='{{.Id}}' $DOCKER_IMAGE:$DOCKER_TAG || echo ''").trim()
def localImageHash = sh(returnStdout: true, script: "docker images --no-trunc -q $DOCKER_IMAGE:$DOCKER_TAG").trim()
if (localImageHash != remoteImageHash) {
sh 'docker push $DOCKER_IMAGE:$DOCKER_TAG'
} else {
echo "镜像没有更新,跳过推送操作。"
}
影响效果:
减少了不必要的推送,每次构建大约节省了3到5分钟。
我扩展了Jenkins流水线,使其能够使用parallel
指令,从而使ESLint验证、SonarQube扫描和单元测试可以同时运行。
更新后的项目管道:
阶段('静态代码分析阶段') {
并行 {
阶段('前端 ESLint') {
执行 {
步骤 {
sh 'npm run lint'
}
}
}
阶段('后端 SonarQube') {
执行 {
在SonarQube环境配置下 {
步骤 {
sh 'sonar-scanner' // 执行SonarQube扫描命令
}
}
}
}
}
}
效果:
将静态分析和测试时间缩短了50%。
手动更新 AWS ECS 任务定义既耗时又容易出错。我用 AWS CLI 自动化了这一步。
自动脚本
def 任务定义Json = """
{
"family": "$ECS任务定义名称",
"containerDefinitions": [
{
"name": "后端",
"image": "$DOCKER镜像:$DOCKER标签",
"memory": 512,
"cpu": 256,
"essential": "必需的"
}
]
}
"""
sh "echo '${任务定义Json}' > task-definition.json"
sh "aws ecs 注册任务定义 --cli-input-json file://task-definition.json --region $AWS区域"
sh "aws ecs 更新服务 --cluster $ECS集群名称 --service $ECS服务名称 --task-definition $ECS任务定义名称 --region $AWS区域"
效果:
这样简化了部署过程,节省了5分钟的时间。
经过这些优化,流水线时间从41分钟缩短到仅8分钟——提高了5倍,即原来的五分之一。以下是详细的比较。
对比表
学到的- 日志是你的最佳伙伴:通过分析日志来找到瓶颈。
- 缓存拯救难题:有效利用缓存可以大幅缩短构建时间。
- 并行运行任务:使用并行执行可以快速节省时间。
- 排除无关文件:用
.dockerignore
文件排除无关文件,性能显著提升。 - 自动化重复任务:自动化消除错误并提速工作流程。
优化 CI/CD 管道是一次令人印象深刻的经历。通过定位关键瓶颈并实施战略性更改,将一个耗时 41 分钟的繁琐任务转变为只需 8 分钟的高效流程。结果如何?更快的部署,更快乐的开发人员们,以及更多时间专注于功能。
如果你遇到管道效率低的问题,可以从首先识别瓶颈开始,启用缓存,并行执行任务,并自动化重复的任务。即使是小小的调整也能带来巨大的效果。
你通过优化CI/CD流水线节省了多久时间?在下方评论区分享你的经验与技巧!
共同学习,写下你的评论
评论加载中...
作者其他优质文章