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

365

* ПРИМЕЧАНИЕ: если на вашем сервере все еще есть проблемы из-за перепутанных ядер, и вы не можете перезагрузиться - самое простое решение, предложенное с установленной в вашей системе 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 не сработал - и у них была включена блокировка консоли. Я отключил гашение консоли, поэтому скрестим пальцы, у меня будет больше информации после следующего сбоя.

Просто хочу узнать, является ли это обычная тема или «только мы». Странно, что это разные устройства в разных центрах обработки данных, купленные в разное время и управляемые разными администраторами (я использую FastMail.FM) ... а теперь даже оборудование другого производителя. Большинство машин, которые выходили из строя, работали неделями / месяцами и работали с ядрами серии 3.1 или 3.2.

Самым последним сбоем была машина, которая работала всего около 6 часов и работала 3.2.21.

Временное решение

Ок, люди, вот как я обошел это.

  1. отключено ntp: /etc/init.d/ntp stop
  2. создан http://linux.brong.fastmail.fm/2012-06-30/fixtime.pl (код, украденный у Марко, см. в блогах в комментариях)
  3. побежал fixtime.plбез аргумента, чтобы увидеть, что был набор второй прыжок
  4. побежал fixtime.plс аргументом, чтобы удалить второй прыжок

ПРИМЕЧАНИЕ: зависит от adjtimex. Я поместил копию adjtimexдвоичного файла squeeze по адресу http://linux.brong.fastmail.fm/2012-06-30/adjtimex - он будет работать без зависимостей в 64-битной системе squeeze. Если вы поместите его в тот же каталог, что fixtime.plи он, он будет использоваться, если системного нет. Очевидно, что если у вас нет 64-битного сжатия, найдите свой.

Я собираюсь начать ntpснова завтра.

Как предположил анонимный пользователь, альтернативой бегу adjtimexявляется установка времени самостоятельно, что, вероятно, также сбросит счетчик секунд.

Брон Гондвана
источник
58
Сегодня есть скачок второй, 30-й. Я не решаюсь сказать, что это ваша проблема, но я буду внимательно следить за своими машинами Debian.
Jscott
2
с утра мы потеряли по крайней мере 9 различных коробок сжатия Debian от разных производителей, все с запущенным ядром squeeze 2.6.32. мы также не смогли получить аварийный дамп из-за гашения консоли ...
kargig
3
lkml публикация об этом lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html
Дэниел С. Стерлинг
2
Спасибо за сообщение об этом! Сейчас я смотрю на свои серверы очень, очень внимательно.
Янне Пиккарайнен
5
В ветке LKML указано, что date -s "`date`"помогает - это, безусловно, помогло мне.
Заостренный

Ответы:

321

Это вызвано живой блокировкой, когда 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 Джона Стулца отмечает, что может также возникнуть тупик, когда фактически применяется високосная секунда, поэтому вы можете захотеть отключить високосную секунду путем перезагрузки или использования 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, скачкообразно нагружая процессор.

Даниэль С. Стерлинг
источник
7
Спасибо за отличный ответ. Таким образом, остальные наши серверы сидят в ожидании сбоя. Прекрасный. Роллинг возобновляется, вот и мы!
Брон Гондвана
3
Как узнать adjtimex, было ли выпущено, печатает ли ядро ​​что-то в dmesg? Какова вероятность того, что система, которая не потерпела крах до отключения ntpd, потерпит крах?
Юбер Карио
3
Юбер: запустите "adjtimex" (обычно он упакован отдельно) и найдите флаг 16, чтобы указать на ожидание високосной секунды.
Доминик Клил
22
Ты будешь ненавидеть реп шапку.
Уэсли
26
@WesleyDavid: Не беспокойтесь, шапка представителя будет сброшена в полночь UTC. Может быть.
mmyers
33

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

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

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

HikeOnPast
источник
8
date -s "`date`"работал на меня.
Заостренный
@DeanB: я написал в 3 часа утра по UTC, что сброс часов делает свое дело, к сожалению, потребовалось некоторое время, чтобы модерироваться. Мы тоже начали перезагружать серверы
Грегор
24

Простая программа на 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 после второй секунды.

джон
источник
Что (void) argc;достигается? Молчать предупреждение о неиспользованной переменной? Разве не использовать int main()то же самое? Не пытаясь быть педантом, мне искренне любопытно.
gparent
18

Посмертное, кажется ./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
Грегор
источник
почему sntp -sи нет ntpdate?
ошибка разработчика
ntpdate - это просто оболочка для sntp, конечно, также можно использовать ntpdate.
Грегор
ах я полностью пропустил, есть пакет ntpdate для сжатия, где это на самом деле двоичный файл. Я отредактировал свою публикацию, чтобы включить это.
Грегор
Я также слышал похожие сообщения об исправлении этой проблемы (например, об использовании date -s). Похоже, что исправление просто требует установки системного времени вместо его поворота (поведение ntpd по умолчанию, когда смещение мало). Я предполагаю, что установка времени заставляет внутреннюю механику отсчета времени ядра сбрасываться самостоятельно.
Патрик
4
Загрузка ЦП в моих java-приложениях тоже увеличилась (с большим количеством процессорного времени, проведенного в softirqd), это исправило это.
Юбер Карио
16

http://my.opera.com/marcomarongiu/blog/2012/03/12/no-step-back, похоже, указывает на то, что ядро ​​Debian squeeze не справится с прыжком в секунду.

Эта ветка на 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. "

Лука Филипоцци
источник
Но ядро ​​3.2.21, по-видимому, должно - это то, что работало, по крайней мере, на одной из разбитых машин
Брон Гондвана
На некоторых из тех машин, на которые указал Брон, мы действительно выложили исправление, которое должно корректно обрабатывать предстоящую високосную секунду.
Козимо
Вы можете опубликовать исправление где-нибудь, чтобы другие могли просмотреть / предложить идеи / попробовать?
Каргиг
У меня нет решения ... Я просто собираю информацию. Возможно, следовало бы поставить это как комментарий к первоначальному вопросу.
Лука Филипоцци
4
my.opera.com/marcomarongiu/blog/2012/06/01/… содержит больше подробностей о том, как это исправить
Брон Гондвана