找回密码
立即注册
搜索
发回帖 发新帖

5432

积分

0

好友

700

主题
发表于 昨天 21:02 | 查看: 11| 回复: 0

晚上八点,小林推开实验室的门,发现老周正盯着流水线页面发呆。

「周哥,看什么呢?」

「你昨天的流水线。」老周指了指屏幕,「lint 跑 40 秒,test 跑 1 分 20 秒。build 要是好了,至少 3 分钟。」

「那怎么了?」

「你每次推代码,都等 5 分钟。」

「一天推 10 次,就是 50 分钟。一年呢?」

小林拿出手机算了算。

「按 250 个工作日算……大概 208 个小时。」

运维小白成长记第14话主题插画:cache与artifacts一个省时间一个省力气

顺便说一句:50 分钟/天 × 365 天 = 304 小时,× 250 个工作日 = 208 小时。

两个数都对,但口径不同。报出来的账,得经得起追问。

「208 小时,差不多 26 个工作日。」老周说。

「而且 Runner 跑着占 CPU、内存、网络,这些在云上都是按分钟计费的。」

「所以今天教你两个东西:cache 和 artifacts。一个省时间,一个省力气。」

GitLab CI流水线一年等待时间算账表

一、这俩到底差在哪

老周在白板上画了两栏:

  • cache(缓存):跨流水线复用,存依赖和中间产物,加速后续构建
  • artifacts(制品):同一流水线内传递,存构建结果和测试报告,可下载

「简单说 ——」

「cache 是『上次留下的东西,这次接着用』;artifacts 是『这次做出来的东西,给别人用』。」

小林问:「pip 依赖算哪个?」

「cache。因为下次构建还要用。」

「那测试报告呢?」

「artifacts。因为它是这次做出来的,给人看的。」

cache与artifacts对比表格:一个省时间一个省力气

老周给了个口诀:

「『下次还要用的』是 cache,『这次做出来的』是 artifacts。」

二、配个缓存,先快起来

test-api:
  stage: test
  image: python:3.13-slim
  cache:
    key: api-deps
    paths:
      - .pip-cache/
  variables:
    PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
  script:
    - pip install -r api/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

推一次,再跑 —— 从 30 秒降到 8 秒。

「快了。」小林说。

「但先别高兴。」老周说,「你这个写法里,藏着一个小矛盾。」

他指了指原来的 script:

pip install --no-cache-dir -r api/requirements.txt

「--no-cache-dir 和 PIP_CACHE_DIR 是打架的。」

「一个说『禁用缓存目录』,一个说『缓存放这儿』。两个都写,pip 听前者的:一个字节都不写。」

「那为什么刚才变快了?」

「因为 GitLab 那一层缓存仍然生效,但 pip 不会再往里写新东西 —— 也就是说,你今天快,下周依赖更新时它会突然不快。」

「把 --no-cache-dir 去掉。」

pip缓存配置正确写法与冲突写法对比

这条坑不只在 GitLab CI 里。任何地方配 pip 缓存,都容易同时留下这两个参数。

看到「缓存配了但没效果」,先搜 --no-cache-dir。

三、让缓存跟着依赖自动失效

「那如果依赖变了呢?」

「问得好。」老周说,「requirements.txt 变了、缓存还是旧的,可能装成旧版本的包,你却以为装的是新的。」

「让 key 跟着文件走。」

  cache:
    key:
      files:
        - api/requirements.txt

「requirements.txt 一变,key 就变,旧缓存自动失效。」

四、artifacts:把测试报告留下来

test-scripts:
  stage: test
  image: bats/bats:latest
  script:
    - bats --formatter tap tests/ | tee test-results.tap
  artifacts:
    name: "bats-results-$CI_COMMIT_SHORT_SHA"
    paths:
      - test-results.tap
    expire_in: 1 week

「tee 同时输出到屏幕和文件,expire_in 一周后自动删。」老周说。

「在哪下载?」

「流水线页面,任务右侧有 Browse 和 Download。」

下载打开长这样:

1..6
ok 1 disk-check 正常运行时退出码为 0 或 2
ok 2 disk-check 阈值无效时退出码为 1
...

「这就是制品。你可以把它接到监控、报表、通知。」

五、制品还能在阶段之间传

「build 构建了镜像,deploy 要部署 —— 怎么让 deploy 知道该部署哪个版本?」

「写进文件,当制品传下去。」

build-image:
  script:
    - echo "$DOCKER_IMAGE:$CI_COMMIT_SHORT_SHA" > image-tag.txt
  artifacts:
    paths:
      - image-tag.txt

deploy-api:
  needs:
    - build-image
  script:
    - IMAGE_TAG=$(cat image-tag.txt)

「needs让 deploy 等 build 完成,并自动下载它的制品。」

但 needs 有个副作用要注意:它会打破「必须等上一个 stage 全绿」的默认规则。

写了 needs: [build-image],它就只等 build-image,不再等 test 阶段。

能省时间,也可能让「测试没过就部署」成为现实。所以 needs 里写谁,要沿着真实依赖链写。

六、别忘了清理

「缓存和制品不能无限存。」

Admin Area → Settings → CI/CD:

  • Default artifacts expiration:默认 30 天,改成 7 天
  • Keep the latest artifacts for all jobs:保留最新制品

Runner 本地也有缓存:

[runners.cache]
Type = "local"
Path = "/cache"
Shared = true

「教学环境本地缓存够用。生产环境可以用 S3、MinIO 做分布式缓存 —— 否则每个 Runner 各存一份,命中率很低。」

「那缓存坏了呢?」

「清掉。GitLab 界面 CI/CD → Pipelines → Clear runner caches。」

七、优化之后

lint    passed
test    passed          ← 从 1 分 20 秒降到 50 秒
build   failed (allowed)   ← Registry 还没部署

「test 快了 30 秒。」小林说。

「这就是缓存的威力。」

小林收拾东西,走到门口回头问:

「周哥,省下来的时间干什么?」

「干更重要的事。」老周说,「比如设计更好的流水线,或者早点下班。」

「那省下来的钱呢?」

「买更好的服务器。」老周笑了,「或者给领导看:自动化之后资源利用率提高了,可以申请更多预算。」

下一篇:《自动构建镜像》—— 你会把配置改对,但改到另一台机器上。




上一篇:沪深交易所二进制协议C11实现:帧编解码与消息分派
下一篇:Chrome 关闭硬件加速的 3 种方法:解决黑屏与卡顿
您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-11-1 02:30 , Processed in 0.069815 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表