363 votos

¿Alguien más está experimentando altas tasas de caídas del servidor Linux durante un día bisiesto?

*NOTA: si su servidor sigue teniendo problemas debido a kernels confusos, y no puede reiniciar - la solución más simple propuesta con gnu date instalado en su sistema es: date -s now. Esto restablecerá la variable interna del kernel "time_was_set" y arreglará los bucles futex que acaparan la CPU en java y otras herramientas del espacio de usuario. He probado este comando en mi propio sistema y he confirmado que hace lo que dice en la lata *.

POSTMORTEM

Anticlímax: lo único que murió fue mi enlace VPN (openvpn) con el clúster, así que hubo unos segundos emocionantes mientras se restablecía. Todo lo demás estaba bien, y el inicio de ntp fue limpiamente después de que el segundo bisiesto había pasado.

He escrito mi experiencia completa del día en http://blog.fastmail.fm/2012/07/03/a-story-of-leaping-seconds/

Si miras el blog de Marco en http://my.opera.com/marcomarongiu/blog/2012/06/01/an-humble-attempt-to-work-around-the-leap-second - tiene una solución para escalonar el cambio de hora a lo largo de 24 horas utilizando ntpd -x para evitar el salto de 1 segundo. Este es un método alternativo de smearing a la ejecución de su propia infraestructura ntp.


Justo hoy, sábado 30 de junio de 2012, a partir del inicio del día GMT. Hemos tenido un puñado de servidores en diferentes centros de datos gestionados por diferentes equipos que se han quedado a oscuras, sin responder a los pings y con la pantalla en blanco.

Todos ellos están ejecutando Debian Squeeze - con todo, desde el kernel de serie hasta construcciones personalizadas 3.2.21. La mayoría son blades Dell M610, pero también acabo de perder un Dell R510 y otros departamentos también han perdido máquinas de otros proveedores. También hubo un IBM x3550 más antiguo que se estrelló y que pensé que no estaba relacionado, pero ahora me lo estoy preguntando.

El único accidente del que obtuve una captura de pantalla decía:

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

Desgraciadamente, todas las hojas tenían supuestamente configurado el kdump, pero murieron tan fuerte que el kdump no se activó - y tenían activado el blanqueo de la consola. He desactivado la supresión de la consola ahora, así que crucemos los dedos para tener más información después de la próxima caída.

Sólo quiero saber si es algo común o "sólo nosotros". Es realmente extraño que se trate de unidades diferentes en distintos centros de datos, compradas en distintos momentos y dirigidas por distintos administradores (yo dirijo las de FastMail.FM)... y ahora incluso hardware de distintos proveedores. La mayoría de las máquinas que se estropearon llevaban semanas/meses funcionando con kernels de la serie 3.1 o 3.2.

La última caída se produjo en una máquina que sólo llevaba unas 6 horas funcionando con la versión 3.2.21.

LA SOLUCIÓN

Ok gente, aquí está cómo trabajé alrededor de él.

  1. deshabilitado el ntp: /etc/init.d/ntp stop
  2. creado http://linux.brong.fastmail.fm/2012-06-30/fixtime.pl (código robado a Marco, ver entradas del blog en los comentarios)
  3. corrió fixtime.pl sin un argumento para ver que había un conjunto de segundos bisiestos
  4. corrió fixtime.pl con un argumento para eliminar el segundo bisiesto

NOTA: depende de adjtimex . He puesto una copia del apretón adjtimex binario en http://linux.brong.fastmail.fm/2012-06-30/adjtimex - se ejecutará sin dependencias en un sistema squeeze de 64 bits. Si lo pones en el mismo directorio que fixtime.pl Se utilizará si el del sistema no está presente. Obviamente, si usted no tiene squeeze 64 bits encontrar su propio.

Voy a empezar ntp de nuevo mañana.

Como sugirió un usuario anónimo, una alternativa a la ejecución de adjtimex es ajustar la hora tú mismo, lo que presumiblemente también borrará el contador de segundos intercalares.

318voto

Buggieboy Puntos 1875

Esto es causado por un livelock cuando ntpd llama a adjtimex(2) para decirle al kernel que inserte un segundo bisiesto. Ver la publicación de lkml http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html

Red Hat también debería actualizar su artículo KB. https://access.redhat.com/knowledge/articles/15145

ACTUALIZACIÓN: Red Hat tiene un segundo artículo de KB sólo para este problema aquí: https://access.redhat.com/knowledge/solutions/154713 - el artículo anterior es para un problema anterior no relacionado

La solución es desactivar ntpd. Si ntpd ya ha emitido la llamada adjtimex(2), es posible que tenga que desactivar ntpd y reiniciar para estar 100% seguro.

Esto afecta a RHEL 6 y a otras distros que ejecutan kernels más nuevos (más recientes que aproximadamente 2.6.26), pero no a RHEL 5.

La razón por la que esto ocurre antes de el segundo bisiesto está realmente programado para ocurrir es que ntpd deja que el kernel maneje el segundo bisiesto a medianoche, pero necesita alertar al kernel para que inserte el segundo bisiesto antes de medianoche. ntpd, por lo tanto, llama a adjtimex(2) en algún momento durante el día del segundo bisiesto, momento en el que se activa este error.

Si tiene instalado adjtimex(8), puede utilizar este script para determinar si la flag 16 está activada. La flag 16 es "insertar el segundo bisiesto":

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

ACTUALIZACIÓN:

Red Hat ha actualizado su artículo de KB para señalar: "Los clientes de RHEL 6 pueden verse afectados por un problema conocido que hace que NMI Watchdog detecte un cuelgue al recibir el anuncio de los segundos de salto de NTP. Este problema se está solucionando de manera oportuna. Si sus sistemas recibieron el anuncio de los segundos intercalares y no experimentaron este problema, entonces ya no están afectados."

ACTUALIZACIÓN: El lenguaje anterior ha sido eliminado del artículo de Red Hat; y se ha añadido una segunda solución de KB que detalla el problema de caída de adjtimex(2): https://access.redhat.com/knowledge/solutions/154713

Sin embargo, el cambio de código en el post de LKML por el ingeniero de IBM John Stultz señala que también puede haber un bloqueo cuando se aplica realmente el segundo bisiesto, por lo que es posible que desee desactivar el segundo bisiesto reiniciando o utilizando adjtimex(8) después de desactivar ntpd.

ACTUALIZACIÓN FINAL:

Bueno, no soy un desarrollador del kernel, pero he vuelto a revisar el parche de John Stultz aquí: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6b43ae8a619d17c4935c3320d2ef9e92bdeed05d

Si estoy leyendo bien esta vez, me equivoqué al decir que hay otro punto muerto cuando se aplica el segundo bisiesto. Esa parece ser la opinión de Red Hat también, basada en su entrada de KB. Sin embargo, si ha desactivado ntpd, manténgalo desactivado durante otros 10 minutos, para no llegar al punto muerto cuando ntpd llame a adjtimex(2).

Pronto sabremos si hay más fallos :)

ACTUALIZACIÓN DEL SEGUNDO SALTO:

He pasado las últimas horas leyendo el código del kernel de ntpd y del pre-patch (con errores), y aunque puedo estar muy equivocado aquí, intentaré explicar lo que creo que estaba pasando:

En primer lugar, ntpd llama a adjtimex(2) todo el tiempo. Lo hace como parte de su "filtro de bucle de reloj", definido en local_clock en ntp_loopfilter.c. Puedes ver ese código aquí: http://www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c (desde la versión 4.2.6 de ntp).

El filtro de bucle de reloj se ejecuta con bastante frecuencia - se ejecuta cada vez que ntpd sondea sus servidores de subida, que por defecto es cada 17 minutos o más. La parte relevante del filtro de bucle de reloj es:

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

Y luego:

ntp_adjtime(&ntv)

En otras palabras, en los días en que hay un segundo bisiesto, ntpd establece la flag "STA_INS" y llama a adjtimex(2) (a través de su envoltorio de portabilidad).

Esa llamada al sistema llega al kernel. Aquí está el código relevante del kernel: https://github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c

La ruta de código del núcleo es más o menos la siguiente:

  • línea 663 - inicio de la rutina do_adjtimex.
  • línea 691 - cancelar cualquier temporizador de segundos bisiestos existente.
  • línea 709 - tomar el ntp_lock spinlock (este bloqueo está involucrado en la posible caída de livelock)
  • línea 724 - llamar a process_adjtimex_modes.
  • línea 616 - llamar a process_adj_status.
  • línea 590 - establecer la variable global time_status, basada en las banderas establecidas en la llamada adjtimex(2)
  • línea 592 - comprobar la variable global time_state. en la mayoría de los casos, llamar a ntp_start_leap_timer.
  • línea 554 - comprobar la variable global time_status. STA_INS se establecerá, así que establece time_state a TIME_INS y llama a hrtimer_start (otra función del kernel) para iniciar el temporizador de segundos bisiestos. en el proceso de creación de un temporizador, este código agarra el xtime_lock. si esto ocurre mientras otra CPU ya ha agarrado el xtime_lock y el ntp_lock, luego el kernel livelocks. por eso John Stultz escribió el parche para evitar el uso de hrtimers. Esto es lo que estaba causando problemas a todos hoy.
  • línea 598 - si ntp_start_leap_timer no inició realmente un temporizador bisiesto, establecer time_state a TIME_OK
  • línea 751 - asumiendo que el kernel no tiene livelock, la pila es desenrollada y el spinlock ntp_lock es liberado.

Hay un par de cosas interesantes aquí.

Primero, la línea 691 cancela el temporizador existente cada vez que se llama a adjtimex(2). Luego, la línea 554 vuelve a crear ese temporizador. Esto significa que cada vez que ntpd ejecutaba su filtro de bucle de reloj, se invocaba el código buggy.

Por lo tanto, creo que Red Hat se equivocó cuando dijo que una vez que ntpd había establecido la flag de los segundos bisiestos, el sistema no se bloquearía. Creo que cada sistema que ejecutaba ntpd tenía la posibilidad de bloquearse cada 17 minutos (o más) durante el período de 24 horas antes del segundo salto. Creo que esto también puede explicar por qué tantos sistemas se bloquearon; una única posibilidad de bloqueo sería mucho menos probable que se produjera en comparación con 3 posibilidades por hora.

ACTUALIZACIÓN: En la solución KB de Red Hat en https://access.redhat.com/knowledge/solutions/154713 Los ingenieros de Red Hat han llegado a la misma conclusión (que la ejecución de ntpd golpearía continuamente el código defectuoso). Y de hecho lo hicieron varias horas antes que yo. Esta solución no estaba vinculada al artículo principal en https://access.redhat.com/knowledge/articles/15145 Así que no me di cuenta hasta ahora.

En segundo lugar, esto explica por qué los sistemas cargados eran más propensos a estrellarse. Los sistemas cargados manejan más interrupciones, lo que hace que la función del kernel "do_tick" sea llamada más a menudo, dando más oportunidad a este código de ejecutarse y agarrar el ntp_lock mientras se crea el temporizador.

En tercer lugar, ¿existe la posibilidad de que el sistema se cuelgue cuando se produzca realmente el bisiesto? No lo sé con seguridad, pero posiblemente sí, porque el temporizador que se dispara y ejecuta realmente el ajuste del salto de segundo (ntp_leap_second, en la línea 388) también coge el spinlock ntp_lock, y tiene una llamada a hrtimer_add_expires_ns. No sé si esa llamada también podría causar un livelock, pero no parece imposible.

Por último, ¿qué es lo que hace que se desactive la flag del segundo salto después de que se haya ejecutado el segundo salto? La respuesta es que ntpd deja de fijar la flag del segundo salto en algún momento después de la medianoche cuando llama a adjtimex(2). Como la flag no está activada, la comprobación de la línea 554 no será verdadera, y no se creará ningún temporizador, y la línea 598 restablecerá la variable global time_state a TIME_OK. Esto explica por qué si se comprueba la flag con adjtimex(8) justo después del segundo bisiesto, todavía se vería la flag del segundo bisiesto activada.

En resumen, el mejor consejo para hoy parece ser el primero que di después de todo: desactivar ntpd, y desactivar la flag de los segundos intermedios.

Y algunas reflexiones finales:

  • ninguno de los proveedores de Linux se dio cuenta del parche de John Stultz y lo aplicó a sus núcleos :(
  • ¿por qué John Stultz no alertó a algunos de los vendedores de que esto era necesario? tal vez la posibilidad de que el livelock pareciera lo suficientemente bajo como para hacer ruido no estaba justificada.
  • He oído informes de que los procesos de Java se bloquean o dan vueltas cuando se aplica el segundo salto. Quizá deberíamos seguir el ejemplo de Google y replantearnos cómo aplicamos los segundos intercalares a nuestros sistemas: http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html

06/02 Actualización de John Stultz:

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

El post contenía un recorrido paso a paso de por qué el segundo bisiesto causaba que los temporizadores futex expiraran prematuramente y de forma continua, aumentando la carga de la CPU.

33voto

HikeOnPast Puntos 504

Esto nos afectó mucho. Después de reiniciar muchos de nuestros hosts, lo siguiente resultó ser vergonzosamente sencillo y totalmente eficaz sin necesidad de reiniciar el host:

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

Lo único que hay que hacer es reiniciar el reloj del sistema. Caramba. Lo que he dado por haber sabido esto hace seis horas.

24voto

jon Puntos 785

Un sencillo programa en C que borra el bit del segundo bisiesto en el campo de estado de la hora 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;
}

Guardar como lsec.c compilar con gcc -Wall -Wextra -o lsec lsec.c y ejecutar como root.

Probablemente querrá detener ntpd antes de ejecutarlo, y reiniciar ntpd después del segundo salto.

18voto

Gregor Puntos 181

Postmortem parece que ./lsec no tiene efecto.

Lo que estamos viendo es un montón de procesos softirqd comiendo CPU (normalmente lineal a la carga de procesos java)

Lo que sí funciona para arreglar el POSTMORTEM con los segundos intercalares ya aplicados por ntp es lo siguiente:

Parece que es suficiente con emitirlo:

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

Esto debería reducir la carga sin necesidad de reiniciar ntpd o reiniciar. Alternativamente puede emitir:

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

16voto

Luca Filipozzi Puntos 314

http://my.opera.com/marcomarongiu/blog/2012/03/12/no-step-back parece indicar que el kernel de Debian squeeze no maneja el segundo bisiesto.

Este hilo en comp.protocols.tim.ntp también es interesante: https://groups.google.com/forum/?fromgroups#!topic/comp.protocols.time.ntp/KSflIgjUdPE

Dicho esto, el segundo bisiesto aún no se ha producido: 23:59:60 UTC

Finalmente, https://access.redhat.com/knowledge/articles/15145 dice lo siguiente: "Cuando se produce el segundo bisiesto, el kernel imprime un mensaje en el registro del sistema. Existe la posibilidad de que la impresión de este mensaje provoque el bloqueo del kernel en Red Hat Enterprise Linux".

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: