Кто-нибудь еще испытывает высокую частоту сбоев сервера Linux в течение високосного второго дня?

* ПРИМЕЧАНИЕ: если на вашем сервере все еще есть проблемы из-за перепутанных ядер, и вы не можете перезагрузиться - самое простое решение, предложенное с установленной в вашей системе gnu date: date -s now. Это сбросит внутреннюю переменную ядра "time_was_set" и исправит петли фьючнса, сжимающие процессор, в Java и других инструментах пользовательского пространства. Я установил эту команду на моей собственной системе и подтвердил, что она делает то, что говорит на жестяной коробке *

POSTMORTEM

Anticlimax: единственной вещью, которая умерла, была моя VPN (openvpn) связь с кластером, поэтому было несколько захватывающих секунд, пока он восстанавливался. Все остальное было хорошо, и запуск ntp прошел чисто после того, как прошла секунда.

Я написал свой полный опыт дня на http://blog.fastmail.fm/2012/07/03/a-story-of-leaping-seconds/

Если вы посмотрите на блог Марко по адресу http://my.opera.com/marcomarongiu/blog/2012/06/01/an-humble-attempt-to-work-around-the-leap-second - у него есть решение для поэтапное изменение времени в течение 24 часов с помощью ntpd -x, чтобы избежать пропуска через 1 секунду. Это альтернативный метод размазывания для запуска собственной инфраструктуры ntp.


Только сегодня, суббота, 30 июня 2012 года - начало вскоре после начала дня по Гринвичу. У нас было несколько серверов в разных центрах обработки данных, которые управляются разными командами, и все они теряют сознание - не реагируют на эхо-запросы, экран пуст.

Все они работают под управлением Debian Squeeze - от стандартного ядра до пользовательских сборок 3.2.21. Большинство из них являются блейд-серверами Dell M610, но я также только что потерял Dell 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

К сожалению, на всех блейдах, предположительно, был настроен kdump, но они погибли настолько сильно, что kdump не сработал - и у них была включена блокировка консоли. Я отключил гашение консоли, поэтому скрестим пальцы, у меня будет больше информации после следующего сбоя.

Просто хочу узнать, является ли это обычная тема или "только мы". It's really odd that they're different units in different datacentres bought at different times and run by different admins (I run the FastMail.FM ones)... and now even different vendor hardware. Most of the machines which crashed had been up for weeks/months and were running 3.1 or 3.2 series kernels.

The most recent crash was a machine which had only been up about 6 hours running 3.2.21.

THE WORKAROUND

Ok people, here's how I worked around it.

  1. disabled ntp: /etc/init.d/ntp stop
  2. created http://linux.brong.fastmail.fm/2012-06-30/fixtime.pl (code stolen from Marco, see blog posts in comments)
  3. побежал fixtime.pl without an argument to see that there was a leap second set
  4. побежал fixtime.pl with an argument to remove the leap second

NOTE: depends on adjtimex, I've put a copy of the squeeze adjtimex binary at http://linux.brong.fastmail.fm/2012-06-30/adjtimex — it will run without dependencies on a squeeze 64 bit system. If you put it in the same directory as fixtime.pl, it will be used if the system one isn't present. Obviously if you don't have squeeze 64-bit… find your own.

I'm going to start ntp again tomorrow.

As an anonymous user suggested - an alternative to running adjtimex is to just set the time yourself, which will presumably also clear the leapsecond counter.

5 ответов

Решение

Это вызвано живой блокировкой, когда ntpd вызывает adjtimex(2), чтобы сообщить ядру о необходимости добавления дополнительной секунды. Смотрите публикацию lkml http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html

Red Hat также должна обновить свою статью базы знаний. https://access.redhat.com/knowledge/articles/15145

ОБНОВЛЕНИЕ: Red Hat имеет вторую статью KB для этой проблемы здесь: https://access.redhat.com/knowledge/solutions/154713 - предыдущая статья предназначена для более ранней, не связанной проблемы

Обходной путь - просто отключить ntpd. Если 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"'

ОБНОВИТЬ:

Red Hat обновила свою статью базы знаний, чтобы отметить: "Клиенты RHEL 6 могут быть затронуты известной проблемой, которая заставляет NMI Watchdog обнаруживать зависание при получении объявления о високосной секунде NTP. Эта проблема решается своевременно. Если ваши системы получили объявление високосного и не возникло этой проблемы, то они больше не затрагиваются ".

ОБНОВЛЕНИЕ: вышеупомянутый язык был удален из статьи Red Hat; и было добавлено второе решение в КБ, детализирующее проблему с ошибкой adjtimex(2): https://access.redhat.com/knowledge/solutions/154713

Тем не менее, изменение кода в сообщении LKML IBM Engineer Джона Стульца (John Stultz) отмечает, что может также возникнуть тупик, когда фактически применяется високосная секунда, поэтому вы можете захотеть отключить високосную секунду путем перезагрузки или использования adjtimex(8) после отключения ntpd.

ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ:

Ну, я не разработчик ядра, но я снова рассмотрел патч Джона Стульца здесь: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6b43ae8a619d17c4935c3320d2ef9e92bdeed05d

Если я правильно читаю на этот раз, я ошибся из-за того, что возникла еще одна тупиковая ситуация, когда применяется високосная секунда. Похоже, это мнение Red Hat, основанное на их записи в КБ. Однако, если вы отключили ntpd, оставьте его отключенным еще на 10 минут, чтобы вы не зашли в тупик, когда ntpd вызывает adjtimex(2).

Мы скоро узнаем, есть ли еще ошибки:)

ПОСТ-ЛИП ВТОРОЕ ОБНОВЛЕНИЕ:

Я провел последние несколько часов, читая код ядра ntpd и pre-patch (глючный), и, хотя я могу ошибаться, я попытаюсь объяснить, что происходит:

Во-первых, ntpd постоянно вызывает adjtimex(2). Он делает это как часть своего "фильтра петли часов", определенного в local_clock в ntp_loopfilter.c. Вы можете увидеть этот код здесь: http://www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c (из ntp версии 4.2.6).

Фильтр с циклом синхронизации запускается довольно часто - он запускается каждый раз, когда 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

Кодовый путь ядра примерно такой:

  • строка 663 - начало процедуры do_adjtimex.
  • строка 691 - отменить любой существующий таймер високосной секунды.
  • строка 709 - захватить спин-блокировку ntp_lock (эта блокировка участвует в возможном сбое livelock)
  • строка 724 - вызвать process_adjtimex_modes.
  • строка 616 - вызвать process_adj_status.
  • строка 590 - установить глобальную переменную time_status, основываясь на флагах, установленных в вызове adjtimex(2)
  • строка 592 - проверка глобальной переменной time_state. в большинстве случаев вызывайте ntp_start_leap_timer.
  • строка 554 - проверка глобальной переменной time_status. Будет установлено STA_INS, поэтому установите для time_state значение TIME_INS и вызовите hrtimer_start (еще одну функцию ядра), чтобы запустить таймер для високосных секунд. в процессе создания таймера этот код захватывает xtime_lock. если это происходит, когда другой процессор уже захватил xtime_lock и ntp_lock, то ядро ​​блокирует работу. Вот почему Джон Стульц написал патч, чтобы избежать использования hrtimers. Это то, что вызывало у всех проблемы сегодня.
  • строка 598 - если ntp_start_leap_timer фактически не запускает таймер скачка, установите для time_state значение TIME_OK
  • строка 751 - при условии, что ядро ​​не выполняет живую блокировку, стек разматывается и освобождается спин-блокировка ntp_lock.

Здесь есть пара интересных вещей.

Во-первых, строка 691 отменяет существующий таймер при каждом вызове adjtimex(2). Затем 554 воссоздает этот таймер. Это означает, что каждый раз, когда ntpd запускал свой фильтр циклов синхронизации, вызывался ошибочный код.

Поэтому я считаю, что Red Hat ошиблась, когда они сказали, что как только ntpd установит флаг високосной секунды, система не будет аварийно завершать работу. Я полагаю, что каждая система, на которой запущен ntpd, могла блокироваться в режиме реального времени каждые 17 минут (или более) в течение 24-часового периода перед високосной секундой. Я считаю, что это также может объяснить, почему так много систем вышло из строя; вероятность единовременного сбоя будет гораздо меньше, чем 3 случая в час.

ОБНОВЛЕНИЕ: В решении Red Hat KB на https://access.redhat.com/knowledge/solutions/154713 инженеры Red Hat пришли к такому же выводу (что запуск ntpd будет постоянно попадать в код ошибки). И действительно, они сделали это за несколько часов до меня. Это решение не было связано с основной статьей по адресу https://access.redhat.com/knowledge/articles/15145, поэтому я не заметил его до сих пор.

Во-вторых, это объясняет, почему загруженные системы более подвержены сбоям. Загруженные системы будут обрабатывать больше прерываний, вызывая более частый вызов функции ядра "do_tick", что даст больше шансов для этого кода запустить и захватить ntp_lock во время создания таймера.

В-третьих, существует ли вероятность сбоя системы, когда фактически происходит дополнительная секунда? Я не знаю наверняка, но, возможно, да, потому что таймер, который запускает и фактически выполняет настройку високосной секунды (ntp_leap_second, в строке 388), также захватывает спин-блокировку ntp_lock и имеет вызов hrtimer_add_expires_ns. Я не знаю, может ли этот вызов также вызвать живую блокировку, но это не кажется невозможным.

Наконец, что вызывает отключение флага високосной секунды после запуска високосной секунды? Ответ там - ntpd перестает устанавливать флаг високосной секунды в какой-то момент после полуночи, когда он вызывает adjtimex(2). Поскольку флаг не установлен, проверка в строке 554 не будет истинной, и таймер не будет создан, а строка 598 сбросит глобальную переменную time_state в TIME_OK. Это объясняет, почему, если вы проверите флаг с помощью adjtimex(8) сразу после високосной секунды, вы все равно увидите установленный флаг високосной секунды.

Короче говоря, лучший совет на сегодня, кажется, первый, который я дал в конце концов: отключить ntpd и отключить флаг високосной секунды.

И несколько заключительных мыслей:

  • никто из поставщиков Linux не заметил патч Джона Стульца и применил его к своим ядрам:(
  • почему Джон Стульц не предупредил некоторых продавцов, что это было необходимо? возможно, вероятность живого шлюза казалась достаточно низкой, поэтому шум не оправдывался.
  • Я слышал сообщения о блокировке или вращении Java-процессов, когда была применена дополнительная секунда. Возможно, нам следует последовать примеру Google и переосмыслить, как мы применяем дополнительные секунды к нашим системам: http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html

06/02 Обновление от Джона Стульца:

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

Пост содержал пошаговое объяснение того, почему високосная секунда вызвала преждевременное и непрерывное истечение таймеров futex, скачкообразно нагружая процессор.

Это сильно поразило нас. После перезапуска многих из наших хостов, следующее оказалось довольно простым и эффективным без перезагрузки хоста:

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

Все, что требуется, это сбросить системные часы. Sheesh. Что я дал, чтобы знать это шесть часов назад.

Простая программа на 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.

Вы, вероятно, захотите остановить ntpd перед его запуском и перезапустить ntpd после второй секунды.

Посмертное, кажется./lsec не имеет эффекта.

То, что мы видим, это множество процессов softirqd, потребляющих процессор (обычно линейно загружаемых процессами Java)

Что работает, чтобы исправить POSTMORTEM с високосными секундами, уже примененными ntp, является следующим:

Кажется, достаточно просто выпустить:

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

Это должно уменьшить нагрузку без перезагрузки или перезагрузки 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 squeeze не справится с прыжком в секунду.

Эта ветка на comp.protocols.tim.ntp также представляет интерес: https://groups.google.com/forum/?fromgroups

Тем не менее, високосного еще не произошло: 23:59:60 UTC

Наконец, https://access.redhat.com/knowledge/articles/15145 может сказать следующее: "Когда происходит високосная секунда, ядро ​​выводит сообщение в системный журнал. Существует вероятность, что печать этого сообщения может привести к сбою ядра в Red Hat Enterprise Linux."

Другие вопросы по тегам