GitLab同流水线第二个作业无法找到缓存问题求助
核心问题
你配置的slowcompile和slow两个作业使用完全一致的缓存key与pull策略,第一个作业能正常提取本地缓存,但后续的slow作业却提示缓存不存在,且重新运行流水线时slowcompile仍能找到缓存。
可能原因及解决方法
1. Runner本地缓存未开启共享
GitLab Runner默认的本地缓存是单作业隔离的,每个作业会使用独立的缓存目录,除非你在Runner配置里开启了缓存共享。如果两个作业跑在同一个Runner但没开共享,或者跑在不同Runner节点,后续作业就访问不到前一个作业的本地缓存。
解决步骤:
编辑Runner的config.toml配置文件,开启缓存共享:
[[runners]] # 其他Runner配置... [runners.cache] shared = true
保存后重启Runner服务。如果是使用Docker Runner,还需要确保缓存目录挂载正确。
2. 作业未在同一Runner执行
如果两个作业分配到了不同的Runner节点,即使缓存key相同,本地缓存也无法跨节点共享——因为本地缓存是存在每个Runner节点的本地磁盘里的。
验证方式:
查看两个作业日志的开头,找类似Running on runner-xxxxxx-project-xxxx-concurrent-0 via your-hostname...的行,确认节点标识(hostname或Runner ID)是否一致。
解决方法:
给两个作业添加相同的tags,绑定到同一个Runner:
slowcompile: stage: build tags: [your-specific-runner-tag] # 其他配置... slow: stage: build tags: [your-specific-runner-tag] # 其他配置...
3. pull策略的认知偏差
pull策略只允许作业拉取缓存,不会上传缓存。第一个作业能提取缓存,说明这个缓存是之前流水线上传的,但同流水线的后续作业如果没有办法访问到这个缓存的存储位置(比如不同Runner),就会失败。
补充说明:
如果你的场景是需要在同流水线内传递缓存,应该让第一个作业使用默认的push-pull策略(无需显式配置),这样第一个作业会先拉取缓存,执行完后上传更新后的缓存,后续作业就能拉取到。
4. 缓存目录权限冲突
第一个作业提取缓存后,可能修改了缓存文件/目录的权限,导致第二个作业的执行用户无法读取。
验证方式:
在slowcompile的脚本末尾加上:
- ls -ld externals/ externals_st/ fast*/ slow*/ - id
在slow的脚本开头加上同样的命令,对比输出的权限和用户ID是否一致。
解决方法:
在slowcompile的脚本末尾添加权限调整命令:
- chmod -R 755 externals/ externals_st/ fast*/ slow*/
确保后续作业的用户能读取这些目录。
5. Runner版本存在bug
旧版GitLab Runner(比如14.x及更早)在本地缓存共享的逻辑上可能存在bug,尤其是使用shell或Docker executor时。
解决方法:
把GitLab Runner升级到最新稳定版本,升级后重启Runner服务。
总结
最常见的原因是Runner未开启缓存共享,或者两个作业跑在不同Runner节点。优先排查这两点,再考虑权限或版本问题。如果无法配置共享Runner,改用分布式缓存(如S3、阿里云OSS等)是更通用的解决方案。
内容的提问来源于stack exchange,提问作者James Foster

