目录

golang 的 timer 在调整系统时间下的行为

目录

文章简介:golang 的 timer 在调整系统时间下的行为

在测试 k3s 重启自动续签证书时,发现手动调整机器时间后,calico Unauthorized,pod 因无法创建 network sandbox 无法启动,且可以看到 calico-node -monitor-token 没有执行。 calico-node -monitor-token 是 calico 后台刷新证书的程序,,每次刷新都会 time.After max(nextExpiration/4, 5s*4)。但是实测下来,直接手工调整时间后,calico 并没有主动重新申请 token,这里涉及到 time.After 的工作机制。

linux 时间有 CLOCK_REALTIME_COARSE(墙上时钟) 和 CLOCK_MONOTONIC_COARSE (单调时钟),这两种时钟详细解释见 这里

从 golang 中找到的代码看到 time.After 调用栈见:

1
2
[checkTimers](https://github.com/golang/go/blob/release-branch.go1.22/src/runtime/proc.go#L3945)
  [runtime·nanotime1](https://github.com/golang/go/blob/release-branch.go1.22/src/runtime/sys_linux_amd64.s#L258)

可以看到 golang 中的 timer.Timer 使用的是 CLOCK_MONOTONIC_COARSE 也即单调时钟,date 命令调整时间并不会体现在这里获得到的时间,所以调整时间并不会让 calico 按照墙上时钟快速触发。

问题确认即可快速确认方案,如果为了规避时间问题,可以只重启 k3s 即可,如果期望可以快速使用 date 调整时间 calico 快速恢复,可以考虑重启 calico-node 进程重新生成 kubeconf。

golang issue 12914 中讨论了 nanotime 第三方无法调用,以及当前的进展。当前如果希望获得 单调时钟,可以参考 这个