Crates.io | clock-bound-d |
lib.rs | clock-bound-d |
version | |
source | src |
created_at | 2021-11-01 22:29:41.234984+00 |
updated_at | 2025-05-07 23:01:22.311192+00 |
description | A daemon to provide clients with an error bounded timestamp interval. |
homepage | |
repository | https://github.com/aws/clock-bound |
max_upload_size | |
id | 475456 |
Cargo.toml error: | TOML parse error at line 27, column 1 | 27 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
The ClockBound daemon clockbound
interfaces with the Chrony daemon chronyd
and the Operating System clock to provide clients with a bound on the error of the system clock. The ClockBound daemon periodically updates a shared memory segment that stores parameters to calculate the bound on clock error at any time. The ClockBound clients open the shared memory segment and read a timestamp interval within which true time exists.
The ClockBound daemon has support for features that are provided by the Linux VMClock. When the VMClock indicates that a clock disruption has occurred, the ClockBound daemon will communicate with Chrony and tell it to resynchronize the clock. The ClockBound client via its API will present an accurate representation of the clock status while this occurs.
If the ClockBound daemon is running in an environment where clock disruptions are not expected to occur, the ClockBound daemon can be started with CLI option --disable-clock-disruption-support
. This CLI option will bypass the requirement to have VMClock available and ClockBound will not handle clock disruptions.
The ClockBound daemon continuously communicates with Chrony daemon chronyd to compose the clock error bound parameters. The Chrony daemon must be running to synchronize the system clock and provide clock correction parameters.
chronyd
is already set as the default NTP daemon for you.chronyd
and syncing to the Amazon Time Sync Service.The Chrony daemon chronyd
has the ability to drop privileges once initialized. The rest of this guide assumes that chronyd
runs under the chrony
system user, which is the default for most distributions.
Note that this impacts which process can communicate with chronyd
. The ClockBound daemon clockbound
communicates with Chrony daemon chronyd
over Unix Datagram Socket (usually at /var/run/chrony/chronyd.sock
). The Chrony daemon sets permissions such that only processes running under root
or the chrony
user can write to it.
IMPORTANT: configuring the maxclockerror directive
Several sources of synchronization errors are taken into account by clockbound
to provide the guarantee that true time is within a clock error bound interval. One of these components captures the stability of the local oscillator the system clock is built upon. By default, chronyd
uses a very optimistic value of 1 PPM, which is appropriate for a clock error estimate but not for a bound. The exact value to use depends on your hardware (you should check), otherwise, a value of 50 PPM should be appropriate for most configuration to capture the maximum drift in between clock updates.
Update the /etc/chrony.conf
configuration file and add the following directive to configure a 50 PPM max drift rate:
# Ensures chronyd grows local dispersion at a rate that is realistic and
# aligned with clockbound.
maxclockerror 50
# Restart chronyd to ensure the configuration change is applied.
sudo systemctl restart chronyd
The VMClock is a vDSO-style clock provided to VM guests.
During maintenance events, VM guests may experience a clock disruption and it is possible that the underlying clock hardware is changed. This violates assumptions made by time-synchronization software running on VM guests. The VMClock allows us to address this problem by providing a mechanism for user-space applications such as ClockBound to be aware of clock disruptions, and take appropriate actions to ensure correctness for applications that depend on clock accuracy.
For more details, see the description provided in file vmclock-abi.h.
The VMClock is included by default in:
kernel-5.10.223-211.872.amzn2
and later.kernel-6.1.102-108.177.amzn2023
and later.6.13
and later.If you are running a Linux kernel that is mentioned above, you will see VMClock at file path /dev/vmclock0
, assuming that the cloud provider supports it for your virtual machine.
Amazon Web Services (AWS) is rolling out VMClock support on EC2. This is being added first on AWS Graviton, with Intel and AMD following soon after.
VMClock at path /dev/vmclock0
may not have the read permissions needed by ClockBound. Run the following command to add read permissions.
sudo chmod a+r /dev/vmclock0
ClockBound daemon can be installed using Cargo. Instructions on how to install Cargo can be found at doc.rust-lang.org.
Install dependencies:
sudo yum install gcc
Run cargo build with the release flag:
cargo build --release
Cargo install will place the ClockBound daemon binary at this relative path:
target/release/clockbound
Optionally, copy the ClockBound daemon binary to the /usr/local/bin
directory:
sudo cp target/release/clockbound /usr/local/bin/
The ClockBound daemon clockbound
needs to:
/var/run/clockbound/shm0
./dev/vmclock0
. This is not required if clockbound
is started with the --disable-clock-disruption-support
option.--max-drift-rate
parameter that matches chronyd
configuration.# Set up ClockBound permissions.
sudo mkdir -p /run/clockbound
sudo chmod 775 /run/clockbound
sudo chown chrony:chrony /run/clockbound
sudo chmod a+r /dev/vmclock0
# Start the ClockBound daemon.
sudo -u chrony /usr/local/bin/clockbound --max-drift-rate 50
The rest of this section assumes the use of systemd
to control the clockbound
daemon.
/usr/lib/systemd/system/clockbound.service
with the following contents.The clockbound
daemon runs under the chrony
user to access chronyd
UDS socket.
The aim is to ensure the RuntimeDirectory
that contains the file backing the shared memory segment is preserved over clockbound restart events. This lets client code run without interruption when the clockbound daemon is restarted.
Depending on the version of systemd used (>=235), the RuntimeDirectory
can be used in combination with
RuntimeDirectoryPreserve
.
Systemd version >= 235
[Unit]
Description=ClockBound
[Service]
Type=simple
Restart=always
RestartSec=10
PermissionsStartOnly=true
ExecStartPre=/bin/chmod a+r /dev/vmclock0
ExecStart=/usr/local/bin/clockbound --max-drift-rate 50
RuntimeDirectory=clockbound
RuntimeDirectoryPreserve=yes
WorkingDirectory=/run/clockbound
User=chrony
Group=chrony
[Install]
WantedBy=multi-user.target
Systemd version < 235
[Unit]
Description=ClockBound
[Service]
Type=simple
Restart=always
RestartSec=10
PermissionsStartOnly=true
ExecStartPre=/bin/chmod a+r /dev/vmclock0
ExecStartPre=/bin/mkdir -p /run/clockbound
ExecStartPre=/bin/chmod 775 /run/clockbound
ExecStartPre=/bin/chown chrony:chrony /run/clockbound
ExecStartPre=/bin/cd /run/clockbound
ExecStart=/usr/local/bin/clockbound --max-drift-rate 50
WorkingDirectory=/run/clockbound
User=chrony
Group=chrony
[Install]
WantedBy=multi-user.target
clockbound
daemonsudo systemctl daemon-reload
sudo systemctl enable clockbound
sudo systemctl start clockbound
systemctl status clockbound
/var/log/daemon.log
or through# Show the ClockBound daemon logs.
sudo journalctl -u clockbound
# Follow the ClockBound daemon logs.
sudo journalctl -f -u clockbound
The value of the clock status written to the shared memory segment is driven by the Finite State Machine described below. The clock status exposed is a combination of the clock status known by chronyd as well as the disruption status due to LM passed on by the Time Sync service over RusTick.
Each transition in the FSM is triggered by either:
Unknown
, Synchronized
, FreeRunning
.Unknown
, Reliable
, Disrupted
.If ClockBound daemon was started with CLI option --disable-clock-disruption-support
, then the FSM is as follows:
Steps to setup the PHC on Amazon Linux and Chrony is provided here:
On non-Amazon Linux distributions, the ENA Linux driver will need to be installed and configured with support for the PHC enabled:
To get accurate clock error bound values when chronyd
is synchronizing to the PHC (since chronyd
assumes the PHC itself has 0 error bound which is not necesarily true), a PHC reference ID and PHC network interface (i.e. ENA interface like eth0) need to be supplied for ClockBound to read the clock error bound of the PHC and add it to chronyd
's clock error bound. This can be done via CLI args -r
(ref ID) and -i
(interface). Ref ID is seen in chronyc tracking
, i.e.:
$ chronyc tracking
Reference ID : 50484330 (PHC0) <-- This 4 character ASCII code
Stratum : 1
Ref time (UTC) : Wed Nov 15 18:24:30 2023
System time : 0.000000014 seconds fast of NTP time
Last offset : +0.000000000 seconds
RMS offset : 0.000000060 seconds
Frequency : 6.614 ppm fast
Residual freq : +0.000 ppm
Skew : 0.019 ppm
Root delay : 0.000010000 seconds
Root dispersion : 0.000001311 seconds
Update interval : 1.0 seconds
Leap status : Normal
and network interface should be the primary network interface (from ifconfig
, the interface with index 0) - on Amazon Linux 2 this will generally be eth0
, and on Amazon Linux 2023 this will generally be ens5
.
For example:
/usr/local/bin/clockbound -r PHC0 -i eth0
To have your systemd unit do this, you'll need to edit the above line to supply the right arguments.
For example:
[Unit]
Description=ClockBound
[Service]
Type=simple
Restart=always
RestartSec=10
PermissionsStartOnly=true
ExecStartPre=/bin/chmod a+r /dev/vmclock0
ExecStart=/usr/local/bin/clockbound --max-drift-rate 50 -r PHC0 -i eth0
RuntimeDirectory=clockbound
RuntimeDirectoryPreserve=yes
WorkingDirectory=/run/clockbound
User=chrony
Group=chrony
[Install]
WantedBy=multi-user.target
ClockBound reads from the VMClock to know that the clock is disrupted.
If you would like to do testing of ClockBound, simulating various VMClock states, one possibility is to use the vmclock-updater CLI tool.
See the vmclock-updater README.md for more details.
The ClockBound daemon supports triggering fake clock disruption events.
Sending POSIX signal SIGUSR1
to the ClockBound process turns clock disruption status ON.
Sending POSIX signal SIGUSR2
to the ClockBound process turns clock disruption status OFF.
Quick example, assuming ClockBound is running with PID 1234, starting not disrupted:
# Send a SIGUSR1 signal to ClockBound
kill -SIGUSR1 1234
The ClockBound daemon emits a log message indicating it is entering a forced disruption period.
2023-10-05T05:25:11.373568Z INFO main ThreadId(01) clock-bound-d/src/main.rs:40: Received SIGUSR1 signal, setting forced clock disruption to true
An application using libclockbound will then see a clock status indicating the clock is "DISRUPTED".
# Send a SIGUSR2 signal to ClockBound
kill -SIGUSR2 1234
The ClockBound daemon emits a log message indicating it is leaving a forced disruption period.
2023-10-05T05:25:19.590361Z INFO main ThreadId(01) clock-bound-d/src/main.rs:40: Received SIGUSR2 signal, setting forced clock disruption to false