直接同步主机时钟即可解决,核心是消除服务端与Runner间系统时间差;需用timedatectl status确认时钟同步状态、校验GitLab实例时间一致性、排查NTP异常,并强制校准或启用chrony等高精度同步方案。

直接同步主机时钟即可解决,核心是消除服务端与 Runner 之间的系统时间差,而非调整 Token 配置或放宽验证策略。
确认时钟漂移是否真实存在
在 GitLab Runner 所在主机上执行:
-
对比本地时间与权威时间源:运行
timedatectl status查看系统时钟状态,重点关注System clock synchronized是否为yes,以及RTC time与Universal time的偏差 -
校验与 GitLab 实例时间的一致性:访问 GitLab 实例的 API 端点(如
/api/v4/version),检查响应头中的Date字段;同时在 Runner 主机运行date -R,两者应相差 ≤5 秒 -
排查 NTP 服务异常:若
timedatectl显示未同步,检查systemd-timesyncd或chronyd是否运行,日志可用journalctl -u systemd-timesyncd -n 20
强制并持续同步系统时间
不要依赖默认的 NTP 拉取间隔,尤其在虚拟机或云环境中易出现漂移累积:
使用四维度框架评估任意 GitLab MR 或 GitHub PR 的复杂度:规模(20%),认知负荷(30%),审查工作量(30%),风险/影响(20%)...
- 立即校准:
sudo timedatectl set-ntp false && sudo ntpdate -s time.google.com && sudo timedatectl set-ntp true - 更换更稳定的 NTP 源(如内网 NTP 服务器或
time1.aliyun.com),编辑/etc/systemd/timesyncd.conf中的NTP=行 - 启用
chrony(比默认systemd-timesyncd更适合高精度场景):sudo apt install chrony(Debian/Ubuntu)或sudo apk add chrony(Alpine),再配置/etc/chrony/chrony.conf
避免临时绕过验证带来的风险
虽然 jwt.WithLeeway(60*time.Second) 类似机制在某些 JWT 库中可用,但 GitLab Runner 的认证流程不暴露该配置项,强行修改底层逻辑既不可靠也不被支持:
- GitLab Runner 使用的是 GitLab 自研的 CI token 签发与校验链,其
nbf(not before)和exp(expires)验证由 GitLab Rails 后端统一执行,Runner 仅负责携带并传递 token - 所谓“Token 校验被拒”,本质是 GitLab 应用层拒绝了该 token,错误日志通常含
token expired或token not active yet,而非 Runner 报错 - 试图在 Runner 配置中注入 leeway、伪造时间头、或降级 TLS 验证,均无法影响 GitLab 服务端的时间判断,反而可能引入安全或兼容性问题
验证修复效果
完成时间同步后,需触发一次真实作业验证端到端行为:
- 手动触发一个简单 CI 作业(如
echo "test"),观察 Runner 日志是否仍出现401 Unauthorized或token signed by untrusted key类错误 - 检查 GitLab 侧作业详情页的
Running on信息旁是否有黄色感叹号提示“runner offline”或“stale token” - 抓包验证(可选):用
tcpdump或mitmproxy观察 Runner 向/api/v4/jobs/request发起的请求中,Authorizationheader 是否正常携带 token,且响应状态码为200 OK

















