CodeArts流水线缓存失效返工记录
流水线变慢那一周
7 月 18 日我把订单对账服务接到华为云 CodeArts 流水线,代码源在 CodeArts Repo,构建镜像推 SWR,发布走 SSH 到一台 ECS。目标机还是老机器 s7n.large.2,2 vCPU 4GB,Ubuntu 22.04,Node.js 18.19.1。仓库 1.2 万行,package-lock.json 2.7MB,dist 压缩后 43MB。我按以前 GitLab CI 的经验估过一遍,觉得 8 分钟差不多,结果 7 月 19 日到 7 月 21 日一共 13 次构建,平均 21 分 34 秒,最慢 24 分 51 秒。
慢点几乎都在构建阶段。
这个坑我在周三 22:40 才看明白。
我把每段耗时抄进了表格。拉代码 28 到 36 秒,docker login + push 在 1 分 31 秒到 2 分 04 秒,SSH 部署 56 到 69 秒,只有 npm ci 每次都在 12 到 15 分钟飘。日志里 20 多页都是 fetch GET 200 https://registry.npmmirror.com/...tgz,每次都像第一次下载。我那时已经开始怀疑自己是不是把缓存开关点错了。
我在 CodeArts Build 里确认了缓存已开启,构建机是标准 4 核 8G,镜像是 codeci/node18-build:2024.06,YAML 也照旧项目抄过来。
version: 2.0
env:
runtime:
node: 18.19.1
phases:
build:
commands:
- npm ci --cache /root/.npm --prefer-offline
cache:
paths:
- /root/.npm/**/*
[Cache] restore path '/root/.npm' failed: no such file or directory 2024-07-20 21:16:07 npm ERR! code EACCES 2024-07-20 21:16:07 npm ERR! syscall mkdir 2024-07-20 21:16:07 npm ERR! path /root/.npm/_cacache/tmp 2024-07-20 21:16:07 npm ERR! Your cache folder contains root-owned files 2024-07-20 21:16:07 npm ERR! Log files were not written due to an error writing to the directory: /root/.npm/_logs
报错很直白,CodeArts 的构建用户是 codeci,不是 root。我改了三处,每一处都为了解决一个具体问题。第一处把缓存路径从 /root/.npm 换到 /home/codeci/.npm,这是权限问题。第二处在 pre_build 加 mkdir -p /home/codeci/.npm,避免 restore 时目录不存在直接 miss。第三处把命令行参数改成全局配置,防止后面的脚本有人漏写 --cache,命令是 npm config set cache /home/codeci/.npm --global。我还加了 ls -ld /home/codeci/.npm 和 stat -c '%U %G %a' /home/codeci/.npm,确认 owner 是 codeci codeci,权限 755,EACCES 当场消失。
可速度没回来,4 次重跑里 npm ci 分别是 18:11、17:46、18:23、17:58,比之前还慢了两分钟。
这个阶段我一度想怪网络,去看 VPC 出口和 NAT 网关监控。构建时段带宽峰值 22Mbps,平均 15Mbps,丢包 0.03%,时延 8 到 14ms,没有尖峰。我又拿同一镜像在另一个仓库跑对照,依赖体量 410MB,npm ci 用了 4 分 17 秒。网络这条线我就先放下了。
第二次返工后的配置和账单
把我卡住的是缓存键。我之前用的是 CODEBUILD_RESOLVED_SOURCE_VERSION,也就是提交 SHA。这个方案我一开始是拒绝改的,我怕多分支复用缓存会把依赖污染,后来才意识到我等于把命中率手动打成了 0%。同一个 lock 文件,只要 commit 变了就必 miss。
cache:
key: npm-${CODEBUILD_RESOLVED_SOURCE_VERSION}
paths:
- /home/codeci/.npm/**/*
为了确认不是我猜错,我加了探针命令,把工具链和锁文件哈希全打印出来,再把输出附到制品日志。
node -v
npm -v
sha256sum package-lock.json
printenv | grep CODEBUILD_RESOLVED_SOURCE_VERSION
npm config get cache
du -sh /home/codeci/.npm
同一分支连续两次提交,node/npm 都是 v18.19.1 和 10.2.4,package-lock.json 哈希都等于 9a7d2f1e...c31b,只有提交 SHA 从 f6b4b1d 变成 2d8ca90。我把缓存键改成锁文件哈希 + Node 大版本,具体是 pre_build 里先算 LOCK_HASH,再用 npm-${LOCK_HASH}-node18。改完后第 1 次是冷启动 12 分 49 秒,第 2 次 4 分 12 秒,第 3 次 3 分 56 秒,第 4 次 3 分 40 秒,基本稳定了。
我还做过一次失败尝试,把 node_modules 也塞进缓存,想再省 1 到 2 分钟。那天晚上 23:17 我把配置写成 /codeci/workspace/node_modules/**/*,当晚确实快了 58 秒。第二天镜像从 codeci/node18-build:2024.06 升到 2024.07 后直接炸,日志是:
Error: Cannot find module '../build/Release/sharp-linux-x64.node' Require stack: - /codeci/workspace/node_modules/sharp/lib/sharp.js - /codeci/workspace/node_modules/sharp/lib/constructor.js Node.js v18.19.1 npm ERR! code 1 npm ERR! command sh -c node install/check
我又试了 npm rebuild sharp --verbose,构建多花 2 分 26 秒,最后卡在 prebuild-install WARN install No prebuilt binaries found,这条路也没走通。回滚动作很直接,删掉 node_modules 缓存路径,只保留 /home/codeci/.npm,并恢复 npm ci --prefer-offline --no-audit。我在 pre_build 额外加了 npm config set fetch-retries 2 --global,因为默认重试太久,偶发超时时它会拖到 40 多秒一轮。
version: 2.0
env:
runtime:
node: 18.19.1
phases:
pre_build:
commands:
- export LOCK_HASH=$(sha256sum package-lock.json | awk '{print $1}')
- mkdir -p /home/codeci/.npm
- npm config set cache /home/codeci/.npm --global
- npm config set fetch-retries 2 --global
build:
commands:
- npm ci --prefer-offline --no-audit
- npm run build
- tar -czf dist.tgz dist ecosystem.config.js
cache:
key: npm-${LOCK_HASH}-node18
paths:
- /home/codeci/.npm/**/*
artifacts:
files:
- dist.tgz
部署我也固定成一套命令:scp dist.tgz deploy@x.x.x.x:/srv/reconcile/releases/$CI_PIPELINE_ID/,远端执行 tar -xzf dist.tgz -C /srv/reconcile/current && ln -sfn /srv/reconcile/releases/$CI_PIPELINE_ID /srv/reconcile/live && pm2 reload ecosystem.config.js --env prod。构建超时从 30 分钟收紧到 15 分钟,自动触发只留 main 和 release/*,feature 分支改成人工触发,7 月底少跑了 19 条无效流水线。
我导了 7 月 19 日到 7 月 31 日 62 次记录。改造前平均 19 分 42 秒,P50 19 分 03 秒,P95 24 分 08 秒;改造后平均 6 分 11 秒,P50 5 分 54 秒,P95 8 分 03 秒。部署阶段几乎没变,54 到 68 秒。账单按分钟对过,CodeArts Build 每月免费 500 分钟,超出 0.12 元/分钟,那周因为缓存 miss 多跑 646 分钟,额外 77.52 元。
我盯着账单页面沉默了两分钟。
现在还没处理跨项目共享缓存,另一个同样 Node 18 的前端仓库还在重复下载。下周我准备试 SWR 前面挂私有制品库代理,再看 tarball 命中率;再评估 CodeArts 项目级缓存能不能按 lock hash 做隔离。还有个变量是 Node 升到 20.11 后 lockfileVersion 变化范围,我手里样本还不够,缓存键要不要再拼 lockfileVersion,这件事我还没定。
- 点赞
- 收藏
- 关注作者
评论(0)