Chrony dice que estás sincronizado. El monitoreo sigue gritando “desviación de reloj”. Kerberos rechaza tickets de forma aleatoria. Los handshakes TLS fallan como si fuera 2012 otra vez. Y cada reinicio hace que la máquina “teletransporte” unos segundos (o minutos) fuera de la realidad.
Este es el modo de fallo de cronometraje que más horas de ingeniero consume: NTP funciona técnicamente, pero la deriva persiste. El culpable normalmente no es “mal NTP”. Es la relación entre el reloj del sistema, el reloj de hardware (RTC) y cómo chrony decide corregir el tiempo. Arregla esa relación y el problema deja de parecer espeluznante.
Un modelo mental práctico: ¿quién posee el tiempo?
La medición del tiempo en Linux es una relación de tres partes:
- Reloj del sistema (tiempo del kernel): lo que usan tus procesos. Esto es lo que importa para logs, certificados, timeouts y sistemas distribuidos.
- Reloj de hardware (RTC): un pequeño reloj con batería en la placa base. Es burdo. Se desvía. Sobrevive a la pérdida de energía. No se corrige automáticamente.
- Sincronizador: chrony (en este caso) decide cómo dirigir el reloj del sistema según fuentes de tiempo y reglas (slew vs step, umbrales, offsets, estabilidad).
El patrón de fallo “NTP funciona pero la deriva persiste” suele ser uno de estos:
- RTC está mal, y lo lees al arrancar (o tras suspensión) y recontagias el reloj del sistema con tiempo incorrecto.
- Chrony está sincronizando, pero está limitado a hacer slew lentamente mientras algo más tira constantemente del reloj (host del VM, TSC defectuoso, otro servicio de tiempo).
- Chrony sincroniza con lo equivocado (una fuente local, un upstream inestable, o está aislado por condiciones de red) y se mantiene “feliz” mientras te alejas del tiempo real.
Los bugs de tiempo son esquivos porque todo sigue “funcionando”. Simplemente funciona en la década equivocada. Una de las pocas señales honestas es el delta entre relojes a lo largo del tiempo.
Idea parafraseada, atribuida: Werner Vogels ha impulsado la mentalidad de fiabilidad de que debes esperar fallos y diseñar sistemas para manejarlos.
La medición del tiempo pertenece a ese grupo: asume que tu reloj estará equivocado, y luego contrólalo activamente.
Guía de diagnóstico rápido (comprueba 1.º/2.º/3.º)
Si solo tienes 10 minutos antes de que el canal de incidentes se ponga intenso, haz esto en orden.
1.º: ¿chrony es lo único que dirige el reloj del sistema?
Los conflictos crean el síntoma clásico: “chrony informa sincronizado, pero el tiempo aún salta.” Busca demonios competidores y agentes de tiempo de la virtualización.
2.º: ¿Es estable el reloj del sistema y está haciendo pasos (stepping)?
Los saltos grandes implican correcciones por step (o reinicios externos), no deriva. La deriva implica una frecuencia estable pero incorrecta. La solución difiere.
3.º: ¿El RTC te está envenenando al arrancar o al reanudar?
Si la máquina está correcta después de funcionar un rato pero está mal justo tras el reinicio, sospecha del RTC y de la configuración UTC/localtime antes que de tus servidores NTP.
4.º: ¿La calidad de la fuente de tiempo es real?
Chrony gustosamente elegirá una fuente “alcanzable” pero inestable. Quieres baja jitter, baja dispersión y un estrato sensato (la mayoría de las veces).
5.º: Decide la política: ¿solo slew o permitir steps?
Los sistemas de producción suelen necesitar pasos controlados al arrancar (o tras largos periodos sin sincronía) y slewing en estado estable. Debes configurar eso explícitamente.
Hechos interesantes y contexto histórico (rápido, útil)
- NTP data de los primeros años de los 80, diseñado para un mundo con redes más lentas y relojes mucho peores que hoy.
- Linux distingue “tiempo” de “frecuencia”: disciplinar el reloj significa corregir tanto el desfase actual como la tasa a la que avanza.
- Los chips RTC no son instrumentos de precisión. Muchos son osciladores baratos cuya deriva cambia con la temperatura y la edad.
- UTC vs localtime en el RTC es una guerra cultural: Linux por defecto usa UTC; Windows históricamente prefiere localtime. Las máquinas con arranque dual sufren por ello.
- Existen segundos intercalares porque la Tierra es grosera: la rotación no es perfectamente consistente, así que el tiempo civil inserta segundos ocasionalmente.
- Chrony fue construido para comportarse mejor en redes intermitentes, como portátiles o sistemas que no mantienen conectividad NTP constante.
- El kernel de Linux cambió significativamente con CPUs modernas: la estabilidad del TSC, TSC invariant y la selección de clocksource afectan la deriva.
- La virtualización solía ser un horror para el tiempo: los hipervisores antiguos exponían contadores de ciclo inestables, causando deriva o saltos en invitados.
- PPS (Pulse Per Second) desde GPS puede dar disciplina sub-microsegundo en la configuración adecuada, lo que hace que NTP sobre WAN parezca un cálculo aproximado.
Herramientas y términos que realmente necesitas
No necesitas un doctorado. Necesitas las lentes correctas:
- Offset: cuánto difiere tu reloj del sistema de la fuente en este momento.
- Frecuencia / skew: qué tan rápido corre tu reloj respecto al tiempo real; chrony ajusta esto.
- Step: saltar el reloj inmediatamente (útil en arranque, malo para algunas cargas).
- Slew: acelerar o desacelerar el reloj lentamente hasta que coincida (seguro para la mayoría, lento si estás muy desfasado).
- RTC: el reloj de hardware que lees/escribes vía
hwclock. - Clocksource del kernel: lo que el kernel usa para contar tiempo (TSC, HPET, ACPI PM timer, etc.). Una mala elección puede causar deriva.
Un chiste corto, como prometí: cuando tu reloj deriva, tu línea de tiempo post-mortem se convierte en arte performativo.
Tareas prácticas (comandos, significado de salidas, decisiones)
Las reglas aquí son estrictas: cada tarea incluye un comando ejecutable, qué significa su salida y qué decisión tomar a continuación. Hazlas en orden si no estás seguro.
Task 1: Confirmar tu pila de tiempo (systemd + chrony)
cr0x@server:~$ timedatectl
Local time: Mon 2025-12-30 11:12:03 UTC
Universal time: Mon 2025-12-30 11:12:03 UTC
RTC time: Mon 2025-12-30 11:10:41
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
Significado: “System clock synchronized: yes” es necesario pero no suficiente. La línea interesante es RTC time y RTC in local TZ.
Decisión: Si el RTC difiere más de uno o dos segundos, planifica arreglar la disciplina del RTC (tareas posteriores). Si “RTC in local TZ: yes” en un servidor, probablemente quieras cambiar a UTC salvo que tengas una razón de arranque dual.
Task 2: Asegurarte de que chrony es realmente el motor NTP
cr0x@server:~$ systemctl status chrony --no-pager
● chrony.service - chrony, an NTP client/server
Loaded: loaded (/lib/systemd/system/chrony.service; enabled; preset: enabled)
Active: active (running) since Mon 2025-12-30 09:10:22 UTC; 2h 1min ago
Docs: man:chronyd(8)
man:chronyc(1)
Main PID: 712 (chronyd)
Tasks: 1 (limit: 38219)
Memory: 3.2M
CPU: 1.821s
CGroup: /system.slice/chrony.service
└─712 /usr/sbin/chronyd -F 1
Significado: Chronyd está en ejecución. El “-F 1” indica que está usando corrección de frecuencia desde datos de deriva temprano.
Decisión: Si chrony no está activo, arréglalo primero. Si está activo, busca conflictos a continuación.
Task 3: Detectar conflictos de servicios de tiempo (timesyncd, ntpd, agentes del proveedor)
cr0x@server:~$ systemctl list-units --type=service | egrep -i 'chrony|timesync|ntp|openntpd'
chrony.service loaded active running chrony, an NTP client/server
systemd-timesyncd.service loaded active running Network Time Synchronization
Significado: Tienes systemd-timesyncd ejecutándose junto a chrony. Ese es un duelo clásico por el volante.
Decisión: Deshabilita timesyncd si chrony es la autoridad elegida.
cr0x@server:~$ sudo systemctl disable --now systemd-timesyncd.service
Removed "/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service".
Significado: timesyncd está detenido y no volverá al arrancar.
Decisión: Revisa los síntomas de deriva tras unas horas; si los saltos de tiempo cesan, acabas de resolverlo.
Task 4: Comprobar la visión de salud de sincronía de chrony (tracking)
cr0x@server:~$ chronyc tracking
Reference ID : 192.0.2.10 (ntp1.example.net)
Stratum : 3
Ref time (UTC) : Mon Dec 30 11:12:00 2025
System time : 0.000214567 seconds slow of NTP time
Last offset : -0.000180123 seconds
RMS offset : 0.000355901 seconds
Frequency : 18.421 ppm slow
Residual freq : -0.012 ppm
Skew : 0.098 ppm
Root delay : 0.012345678 seconds
Root dispersion : 0.001234567 seconds
Update interval : 64.0 seconds
Leap status : Normal
Significado: El sistema está ~214 microsegundos lento. Eso está bien. Pero nota Frequency 18.421 ppm slow: tu reloj perdería ~1.6 segundos por día sin corrección.
Decisión: Si la frecuencia es grande (digamos >100 ppm) o el skew es enorme, sospecha un clocksource inestable o virtualización. Si los offsets son pequeños pero tus aplicaciones reportan deriva, puede que tengas eventos de stepping/saltos (Tarea 7/8).
Task 5: Inspeccionar fuentes y comportamiento de selección
cr0x@server:~$ chronyc sources -v
.-- Source mode '^' = server, '=' = peer, '#' = local clock.
/ .-- Source state '*' = current best, '+' = combined, '-' = not combined,
| / '?' = unreachable, 'x' = time may be in error, '~' = too variable.
|| .- xxxx [ yyyy ] +/- zzzz
|| Reachability register (octal) | xxxx = adjusted offset,
|| Log2(Polling interval) | yyyy = measured offset,
|| | zzzz = estimated error.
|| |
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* ntp1.example.net 2 6 377 21 -180us[ -220us] +/- 900us
^+ ntp2.example.net 2 6 377 19 +120us[ +80us] +/- 1100us
^- 203.0.113.44 3 6 377 17 +980us[ +950us] +/- 5500us
Significado: Tienes una fuente preferida (^*) y una de respaldo combinada (^+). La tercera fuente no está combinada (^-), probablemente por peores límites de error.
Decisión: Si la mejor fuente tiene un error alto (+/- decenas de milisegundos), arregla tu upstream o la ruta de red. Si las fuentes fluctúan a unreachable, tu deriva puede ser en realidad largos intervalos sin sincronía.
Task 6: Verificar que el kernel no esté ahogado en ajustes de tiempo
cr0x@server:~$ chronyc activity
200 OK
1 sources online
0 sources offline
0 sources doing burst (return to online)
0 sources doing burst (return to offline)
0 sources with unknown address
Significado: Chrony ve reachability estable. Bien.
Decisión: Si las fuentes están con frecuencia offline, arregla la red/firewalls antes de tocar el tuning de chrony.
Task 7: Buscar evidencia de stepping (saltos de tiempo)
cr0x@server:~$ journalctl -u chrony --since "24 hours ago" --no-pager | egrep -i 'step|slew|makestep|System clock wrong'
Dec 30 09:10:22 server chronyd[712]: System clock wrong by -3.842311 seconds, adjustment started
Dec 30 09:10:22 server chronyd[712]: System clock was stepped by -3.842311 seconds
Significado: Chrony hizo un step al iniciar el servicio. Está bien si es solo al arranque y dentro de un umbral esperado.
Decisión: Si el stepping ocurre durante horas de trabajo, ajusta la política makestep (más adelante), o encuentra el actor externo que fuerza el step (herramientas de VM, scripts manuales, lecturas erróneas del RTC).
Task 8: Comprobar estabilidad del clocksource (deriva a nivel hardware)
cr0x@server:~$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc
cr0x@server:~$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hpet acpi_pm
Significado: Estás usando TSC. Eso suele ser bueno en CPUs modernas con TSC invariant. En algunas plataformas (o ciertas configuraciones de VM) es problemático.
Decisión: Si ves valores de frecuencia salvajes en chronyc tracking o saltos de tiempo correlacionados con cambios de potencia de CPU, prueba otro clocksource en el próximo reinicio vía parámetro de kernel (con cuidado, y con control de cambios).
Task 9: Revisar el RTC en sí y comparar con el tiempo del sistema
cr0x@server:~$ sudo hwclock --show
2025-12-30 11:10:41.123456+00:00
cr0x@server:~$ date -u
Mon Dec 30 11:12:07 UTC 2025
Significado: El RTC está ~86 segundos atrasado. Si reinicias ahora, probablemente arrancarás retrasado y luego chrony corregirá.
Decisión: Si el RTC está consistentemente desviado decenas de segundos o minutos, haz explícita la disciplina del RTC: o escribes el tiempo del sistema al RTC en tiempos controlados, o usas el seguimiento RTC de chrony para compensar.
Task 10: Confirmar si tu RTC se trata como UTC o localtime
cr0x@server:~$ timedatectl show -p RTCInLocalTZ -p Timezone -p LocalRTC
RTCInLocalTZ=no
Timezone=Etc/UTC
LocalRTC=no
Significado: El RTC es UTC. Esta es la práctica sensata por defecto en servidores.
Decisión: Si RTCInLocalTZ=yes y no haces arranque dual, cámbialo (Tarea 11). Si haces arranque dual, decide quién gana y documenta la decisión.
Task 11: Ajustar RTC a UTC (mejor práctica típica en servidores)
cr0x@server:~$ sudo timedatectl set-local-rtc 0 --adjust-system-clock
Significado: El SO tratará el RTC como UTC de ahora en adelante y puede ajustar el reloj del sistema para mantener la hora local consistente.
Decisión: Haz esto en una ventana de mantenimiento si el reloj del sistema podría dar un salto. Luego escribe un tiempo de sistema correcto al RTC (Tarea 12) una vez que chrony sea estable.
Task 12: Escribir el tiempo del sistema corregido al RTC (limpieza única)
cr0x@server:~$ chronyc waitsync 30
200 OK
cr0x@server:~$ sudo hwclock --systohc --utc
Significado: waitsync asegura que chrony esté sincronizado antes de sacar una instantánea al RTC. --systohc escribe el tiempo del sistema en el RTC.
Decisión: Si la deriva del RTC es extrema, puedes repetir esto tras un día y medir la tasa de deriva. Si la deriva es solo “mal normal”, puedes compensar con la deriva de chrony y el comportamiento del RTC en lugar de escrituras frecuentes.
Task 13: Confirmar la política de step/slew de chrony (quieres que sea explícita)
cr0x@server:~$ grep -v '^\s*#' /etc/chrony/chrony.conf | sed '/^\s*$/d'
pool ntp.example.net iburst maxsources 4
driftfile /var/lib/chrony/chrony.drift
rtcsync
makestep 1.0 3
keyfile /etc/chrony/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
Significado: makestep 1.0 3 significa: hacer step si el offset > 1 segundo, pero solo en las primeras 3 actualizaciones. Eso es una política sensata de “arreglar en arranque, luego slew”. rtcsync mantiene el RTC aproximadamente alineado.
Decisión: Si no ves makestep, podrías estar haciendo slew para siempre tras una larga ausencia, lo que parece deriva persistente. Si ves stepping muy permisivo, podrías causar saltos a media jornada.
Task 14: Buscar daño de tiempo por suspensión/reanudación (portátiles, algunos servidores)
cr0x@server:~$ journalctl --since "7 days ago" --no-pager | egrep -i 'suspend|resume|PM: suspend|PM: resume'
Dec 29 18:44:02 server kernel: PM: suspend entry (deep)
Dec 29 19:12:19 server kernel: PM: suspend exit
Significado: Si esto es un portátil o un servidor con gestión agresiva de energía, la reanudación puede causar discontinuidades de tiempo dependiendo de la plataforma/firmware.
Decisión: Si la desviación aumenta tras reanudar, considera una política de step más estricta después de reanudar (hook para reiniciar el servicio), o deshabilitar suspensión profunda en sistemas que deban mantener el tiempo estrictamente.
Task 15: Verificar que nadie esté ajustando el tiempo manualmente (sí, en serio)
cr0x@server:~$ journalctl --since "48 hours ago" --no-pager | egrep -i 'set time|time has been changed|CLOCK_SET|adjtimex'
Dec 30 10:03:11 server systemd[1]: Time has been changed
Significado: Algo disparó un cambio de tiempo. Eso puede ser un step de chrony, un administrador, o algún otro agente.
Decisión: Correlaciona timestamps con los logs de chrony (Tarea 7). Si no es chrony, caza al culpable: gestión de configuración, herramientas del hipervisor o scripts caseros.
Ajustes de chrony que realmente cambian resultados
Chrony suele estar “bien” por defecto. Pero “bien” no es lo mismo que “aburrido”, y aburrido es lo que quieres para el tiempo. Estos son los mandos que importan cuando la deriva persiste.
Makestep: controla cuándo se permite hacer step
Por qué te importa: Si un servidor arranca 30 segundos mal y solo permites slew, puede tardar mucho en converger. Durante ese tiempo obtienes fallos de autenticación y orden de logs confuso. Si permites step en cualquier momento, algunas aplicaciones fallarán cuando el tiempo retroceda.
Lo que hago en la mayoría de servidores Debian:
- Permitir steps al inicio solo, con umbral bajo.
- Después de eso, solo correcciones por slew.
Política ejemplo (ya común en defaults tipo Debian, pero verifica):
cr0x@server:~$ sudo bash -lc 'printf "%s\n" "makestep 1.0 3" | tee /etc/chrony/conf.d/10-makestep.conf'
makestep 1.0 3
Significado: Hacer step solo si el offset es más de un segundo y solo durante las primeras tres actualizaciones.
Decisión: Si tus offsets en arranque rutinariamente son mayores de un segundo (RTC malo, larga desconexión), arregla el problema del RTC en lugar de aumentar este umbral a algo perezoso como 30 segundos.
rtcsync vs seguimiento de deriva del RTC: sabe lo que compras
rtcsync indica a chronyd que periódicamente copie el tiempo del sistema al RTC (vía el modo del kernel de 11 minutos). Ayuda a mantener el RTC lo bastante cerca para que un reinicio no empiece con gran error.
Pero si tu RTC deriva extremadamente, escribir con frecuencia no arregla el oscilador; solo oculta el síntoma hasta el próximo apagado largo. Si necesitas más, considera:
- Mejorar el entorno del RTC (actualizaciones de firmware, deshabilitar características de energía extrañas).
- Usar una fuente de tiempo upstream estable (servidores NTP internos, PTP en algunos entornos).
- Para sistemas estrictos, una referencia local (PPS, GPS) y una estrategia de holdover más rígida.
Intervalo de poll y comportamiento burst: deja de ser tímido en el arranque
iburst es bueno: usa muestras rápidas al inicio para converger más rápido. Manténlo para fuentes de red. Si tu red es con pérdida, puede que necesites mantener más fuentes y evitar puntos únicos de fallo de tiempo.
Para una línea pool:
cr0x@server:~$ grep -R "^\s*pool\|^\s*server" /etc/chrony
/etc/chrony/chrony.conf:pool ntp.example.net iburst maxsources 4
Significado: Usar un pool (DNS rotativo) con hasta 4 fuentes. Eso está bien.
Decisión: Para producción, prefiere múltiples fuentes internas estables si las tienes; de lo contrario múltiples fuentes externas con reglas de firewall sensatas (UDP 123) y buen DNS.
Estrato local y “seré mi propio reloj”: no lo hagas
Chrony puede anunciarse como fuente de tiempo aun sin upstream. Eso es útil para laboratorios aislados, y peligroso en cualquier otro lugar. Crearás a un mentiroso confiado: un servidor que dice a otros “yo soy el tiempo” mientras deriva.
Si ves directivas de local stratum, pausa y pregunta por qué. La mayoría de ambientes no deberían hacer esto salvo que sea un fallback diseñado conscientemente.
Reloj de hardware y hwclock: hazlo aburrido
El RTC no es un reloj atómico. Es un pequeño chip con batería, a menudo lo bastante preciso para un reloj de muñeca y no mucho más. Y aun así lo tratamos como una verdad sagrada al arrancar. Eso es culpa nuestra.
Cómo se ve “RTC está mal”
- El tiempo es correcto después de estar arriba horas, pero está mal justo después de reiniciar.
- El tiempo está desfasado por una cantidad consistente tras cada pérdida de energía.
- Máquinas con arranque dual muestran errores exactos de una hora alrededor de cambios DST (mismatch localtime/UTC).
Deja de hacer escrituras incontroladas al RTC
Algunos administradores ejecutan cron jobs como “hwclock –systohc every minute.” Eso convierte las escrituras al RTC en un ritual ruidoso y aumenta la posibilidad de escribir tiempo incorrecto durante una sincronía transitoria. Si vas a escribir al RTC, hazlo después de confirmar sincronía y no constantemente.
Medir la tasa de deriva del RTC (para elegir una política)
Puedes cuantificar la deriva sin herramientas especiales. Haz esto:
- Sincroniza el tiempo del sistema vía chrony.
- Escribe el tiempo del sistema al RTC una vez.
- Tras 24 horas, compara el RTC con el tiempo del sistema otra vez (sin escribir).
Comandos para el paso de comparación:
cr0x@server:~$ sudo hwclock --show
2025-12-31 11:11:12.000000+00:00
cr0x@server:~$ date -u
Tue Dec 31 11:12:07 UTC 2025
Significado: El RTC está ~55 segundos lento en ~24h, lo cual es severo. Eso no es un problema de tuning de chrony; es hardware/firmware o un problema de plataforma.
Decisión: Para ese nivel de deriva, confía en la disciplina NTP y trata el RTC como “solo para bootstrap al arrancar”, mientras investigas actualizaciones BIOS, problemas de placa base o reemplazo de hardware si importa.
Virtualización y portátiles: fábricas de deriva
En servidores bare metal con clocksource estables, chrony suele converger y mantenerse aburrido. Las VMs y portátiles añaden caos:
- Agentes de sincronía de tiempo del VM pueden hacer step en el reloj del invitado a espaldas de chrony.
- Escalado de frecuencia de CPU y estados de sueño pueden cambiar el comportamiento del oscilador y la estabilidad temporal.
- Sobrecarga del host puede retrasar la planificación de vCPU, haciendo que el tiempo parezca “atrasado” y luego se ponga al día.
Detectar una VM y revisar funciones de tiempo del hipervisor
cr0x@server:~$ systemd-detect-virt
kvm
Significado: Estás en KVM. Eso suele estar bien, pero debes asegurarte de que el invitado use relojes paravirtualizados y que no haya herramientas de agente compitiendo por el tiempo.
Decisión: Si ejecutas agentes de invitados que sincronizan el tiempo, deshabilita su sincronía de tiempo o configúralos para no pelear con chrony.
Comprobar el estado de disciplina de tiempo del kernel (estado NTP del kernel)
cr0x@server:~$ timedatectl timesync-status
Server: 192.0.2.10 (ntp1.example.net)
Poll interval: 1min 4s (min: 32s; max 34min 8s)
Leap: normal
Version: 4
Stratum: 3
Reference: 9C00020A
Precision: 1us (-20)
Root distance: 1.652ms (max: 5s)
Offset: -214us
Delay: 1.233ms
Jitter: 211us
Significado: Aunque chrony es el cliente real, systemd aún puede reportar el estado de disciplina NTP del kernel. Esto da otra vista de offset/jitter.
Decisión: Si root distance es enorme o el offset oscila, enfócate en la calidad de las fuentes y en la planificación del virtualizador primero.
Segundo chiste corto: si estás depurando la deriva del reloj de una VM a las 3 a.m., recuerda que el invitado no llega tarde: simplemente vive en otra zona horaria llamada “contención del host”.
Tres mini-historias corporativas (cómo falla esto en la vida real)
Mini-historia 1: El incidente causado por una suposición equivocada
La compañía tenía una flota de nodos API basados en Debian detrás de un balanceador. Todo parecía normal: baja latencia, pocas tasas de error. Entonces, durante una rotación de certificados, un pequeño porcentaje de nodos empezó a fallar llamadas TLS salientes con “certificate not yet valid”. Las fallas no fueron uniformes; llegaron en oleadas.
El ingeniero on-call revisó chrony y vio que estaba sincronizado. Eso pareció descartar el sesgo del reloj. Escalaron a redes y PKI, porque “NTP está bien”. Esa suposición fue la trampa: “sincronizado” se interpretó como “estable”.
El problema real fue en el arranque: el RTC se mantenía en hora local en algunos hosts debido a un artefacto de imaging de pruebas de hardware para arranque dual. Al reiniciar, esos nodos arrancaban minutos fuera, y luego chrony los ajustaba en unos pocos ciclos de actualización. Entre el arranque y la estabilización, las ventanas de validez TLS los castigaron.
La solución no fue sofisticada. Estandarizaron RTC a UTC, deshabilitaron el segundo servicio de tiempo que a veces peleaba con chrony y añadieron una puerta de salud: los nodos no podían entrar al pool del balanceador hasta que chronyc waitsync tuviera éxito.
La lección: “NTP sincronizado” es un estado, no una garantía. Trata el tiempo como cualquier otra dependencia. No pones un nodo en servicio solo porque el proceso está en ejecución.
Mini-historia 2: La optimización que salió mal
Un equipo de performance quería arranques más rápidos y menos ruido en segundo plano. Notaron que chrony a veces hacía un estallido inicial y un step al inicio. Eso parecía “desordenado”. Alguien decidió eliminar iburst y deshabilitar totalmente el stepping—solo slew, siempre. Parecía más elegante. El tiempo debería ser suave, ¿no?
Funcionó bien en nodos sanos. Luego, un subconjunto de máquinas pasó un fin de semana en un rack con el switch top-of-rack mal configurado. Sin reachability NTP durante dos días. Cuando arreglaron la red, los servidores estaban decenas de segundos fuera.
La corrección solo por slew significó que tardaron mucho en converger. Durante esa convergencia, los trazados distribuidos se desordenaron, caches expiraron demasiado pronto/tarde, y un job por lotes que dependía de particiones basadas en tiempo empezó a leer rutas “futuras”. Operaciones no pudo decidir qué pasó cuándo, lo que es una miseria especial.
Restauraron una política makestep sensata: step solo temprano en el proceso de sincronía. También añadieron alertas sobre “tiempo desde la última sincronía” y “offset absoluto actual”, no solo “demonio en ejecución”.
Lección de optimización: el tiempo suave es bueno, pero la corrección es mejor. El step al arranque no es una falla moral; es una corrección controlada. Hazlo explícito y acotado.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Una empresa tipo banco corría un entorno mixto: bases de datos bare metal, servidores de aplicaciones en VM y algunos appliances legacy. Su arquitectura de tiempo era poco glamorosa: dos servidores NTP internos por datacenter, cada uno con múltiples upstreams, y gestión de configuración estricta para asegurar que cada nodo usara chrony con la misma política base.
Una mañana, un proveedor upstream tuvo problemas que causaron picos de jitter NTP. Muchos entornos habrían degradado silenciosamente. En este caso, la selección de fuentes de chrony y los máximos de error ayudaron, pero el héroe real fue la práctica aburrida: tenían una comprobación rutinaria que comparaba la salida de chronyc tracking entre una muestra de nodos y alertaba sobre outliers en frecuencia y skew, no solo offset.
Detectaron dos clusters de VM donde los retrasos en la planificación del host hacían que los invitados se desviaran más de lo habitual. Esos invitados no parecían “caídos”. Parecían “un poco raros”. La detección de outliers los marcó antes de que empezaran a fallar las autenticaciones.
La mitigación fue simple: anclar temporalmente recursos de vCPU para los peores y reequilibrar cargas. La solución a largo plazo incluyó ajustar la configuración temporal del hipervisor y asegurar que los agentes invitados no estuvieran haciendo stepping.
El punto: la medición del tiempo es uno de esos dominios donde los procesos aburridos son todo el juego. Alerta sobre las métricas correctas, aplica consistencia y lo raro se hace visible temprano.
Errores comunes: síntoma → causa raíz → solución
-
Síntoma: Chrony muestra “System clock synchronized: yes” pero los logs de tu app muestran tiempo hacia atrás.
Causa raíz: Stepping del reloj en tiempo de ejecución (chronymakestepdemasiado permisivo, o otro agente haciendo step).
Solución: Restringe el stepping al arranque (makestep 1.0 3estilo), deshabilita servicios de tiempo competidores e investiga herramientas de VM que sincronicen el tiempo. -
Síntoma: El tiempo está mal justo después de reiniciar, luego se corrige lentamente.
Causa raíz: RTC está mal o tratado como localtime cuando debería ser UTC.
Solución: Ajusta RTC a UTC (timedatectl set-local-rtc 0), luego tras sincronía escribe el tiempo del sistema al RTC una vez (hwclock --systohc --utc). -
Síntoma: El offset sigue creciendo a pesar de “buenas” fuentes.
Causa raíz: Clocksource inestable o planificación de virtualización causando inestabilidad de frecuencia; chrony corrige constantemente pero pierde terreno.
Solución: Valida el clocksource, actualiza firmware, considera un clocksource alternativo y arregla la contención del hipervisor. -
Síntoma: Chrony alterna la mejor fuente con frecuencia, con
~“demasiado variable”.
Causa raíz: Mala calidad upstream NTP, ruta de red asimétrica o firewall/NAT raro.
Solución: Usa menos fuentes pero mejores; prefiere NTP interno; asegura UDP 123 estable; evita hairpin NAT para tiempo. -
Síntoma: La deriva ocurre principalmente tras suspensión/reanudación.
Causa raíz: Comportamiento de firmware/clocksource durante el sueño; discontinuidades de tiempo al reanudar.
Solución: Re-sincroniza inmediatamente al reanudar (reinicia chrony o fuerza burst), o deshabilita sueño profundo en sistemas con necesidades temporales estrictas. -
Síntoma: Kerberos “clock skew too great” esporádico en solo algunos nodos.
Causa raíz: Los nodos convergen lentamente tras cortes por política slew-only, o RTC envenenando al arrancar.
Solución: Permite stepping controlado temprano, impide que los servicios entren en producción hastachronyc waitsync, arregla disciplina RTC. -
Síntoma: Tras cambiar zona horaria/DST, los timestamps están desfasados exactamente una hora.
Causa raíz: RTC en localtime combinado con transiciones DST, o conflictos por arranque dual.
Solución: Estandariza RTC a UTC en hosts Linux; si haces arranque dual, elige una política y aplícala consistentemente.
Listas de verificación / plan paso a paso
Checklist A: Detener la hemorragia (15–30 minutos)
- Confirma que chrony está en ejecución:
systemctl status chrony. - Deshabilita demonios de sincronía de tiempo competidores: elimina
systemd-timesyncdsi chrony es primario. - Comprueba pasos recientes:
journalctl -u chrony | egrep -i 'stepped|wrong by'. - Inspecciona tracking y fuentes:
chronyc trackingychronyc sources -v. - Si el offset es grande y estás poco después del arranque, permite un step controlado (configura
makestep) y reinicia chrony en una ventana de mantenimiento.
Checklist B: Hacer el comportamiento del RTC determinista (1–2 horas)
- Decide la política de RTC: UTC para servidores salvo que exista una razón fuerte.
- Fija la política:
timedatectl set-local-rtc 0 --adjust-system-clock. - Espera la sincronía:
chronyc waitsync 30. - Escribe el tiempo correcto del sistema al RTC una vez:
hwclock --systohc --utc. - Habilita
rtcsyncen chrony para “mantener el RTC lo bastante cerca”.
Checklist C: Verificar estabilidad a lo largo del tiempo (próximas 24–72 horas)
- Registra la línea base:
chronyc trackingfrecuencia/skew y diferencia RTC (hwclock --showvsdate -u). - Vigila eventos de stepping en logs.
- Si la frecuencia es extrema o inestable, investiga clocksource y virtualización.
- Alerta sobre “tiempo desde la última sincronía” y “offset absoluto”, no solo “chrony activo”.
Preguntas frecuentes
1) Chrony dice sincronizado. ¿Por qué mi monitoreo sigue reportando deriva?
El monitoreo puede compararse contra otra referencia (otro servidor NTP, un appliance de monitoreo, o sesgo a nivel de aplicación). Verifica con chronyc tracking y asegúrate de que ningún otro servicio esté cambiando el tiempo. También revisa eventos de stepping en journalctl.
2) ¿Debo mantener el reloj de hardware en UTC o en hora local?
UTC para servidores. La hora local es principalmente para conveniencia de arranque dual con Windows. UTC evita rarezas de DST y reduce incidentes de “exactamente una hora de diferencia”.
3) ¿Es seguro permitir stepping del tiempo?
Sí, si lo acotas. Permite stepping temprano tras el arranque (o tras largos periodos sin sincronía) usando makestep. Evita steps en estado estable para sistemas sensibles a saltos hacia atrás.
4) ¿Qué significa “Frequency 18 ppm slow” en chronyc tracking?
Tu reloj corre lento en 18 partes por millón. Eso es aproximadamente 1.6 segundos por día sin corrección. Chrony compensa ajustando la tasa del reloj del sistema.
5) Mi RTC difiere del tiempo del sistema por un minuto. ¿Es normal?
No. Unos pocos segundos en días puede ocurrir en RTC débiles. Un minuto sugiere problemas de firmware/hardware, mala configuración (localtime/UTC), o que el RTC no se mantiene (sin rtcsync y sin política de sincronía periódica).
6) ¿Necesito ejecutar hwclock --systohc regularmente?
Generalmente no. Usa rtcsync y deja que el sistema mantenga el RTC lo bastante cerca. Haz una escritura única tras arreglar la configuración, y solo añade escrituras programadas si has medido la necesidad.
7) ¿Puede la virtualización causar deriva incluso con fuentes NTP perfectas?
Sí. Retrasos en la planificación del invitado, relojes virtuales inestables y herramientas del hipervisor que hacen step pueden crear deriva o saltos. Confirma el tipo de virtualización y elimina mecanismos de sincronía competidores.
8) ¿Cuál es la forma más rápida de probar que el RTC es el problema?
Compara RTC con el tiempo del sistema inmediatamente antes de reiniciar, reinicia y luego compara de nuevo justo después del arranque antes de que chrony converja. Si el tiempo post-arranque empieza mal en la misma dirección, el RTC está envenenando el reloj del sistema al inicio.
9) ¿Por qué la deriva empeora durante carga alta de CPU?
Bajo carga intensa, los invitados de VM pueden ser desplanificados y “quedarse atrás”, luego ponerse al día. En metal desnudo, la carga puede exponer rarezas del clocksource o comportamiento de gestión de energía del firmware. El síntoma suele ser aumento de jitter y estimaciones de frecuencia inestables.
10) ¿Debería reemplazar chrony por otro cliente NTP?
No como primer movimiento. Chrony es generalmente excelente en Debian, especialmente para conectividad intermitente y redes modernas. La mayoría de los bugs de “deriva con chrony” son en realidad mala gestión del RTC, conflictos o problemas de calidad upstream.
Conclusión: siguientes pasos para detener la deriva temporal
Cuando NTP “funciona” pero la deriva persiste, no estás frente a un único problema. Estás frente a un problema de gobernanza: quién puede ajustar el tiempo, cuándo y con qué autoridad.
- Escoge una autoridad de tiempo en el host (chrony) y elimina competidores (timesyncd, agentes del proveedor que hagan step).
- Haz explícita la política de stepping: step temprano, slew después. Usa
makestepcon intención. - Arregla el contrato del RTC: configura RTC en UTC, escribe el tiempo correcto una vez tras la sincronía y usa
rtcsyncpara mantenerlo lo bastante cerca. - Valida el clocksource de la plataforma si la frecuencia/skew parece inestable, especialmente en VMs.
- Operacionalízalo: impide que los servicios entren en producción hasta la sincronía y alerta sobre offset y pérdida de sincronía—no solo “demonio arriba”.
Si haces esas cinco cosas, la medición del tiempo en Debian 13 será lo que debería ser: invisible, aburrida y no la razón por la cual tu pila de autenticación de repente está “misteriosamente inestable”.