Toute autre personne connaissant un taux élevé de pannes de serveur Linux lors d'une deuxième journée bissextile?

365

* REMARQUE: si votre serveur rencontre toujours des problèmes en raison de noyaux confus et qu'il est impossible de redémarrer, la solution la plus simple proposée avec gnu date installée sur votre système est la suivante: date -s. Cela réinitialisera la variable interne "time_was_set" du noyau et corrigera les boucles futex monopolisant le processeur dans Java et d'autres outils de l'espace utilisateur. J'ai tracé cette commande sur mon propre système et confirmé qu'il fait ce qu'il dit sur l'étain *

AUTOPSIE

Anticlimax: la seule chose qui est morte est mon lien VPN (openvpn) vers le cluster. Il a donc fallu quelques secondes excitantes pour le rétablir. Tout allait bien, et le démarrage de NTP s'est bien passé après la seconde de seconde.

J'ai écrit toute mon expérience du jour sur http://blog.fastmail.fm/2012/07/03/a-story-of-leaping-seconds/

Si vous consultez le blog de Marco à l' adresse http://my.opera.com/marcomarongiu/blog/2012/06/01/an-humble-attempt-to-work-around-the-leap-second - il a une solution pour en échelonnant le changement d'heure sur 24 heures en utilisant ntpd -x pour éviter le saut d'une seconde. Il s'agit d'une méthode de maculation alternative à l'exécution de votre propre infrastructure ntp.


Aujourd'hui, samedi 30 juin 2012 - débutant peu de temps après le début de la journée, GMT. Une poignée de serveurs situés dans différents centres de données a été gérée par différentes équipes et ne répond plus aux pings, mais est vide.

Ils exécutent tous Debian Squeeze - avec tout, du noyau stock aux versions 3.2.21 personnalisées. La plupart sont des serveurs lames Dell M610, mais je viens également de perdre un Dell R510 et d'autres départements ont également perdu des machines d'autres fournisseurs. Il y avait aussi un ancien IBM x3550 qui s'est écrasé et qui, à mon avis, pourrait ne pas être apparenté, mais maintenant, je me pose des questions.

Le crash dont je viens de recevoir un vidage d'écran a déclaré:

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

Malheureusement, kdump était censé avoir été configuré sur toutes les lames, mais elles sont mortes si fort que kdump ne s'est pas déclenché - et le masquage de la console est activé. J'ai désactivé le masquage de la console maintenant, donc je croiserai les doigts pour plus d'informations après le prochain crash.

Je veux juste savoir si c'est un fil conducteur ou "juste nous". Il est vraiment étrange qu'ils soient des unités différentes dans différents centres de données achetés à des moments différents et gérés par différents administrateurs (j'utilise les ordinateurs FastMail.FM) ... et maintenant même des matériels de fournisseurs différents. La plupart des machines qui sont tombées en panne étaient en service depuis des semaines / mois et utilisaient des noyaux 3.1 ou 3.2.

Le crash le plus récent était une machine qui fonctionnait depuis environ 3 heures 3.2.21.

Le contournement

Ok les gens, voici comment j'ai travaillé autour de cela.

  1. ntp désactivé: /etc/init.d/ntp stop
  2. créé http://linux.brong.fastmail.fm/2012-06-30/fixtime.pl (code volé à Marco, voir les articles de blog dans les commentaires)
  3. a couru fixtime.plsans argument pour voir qu'il y avait un deuxième ensemble bissextile
  4. couru fixtime.plavec un argument pour supprimer le saut de seconde

NOTE: dépend de adjtimex. J'ai mis une copie du adjtimexbinaire squeeze à l' adresse http://linux.brong.fastmail.fm/2012-06-30/adjtimex - il s'exécutera sans dépendances sur un système squeeze 64 bits. Si vous le mettez dans le même répertoire que fixtime.pl, il sera utilisé si le système n’est pas présent. Évidemment, si vous n’avez pas à compresser 64 bits… trouvez le vôtre.

Je vais ntprecommencer demain.

Comme suggéré par un utilisateur anonyme, une alternative à la course adjtimexconsiste simplement à régler le temps vous-même, ce qui effacera probablement également le compteur en secondes.

Bron Gondwana
la source
58
Il y a une seconde aujourd'hui, le 30. J'hésite à dire que c'est votre problème, mais je surveillerai de près mes machines Debian.
Jscott
2
depuis le matin, nous avons perdu au moins 9 boîtes de compression Debian différentes de divers fournisseurs, toutes exécutant le noyau 2.6.32 de stock. Nous n'avons pas réussi à obtenir un vidage
mémoire en
3
message de lkml à propos de ce lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html
Daniel S. Sterling le
2
Merci d'avoir signalé cela! Je regarde maintenant très étroitement mes serveurs.
Janne Pikkarainen
5
Le fil de discussion LKML a indiqué que cela date -s "`date`"aide - cela m'a certainement aidé.
Pointu

Réponses:

321

Cela est dû à un livelock lorsque ntpd appelle adjtimex (2) pour dire au noyau d’insérer une seconde intercalaire. Voir la publication de lkml http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html

Red Hat devrait également mettre à jour son article de base de connaissances. https://access.redhat.com/knowledge/articles/15145

MISE À JOUR: Red Hat a publié un deuxième article sur la base de connaissances pour ce problème: https://access.redhat.com/knowledge/solutions/154713 - l'article précédent concerne un problème antérieur, sans rapport avec ce dernier.

La solution consiste simplement à désactiver ntpd. Si ntpd a déjà émis l'appel adjtimex (2), vous devrez peut-être désactiver ntpd et redémarrer pour être sûr à 100%.

Cela concerne RHEL 6 et les autres distributions utilisant des noyaux plus récents (plus récents que les 2.6.26 environ), mais pas RHEL 5.

La raison pour laquelle cela se produit avant que la seconde intercalaire ne soit réellement programmée est que ntpd permet au noyau de gérer la seconde intercalaire à minuit, mais il doit en avertir le noyau d'insérer la seconde intercalaire avant minuit. ntpd appelle donc adjtimex (2) à un moment quelconque de la journée de la seconde intercalaire, moment auquel ce bogue est déclenché.

Si vous avez installé adjtimex (8), vous pouvez utiliser ce script pour déterminer si l'indicateur 16 est défini. Le drapeau 16 est "insertion d'une seconde intercalaire":

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

MISE À JOUR:

Red Hat a mis à jour son article de la base de connaissances pour indiquer: "Les clients de RHEL 6 peuvent être affectés par un problème connu qui permet à NMI Watchdog de détecter un blocage lors de la réception de l'annonce NTP en une seconde. Ce problème est résolu rapidement. Si vos systèmes sont reçus l'annonce de la seconde de saut et n'a pas rencontré ce problème, alors ils ne sont plus affectés. "

MISE À JOUR: La langue ci-dessus a été supprimée de l'article de Red Hat. et une deuxième solution de base de connaissances a été ajoutée, détaillant le problème de crash adjtimex (2): https://access.redhat.com/knowledge/solutions/154713.

John Stultz, ingénieur chez IBM, a cependant ajouté qu'il y avait peut-être un blocage lorsque la seconde intercalaire est réellement appliquée. Vous pouvez donc désactiver cette dernière en la redémarrant ou en utilisant adjtimex (8) après avoir désactivé ntpd.

MISE À JOUR FINALE:

Bien, je ne suis pas un développeur de noyau, mais j’ai revu le correctif de John Stultz ici: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d

Si je le lis bien cette fois, je me suis trompé sur le fait qu'il y avait une autre impasse lorsque la seconde intercalaire est appliquée. Cela semble également être l'opinion de Red Hat, basée sur son entrée dans la base de connaissances. Cependant, si vous avez désactivé ntpd, maintenez-le désactivé pendant 10 minutes supplémentaires afin d'éviter tout blocage lorsque ntpd appelle adjtimex (2).

Nous verrons s'il y a bientôt d'autres bugs :)

DEUXIÈME MISE À JOUR POST-LEAP:

J'ai passé les dernières heures à lire le code du noyau ntpd et pre-patch (buggy) et, même si je me trompe peut-être, je vais tenter d'expliquer ce qui se passait:

Premièrement, ntpd appelle adjtimex (2) tout le temps. Cela fait partie de son "filtre de boucle d'horloge", défini dans local_clock dans ntp_loopfilter.c. Vous pouvez voir ce code ici: http://www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c (à partir de la version 4.2.6 de ntp).

Le filtre de boucle d'horloge fonctionne assez souvent - il s'exécute chaque fois que ntpd interroge ses serveurs en amont, ce qui correspond par défaut toutes les 17 minutes ou plus. Le bit pertinent du filtre de boucle d'horloge est:

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

Puis:

ntp_adjtime(&ntv)

En d'autres termes, les jours où il y a une seconde intercalaire, ntpd définit l'indicateur "STA_INS" et appelle adjtimex (2) (via son gestionnaire de portabilité).

Cet appel système se rend au noyau. Voici le code du noyau approprié: https://github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c

Le codepath du noyau est à peu près ceci:

  • ligne 663 - début de la routine do_adjtimex.
  • ligne 691 - annule toute minuterie en secondes intercalaires existante.
  • ligne 709 - récupère le spinlock ntp_lock (ce verrou est impliqué dans un possible crash de livelock)
  • ligne 724 - appelez process_adjtimex_modes.
  • ligne 616 - appelez process_adj_status.
  • ligne 590 - définit la variable globale time_status, en fonction des indicateurs définis dans l'appel adjtimex (2)
  • ligne 592 - vérifie la variable globale time_state. dans la plupart des cas, appelez ntp_start_leap_timer.
  • ligne 554 - Vérifiez la variable globale time_status. STA_INS sera défini, donc définissez time_state sur TIME_INS et appelez hrtimer_start (une autre fonction du noyau) pour démarrer le temporisateur par seconde intercalaire. en train de créer une minuterie, ce code récupère le xtime_lock. si cela se produit alors qu'un autre processeur a déjà saisi les clés xtime_lock et ntp_lock, le noyau livelocks. C'est pourquoi John Stultz a écrit le correctif pour éviter d'utiliser des horloges. C'est ce qui causait des problèmes à tout le monde aujourd'hui.
  • ligne 598 - si ntp_start_leap_timer n'a pas démarré un retardateur, définissez time_state sur TIME_OK
  • ligne 751 - en supposant que le noyau ne fonctionne pas, la pile est déroulée et le verrou tournant ntp_lock est libéré.

Il y a quelques choses intéressantes ici.

Premièrement, la ligne 691 annule la minuterie existante chaque fois que adjtimex (2) est appelé. Ensuite, 554 recrée ce minuteur. Cela signifie que chaque fois que ntpd a exécuté son filtre de boucle d’horloge, le code du buggy a été appelé.

C’est pourquoi je pense que Red Hat avait tort quand ils ont déclaré qu’une fois que ntpd aurait défini le drapeau de la seconde intercalaire, le système ne planterait plus. Je pense que chaque système exécutant ntpd pouvait potentiellement survivre toutes les 17 minutes (ou plus) pendant les 24 heures précédant le saut de seconde. Je crois que cela peut aussi expliquer pourquoi autant de systèmes se sont écrasés. une chance unique de chute serait beaucoup moins susceptible de frapper que 3 chances par heure.

MISE À JOUR: Dans la solution de base de connaissances de Red Hat à l’ adresse https://access.redhat.com/knowledge/solutions/154713 , les ingénieurs de Red Hat sont parvenus à la même conclusion (l’exécution de ntpd ne cesserait de frapper le code du buggy). Et en effet, ils l'ont fait plusieurs heures avant moi. Cette solution n'était pas liée à l'article principal à l' adresse https://access.redhat.com/knowledge/articles/15145 , je ne l'avais donc pas remarquée jusqu'à présent.

Deuxièmement, cela explique pourquoi les systèmes chargés étaient plus susceptibles de tomber en panne. Les systèmes chargés gèrent davantage d'interruptions, ce qui entraîne l'appel de la fonction de noyau "do_tick" plus souvent, ce qui donne une chance supplémentaire à ce code de s'exécuter et de récupérer le ntp_lock pendant la création du temporisateur.

Troisièmement, y a-t-il une chance que le système se bloque lorsque la seconde intercalaire se produit réellement? Je ne sais pas avec certitude, mais peut-être que oui, car le minuteur qui déclenche et exécute le réglage en secondes (ntp_leap_second, ligne 388) saisit également le spinlock ntp_lock et effectue un appel à hrtimer_add_expires_ns. Je ne sais pas si cet appel pourrait également causer un délai de livraison, mais cela ne semble pas impossible.

Enfin, pourquoi le drapeau de seconde intercalaire est-il désactivé une fois la seconde intercalaire écoulée? La réponse est que ntpd cesse de définir l'indicateur de seconde intercalaire à partir de minuit, lorsqu'il appelle adjtimex (2). Comme l'indicateur n'est pas défini, la vérification de la ligne 554 ne sera pas vraie, aucune minuterie ne sera créée et la ligne 598 réinitialisera la variable globale time_state en TIME_OK. Cela explique pourquoi, si vous avez coché le drapeau avec adjtimex (8) juste après la seconde de saut, vous verriez toujours le drapeau défini.

En bref, le meilleur conseil pour aujourd'hui semble être le premier que j'ai donné après tout: désactiver ntpd et désactiver l'indicateur de saut de seconde.

Et quelques réflexions finales:

  • aucun des vendeurs de Linux n'a remarqué le correctif de John Stultz et l'a appliqué à leurs noyaux :(
  • pourquoi John Stultz n'a-t-il pas averti certains des fournisseurs que c'était nécessaire? peut-être que la chance du livelock semblait assez faible pour que le bruit ne soit pas garanti.
  • J'ai entendu parler de processus Java bloqués ou en rotation lorsque la seconde intercalaire était appliquée. Peut-être devrions-nous suivre l'exemple de Google et repenser la manière dont nous appliquons des secondes intercalaires à nos systèmes: http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html

06/02 Mise à jour de John Stultz:

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

Le message contenait une explication pas à pas des raisons pour lesquelles la seconde intercalaire avait provoqué une expiration prématurée et continue des minuteries futex, alourdissant ainsi la charge du processeur.

Daniel S. Sterling
la source
7
Merci pour l'excellente réponse. Donc, le reste de nos serveurs sont assis en attente de crash. Charmant. Le roulement redémarre ici nous arrivons!
Bron Gondwana
3
Comment savoir si le fichier adjtimexa été publié, le noyau affiche-t-il quelque chose dans dmesg? Quelle est la probabilité qu’un système qui ne s’est pas arrêté avant de désactiver ntpd tombe en panne?
Hubert Kario
3
Hubert: lancez "adjtimex" (il est généralement emballé séparément) et recherchez l'indicateur 16 pour indiquer une seconde intercalaire en attente.
Dominic Cleal
22
Vous allez détester le bonnet de rep.
Wesley
26
@WesleyDavid: Pas de panique, la limite de répétition sera réinitialisée à minuit UTC. Peut être.
mmyers
33

Cela nous a frappé fort. Après avoir redémarré un grand nombre de nos hôtes, les éléments suivants se sont révélés être d'une simplicité embarrassante et pleinement efficaces sans redémarrage d'hôte:

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

Tout ce qui est nécessaire est de réinitialiser l'horloge système. Sheesh. Ce que j'ai donné, je le sais depuis six heures.

Randonnée pédestre
la source
8
date -s "`date`"a travaillé pour moi.
Pointu
@DeanB: J'ai posté à 3 heures du matin UTC pour réinitialiser l'horloge, malheureusement, il a fallu un certain temps pour se modérer. Nous avons également démarré le redémarrage des serveurs
Gregor, le
24

Un simple programme en C qui efface le bit de seconde intercalaire dans le champ d'état temporel du noyau:

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

Enregistrer sous lsec.c, compiler avec gcc -Wall -Wextra -o lsec lsec.cet exécuter en tant que root.

Vous voudrez probablement arrêter ntpd avant de l'exécuter et redémarrer ntpd après la seconde intercalaire.

jon
la source
Qu'est-ce que (void) argc;accomplir? Faire taire l'avertissement pour la variable non utilisée? Ne pas utiliser int main()accomplir la même chose? N'essayant pas d'être un pédant, je suis vraiment curieux.
gparent
18

Post mortem, il semble que ./lsec n'a pas d'effet.

Nous constatons un grand nombre de processus softirqd consommant du processeur (généralement linéaires par rapport à la charge des processus java)

Ce qui fonctionne pour réparer POSTMORTEM avec les secondes intercalaires déjà appliquées par NTP est le suivant:

Il semble suffire de simplement émettre:

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

Cela devrait réduire la charge sans redémarrage ni redémarrage de ntpd. Sinon, vous pouvez émettre:

apt-get install ntpdate
/etc/init.d/ntpd stop; ntpdate pool.ntp.org; /etc/init.d/ntpd start
Gregor
la source
pourquoi sntp -set non ntpdate?
errordeveloper
ntpdate est juste un wrapper à sntp ici, bien sûr que c'est bien d'utiliser ntpdate aussi.
Gregor
ah j'ai complètement raté il y a un paquet ntpdate pour squeeze où il s'agit en fait d'un fichier binaire. J'ai modifié mon message pour l'inclure.
Gregor
J'ai entendu des rapports similaires sur la résolution de ce problème (par exemple, l'utilisation date -s). Il semble que le correctif nécessite simplement de régler l’heure du système au lieu de la modifier (le comportement par défaut de ntpd lorsque offset est petit). Je suppose que la définition de l'heure provoque la réinitialisation des mécanismes de chronométrage internes du noyau.
Patrick
4
L’utilisation du processeur par mes applications java a également augmenté (avec beaucoup de temps processeur dans softirqd), cela a été corrigé.
Hubert Kario
16

http://my.opera.com/marcomarongiu/blog/2012/03/12/no-step-back semble indiquer que le noyau squeeze de Debian ne gérera pas la seconde intercalaire.

Ce fil de discussion sur comp.protocols.tim.ntp est également intéressant: https://groups.google.com/forum/?fromgroups#!topic/comp.protocols.time.ntp/KSflIgjUdPE

Cela dit, la seconde intercalaire n'a pas encore eu lieu: 23:59:60 UTC

Enfin, https://access.redhat.com/knowledge/articles/15145 indique ce qui suit: "Lorsque la seconde intercalaire se produit, le noyau imprime un message dans le journal système. Il est possible que l'impression de ce message peut provoquer le blocage du noyau dans Red Hat Enterprise Linux. "

Luca Filipozzi
la source
Mais le noyau 3.2.21 devrait, vraisemblablement - ce qui est ce qu’au moins une des machines s’est écrasée
Bron Gondwana
Sur certaines de ces machines qui, selon Bron, ont indiqué que nous avions en fait mis au point un correctif qui devrait correctement prendre en charge la seconde intercalaire à venir.
Cosimo
pouvez-vous poster le correctif quelque part afin que d'autres puissent examiner / suggérer des idées / essayer?
Kargig
Je n'ai pas de solution ... Je ne fais que collecter des informations. Peut-être aurait-il fallu mettre cela comme un commentaire par rapport à la question initiale.
Luca Filipozzi
4
my.opera.com/marcomarongiu/blog/2012/06/01/… contient plus de détails sur la réparation
Bron Gondwana