Qualcun altro ha riscontrato alti tassi di crash del server Linux durante un secondo giorno bisestile?


365

* NOTA: se il tuo server ha ancora problemi a causa di kernel confusi e non riesci a riavviare - la soluzione più semplice proposta con gnu date installata sul tuo sistema è: date -s now. Ciò ripristinerà la variabile "time_was_set" interna del kernel e risolverà i loop futex di hogging della CPU in java e altri strumenti per lo spazio utente. Ho modificato questo comando sul mio sistema e ho confermato che sta facendo ciò che dice sulla scatola *

POSTMORTEM

Anticlimax: l'unica cosa che è morta era il mio collegamento VPN (openvpn) al cluster, quindi ci sono stati alcuni eccitanti secondi mentre si ristabiliva. Tutto il resto andava bene, e l'avvio di ntp è andato bene dopo che era passato il secondo di salto.

Ho scritto la mia intera esperienza del giorno su http://blog.fastmail.fm/2012/07/03/a-story-of-leaping-seconds/

Se guardi il blog di Marco su http://my.opera.com/marcomarongiu/blog/2012/06/01/an-humble-attempt-to-work-around-the-leap-second - ha una soluzione per la modifica graduale del tempo su 24 ore usando ntpd -x per evitare il salto di 1 secondo. Questo è un metodo alternativo per eseguire la propria infrastruttura ntp.


Proprio oggi, sabato 30 giugno 2012, a partire subito dopo l'inizio della giornata GMT. Abbiamo avuto una manciata di server in diversi data center gestiti da diversi team che si oscurano tutti - non rispondendo ai ping, schermo vuoto.

Stanno tutti eseguendo Debian Squeeze - con qualsiasi cosa, dal kernel stock alle build 3.2.21 personalizzate. La maggior parte sono blade Dell M610, ma ho anche perso un Dell R510 e anche altri dipartimenti hanno perso macchine di altri fornitori. C'era anche un vecchio IBM x3550 che si è schiantato e che pensavo potesse non essere correlato, ma ora mi chiedo.

L'unico incidente da cui ho avuto una discarica da schermo ha detto:

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

Sfortunatamente tutti i blade presumibilmente avevano configurato kdump, ma sono morti così duramente che kdump non si è innescato - e avevano attivato il blanking della console. Ora ho disabilitato il blanking della console, quindi incrociando le dita avrò maggiori informazioni dopo il prossimo incidente.

Voglio solo sapere se è un thread comune o "solo noi". È davvero strano che siano unità diverse in diversi datacenter acquistati in momenti diversi e gestiti da amministratori diversi (eseguo quelli FastMail.FM) ... e ora anche hardware di fornitori diversi. La maggior parte delle macchine che si sono schiantate era rimasta in funzione per settimane / mesi e utilizzavano kernel della serie 3.1 o 3.2.

L'incidente più recente è stata una macchina che era rimasta in funzione circa 6 ore consecutive 3.2.21.

IL LAVORO

Ok gente, ecco come ci ho lavorato.

  1. ntp disabilitato: /etc/init.d/ntp stop
  2. creato http://linux.brong.fastmail.fm/2012-06-30/fixtime.pl (codice rubato da Marco, vedi post sul blog nei commenti)
  3. ha funzionato fixtime.plsenza argomenti per vedere che c'era un secondo salto
  4. correva fixtime.plcon un argomento per rimuovere il secondo balzo

NOTA: dipende da adjtimex. Ho messo una copia del file adjtimexbinario di compressione su http://linux.brong.fastmail.fm/2012-06-30/adjtimex - funzionerà senza dipendenze su un sistema di compressione a 64 bit. Se lo metti nella stessa directory di fixtime.pl, verrà utilizzato se quello di sistema non è presente. Ovviamente se non hai una compressione a 64 bit ... trova il tuo.

Ricomincio ntpdomani.

Come suggerito da un utente anonimo, un'alternativa alla corsa adjtimexè semplicemente impostare l'ora, che presumibilmente cancellerà anche il contatore dei secondi.


58
Oggi c'è un balzo in avanti, il 30. Sono titubante nel dire che questo è il tuo problema, ma guarderò da vicino le mie macchine Debian.
jscott,

2
dalla mattina abbiamo perso almeno 9 diversi debian squeeze box di vari venditori che eseguono tutti i kernel stock squeeze 2.6.32. non siamo stati in grado di ottenere un dump di arresto anomalo a causa del blanking della console ...
Kargig,


2
Grazie per aver segnalato questo! Ora sto fissando i miei server molto, molto da vicino.
Janne Pikkarainen,

5
Il thread LKML ha indicato che date -s "`date`"aiuta - sicuramente mi ha aiutato.
Punta

Risposte:


321

Ciò è causato da un livelock quando ntpd chiama adjtimex (2) per dire al kernel di inserire un secondo di salto. Vedi i post di lkml http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html

Red Hat dovrebbe anche aggiornare anche l'articolo KB. https://access.redhat.com/knowledge/articles/15145

AGGIORNAMENTO: Red Hat ha un secondo articolo KB solo per questo problema qui: https://access.redhat.com/knowledge/solutions/154713 - l'articolo precedente riguarda un problema precedente non correlato

La soluzione è semplicemente disattivare ntpd. Se ntpd ha già emesso la chiamata adjtimex (2), potrebbe essere necessario disabilitare ntpd e riavviare per essere sicuri al 100%.

Ciò riguarda RHEL 6 e altre distro che eseguono kernel più recenti (più recenti di circa 2.6.26), ma non RHEL 5.

Il motivo per cui ciò sta accadendo prima che il secondo salto sia effettivamente programmato è che ntpd consente al kernel di gestire il secondo salto a mezzanotte, ma deve avvisare il kernel di inserire il salto prima di mezzanotte. ntpd quindi chiama adjtimex (2) qualche volta durante il giorno del secondo bisestile, a quel punto questo bug viene attivato.

Se hai installato adjtimex (8), puoi usare questo script per determinare se il flag 16 è impostato. Flag 16 è "inserimento secondo salto":

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

AGGIORNARE:

Red Hat ha aggiornato il loro articolo KB per notare: "I clienti di RHEL 6 potrebbero essere interessati da un problema noto che fa sì che NMI Watchdog rilevi un blocco durante la ricezione dell'annuncio del secondo bisestile NTP. Questo problema viene risolto in modo tempestivo. Se i sistemi hanno ricevuto l'annuncio del secondo e non ha riscontrato questo problema, quindi non sono più interessati. "

AGGIORNAMENTO: la lingua sopra è stata rimossa dall'articolo di Red Hat; e una seconda soluzione KB è stata aggiunta in dettaglio il problema di crash di adjtimex (2): https://access.redhat.com/knowledge/solutions/154713

Tuttavia, la modifica del codice nel post LKML dell'ingegnere IBM John Stultz nota che potrebbe esserci anche un deadlock quando viene effettivamente applicato il secondo bisestile, quindi potresti voler disabilitare il secondo bisestile riavviando o usando adjtimex (8) dopo aver disabilitato ntpd.

AGGIORNAMENTO FINALE:

Bene, non sono uno sviluppatore del kernel, ma ho rivisto di nuovo la patch di John Stultz qui: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d

Se sto leggendo bene questa volta, mi sbagliavo sul fatto che ci fosse un altro deadlock quando viene applicato il secondo bisestile. Anche questa sembra essere l'opinione di Red Hat, basata sulla loro voce KB. Tuttavia, se hai disabilitato ntpd, mantienilo disabilitato per altri 10 minuti, in modo da non colpire il deadlock quando ntpd chiama adjtimex (2).

Scopriremo presto se ci saranno altri bug :)

SECONDO AGGIORNAMENTO POST-LEAP:

Ho passato le ultime ore a leggere il codice del kernel ntpd e pre-patch (buggy), e mentre potrei sbagliarmi qui, cercherò di spiegare cosa penso stia succedendo:

Innanzitutto, ntpd chiama adjtimex (2) sempre. Lo fa come parte del suo "filtro loop clock", definito in local_clock in ntp_loopfilter.c. Puoi vedere quel codice qui: http://www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c (dalla versione 4.2.6 di ntp).

Il filtro del loop di clock viene eseguito abbastanza spesso: viene eseguito ogni volta che ntpd esegue il polling dei suoi server upstream, che per impostazione predefinita è ogni 17 minuti o più. Il bit rilevante del filtro del loop di clock è:

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

E poi:

ntp_adjtime(&ntv)

In altre parole, nei giorni in cui c'è un balzo in secondo, ntpd imposta il flag "STA_INS" e chiama adjtimex (2) (tramite il suo portabilità-wrapper).

Quella chiamata di sistema arriva al kernel. Ecco il codice kernel rilevante: https://github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c

Il codepath del kernel è approssimativamente questo:

  • riga 663 - inizio della routine do_adjtimex.
  • riga 691 - annulla qualsiasi timer esistente dei secondi saltati.
  • linea 709 - prendi lo spinlock ntp_lock (questo lock è coinvolto nel possibile crash del livelock)
  • linea 724 - chiama process_adjtimex_modes.
  • linea 616 - chiama process_adj_status.
  • riga 590 - imposta la variabile globale time_status, basata sui flag impostati nella chiamata adjtimex (2)
  • riga 592 - controlla la variabile globale time_state. nella maggior parte dei casi, chiama ntp_start_leap_timer.
  • riga 554 - controlla la variabile globale time_status. Verrà impostato STA_INS, quindi imposta time_state su TIME_INS e chiama hrtimer_start (un'altra funzione del kernel) per avviare il secondo del salto. nel processo di creazione di un timer, questo codice prende xtime_lock. se ciò accade mentre un'altra CPU ha già catturato xtime_lock e ntp_lock, allora i kernel livelock. questo è il motivo per cui John Stultz ha scritto la patch per evitare di usare hrtimer. Questo è ciò che stava causando problemi a tutti oggi.
  • riga 598 - se ntp_start_leap_timer non ha effettivamente avviato un timer di salto, impostare time_state su TIME_OK
  • riga 751 - supponendo che il kernel non si blocchi, lo stack viene srotolato e lo spinlock ntp_lock viene rilasciato.

Ci sono un paio di cose interessanti qui.

Innanzitutto, la riga 691 annulla il timer esistente ogni volta che viene chiamato adjtimex (2). Quindi, 554 ricrea quel timer. Ciò significa che ogni volta che ntpd ha eseguito il suo filtro loop clock, è stato invocato il codice buggy.

Quindi credo che Red Hat si sbagliasse quando affermarono che una volta che ntpd aveva impostato la bandiera del secondo bisestile, il sistema non si sarebbe bloccato. Credo che ogni sistema che esegue ntpd avesse il potenziale di legarsi in blocco ogni 17 minuti (o più) per il periodo di 24 ore prima del secondo bisestile. Credo che ciò possa anche spiegare perché così tanti sistemi si sono schiantati; una possibilità di crash di una volta sarebbe molto meno probabile che colpisse rispetto a 3 possibilità all'ora.

AGGIORNAMENTO: Nella soluzione KB di Red Hat all'indirizzo https://access.redhat.com/knowledge/solutions/154713 , gli ingegneri di Red Hat sono giunti alla stessa conclusione (che l'esecuzione di ntpd avrebbe colpito continuamente il codice errato). E infatti lo hanno fatto diverse ore prima di me. Questa soluzione non era collegata all'articolo principale su https://access.redhat.com/knowledge/articles/15145 , quindi non me ne sono accorto fino ad ora.

In secondo luogo, questo spiega perché i sistemi caricati avevano maggiori probabilità di arrestarsi in modo anomalo. I sistemi caricati gestiranno un numero maggiore di interruzioni, facendo sì che la funzione del kernel "do_tick" venga chiamata più spesso, dando più possibilità a questo codice di essere eseguito e catturare ntp_lock durante la creazione del timer.

Terzo, c'è la possibilità che il sistema si blocchi quando si verifica effettivamente il secondo bisestile? Non lo so per certo, ma forse sì, perché il timer che spara ed esegue effettivamente la regolazione del secondo bisestile (ntp_leap_second, sulla linea 388) prende anche lo spinlock ntp_lock e ha una chiamata a hrtimer_add_expires_ns. Non so se quella chiamata potrebbe anche essere in grado di causare un livelock, ma non sembra impossibile.

Infine, cosa causa la disabilitazione del flag del secondo intercalare dopo l'esecuzione del secondo intercalare? La risposta è ntpd smette di impostare il flag del secondo bisestile ad un certo punto dopo la mezzanotte quando chiama adjtimex (2). Poiché il flag non è impostato, il controllo sulla riga 554 non sarà vero e non verrà creato alcun timer e la riga 598 reimposterà la variabile globale time_state su TIME_OK. Questo spiega perché se si controlla la bandiera con adjtimex (8) subito dopo il secondo bisestile, si vedrebbe comunque impostato il flag bisestile.

In breve, il miglior consiglio per oggi sembra essere il primo che ho dato dopo tutto: disabilitare ntpd e disabilitare il flag del secondo bisestile.

E alcuni pensieri finali:

  • nessuno dei fornitori di Linux ha notato la patch di John Stultz e l'ha applicata ai loro kernel :(
  • perché John Stultz non ha avvisato alcuni dei venditori che ciò era necessario? forse la possibilità che il livelock sembrasse abbastanza basso facendo rumore non era giustificata.
  • Ho sentito rapporti di processi Java bloccarsi o girare quando è stato applicato il secondo bisestile. Forse dovremmo seguire l'esempio di Google e ripensare il modo in cui applichiamo i secondi intercalari ai nostri sistemi: http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html

06/02 Aggiornamento da John Stultz:

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

Il post conteneva una spiegazione dettagliata del motivo per cui il secondo balzo ha fatto scadere prematuramente e continuamente i timer futex, aumentando il carico della CPU.


7
Grazie per l'ottima risposta. Quindi il resto dei nostri server è in attesa di crash. Bello. Il rotolamento riparte qui arriviamo!
Bron Gondwana,

3
Come faccio a sapere se adjtimexè stato rilasciato, il kernel stampa qualcosa in dmesg? Che possibilità c'è che un sistema che non si è arrestato in modo anomalo prima di spegnere ntpd si arresti in modo anomalo?
Hubert Kario,

3
Hubert: esegui "adjtimex" (di solito è confezionato separatamente) e cerca la bandiera 16 per indicare un secondo salto in sospeso.
Dominic Cleal,

22
Stai per odiare il tappo rappresentante.
Wesley,

26
@WesleyDavid: nessun problema, il limite di reimpostazione verrà ripristinato a mezzanotte UTC. Può essere.
mmyers

33

Questo ci ha colpito duramente. Dopo aver riavviato molti dei nostri host, si è rivelato imbarazzantemente semplice e pienamente efficace senza un riavvio dell'host:

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

Tutto ciò che serve è resettare l'orologio di sistema. Sheesh. Quello che ho dato per averlo saputo sei ore fa.


8
date -s "`date`"ha funzionato per me.
Punta

@DeanB: ho pubblicato alle 3 del mattino UTC che reimpostare l'orologio fa il trucco, sfortunatamente ci è voluto un po 'per essere moderato. Abbiamo iniziato anche a riavviare i server
Gregor il

24

Un semplice programma C che cancella il secondo bit di salto nel campo dello stato temporale del kernel:

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

Salva con nome lsec.c, compila con gcc -Wall -Wextra -o lsec lsec.ced esegui come root.

Probabilmente vorrai interrompere ntpd prima di eseguirlo e riavviare ntpd dopo il secondo bisestile.


Cosa (void) argc;compie? Disattiva l'avviso per la variabile non utilizzata? L'uso non int main()compirebbe lo stesso? Non cercando di essere un pedante, sono sinceramente curioso.
gparent

18

Sembra che Postmortem ./lsec non abbia alcun effetto.

Quello che stiamo vedendo è un sacco di processi softirqd che consumano CPU (solitamente lineari rispetto al carico di processi java)

Cosa funziona per correggere POSTMORTEM con i secondi intercalari già applicati da ntp è il seguente:

Sembra essere sufficiente emettere:

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

Ciò dovrebbe ridurre il carico senza riavviare o riavviare ntpd. In alternativa puoi emettere:

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

perché sntp -se no ntpdate?
errordeveloper

ntpdate è solo un wrapper per sntp qui, sicuramente va bene usare anche ntpdate.
Gregor,

ah mi sono completamente perso c'è un pacchetto ntpdate per squeeze in cui è in realtà un binario. Ho modificato il mio post per includerlo.
Gregor,

Ho sentito anche rapporti simili su come risolvere questo problema (come l'utilizzo date -s). Sembra che la correzione richieda solo di impostare l'ora di sistema invece di ruotarla (il comportamento predefinito di ntpd quando offset è piccolo). Immagino che l'impostazione del tempo causi il ripristino automatico della meccanica interna del tempo.
Patrick,

4
Anche l'utilizzo della CPU delle mie app java è aumentato (con un'elevata quantità di tempo CPU trascorso in softirqd), questo ha risolto il problema.
Hubert Kario,

16

http://my.opera.com/marcomarongiu/blog/2012/03/12/no-step-back sembra indicare che il kernel di compressione Debian non gestirà il secondo salto.

Questa discussione su comp.protocols.tim.ntp è interessante, anche: https://groups.google.com/forum/?fromgroups#!topic/comp.protocols.time.ntp/KSflIgjUdPE

Detto questo, il secondo salto non è ancora avvenuto: 23:59:60 UTC

Infine, https://access.redhat.com/knowledge/articles/15145 ha il seguente da dire: "Quando si verifica il secondo bisestile, il kernel stampa un messaggio nel registro di sistema. È possibile che la stampa di questo messaggio può causare l'arresto anomalo del kernel in Red Hat Enterprise Linux. "


Ma il kernel 3.2.21 dovrebbe, presumibilmente - che è quello che almeno una delle macchine andava in crash
Bron Gondwana,

Su alcune di quelle macchine che Bron ha indicato, abbiamo effettivamente implementato una correzione che dovrebbe gestire correttamente il secondo salto successivo.
Cosimo,

puoi pubblicare la correzione da qualche parte in modo che altri possano rivedere / suggerire idee / provare?
Kargig,

Non ho una soluzione ... Sto solo raccogliendo informazioni. Forse avrebbe dovuto mettere questo come un commento contro la domanda originale.
Luca Filipozzi,

4
my.opera.com/marcomarongiu/blog/2012/06/01/… contiene maggiori dettagli su come risolverlo
Bron Gondwana,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.