Skip to main content
Skip to content

无法访问的 NTP 服务器导致的时钟漂移

当 你的 GitHub Enterprise Server 实例 无法到达其配置的时间服务器时,其时钟会偏离实际时间。 登录、集成和 GitHub Actions 随后都可能会因原因中根本不会提到时钟的问题而失败。

故障特征

你实际看到的内容中很少提到时钟。 症状反而出现在任何依赖于两个系统时间一致的事物上。

  • 用户无法登录,或者会话比预期更早结束。
  • GitHub Connect 无法连接,或者许可证页返回服务器错误。
  • GitHub Actions 作业可能无法启动,或者令牌被拒绝为无效。
  • /var/log/github/exceptions.log 包含有关令牌过期声明时间过于靠后的错误,例如 'Expiration time' claim ('exp') is too far in the future。
  • Web 界面、日志或提交中的时间戳与预期时间不匹配。

由时钟错误的实例签名的令牌在接收它的系统看来像是无效的,即使令牌本身没有任何错误。 这就是为什么这些故障指向身份验证而不是时间。

原因

GitHub Enterprise Server 通过 UDP 端口 123 与网络时间协议 (NTP) 服务器同步来保持时钟准确。 它至少需要持续地连接到其中一个。

由于常见原因,配置的服务器变得无法访问。

  • 防火墙或安全组会阻止出站 UDP 端口 123,这一点很容易被忽略,因为实例的其余部分仍可正常工作。
  • 内部时间服务器已停用或重命名,并且实例仍指向旧地址。
  • 主机名无法再解析。
  • 只配置了一台服务器,因此当它不可用时,没有可回退的服务器。

如果无法访问任何已配置的服务器,chrony 会继续维持本地系统时钟运行,且没有外部校正,并报告由 GitHub Enterprise Server 配置的 10 级后备层级。 这不是硬件时钟,它是在 chrony 外部管理的单独设备。

此时不会发生故障,也不会引发任何错误。 时钟只是不再被校正并开始漂移,起初很缓慢,直到某个依赖精确时间的东西出问题。 偏移越大,影响越广。

同时尝试设置虚拟机时钟的虚拟机监控程序可以通过与实例自己的同步作斗争来生成相同的结果。

确认该问题

  1. 通过 SSH 连接到管理 shell。 有关详细信息,请参阅“访问管理 shell (SSH)”。

  2. 列出时间源及其状态。

    sudo chronyc sources -v
    

MS读取每个源左侧的列。 一个 ? 表示 chrony 未使用该源。 它本身不是网络问题的证明,因为对于本身未同步的服务器以及尚未提供足够度量的源,会出现相同的标记。

用于识别不可访问源的是同一行上的支持证据。 在下面的输出中,Reach 是 0,这意味着最近的轮询都没有得到答复,LastRx 是 -,这意味着从未有样本到达过。 两个服务器都未响应。

MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^? ntp1.example.com              0  10     0     -     +0ns[   +0ns] +/-    0ns
^? ntp2.example.com              0  10     0     -     +0ns[   +0ns] +/-    0ns

如果源已标记 *,则 chrony 已选择它,从而排除了可达性问题。 它无法确认时钟是准确的,因为 chrony 会逐渐更正较大的偏移量,并且在此期间,实例的时间可能与实际时间相差很大。 无论如何,继续执行剩余检查。

  1. 检查实例实际同步到的内容。

    sudo chronyc tracking
    

    括号中具有空名称的引用 ID 以及层 10,表示实例已放弃其配置的服务器,并且正在使用自己的时钟。

    Reference ID    : 7F7F0101 ()
    Stratum         : 10
    System time     : 0.000000000 seconds fast of NTP time
    

    Stratum 计算实例与参考时钟相差多少级,实例始终比它所遵循的服务器多报告 1 级。 10 的值是特定的:它是 GitHub Enterprise Server 在没有可用源时配置的回退值,因此,将它与未命名的引用 ID 一起看到就是一个信号。

    一个正常的实例会指明它正在跟随的服务器,并报告比该服务器高一层的层级。

    Reference ID    : D9723B03 (ntp1.example.com)
    Stratum         : 3
    System time     : 0.000079420 seconds fast of NTP time
    

System time 根据实例所同步的服务器进行度量,因此当实例遵循自己的时钟时,该值毫无意义。 无论时钟漂移了多少,读数都接近于零。

  1. 通过将实例时钟与你信任的源进行比较来衡量偏移。

    date -u
    

    注意它偏离了多远。 很大的差异表明时钟一直在持续漂移且未受控制。

  2. 如果希望了解每个源的支持详细信息(例如偏斜程度和保留的样本数),请使用以下命令。

    sudo chronyc sourcestats -v
    

解决问题

首先恢复同步,然后纠正在失去同步期间累积的漂移。 更正偏移而不修复可达性,只是在它再次出现之前争取一点时间。

  1. 在管理控制台的“时间”部分中检查实例被配置为使用哪些服务器。 有关详细信息,请参阅“配置时间同步”。

  2. 确认实例可以访问它们。 必须在实例和服务器之间的每个防火墙和安全组中,向每台服务器打开出站 UDP 端口 123。 有关详细信息,请参阅“网络端口”。

  3. 如果服务器已消失,或者无法打开到该服务器的路径,请配置实例可以访问的服务器。 配置至少两个,以便其中一个失效不会导致实例一个也不剩。

  4. 确认 chrony 已再次选择源。 其中一个现在应标记为*,并带有非零的Reach。

    sudo chronyc sources -v
    
  5. 更正实例处于未同步状态期间累积的偏差。 NTP 自行更正小差异,但大差异需要以下命令。 有关详细信息,请参阅“配置时间同步”。

    sudo chronyc -a makestep
    
  6. 确认时钟现在与您信任的时间来源一致。 这是一个检查,告诉你漂移实际上已经消失,而不是仍在纠正。

    date -u
    
  7. 重试之前失败的操作。

防止再次发生

  • 配置至少两个时间服务器,因此丢失一个服务器不会停止同步。
  • 更改服务器后,请检查实例是否可以实际访问它们。 配置的服务器不一定是正常工作的服务器,当服务器停止应答时,不会发出任何警告。
  • 当防火墙规则发生更改时,确保出站 UDP 端口 123 对时间服务器开放。
  • 阻止虚拟机监控程序设置虚拟机的时钟,以免与实例自身的同步机制发生冲突。 有关详细信息,请参阅虚拟化提供商提供的文档。
  • 检查时间源作为例程运行状况检查的一部分。 时钟漂移通常无害,但一旦出问题,趁问题还小时发现它,可省去排查多个互不相关的故障是否由时钟导致的麻烦。

联系 GitHub 支持

如果在检查配置和网络路径后实例仍无法访问时间服务器,或者如果原始症状在时钟准确后继续,请联系 GitHub 支持 而不是继续。 有关详细信息,请参阅“创建支持工单”。

如果已打开支持工单,附加支持包有助于 GitHub 支持 更快地诊断问题。 有关详细信息,请参阅“向GitHub支持提供数据”。

延伸阅读