Switch to using chrony for time synchronisation
authorTom Hughes <tom@compton.nu>
Wed, 27 Mar 2019 20:35:28 +0000 (20:35 +0000)
committerTom Hughes <tom@compton.nu>
Wed, 27 Mar 2019 21:28:09 +0000 (21:28 +0000)
cookbooks/munin/files/default/plugins/chrony [new file with mode: 0755]
cookbooks/ntp/attributes/default.rb
cookbooks/ntp/recipes/default.rb
cookbooks/ntp/templates/default/chrony.conf.erb [new file with mode: 0644]
cookbooks/ntp/templates/default/ntp.conf.erb [deleted file]
roles/base.rb

diff --git a/cookbooks/munin/files/default/plugins/chrony b/cookbooks/munin/files/default/plugins/chrony
new file mode 100755 (executable)
index 0000000..314860f
--- /dev/null
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+: <<=cut
+
+=head1 NAME
+
+parse Chrony Tracking output for timeserver status information
+
+=head1 APPLICABLE SYSTEMS
+
+Any system with a local chronyd service.
+
+=head1 CONFIGURATION
+
+No configuration.
+
+=head1 MAGIC MARKERS
+
+  #%# family=auto
+  #%# capabilities=autoconf
+
+=head1 VERSION
+
+Revision 0.1 2008/08/23 13:06:00 joti
+
+  First version only chronyc tracking, autodetection included.
+
+Revision 0.2 2008/10/11 16:09:00 joti
+
+  Added scaling of other values to match with frequency, added more description to fields
+
+Revision 0.3 2014/02/16 zjttoefs
+
+  reduce forking by using awk
+  do not limit output precision
+  add stratum monitoring
+  detect slow/fast time or freqency and adjust sign of value accordingly
+  remove commented out code
+
+Revision 0.4 2016/11/10 Lars Kruse
+
+  rewrite field handling
+  use "which" for "chronyc" location
+  switch from "bash" to "sh"
+  fix exit code of failing "autoconf"
+
+=head1 AUTHOR
+
+  joti
+  zjttoefs
+  Lars Kruse <devel@sumpfralle.de>
+
+=cut
+
+CHRONYC="$(which chronyc | head -1)"
+
+# Frequency has extremely higher values than other. Therefore they are fitted by scaling via suitable factors.
+# field definitions:
+#   - munin fieldname
+#   - factor for graph visualization (all values are supposed to reach a similar dimension)
+#   - regular expression of the chrony output line (may not contain whitespace, case insensitive)
+#   - label (may include "%d" for including the factor; may contain whitespace)
+fields="stratum                1       ^Stratum                Stratum
+       systime         1000    ^System.time            System Time (x%d)
+       frequency       1       ^Frequency              Frequency (ppm)
+       residualfreq    100     ^Residual.freq          Residual Freq (ppm, x%d)
+       skew            100     ^Skew                   Skew (ppm, x%d)
+       rootdelay       1000    ^Root.delay             Root delay (seconds, x%d)
+       rootdispersion  1000    ^Root.dispersion        Root dispersion (seconds, x%d)"
+
+# chrony example output (v2.4.1):
+#   Reference ID    : 131.188.3.221 (ntp1.rrze.uni-erlangen.de)
+#   Stratum         : 2
+#   Ref time (UTC)  : Thu Nov 10 22:39:50 2016
+#   System time     : 0.000503798 seconds slow of NTP time
+#   Last offset     : +0.000254355 seconds
+#   RMS offset      : 0.002186779 seconds
+#   Frequency       : 17.716 ppm slow
+#   Residual freq   : +0.066 ppm
+#   Skew            : 4.035 ppm
+#   Root delay      : 0.042980 seconds
+#   Root dispersion : 0.005391 seconds
+#   Update interval : 258.4 seconds
+#   Leap status     : Normal
+
+
+if [ "$1" = "autoconf" ]; then
+       if [ -n "$CHRONYC" ] && [ -x "$CHRONYC" ]; then
+               echo yes
+       else
+               echo "no (missing 'chronyc' executable)"
+       fi
+       exit 0
+fi
+
+if [ "$1" = "config" ]; then
+       echo 'graph_title Chrony Tracking Stats'
+       echo 'graph_args --base 1000 -l 0'
+       echo 'graph_vlabel (seconds,ppm)'
+       echo 'graph_category time'
+       echo "$fields" | while read fieldname factor regex label; do
+               # insert the factor, if "%d" is part of the label
+               printf "${fieldname}.label $label\n" "$factor"
+               echo "${fieldname}.type GAUGE"
+       done
+       exit 0
+fi
+
+chrony_status="$("$CHRONYC" tracking)"
+echo "$fields" | while read fieldname factor regex label; do
+       status_line="$(echo "$chrony_status" | grep -i -- "$regex " | cut -d ":" -f 2-)"
+       if [ -z "$status_line" ]; then
+               value="U"
+       else
+               # the keyword "slow" indicates negative values
+               value="$(echo "$status_line" | awk '{ /slow/ ? SIGN=-1 : SIGN=1; print $1 * SIGN * '"$factor"' }')"
+       fi
+       echo "${fieldname}.value $value"
+done
index 5d9d724398aab5fa5dd4c19cdefa5338b80b4dcd..33299d65be717fec1861686bd60dc31897ec3f0f 100644 (file)
@@ -1,11 +1,2 @@
-case node[:platform]
-when "ubuntu", "debian"
-  default[:ntp][:service] = "ntp"
-when "redhat", "centos", "fedora"
-  default[:ntp][:service] = "ntpd"
-end
-
-default[:ntp][:is_server] = false
-default[:ntp][:servers]   = ["0.us.pool.ntp.org", "1.us.pool.ntp.org"]
-
-default[:tz] = "Etc/UTC"
+default[:ntp][:servers] = ["0.us.pool.ntp.org", "1.us.pool.ntp.org"]
+default[:ntp][:tz] = "Etc/UTC"
index 7be4ab4373f9b6a2657630fa14c22642c1c45c2f..0cd8dea24ae0eba23629a1a2ca16b3deeb812cc6 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-require "socket"
+service "ntp" do
+  action [:stop, :disable]
+end
+
+package "ntp" do
+  action :purge
+end
+
+package "ntpdate" do
+  action :purge
+end
+
+if File.directory?("/etc/munin/plugins")
+  Dir.new("/etc/munin/plugins").each do |plugin|
+    next unless plugin.match?(/^ntp_/)
+
+    munin_plugin plugin do
+      action :delete
+    end
+  end
+end
 
 package %w[
-  ntp
-  ntpdate
+  chrony
   tzdata
 ]
 
@@ -33,38 +52,22 @@ execute "dpkg-reconfigure-tzdata" do
 end
 
 link "/etc/localtime" do
-  to "/usr/share/zoneinfo/#{node[:tz]}"
+  to "/usr/share/zoneinfo/#{node[:ntp][:tz]}"
   owner "root"
   group "root"
   notifies :run, "execute[dpkg-reconfigure-tzdata]", :immediately
 end
 
-service "ntp" do
-  action [:enable, :start]
-  supports :status => true, :restart => true
-end
-
-template "/etc/ntp.conf" do
-  source "ntp.conf.erb"
+template "/etc/chrony/chrony.conf" do
+  source "chrony.conf.erb"
   owner "root"
   group "root"
   mode 0o644
-  notifies :restart, "service[ntp]"
+  notifies :restart, "service[chrony]"
 end
 
-munin_plugins = %w[ntp_kernel_err ntp_kernel_pll_freq ntp_kernel_pll_off ntp_offset]
-
-munin_plugin "ntp_kernel_err"
-munin_plugin "ntp_kernel_pll_freq"
-munin_plugin "ntp_kernel_pll_off"
-munin_plugin "ntp_offset"
-
-if File.directory?("/etc/munin/plugins")
-  Dir.new("/etc/munin/plugins").each do |plugin|
-    next unless plugin.match(/^ntp_/) && !munin_plugins.include?(plugin)
-
-    munin_plugin plugin do
-      action :delete
-    end
-  end
+service "chrony" do
+  action [:enable, :start]
 end
+
+munin_plugin "chrony"
diff --git a/cookbooks/ntp/templates/default/chrony.conf.erb b/cookbooks/ntp/templates/default/chrony.conf.erb
new file mode 100644 (file)
index 0000000..2c4cfc4
--- /dev/null
@@ -0,0 +1,31 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Servers
+<% node[:ntp][:servers].each do |server| -%>
+pool <%= server %> iburst
+<% end -%>
+
+# This directive specify the location of the file containing ID/key pairs for
+# NTP authentication.
+keyfile /etc/chrony/chrony.keys
+
+# This directive specify the file into which chronyd will store the rate
+# information.
+driftfile /var/lib/chrony/chrony.drift
+
+# Uncomment the following line to turn logging on.
+#log tracking measurements statistics
+
+# Log files location.
+logdir /var/log/chrony
+
+# Stop bad estimates upsetting machine clock.
+maxupdateskew 100.0
+
+# This directive enables kernel synchronisation (every 11 minutes) of the
+# real-time clock. Note that it can’t be used along with the 'rtcfile' directive.
+rtcsync
+
+# Step the system clock instead of slewing it if the adjustment is larger than
+# one second, but only in the first three clock updates.
+makestep 1 3
diff --git a/cookbooks/ntp/templates/default/ntp.conf.erb b/cookbooks/ntp/templates/default/ntp.conf.erb
deleted file mode 100644 (file)
index ffb263c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Exchange time with everybody, but don't allow configuration
-restrict default kod notrap nomodify nopeer noquery
-
-# Local users may interrogate the ntp server more closely
-restrict 127.0.0.1
-restrict ::1
-
-# Servers
-<% node[:ntp][:servers].each do |server| -%>
-server <%= server %> iburst
-<% end -%>
-
-# Drift file
-driftfile /var/lib/ntp/ntp.drift
index d680fddb110e442b3043d208d6b83e0cb21cebb1..63c763af109c7467984c3454fa44a9c392a1e187 100644 (file)
@@ -15,8 +15,8 @@ default_attributes(
   },
   :munin => {
     :plugins => {
-      :ntp_offset => {
-        :offset => { :warning => "100", :critical => "250" }
+      :chrony => {
+        :systime => { :warning => "100", :critical => "250" }
       }
     }
   },