Хто-небудь ще відчуває високі показники збоїв на сервері Linux протягом високосного другого дня?


365

* ПРИМІТКА: якщо ваш сервер все ще має проблеми через заплутані ядра, і ви не можете перезавантажити - найпростіше рішення, запропоноване з датою gnu, встановленою у вашій системі, є: date -s now. Це скине внутрішню змінну ядра "time_was_set" ядра та виправить CPU, що вивішує петлі futex у Java та інших інструментах простору користувача. Я розставив цю команду у власній системі, підтвердив, що вона робить те, що написано на бляшанці *

ПОСТМОРТЕМ

Антиклімакс. Єдине, що загинуло, - це моє 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 р. - починається незабаром після початку дня GMT. У нас було декілька серверів у різних центрах обробки даних, якими керували різні команди, всі темніють - не реагуючи на пінг, порожній екран.

Вони працюють під керуванням 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бінарного видавлення на http://linux.brong.fastmail.fm/2012-06-30/adjtimex - вона буде працювати без залежностей від 64-бітної системи. Якщо ви помістите його в той самий каталог fixtime.pl, що і він, він буде використаний, якщо його немає. Очевидно, якщо у вас немає 64-бітного стискання ... знайдіть свій власний.

Я збираюся розпочати ntpзнову завтра.

Як запропонував анонімний користувач - альтернативою запуску adjtimexє просто встановити час самостійно, що, імовірно, також очистить лічильник секунд.


58
Сьогодні є другий стрибок, 30-й. Я маю на увазі, що це ваша проблема, але я буду уважно спостерігати за своїми машинами Debian.
jscott

2
з ранку Ми втратили щонайменше 9 різних скриньок для видавлювання Debian у різних постачальників, всі ядра білого складу видаляють 2.6.32 ядра. ми так і не змогли отримати дамп аварійного завершення через
блокування

3
lkml розміщую повідомлення про це lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html
Даніель С. Стерлінг

2
Дякуємо, що повідомили про це! Зараз я дуже-дуже пильно дивлюся на свої сервери.
Janne Pikkarainen

5
Нитка LKML вказала, що date -s "`date`"допомагає - це, безумовно, допомогло мені.
Pointy

Відповіді:


321

Це викликано потоком життя, коли ntpd викликає adjtimex (2), щоб сказати ядру вставити високосну секунду. Дивіться публікацію в lkml http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html

Red Hat також повинен оновлювати свою статтю KB. 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 оновив свою статтю KB, щоб зазначити: "Замовниками RHEL 6 може бути зачеплена відома проблема, яка змушує сторожового NMI виявити зависання при отриманні повідомлення про випускну секунду. Це питання вирішується своєчасно. Якщо ваші системи отримали оголошення про випускну секунду, і це питання не виникло, тоді вони більше не зачіпаються ".

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

Однак зміна коду у публікації LKML від інженера IBM Джона Стульца зазначає, що також може бути глухий кут, коли застосовано стрибкову секунду, тому ви, можливо, захочете відключити високосну секунду шляхом перезавантаження або використання adjtimex (8) після відключення ntpd.

ЗАКЛЮЧНЕ ОНОВЛЕННЯ:

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

Якщо я читаю це правильно цього разу, я помилявся з приводу того, що стався ще один глухий кут, коли застосовано високосну секунду. Це, мабуть, також є думкою Red Hat, виходячи з їхньої статті KB. Однак якщо ви відключили ntpd, тримайте його відключеним ще 10 хвилин, щоб ви не потрапили в тупик, коли ntpd викликає adjtimex (2).

Ми дізнаємось, чи скоро з’являться ще помилки :)

ДРУГЕ ОНОВЛЕННЯ ПОСТАВКИ:

Останні кілька годин я провів за читанням ядра ntpd та попереднього виправлення (баггі), і, хоча тут я можу помилятися, я спробую пояснити, що я думаю, що відбувалося:

По-перше, 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 spinlock (цей замок задіяний у можливій аварії лайфлака)
  • рядок 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, тоді ядра ядра. саме тому Джон Стульц написав патч, щоб уникнути використання хртимерів. Це те, що завдало сьогодні всім неприємностей.
  • рядок 598 - якщо ntp_start_leap_timer насправді не запустив стрибковий таймер, встановіть time_state на TIME_OK
  • рядок 751 - якщо припустимо, що ядро ​​не розгортається, стек розкручується і вивільняється спінлок ntp_lock.

Тут є кілька цікавих речей.

По-перше, рядок 691 скасовує існуючий таймер щоразу, коли викликається adjtimex (2). Потім 554 знову створює цей таймер. Це означає, що кожного разу, коли ntpd запускав свій фільтр тактового циклу, викликався код помилки.

Тому я вважаю, що Red Hat помилився, коли вони сказали, що після того, як ntpd встановив прапор високосної секунди, система не вийде з ладу. Я вважаю, що кожна система, яка працює з ntpd, мала потенціал запускати кожні 17 хвилин (або більше) за 24 години до високосної секунди. Я вважаю, що це також може пояснити, чому так багато систем вийшло з ладу; одноразова ймовірність аварії була б набагато рідшою, ніж 3 шанси на годину.

ОНОВЛЕННЯ: У рішенні KB Red Hat за адресою 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

Все, що потрібно - це скинути системний годинник. Шиш. Що я даю, я знав це шість годин тому.


8
date -s "`date`"працював на мене.
Pointy

@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?
errordeveloper

ntpdate - це просто обгортка для sntp, впевнений, що добре використовувати і ntpdate.
Грегор

ах я повністю пропустив, є пакет ntpdate для видавлювання, де він насправді є двійковим. Я відредагував свою публікацію, щоб включити її.
Грегор

Я також чув подібні повідомлення про виправлення цієї проблеми (наприклад, використання date -s). Здається, що для виправлення потрібно просто встановити системний час, а не зменшувати його (поведінка ntpd за замовчуванням, коли зсув невеликий). Я здогадуюсь, що встановлення часу призводить до того, що внутрішня механіка зберігання ядра зміниться.
Патрік

4
У моїх програмах Java додаткові процесори також зросли (з великою кількістю часу процесора, витраченого на softirqd), це виправлено.
Хуберт Каріо

16

http://my.opera.com/marcomarongiu/blog/2012/03/12/no-step-back, схоже, вказує на те, що ядро ​​стискання Debian не обробляє високосну секунду.

Ця тема в 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, мабуть, повинно бути - ось чим працювала хоча б одна з машин, що розбилися
Брон Гондвана

На кількох із тих машин, на які Брон вказав, ми фактично розгорнули виправлення, яке повинно правильно обробити майбутню стрибкову секунду.
Козимо

чи можете ви опублікувати виправлення десь, щоб інші могли переглянути / запропонувати ідеї / спробувати?
kargig

У мене немає виправлення ... Я просто збираю інформацію. Можливо, слід було б поставити це як коментар проти початкового питання.
Лука Філіпоцзі

4
my.opera.com/marcomarongiu/blog/2012/06/01/… містить більш детальну інформацію про її виправлення
Брон Гондвана
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.