Czy ktoś jeszcze doświadcza dużej liczby awarii serwera Linux podczas drugiego dnia przestępnego?

365

* UWAGA: jeśli twój serwer nadal ma problemy z powodu pomieszanych jąder i nie możesz zrestartować komputera - najprostszym rozwiązaniem proponowanym z zainstalowaną datą gnu w twoim systemie jest: data-teraz. Spowoduje to zresetowanie wewnętrznej zmiennej „time_was_set” jądra i naprawi zapętlające się pętle futex CPU w java i innych narzędziach przestrzeni użytkownika. Zgubiłem to polecenie we własnym systemie i potwierdziłem, że robi to, co jest napisane na puszce *

SEKCJA ZWŁOK

Anticlimax: jedyną rzeczą, która umarła, był mój link VPN (openvpn) do klastra, więc było kilka ekscytujących sekund, gdy zostało ponownie ustanowione. Wszystko inne było w porządku, a uruchomienie ntp poszło gładko po upływie sekundy przestępnej.

Całe moje doświadczenie dnia napisałem na stronie http://blog.fastmail.fm/2012/07/03/a-story-of-leaping-seconds/

Jeśli spojrzysz na bloga Marco pod adresem http://my.opera.com/marcomarongiu/blog/2012/06/01/an-humble-attempt-to-work-around-the-leap-second - ma on rozwiązanie zmieniając czas w ciągu 24 godzin za pomocą ntpd -x, aby uniknąć 1-sekundowego pominięcia. Jest to alternatywna metoda rozmazywania w stosunku do prowadzenia własnej infrastruktury NTTP.


Właśnie dzisiaj, w sobotę 30 czerwca 2012 r. - rozpoczynając wkrótce po rozpoczęciu dnia GMT. Mieliśmy garstkę serwerów w różnych centrach danych, którymi zarządzają różne zespoły, wszystkie stają się ciemne - nie reagujemy na pingi, ekran jest pusty.

Wszystkie działają w systemie Debian Squeeze - od wszystkiego, od podstawowego jądra po niestandardowe kompilacje 3.2.21. Większość to ostrza Dell M610, ale właśnie zgubiłem Dell R510, a inne działy straciły również maszyny innych dostawców. Był też starszy IBM x3550, który się zawiesił i który, jak myślałem, może być niezwiązany, ale teraz się zastanawiam.

Jedna awaria, z której zrobiłem zrzut ekranu, powiedziała:

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

Niestety, wszystkie ostrza podobno miały skonfigurowane kdump, ale zginęły tak mocno, że kdump nie uruchomił się - i miały włączone wygaszanie konsoli. Wyłączyłem teraz wygaszanie konsoli, więc kciuki będę miał więcej informacji po następnej awarii.

Po prostu chcę wiedzieć, czy jest to wspólny wątek, czy „tylko my”. To naprawdę dziwne, że są to różne jednostki w różnych centrach danych kupowane w różnych momentach i prowadzone przez różnych administratorów (uruchamiam FastMail.FM) ... a teraz nawet inny sprzęt dostawcy. Większość maszyn, które uległy awarii, działała od tygodni / miesięcy i korzystała z jądra serii 3.1 lub 3.2.

Ostatnia awaria była maszyną, która działała tylko około 6 godzin z uruchomioną wersją 3.2.21.

OBEJŚCIE

Ok ludzie, oto jak to obejrzałem.

  1. wyłączone ntp: /etc/init.d/ntp stop
  2. utworzono http://linux.brong.fastmail.fm/2012-06-30/fixtime.pl (kod skradziony Marco, zobacz komentarze na blogu w komentarzach)
  3. przebiegła fixtime.plbez argumentu, aby zobaczyć, że nastąpił drugi zestaw przestępny
  4. pobiegł fixtime.plz argumentem, aby usunąć sekundę przestępną

UWAGA: zależy od adjtimex. Umieściłem kopię pliku adjtimexbinarnego squeeze na http://linux.brong.fastmail.fm/2012-06-30/adjtimex - będzie działał bez zależności od 64-bitowego systemu squeeze. Jeśli umieścisz go w tym samym katalogu co fixtime.pl, będzie on używany, jeśli nie ma go w systemie. Oczywiście, jeśli nie masz squeeze 64-bit… znajdź swój własny.

Zacznę od ntpjutra.

Jak zasugerował anonimowy użytkownik - alternatywą dla biegania adjtimexjest po prostu samodzielne ustawienie czasu, co prawdopodobnie spowoduje również skasowanie licznika upływu czasu.

Bron Gondwana
źródło
58
Dzisiaj jest 30 sekund. Waham się sugerować, że to twój problem, ale będę uważnie obserwował moje maszyny Debiana.
jscott,
2
od rana Straciliśmy co najmniej 9 różnych pakietów ściśnięcia Debiana od różnych dostawców, wszystkie działające jądro wyciskają jądro 2.6.32. nie udało nam się również zrobić zrzutu awaryjnego z powodu
wygaszenia
3
lkml publikuje o tym lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html
Daniel S. Sterling
2
Dziękujemy za zgłoszenie tego! Patrzę teraz bardzo uważnie na moje serwery.
Janne Pikkarainen
5
Wątek LKML wskazał, że to date -s "`date`"pomaga - z pewnością mi pomogło.
Pointy

Odpowiedzi:

321

Jest to spowodowane przez blokadę aktywności, gdy ntpd wywołuje adjtimex (2), aby poinformować jądro, aby wstawiło sekundę przestępną. Zobacz publikowanie lkml http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html

Red Hat powinien również aktualizować swój artykuł KB. https://access.redhat.com/knowledge/articles/15145

AKTUALIZACJA: Red Hat ma drugi artykuł KB tylko na ten temat tutaj: https://access.redhat.com/knowledge/solutions/154713 - poprzedni artykuł dotyczy wcześniejszego niezwiązanego problemu

Obejściem problemu jest po prostu wyłączenie ntpd. Jeśli ntpd wydało już wywołanie adjtimex (2), może być konieczne wyłączenie ntpd i ponowne uruchomienie, aby być w 100% bezpiecznym.

Wpływa to na RHEL 6 i inne dystrybucje, w których działają nowsze jądra (nowsze niż około 2.6.26), ale nie RHEL 5.

Powodem tego jest występujący przed drugim skokiem jest rzeczywiście planowane jest to, że występuje jądro ntpd pozwala obsłużyć drugi skok na północy, ale musi powiadomić jądro wstawić skok sekund przed północą. W związku z tym ntpd wywołuje adjtimex (2) w dniu drugiego przestępnego momentu, w którym to momencie ten błąd jest wywoływany.

Jeśli masz zainstalowany adjtimex (8), możesz użyć tego skryptu, aby ustalić, czy flaga 16 jest ustawiona. Flaga 16 „wstawia sekundę przestępną”:

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

AKTUALIZACJA:

Red Hat zaktualizował swój artykuł KB, aby zauważyć: „Znany problem może dotyczyć klientów RHEL 6, który powoduje, że NMI Watchdog wykrywa zawieszenie po otrzymaniu powiadomienia o upływie czasu NTP. Problem ten jest rozwiązywany w odpowiednim czasie. Jeśli Twoje systemy otrzymały zawiadomienie o upłynięciu drugiej godziny i nie wystąpił ten problem, nie ma to już wpływu ”.

AKTUALIZACJA: Powyższy język został usunięty z artykułu Red Hat; i dodano drugie rozwiązanie KB szczegółowo opisujące awarię adjtimex (2): https://access.redhat.com/knowledge/solutions/154713

Jednak zmiana kodu w poście LKML przez inżyniera IBM Johna Stultza zauważa, że ​​może również wystąpić impas, gdy sekunda przestępna jest rzeczywiście zastosowana, więc możesz chcieć wyłączyć sekundę przestępną poprzez ponowne uruchomienie lub użycie adjtimex (8) po wyłączeniu ntpd.

AKTUALIZACJA KOŃCOWA:

Cóż, nie jestem programistą jądra, ale ponownie sprawdziłem łatkę Johna Stultza tutaj: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d

Jeśli tym razem dobrze go czytam, pomyliłem się co do kolejnego impasu po zastosowaniu sekundy przestępnej. To wydaje się być również opinią Red Hata, opartą na ich wpisie w KB. Jeśli jednak wyłączyłeś ntpd, wyłącz go na kolejne 10 minut, aby nie uderzyć w impas, gdy ntpd wywołuje adjtimex (2).

Dowiemy się, czy wkrótce będą więcej błędów :)

DRUGA AKTUALIZACJA PO SKOKU:

Ostatnie kilka godzin spędziłem na czytaniu kodu jądra ntpd i pre-patcha (buggy), i chociaż mogę się tutaj bardzo mylić, postaram się wyjaśnić, co się dzieje:

Po pierwsze, ntpd cały czas wywołuje adjtimex (2). Robi to jako część swojego „filtra pętli zegara”, zdefiniowanego w local_clock w ntp_loopfilter.c. Możesz zobaczyć ten kod tutaj: http://www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c (z wersji ntp 4.2.6).

Filtr pętli zegara działa dość często - działa za każdym razem, gdy ntpd odpytuje swoje serwery nadrzędne, co domyślnie co 17 minut lub dłużej. Odpowiedni bit filtra pętli zegara to:

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

I wtedy:

ntp_adjtime(&ntv)

Innymi słowy, w dni, w których następuje sekunda przestępna, ntpd ustawia flagę „STA_INS” i wywołuje adjtimex (2) (za pomocą opakowania przenośności).

To wywołanie systemowe dociera do jądra. Oto odpowiedni kod jądra: https://github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c

Ścieżka kodowa jądra wygląda mniej więcej tak:

  • linia 663 - początek procedury do_adjtimex.
  • linia 691 - anuluj dowolny istniejący licznik sekund przestępnych.
  • linia 709 - weź blokadę ntp_lock (ta blokada bierze udział w możliwej awarii livelock)
  • linia 724 - wywołuje tryby_adjtimex_procesu.
  • linia 616 - wywołanie proces_adj_status.
  • linia 590 - ustaw zmienną globalną time_status, na podstawie flag ustawionych w wywołaniu adjtimex (2)
  • wiersz 592 - sprawdź zmienną globalną time_state. w większości przypadków wywołaj ntp_start_leap_timer.
  • linia 554 - sprawdź zmienną globalną time_status. STA_INS zostanie ustawiony, więc ustaw czas_czasu na TIME_INS i wywołaj hrtimer_start (kolejna funkcja jądra), aby uruchomić drugi licznik czasu przestępnego. podczas tworzenia timera ten kod pobiera xtime_lock. jeśli tak się stanie, gdy inny procesor już chwycił xtime_lock i ntp_lock, oznacza to, że jądro blokuje się. dlatego John Stultz napisał łatkę, aby uniknąć używania hrtimerów. To właśnie sprawiło wszystkim dzisiaj kłopoty.
  • linia 598 - jeśli ntp_start_leap_timer tak naprawdę nie uruchomił timera przestępnego, ustaw czas_czasu na TIME_OK
  • linia 751 - przy założeniu, że jądro nie blokuje się, stos jest rozwijany i zwalniana jest blokada ntp_lock.

Jest tu kilka interesujących rzeczy.

Po pierwsze, linia 691 kasuje istniejący zegar za każdym razem, gdy wywoływany jest adjtimex (2). Następnie 554 ponownie tworzy ten zegar. Oznacza to, że za każdym razem, gdy ntpd uruchamia filtr pętli zegara, wywoływany jest błędny kod.

Dlatego uważam, że Red Hat mylił się, gdy mówili, że gdy ntpd ustawi flagę drugiego skoku, system się nie zawiesi. Wierzę, że każdy system z uruchomionym NTTP miał potencjał do blokowania się co 17 minut (lub więcej) przez 24 godziny przed sekundą przestępną. Wierzę, że może to również wyjaśniać, dlaczego tak wiele systemów uległo awarii; jednorazowa szansa na awarię byłaby znacznie mniej prawdopodobna w porównaniu z 3 szansami na godzinę.

AKTUALIZACJA: W rozwiązaniu KB Red Hata pod adresem https://access.redhat.com/knowledge/solutions/154713 inżynierowie Red Hat doszli do tego samego wniosku (że uruchomienie ntpd ciągle uderzałoby w błędny kod). I rzeczywiście zrobili to kilka godzin wcześniej. To rozwiązanie nie było powiązane z głównym artykułem na https://access.redhat.com/knowledge/articles/15145 , więc do tej pory tego nie zauważyłem.

Po drugie, wyjaśnia to, dlaczego załadowane systemy częściej ulegały awariom. Załadowane systemy będą obsługiwały więcej przerwań, powodując częstsze wywoływanie funkcji jądra „do_tick”, co daje większą szansę na uruchomienie tego kodu i złapanie ntp_lock podczas tworzenia timera.

Po trzecie, czy jest szansa na awarię systemu, gdy rzeczywiście nastąpi sekunda przestępna? Nie wiem na pewno, ale być może tak, ponieważ licznik czasu, który odpala i faktycznie wykonuje regulację drugiego skoku (ntp_leap_second, na linii 388), również chwyta blokadę ntp_lock i ma wywołanie hrtimer_add_expires_ns. Nie wiem, czy to połączenie może również wywołać blokadę ruchu, ale nie wydaje się to niemożliwe.

Wreszcie, co powoduje, że flaga sekund przestępnych jest wyłączana po uruchomieniu sekundy przestępnej? Odpowiedź: ntpd przestaje ustawiać flagę drugiego skoku w pewnym momencie po północy, gdy wywołuje adjtimex (2). Ponieważ flaga nie jest ustawiona, sprawdzenie w wierszu 554 nie będzie prawdziwe i nie zostanie utworzony zegar, a wiersz 598 zresetuje zmienną globalną time_state na TIME_OK. To wyjaśnia, dlaczego jeśli sprawdziłeś flagę za pomocą adjtimex (8) tuż po drugim przestępnym czasie, nadal zobaczysz ustawioną flagę drugiego skoku.

Krótko mówiąc, najlepszą radą na dziś wydaje się być pierwsza, którą dałem przecież: wyłącz ntpd i wyłącz flagę drugiego skoku.

I kilka ostatnich myśli:

  • żaden z dostawców systemu Linux nie zauważył łatki Johna Stultza i nie zastosował jej do swoich jąder :(
  • dlaczego John Stultz nie powiadomił niektórych dostawców, że jest to potrzebne? być może szansa na zastój wydawała się wystarczająco niska, aby hałas nie był uzasadniony.
  • Słyszałem doniesienia o blokowaniu lub wirowaniu procesów Java, gdy zastosowano sekundę przestępną. Być może powinniśmy podążać za wskazówkami Google i przemyśleć, jak stosujemy sekundy przestępne w naszych systemach: http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html

06/02 Aktualizacja od Johna Stultza:

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

Post zawierał krok po kroku wyjaśnienie, dlaczego sekunda przestępna spowodowała, że ​​timery futex wygasały przedwcześnie i ciągle, zwiększając obciążenie procesora.

Daniel S. Sterling
źródło
7
Dzięki za doskonałą odpowiedź. Reszta naszych serwerów czeka na awarię. Śliczny. Toczymy się ponownie, nadchodzimy!
Bron Gondwana
3
Skąd mam wiedzieć, czy adjtimexzostało wydane, czy jądro drukuje coś w dmesg? Jaka jest szansa, że ​​system, który nie zawiesił się przed wyłączeniem NTTP, ulegnie awarii?
Hubert Kario
3
Hubert: uruchom „adjtimex” (zwykle jest pakowany osobno) i poszukaj flagi 16, aby wskazać sekundę przestępną w toku.
Dominic Cleal
22
Będziesz nienawidził czapki z przedstawicielami.
Wesley
26
@WesleyDavid: Nie martw się, limit powtórzeń zostanie zresetowany o północy UTC. Może.
mmyers
33

Uderzyło nas to mocno. Po zrestartowaniu wielu naszych hostów, poniższe okazały się krępująco proste i w pełni skuteczne bez restartu hosta:

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

Wystarczy zresetować zegar systemowy. Do licha. Co dałem wiedzieć o tym sześć godzin temu.

HikeOnPast
źródło
8
date -s "`date`"pracował dla mnie.
Pointy
@DeanB: Napisałem o 3 nad ranem UTC, że resetowanie zegara załatwia sprawę, niestety zajęło trochę czasu, aby być moderowanym. Zaczęliśmy też restartować serwery
Gregor,
24

Prosty program C, który usuwa drugi bit przestępny w polu statusu czasu jądra:

#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;
}

Zapisz jako lsec.c, skompiluj gcc -Wall -Wextra -o lsec lsec.ci uruchom jako root.

Prawdopodobnie będziesz chciał zatrzymać ntpd przed jego uruchomieniem i zrestartować ntpd po drugim przestępnym momencie.

jon
źródło
Co (void) argc;osiąga? Wyciszyć ostrzeżenie o nieużywanej zmiennej? Czy używanie nie int main()osiągnęłoby tego samego? Nie starając się być pedantem, jestem naprawdę ciekawy.
gparent
18

Wydaje się, że postmortem ./lsec nie ma wpływu.

To, co widzimy, to wiele procesów softirqd zjadających procesor (zwykle liniowych do obciążenia procesów Java)

To, co działa, aby naprawić POSTMORTEM z sekundami przestępnymi już zastosowanymi przez ntp, jest następujące:

Wydaje się, że wystarczy po prostu wydać:

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

To powinno zmniejszyć obciążenie bez restartowania lub restartowania NTTP. Alternatywnie możesz wydać:

apt-get install ntpdate
/etc/init.d/ntpd stop; ntpdate pool.ntp.org; /etc/init.d/ntpd start
Gregor
źródło
dlaczego sntp -snie ntpdate?
błędów
ntpdate to tylko opakowanie do sntp tutaj, z pewnością możesz również użyć ntpdate.
Gregor
ah całkowicie tęskniłem za pakietem ntpdate dla squeeze, gdzie jest to właściwie plik binarny. Zredagowałem swój wpis, aby to uwzględnić.
Gregor
Słyszałem również podobne raporty dotyczące naprawienia tego problemu (na przykład używania date -s). Wygląda na to, że poprawka wymaga jedynie ustawienia czasu systemowego zamiast zmieniania go (domyślne zachowanie ntpd, gdy przesunięcie jest małe). Domyślam się, że ustawienie czasu powoduje zresetowanie wewnętrznej mechaniki czasowej jądra.
Patrick
4
Moje aplikacje Java również zwiększyły użycie procesora (przy dużej ilości czasu procesora spędzonego w softirqd), to naprawiło to.
Hubert Kario
16

http://my.opera.com/marcomarongiu/blog/2012/03/12/no-step-back wydaje się wskazywać, że jądro ściśnięcia Debiana nie poradzi sobie z drugim skokiem.

Interesujący jest ten wątek na comp.protocols.tim.ntp, również: https://groups.google.com/forum/?fromgroups#!topic/comp.protocols.time.ntp/KSflIgjUdPE

To powiedziawszy, sekunda przestępna jeszcze się nie wydarzyła: 23:59:60 UTC

Na koniec https://access.redhat.com/knowledge/articles/15145 ma następujące zdanie: „Gdy nastąpi sekunda przestępna, jądro drukuje komunikat w dzienniku systemowym. Istnieje prawdopodobieństwo, że wydruk tego komunikatu może spowodować awarię jądra w systemie Red Hat Enterprise Linux. ”

Luca Filipozzi
źródło
Ale jądro 3.2.21 powinno, prawdopodobnie - co właśnie działała co najmniej jedna z zawieszonych maszyn
Bron Gondwana
Na niektórych z tych maszyn, które wskazał Bron, faktycznie wprowadziliśmy poprawkę, która powinna poprawnie obsłużyć nadchodzący skok.
Cosimo
czy możesz opublikować poprawkę w innym miejscu, aby inni mogli przejrzeć / zasugerować pomysły / spróbować?
kargig
Nie mam poprawki ... Zbieram informacje. Być może powinienem umieścić to w komentarzu do pierwotnego pytania.
Luca Filipozzi
4
my.opera.com/marcomarongiu/blog/2012/06/01/… zawiera więcej szczegółów na temat naprawy
Bron Gondwana