其他任何人遇到高速率的Linux服务器在第二天闰秒崩溃?

*注意:如果您的服务器由于内核混淆而仍然存在问题,并且无法重新启动,那么在您的系统上安装gnu date的最简单解决scheme是:date -s now。 这将重置内核的内部“time_was_set”variables,并修复java和其他用户空间工具中的CPU hogging futex循环。 我已经在我自己的系统上确定了这个命令,

死后

Anticlimax:唯一死的是我的VPN(openvpn)链接到集群,所以重新build立时有一个激动人心的几秒钟。 其他的一切都很好,在闰秒过后,启动ntp就干干净净了。

我写了一天的全部经验在http://blog.fastmail.fm/2012/07/03/a-story-of-leaping-seconds/

如果你看看Marco的博客http://my.opera.com/marcomarongiu/blog/2012/06/01/an-humble-attempt-to-work-around-the-leap-秒 – 他有一个解决scheme使用ntpd -x在24小时内逐步改变时间,避免1秒跳过。 这是运行自己的ntp基础架构的另一种涂抹方法。


就在今天,2012年6月30日星期六 – 格林尼治标准时间开始后不久即将开始。 我们在不同的数据中心有几台服务器,由不同的团队pipe理,所有的服务器都是黑屏的 – 没有响应ping,屏幕空白。

他们都在运行Debian Squeeze – 包含从内核到自定义3.2.21版本的所有内容。 大部分是戴尔M610刀片,但我也刚刚失去了戴尔R510和其他部门也丢失了其他厂商的机器。 还有一个旧的IBM X3550坠毁,我认为可能是不相关的,但现在我想知道。

我所做的一个崩溃从屏幕转储说:

[3161000.864001] BUG: spinlock lockup on CPU#1, ntpd/3358 [3161000.864001] lock: ffff88083fc0d740, .magic: dead4ead, .owner: imapd/24737, .owner_cpu: 0 

不幸的是,所有刀片都configuration了kdump,但是他们死得很厉害,kdump没有触发 – 而且他们开启了控制台消隐function。 我现在已经禁用了控制台消隐function,所以在下一次崩溃之后,我会有更多的信息。

只是想知道这是一个共同的线索还是“只有我们”。 他们在不同的时间购买不同的数据中心的不同单位,并且由不同的pipe理员运行(我运行FastMail.FM),而现在甚至是不同的供应商硬件,真的很奇怪。 大多数坠毁的机器已经运行了几个星期/月,运行的是3.1或3.2系列的内核。

最近的一次碰撞是一台只运行了大约6小时3.2.21的机器。

解决方法

好的人,这是我如何解决它。

  1. 禁用ntp: /etc/init.d/ntp stop
  2. 创build了http://linux.brong.fastmail.fm/2012-06-30/fixtime.pl (从Marco中盗取的代码,请参阅博客文章的评论)
  3. 跑了fixtime.pl没有一个参数,看到有一个飞跃第二集
  4. 用一个参数运行fixtime.pl来删除闰秒

注意:取决于adjtimex 。 我已经在http://linux.brong.fastmail.fm/2012-06-30/adjtimex上放置了一个squeeze adjtimex二进制文件的副本 – 它将在没有依赖于64位系统的情况下运行。 如果你把它放在与fixtime.pl相同的目录中,那么如果系统不存在,它将被使用。 显然,如果你没有挤64位…find你自己的。

我明天要开始ntp

正如匿名用户所build议的 – 运行adjtimex的另一种方法就是自己设置时间,这也可能会清除跳跃计数器。

当ntpd调用adjtimex(2)告诉内核插入一个闰秒时,这是由一个活锁造成的。 查看lkml发帖http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html

红帽也应该更新他们的KB文章。 https://access.redhat.com/knowledge/articles/15145

更新:红帽有这个问题的第二个知识库文章在这里: https : //access.redhat.com/knowledge/solutions/154713 – 上一篇文章是为了一个较早的,不相关的问题

解决方法是closuresntpd。 如果ntpd已经发出了adjtimex(2)调用,则可能需要禁用ntpd并重启以保证100%的安全。

这会影响RHEL 6和运行较新内核的其他发行版(比2.6.26更新),但不会影响RHEL 5。

在闰秒实际上计划发生之前发生的原因是ntpd让内核在午夜处理闰秒,但是需要提醒内核在午夜之前插入闰秒。 ntpd因此在闰秒的某一天的某个时候调用adjtimex(2),此时触发该错误。

如果安装了adjtimex(8),则可以使用此脚本来确定是否设置了标志16。 旗16是“插闰秒”:

 adjtimex -p | perl -p -e 'undef $_, next unless m/status: (\d+)/; (16 & $1) && print "leap second flag is set:\n"' 

更新:

红帽已经更新了他们的知识库文章,注意到:“RHEL 6客户可能会受到一个已知问题的影响,导致NMI看门狗在接收到NTP突发公告时检测到挂起,这个问题正在及时解决。没有经历过这个问题,那么他们就不再受影响了。“

更新:上述语言已从红帽文章中删除; 并添加了第二个KB解决scheme,详细介绍了adjtimex(2)崩溃问题: https : //access.redhat.com/knowledge/solutions/154713

但是,IBM工程师John Stultz在LKML文章中的代码更改指出,实际应用闰秒时可能会出现死锁,因此在禁用ntpd后,可能需要通过重新启动或使用adjtimex(8)来禁用闰秒。

最终更新:

那么,我不是内核开发者,但是我在这里再次回顾了John Stultz的补丁: https ://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a = commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d

如果这次我正在读这篇文章,那么当闰秒被应用时,我错误地认为会出现另一个僵局。 这似乎也是红帽的意见,根据他们的KB条目。 但是,如果您禁用了ntpd,请将其禁用另外10分钟,以便在ntpd调用adjtimex(2)时不会造成死锁。

我们会发现是否还有更多的错误:)

POST-LEAP SECOND UPDATE:

我花了几个小时阅读ntpd和pre-patch(buggy)的内核代码,虽然我可能在这里错了,但我会试着解释一下我的想法:

首先,ntpd始终调用adjtimex(2)。 它作为其在“ntp_loopfilter.c”中local_clock中定义的“时钟循环filter”的一部分。 你可以看到这里的代码: http : //www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c (从ntp版本4.2.6)。

时钟循环filter经常运行 – 每当ntpd轮询其上游服务器时运行,默认情况下是每17分钟或更多。 时钟环路滤波器的相关位是:

 if (sys_leap == LEAP_ADDSECOND) ntv.status |= STA_INS; 

接着:

 ntp_adjtime(&ntv) 

换句话说,在第二个闰秒的时候,ntpd设置“STA_INS”标志并且调用adjtimex(2)(通过它的可移植性包装)。

该系统调用进入内核。 以下是相关的内核代码: https : //github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c

内核代码path大致是这样的:

  • 663行 – do_adjtimex例程的开始。
  • 691行 – 取消任何现有的闰秒计时器。
  • 第709行 – 抓住ntp_lock spinlock(这个锁涉及到可能的livelock崩溃)
  • 第724行 – 调用process_adjtimex_modes。
  • 第616行 – 调用process_adj_status。
  • 第590行 – 根据在adjtimex(2)调用中设置的标志设置time_status全局variables
  • 第592行 – 检查time_state全局variables。 在大多数情况下,请调用ntp_start_leap_timer。
  • 第554行 – 检查time_status全局variables。 STA_INS将被设置,因此将time_state设置为TIME_INS,并调用hrtimer_start(另一个内核函数)来启动闰秒定时器。 在创build定时器的过程中,这段代码抓取了xtime_lock。 如果这种情况发生,而另一个CPU已经抓住了xtime_lock ntp_lock,那么内核就会活锁。 这就是为什么约翰·斯图尔茨(John Stultz)为了避免使用angular质体而写补丁。 这是今天造成大家麻烦的原因。
  • 第598行 – 如果ntp_start_leap_timer实际上没有启动闰秒定时器,则将time_state设置为TIME_OK
  • 第751行 – 假设内核不活锁,堆栈被解除,ntp_lock螺旋锁被释放。

这里有一些有趣的事情。

首先,每当调用adjtimex(2)时,第691行取消现有的定时器。 然后,554重新创build该计时器。 这意味着每次ntpd运行其时钟循环filter,都会调用错误的代码。

所以我相信红帽说错了,一旦ntpd设置了闰秒标志,系统就不会崩溃。 我相信每个运行ntpd的系统都有可能在闰秒前的24小时内每隔17分钟(或更多)活跃一次。 我相信这也可以解释为什么这么多的系统崩溃了; 与一小时三次机会相比,一次碰撞的可能性要小得多。

更新:红帽的KB解决schemehttps://access.redhat.com/knowledge/solutions/154713 ,红帽工程师也得出了同样的结论(运行ntpd将不断碰到错误的代码)。 事实上,他们在我做了几个小时之前就这样做了。 这个解决scheme没有链接到https://access.redhat.com/knowledge/articles/15145上的主要文章,所以直到现在我才注意到它。

其次,这解释了为什么加载的系统更容易崩溃。 加载的系统将会处理更多的中断,导致“do_tick”内核函数被更频繁地调用,给这个代码更多的机会运行,并在定时器创build时获取ntp_lock。

第三,闰秒实际发生时系统是否有崩溃的机会? 我不知道,但可能是的,因为启动的计时器并实际执行闰秒调整(ntp_leap_second,在第388行)也抓住ntp_lock螺旋锁,并调用hrtimer_add_expires_ns。 我不知道这个电话是否也能够导致活锁,但这似乎不可能。

最后,在闰秒运行之后,导致闰秒标志被禁用的原因是什么? 有ntpd的答案停止设置闰秒标志在午夜后的某个时刻,当它调用adjtimex(2)。 由于该标志未被设置,因此第554行的检查将不成立,并且不会创build定时器,并且第598行将把time_state全局variables重置为TIME_OK。 这就解释了为什么如果你在闰秒后用adjtimex(8)检查标志,你仍然会看到闰秒标志设置。

总之,今天最好的build议似乎是我给的第一个:禁用ntpd,并禁用闰秒标志。

还有一些最后的想法:

  • 没有一家Linux供应商注意到了John Stultz的补丁,并将其应用到他们的内核:(
  • 为什么John Stultz没有注意到这是需要的一些供应商呢? 或许活锁的机会似乎足够低,使得噪音是不合理的。
  • 我听说有关Java进程在闰秒被应用时locking或旋转的报道。 也许我们应该效仿谷歌,重新思考我们如何将闰秒应用于我们的系统: http : //googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html

06/02 John Stultz的更新:

https://lkml.org/lkml/2012/7/1/203

这篇文章包含了闰秒为什么会导致futex定时器过早和持续失效的一步一步的介绍,消除了CPU负载。

这打击我们很难。 在重启我们的许多主机之后,没有主机重新启动,结果是令人尴尬的简单和完全有效:

 /etc/init.d/ntp stop ntpdate 0.us.pool.ntp.org /etc/init.d/ntp start 

所有需要的是重置系统时钟。 啧。 我六个小时前已经知道了。

一个简单的C程序,清除内核时间状态字段中的闰秒:

 #include <sys/timex.h> #include <string.h> #include <stdio.h> int main(int argc, char **argv) { struct timex txc; int ret; (void) argc; (void) argv; bzero(&txc, sizeof(txc)); txc.modes = 0; /* fetch */ ret = adjtimex(&txc); if (ret < 0) { perror("adjtimex (get)"); return 1; } txc.modes = ADJ_STATUS; txc.status &= ~16; ret = adjtimex(&txc); if (ret < 0) { perror("adjtimex (set)"); return 1; } return 0; } 

保存为lsec.c ,用gcc -Wall -Wextra -o lsec lsec.c并以root用户gcc -Wall -Wextra -o lsec lsec.c运行。

在运行之前,您可能需要停止ntpd,并在闰秒后重新启动ntpd。

看来似乎./lsec没有效果。

我们所看到的是大量的进程在吃CPU(通常对于java进程是线性的)

通过ntp应用闰秒修复POSTMORTEM的工作如下:

似乎只要发布就足够了:

 export LANG="en_EN"; date -s "`date`" 

这应该减less没有ntpd重新启动或重新启动的负载。 或者,您可以发出:

 apt-get install ntpdate /etc/init.d/ntpd stop; ntpdate pool.ntp.org; /etc/init.d/ntpd start 

http://my.opera.com/marcomarongiu/blog/2012/03/12/no-step-back似乎表明,Debian挤压内核将不会处理闰秒&#x3002;

comp.protocols.tim.ntp上的这个线程是有趣的,也是: https ://groups.google.com/forum/?fromgroups#! topic/ comp.protocols.time.ntp/KSflIgjUdPE

也就是说,闰秒还没有发生:23:59:60 UTC

最后, https://access.redhat.com/knowledge/articles/15145有如下的说法:“当闰秒发生时,内核打印一条消息到系统日志,有机会打印这个消息会导致内核在Red Hat Enterprise Linux中崩溃。“