由时钟偏移导致的 Gitaly PermissionDenied
问题描述
-
访问 GitLab UI 中与仓库相关的页面时返回 HTTP 500。
-
Gitaly pod 日志包含以下关键字:
-
Gitaly pod 的系统时间与
webservice/sidekiqpods 的系统时间相差数秒或更多。
根本原因
Gitaly 使用包含时间戳声明的 JWT 来对其客户端(webservice、sidekiq)进行身份验证。如果节点时钟发生漂移,Gitaly 侧会将该 JWT 视为已过期或尚未生效,从而拒绝该 RPC 并返回 PermissionDenied。在实践中,超过约 30 秒的漂移通常会触发此问题,但具体容差取决于 JWT library 的 leeway 设置。
时钟漂移的常见原因包括:
- 集群节点未配置 NTP,或者 NTP 服务未运行。
- 已配置 NTP,但无法连接到上游时间源(例如被防火墙阻止)。
- 节点运行在硬件上,该硬件的 real-time clock (RTC) 不准确,并且从未完成同步。
排查
-
在 Gitaly 日志中确认
PermissionDenied关键字: -
比较 Gitaly pod 和客户端 pod(
webservice或sidekiq)报告的时间。相差超过几秒就值得怀疑: -
确定受影响 pods 所在的节点,然后直接检查主机时钟:
在每个节点上,检查系统时钟是否与 NTP 源同步。如果 NTP 未启用,则该节点就是漂移的来源。
解决方案
前提条件
- 可通过 SSH 访问所有集群节点(重新调度后,任何节点都可能承载这些 pods)。
- 具有重启 GitLab 组件的权限。
注意事项
- 在运行中的节点上修改系统时间是一项敏感操作。尽可能在维护窗口内执行。
- 将时间大幅回拨可能会影响数据库和分布式系统。优先使用平滑调整,而不是类似
date -s这样的硬切换。
步骤
-
在每个集群节点上配置 NTP,并确保服务处于活动状态。具体使用的工具(chrony、systemd-timesyncd、ntpd 等)取决于你的 OS,本文不作展开。修改完成后,确认每个节点上的系统时钟都已与上游时间源同步。
-
重启 GitLab 组件,以便在时钟对齐后重新生成新的 JWT。根据你的 release 调整工作负载名称:
-
验证修复结果:
- Gitaly 日志不再输出
PermissionDenied条目。 - GitLab UI 中的仓库页面返回 200。
- 在 Gitaly 和 webservice pods 内执行的
date -u现在相差不到一秒。
- Gitaly 日志不再输出
提示
- 若要快速检查整个集群的时钟偏移,可在每个节点上运行
date -u并进行比较;任何异常节点都可能是候选问题节点。