Tutorial

Grafische NTP Statistiken in 29 Minuten…​

Important
Dieses Kapitel wird editiert und ist noch nicht abgeschlossen.

Voraussetzungen

Sie können eine Linux-Distribution Ihrer Wahl installieren und mit deren Paket-Management umgehen. Sie sind sich der verantwortungsvollen Tätigkeit als root auf der Kommandozeile bewusst.

1 Vorbereitung

1.1 NTP Statistiken

Variante 1: Sie haben bereits jede Menge loopstats und/oder peerstats Dateien

Sie sichten den Inhalt des Vezeichnisses (meist) /var/log/ntpstats und prüfen ob die Dateien dem Muster HOSTNAME.(loop|peer)stats.YYYYMMdd entsprechen.[1] Falls nicht, benennen Sie diese um.

Variante 2: Sie benutzen den ntpd der aktuellen Installation

Sie haben den NTP-Daemon schon zur Erzeugung von Statistiken konfiguriert. Falls nicht, ersetzen Sie HOSTNAME in der Beispielkonfigutation und starten ntpd erneut:

mkdir -p /var/log/ntpstats
chown ntp:ntp /var/log/ntpstats
/etc/ntp.conf
statsdir    /var/log/ntpstats/
filegen     loopstats file HOSTNAME.loopstats
filegen     peerstats file HOSTNAME.peerstats

1.2 Linux System

Sie haben bereits Zugriff auf ein Linux-System oder Sie installieren eine Distribution Ihrer Wahl. Sie können eine physischen oder virtuellen Maschine benutzen.

Die Beispiele wurden mit drei verschiedenen Distributionen erfolgreich getestet:

CentOS und Oracle Linux (OL) sind aktuelle Beispiele mit systemd als Init-System und YUM als (RPM-)Paketmanager.

Gentoo Linux benutzt in der gewählten Variante openrc und Portage.

2 ELG Stack

Sie installieren die drei Komponenten Elasticsearch, Logstash und Grafana. Zusätzlich ist Java für die beiden “Elastic-Komponenten” Voraussetzung.

2.1 Installation

Gentoo

emerge -pv elasticsearch grafana-bin jre logstash
[ebuild   R   ~] www-apps/grafana-bin-4.1.2::gentoo  0 KiB
[ebuild   R    ] virtual/jre-1.8.0-r1:1.8::gentoo  0 KiB
[ebuild   R   ~] app-misc/elasticsearch-5.2.2::gentoo  0 KiB
[ebuild   R   ~] app-admin/logstash-bin-5.2.2::gentoo  0 KiB

CentOS und Oracle Linux

Installieren Sie die beiden YUM Repo-Dateien
CentOS 7, yum list installed elasticsearch grafana java\*openjdk logstash
elasticsearch.noarch        5.3.0-1                   @elastic-5.x
grafana.x86_64              4.2.0-1                   @grafana
java-1.8.0-openjdk.x86_64   1:1.8.0.121-0.b13.el7_3   @updates
logstash.noarch             1:5.3.0-1                 @elastic-5.x
Oracle Linux 7, yum list installed elasticsearch grafana java\*openjdk logstash
elasticsearch.noarch        5.3.0-1                   @elastic-5.x
grafana.x86_64              4.2.0-1                   @grafana-stable
java-1.8.0-openjdk.x86_64   1:1.8.0.121-0.b13.el7_3   @ol7_latest
logstash.noarch             1:5.3.0-1                 @elastic-5.x

Logstash Plugins

Falls in Ihrer Logstash-Version nicht bereits enthalten, müssen Sie zwei zusätzliche Filter anonymize und translate installieren.[2][3]

logstash-plugin install logstash-filter-anonymize
logstash-plugin install logstash-filter-translate
Gentoo, logstash-5.2.2
cd /opt/logstash

DEBUG=1 JARS_SKIP='true' bin/logstash-plugin install logstash-filter-anonymize
DEBUG=1 JARS_SKIP='true' bin/logstash-plugin install logstash-filter-translate

Sie können nun die Komponenten nacheinender konfigurieren und testen.

2.2 Logstash

Sie legen Log- und Spool-Verzeichnis an.

mkdir -p /var/opt/ntpstats-ng
mkdir /var/opt/ntpstats-ng/log
mkdir /var/opt/ntpstats-ng/spool
chgrp logstash -R /var/opt/ntpstats-ng
chmod g+w /var/opt/ntpstats-ng/log

2.2.1 Logstash Konfiguration

Sie kopieren drei Dateien in das (leere) Verzeichnis /etc/logstash/conf.d:

Zwei weitere Dateien in das Verzeichnis /etc/logstash:

Zusammenfassung der aktuellen Konfiguration
# 20_ntpstats-ng.conf
input {
    file {
        path => [
            "/var/opt/ntpstats-ng/spool/*.loopstats" (1)
            "/var/opt/ntpstats-ng/spool/*.peerstats" (2)
        ]
    }
}

# 40_ntpstats-ng.conf
filter {
    csv {} (3)
    csv {} (4)
}

# 59_ntpstats-ng.conf
output {
    file {
        path => [ "/var/opt/ntpstats-ng/log/ntpstats-ng-debug-%{+YYYY-MM-dd}.json" ] (5)
    }
}
  1. loopstats Spool

  2. peerstats Spool

  3. loopstats Filter

  4. peerstats Filter

  5. Output im JSON-Format

2.2.2 Logstash Test

tutorial_logstash
Figure 2. Logstash Test
Tip
Sie testen zuerst den Import ohne Elasticsearch und Grafana.
CentOS 7, OL 7, syslogd
systemctl start logstash.service
Gentoo, openrc, logstash-5.2.2
/etc/init.d/logstash start
 * Checking your configuration ...
Sending Logstash's logs to /var/log/logstash which is now configured via log4j2.properties
Configuration OK
[2017-04-10T10:23:44,131][INFO ][logstash.runner] Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash                                                    [ ok ]
 * Starting logstash ...

Starten Sie nun die Beobachtung von logstash und den noch nicht existierenden Dateien.

tail -F /var/log/logstash/logstash-plain.log /var/opt/ntpstats-ng/log/ntpstats-ng-*
==> /var/log/logstash/logstash-plain.log <==
[2017-04-10T10:33:19,494][INFO ][logstash.runner  ] Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
[2017-04-10T10:33:29,706][INFO ][logstash.pipeline] Starting pipeline {"id"=>"main", "pipeline.workers"=>4, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>5, "pipeline.max_inflight"=>500}
[2017-04-10T10:33:29,720][INFO ][logstash.pipeline] Pipeline main started
[2017-04-10T10:33:29,765][INFO ][logstash.agent   ] Successfully started Logstash API endpoint {:port=>9600}
tail: '/var/opt/ntpstats-ng/log/ntpstats-ng-*' kann nicht zum Lesen geöffnet werden: Datei oder Verzeichnis nicht gefunden

Kopieren Sie nun mit Hilfe des Kommandos cat den Inhalt einer ersten Statistik-Datei ins Spool-Verzeichnis.
Ersetzen Sie die Namensmuster durch Ihre aktuellen Werte - im Beispiel localhost.

cat /var/log/ntp/stats/HOSTNAME.loopstats.YYYYMMdd >> /var/opt/ntpstats-ng/spool/HOSTNAME.loopstats
cat /var/log/ntp/stats/localhost.loopstats.20160501 >> /var/opt/ntpstats-ng/spool/localhost.loopstats

Im anderen Terminal sollte Ihnen nach ein paar Sekunden von tail der Output im JSON-Format präsentiert werden.

tail -F /var/log/logstash/logstash-plain.log /var/opt/ntpstats-ng/log/ntpstats-ng-*
==> /var/log/logstash/logstash-plain.log <==
[2017-04-10T11:02:25,251][INFO ][logstash.outputs.file] Opening file {:path=>"/var/opt/ntpstats-ng/log/ntpstats-ng-debug-2017-04-10.json"}

==> /var/opt/ntpstats-ng/log/ntpstats-ng-debug-2017-04-10.json <==
{"stats_host":"localhost","mjd":57509,"clock_offset":-7.76718E-4,"frequency_offset":-2.119,"type":"loopstats","stats_stamp":"2016-05-01T00:06:28.261Z","@timestamp":"2017-04-10T11:05:02.114Z","time_past_midnight":388.261,"frequency_jitter":0.002391,"es_index":"ntpstats-archive-2016-05-01","loop_time_constant":"10","rms_jitter":5.30734E-4}
Tip
Sie haben die unterschiedlichen Datumsangaben bemerkt?
Die Datei localhost.loopstats.20160501 wurde am 2017-04-10 importiert.
Später wird es_index um Anlegen eines Elasticsearch-Index ntpstats-archive-2016-05-01 benutzt.
head -n 1 /var/opt/ntpstats-ng/log/ntpstats-ng-debug-2017-04-10.json | jq [4]
{
  "stats_host": "localhost",
  "mjd": 57509,
  "clock_offset": -0.000776718,
  "frequency_offset": -2.119,
  "type": "loopstats",
  "stats_stamp": "2016-05-01T00:06:28.261Z",
  "@timestamp": "2017-04-10T11:05:02.114Z",
  "time_past_midnight": 388.261,
  "frequency_jitter": 0.002391,
  "es_index": "ntpstats-archive-2016-05-01",
  "loop_time_constant": "10",
  "rms_jitter": 0.000530734
}

Das Feld @timestamp enthält den logstash-Zeitstempel der Verarbeitung.

Das Feld stats_stamp benötigen Sie später bei der Konfiguration der Grafana Data Source.
Es enthält den Zeitstempel der Statistikzeile der mit logstash-filter-ruby berechnet wurde.

sinngemäße Darstellung der Berechnung
mjd                 + time_past_midnight = stats_stamp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
57509 (1)
2016-05-01T00:00:00 (2)
2016-05-01T00:00:00 + 388.261 s (3)
                                         = 2016-05-01T00:06:28.261Z (4)
  1. Modifizierte Julianische Datum

  2. MJD nach ISO8601

  3. Addition der Sekunden nach Mitternacht

  4. Ergebnis nach ISO8601

Löschen Sie Log- und Spool-Dateien und stoppen Sie logstash.

rm /var/opt/ntpstats-ng/log/*
rm /var/opt/ntpstats-ng/spool/*
CentOS 7, OL 7, syslogd
systemctl stop logstash.service
Gentoo, openrc
/etc/init.d/logstash stop

Passen Sie nun die Konfiguration zum späteren Output nach Elasticsearch an. Benutzen Sie die Datei 60_ntpstats-ng.conf.

rm /etc/logstash/conf.d/59_ntpstats-ng.conf
cp 60_ntpstats-ng.conf /etc/logstash/conf.d/
aktualisierte Konfiguration
# 60_ntpstats-ng.conf
output {
    elasticsearch {
        hosts => [ "localhost:9200" ] (1)
        index => "%{es_index}" (2)
    }
}
  1. lokale Elasticsearch-Node

  2. Inhalt des Felds es_index

2.3 Elasticsearch

2.3.1 Elasticsearch Konfiguration

/etc/elasticsearch/elasticsearch.yml
cluster.name: ntpstats-ng

# enable cors
http.cors.enabled: true
http.cors.allow-origin: "*"

Starten Sie elasticsearch:

CentOS 7, OL 7, syslogd
systemctl start elasticsearch.service
Gentoo, openrc, elasticsearch-5.2.2
/etc/init.d/elasticsearch start
 * Starting elasticsearch ...
 * /run/elasticsearch: correcting mode
 * /var/lib/elasticsearch/_default: creating directory
 * /var/lib/elasticsearch/_default: correcting owner
tail -F /var/log/elasticsearch/_default/ntpstats-ng.log
[2017-04-10T12:23:17,710][INFO ][o.e.n.Node            ] [] initializing ...
[2017-04-10T12:23:17,957][INFO ][o.e.e.NodeEnvironment ] [n7G2It1] using [1] data paths, mounts [[/mnt/var (/dev/mapper/vg0-var)]], net usable_space [13.7gb], net total_space [15.9gb], spins? [possibly], types [reiserfs]
[2017-04-10T12:23:17,958][INFO ][o.e.e.NodeEnvironment ] [n7G2It1] heap size [1.9gb], compressed ordinary object pointers [true]
[2017-04-10T12:23:17,959][INFO ][o.e.n.Node            ] node name [n7G2It1] derived from node ID [n7G2It1tSx6rh9RkBNWSMQ]; set [node.name] to override (1)
[2017-04-10T12:23:17,960][INFO ][o.e.n.Node            ] version[5.2.2], pid[31603], build[f9d9b74/2017-02-24T17:26:45.835Z], OS[Linux/4.4.39-gentoo-t440p/amd64], JVM[Oracle Corporation/Java HotSpot(TM) 64-Bit Server VM/1.8.0_121/25.121-b13]
[2017-04-10T12:23:19,390][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [aggs-matrix-stats]
[2017-04-10T12:23:19,390][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [ingest-common]
[2017-04-10T12:23:19,391][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [lang-expression]
[2017-04-10T12:23:19,391][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [lang-groovy]
[2017-04-10T12:23:19,391][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [lang-mustache]
[2017-04-10T12:23:19,391][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [lang-painless]
[2017-04-10T12:23:19,391][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [percolator]
[2017-04-10T12:23:19,391][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [reindex]
[2017-04-10T12:23:19,391][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [transport-netty3]
[2017-04-10T12:23:19,391][INFO ][o.e.p.PluginsService  ] [n7G2It1] loaded module [transport-netty4]
[2017-04-10T12:23:19,392][INFO ][o.e.p.PluginsService  ] [n7G2It1] no plugins loaded
[2017-04-10T12:23:21,597][INFO ][o.e.n.Node            ] initialized
[2017-04-10T12:23:21,598][INFO ][o.e.n.Node            ] [n7G2It1] starting ...
[2017-04-10T12:23:21,797][INFO ][o.e.t.TransportService] [n7G2It1] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}
[2017-04-10T12:23:21,804][WARN ][o.e.b.BootstrapChecks ] [n7G2It1] max file descriptors [32000] for elasticsearch process is too low, increase to at least [65536]
[2017-04-10T12:23:24,865][INFO ][o.e.c.s.ClusterService] [n7G2It1] new_master {n7G2It1}{n7G2It1tSx6rh9RkBNWSMQ}{VrFsoVecQL-fNbcQux9Eng}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-elected-as-master ([0] nodes joined)
[2017-04-10T12:23:24,911][INFO ][o.e.h.HttpServer      ] [n7G2It1] publish_address {127.0.0.1:9200}, bound_addresses {127.0.0.1:9200}
[2017-04-10T12:23:24,911][INFO ][o.e.n.Node            ] [n7G2It1] started
[2017-04-10T12:23:25,042][INFO ][o.e.g.GatewayService  ] [n7G2It1] recovered [0] indices into cluster_state
  1. node.name in /etc/elasticsearch/elasticsearch.yml

Sie kopieren zwei Dateien in das Verzeichnis /etc/elasticsearch/config/templates:

Sie bringen die Vorlagen in die Elasticsearch-Node ein.

cd /etc/elasticsearch/config/templates

curl -XPUT 'http://localhost:9200/_template/template_node/' -d @template_node.json
{"acknowledged":true}

curl -XPUT 'http://localhost:9200/_template/template_ntpstats-ng/' -d @template_ntpstats-ng.json
{"acknowledged":true}

Für Ihre ersten Schritte konfigurieren Sie damit einen Elasticsearch-Cluster mit nur einer Node. Jeder Index wird nur aus einer Shard bestehen (keine Replicas).

template_node.json
{
    "template": "*",
    "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 0
    }
}

Beim erneuten Start von logstash - wie unter [Tutorial#_2_2_2_logstash_test] beschrieben - sehen Sie die zusätzlichen Zeilen logstash.outputs.elasticsearch.

tail -F /var/log/elasticsearch/_default/ntpstats-ng.log
[2017-04-10T12:33:37,693][INFO ][logstash.runner  ] Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
[2017-04-10T12:33:49,687][INFO ][logstash.outputs.elasticsearch] Elasticsearch pool URLs updated {:changes=>{:removed=>[], :added=>[http://localhost:9200/]}}
[2017-04-10T12:33:49,690][INFO ][logstash.outputs.elasticsearch] Running health check to see if an Elasticsearch connection is working {:healthcheck_url=>http://localhost:9200/, :path=>"/"}
[2017-04-10T12:33:50,125][WARN ][logstash.outputs.elasticsearch] Restored connection to ES instance {:url=>#<URI::HTTP:0x45383f5d URL:http://localhost:9200/>}
[2017-04-10T12:33:50,128][INFO ][logstash.outputs.elasticsearch] Using mapping template from {:path=>nil}
[2017-04-10T12:33:50,252][INFO ][logstash.outputs.elasticsearch] Attempting to install template {:manage_template=>{"template"=>"logstash-*", "version"=>50001, "settings"=>{"index.refresh_interval"=>"5s"}, "mappings"=>{"_default_"=>{"_all"=>{"enabled"=>true, "norms"=>false}, "dynamic_templates"=>[{"message_field"=>{"path_match"=>"message", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false}}}, {"string_fields"=>{"match"=>"*", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false, "fields"=>{"keyword"=>{"type"=>"keyword"}}}}}], "properties"=>{"@timestamp"=>{"type"=>"date", "include_in_all"=>false}, "@version"=>{"type"=>"keyword", "include_in_all"=>false}, "geoip"=>{"dynamic"=>true, "properties"=>{"ip"=>{"type"=>"ip"}, "location"=>{"type"=>"geo_point"}, "latitude"=>{"type"=>"half_float"}, "longitude"=>{"type"=>"half_float"}}}}}}}}
[2017-04-10T12:33:50,258][INFO ][logstash.outputs.elasticsearch] Installing elasticsearch template to _template/logstash
[2017-04-10T12:33:50,428][INFO ][logstash.outputs.elasticsearch] New Elasticsearch output {:class=>"LogStash::Outputs::ElasticSearch", :hosts=>[#<URI::Generic:0x5652b18f URL://localhost:9200>]}
[2017-04-10T12:33:50,464][INFO ][logstash.pipeline] Starting pipeline {"id"=>"main", "pipeline.workers"=>4, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>5, "pipeline.max_inflight"=>500}
[2017-04-10T12:33:50,467][INFO ][logstash.pipeline] Pipeline main started
[2017-04-10T12:33:50,535][INFO ][logstash.agent   ] Successfully started Logstash API endpoint {:port=>9600}

3 Statistik-Import

Für den Import der Statistik-Dateien können Sie das Bash-Skript /opt/ntpstats-ng/bin/ntpstats-ng-transmitter verwenden.

Beispiel (alle Optionen in eine Zeile)
ntpstats-ng-transmitter -s /var/log/ntpstats \ (1)
-d /var/opt/ntpstats-ng/spool \ (2)
-t loopstats (3)
-i 10 \ (4)
-v \ (5)
-n (6)
  1. Statistik-Verzeichnis aus ntp.conf

  2. Spool-Verzeichnis für Logstash

  3. nur HOSTNAME.loopstats.YYYMMdd

  4. alle 10 Sekunden eine Datei - an Ihre CPU- und RAM-Performance anpassen

  5. Ausgabe an STDOUT

  6. keine Aktion

Tip
Realer Import ohne Option -n.
ntpstats-ng-transmitter -s /var/log/ntpstats -d /var/opt/ntpstats-ng/spool -t loopstats -i 10 -v
DIR_STATS = /var/log/ntpstats ; DIR_SPOOL = /var/opt/ntpstats-ng/spool ; TYPE = loopstats ; ACTION = cat ; INTERVAL = 10
cat /var/log/ntpstats/localhost.loopstats.20160501 >> /var/opt/ntpstats-ng/spool/localhost.loopstats
elapsed: 10 seconds
cat /var/log/ntpstats/localhost.loopstats.20160502 >> /var/opt/ntpstats-ng/spool/localhost.loopstats
elapsed: 10 seconds
tail -F /var/log/elasticsearch/_default/ntpstats-ng.log
[2017-04-10T13:17:36,921][INFO ][o.e.c.m.MetaDataCreateIndexService] [n7G2It1] [ntpstats-archive-2016-05-01] creating index, cause [auto(bulk api)], templates [template_node, template_ntpstats-ng], shards [1]/[0], mappings [*]
[2017-04-10T13:17:37,581][INFO ][o.e.c.r.a.AllocationService] [n7G2It1] Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[ntpstats-archive-2016-05-01][0]] ...]). (1)
[2017-04-10T13:17:37,724][INFO ][o.e.c.m.MetaDataMappingService] [n7G2It1] [ntpstats-archive-2016-05-01/memWq1lzT9mXKPz8GleTdw] create_mapping [loopstats] (2)
[2017-04-10T13:17:39,198][INFO ][o.e.c.m.MetaDataCreateIndexService] [n7G2It1] [ntpstats-archive-2016-05-02] creating index, cause [auto(bulk api)], templates [template_node, template_ntpstats-ng], shards [1]/[0], mappings [*]
[2017-04-10T13:17:39,475][INFO ][o.e.c.r.a.AllocationService] [n7G2It1] Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[ntpstats-archive-2016-05-02][0]] ...]).
[2017-04-10T13:17:39,534][INFO ][o.e.c.m.MetaDataMappingService] [n7G2It1] [ntpstats-archive-2016-05-02/0mz9b5tBStOW9yZwVjcAQw] create_mapping [loopstats]
  1. Index aus es_index, Shard aus template_node.json

  2. Mapping aus template_ntpstats-ng.json

Tip
Herzlichen Glückwunsch!

4 Grafana

Und nun zur grafischen Darstellung…​

4.1 Grafana Data Source

Sie legen eine neue Elasticsearch-Datenquelle ntpstats-archive an.

Grafana Data Sources
Figure 3. Grafana - Data Sources

Name

ntpstats-archive

Type

Elasticsearch

HTTP settings

URL

http://localhost:9200

Access

direct

Elasticsearch Details

Index name

[ntpstats-archive-]YYYY-MM-DD

Pattern

Daily

Time field name

stats_stamp

Version

5.x

Grafana Edit Data Source
Figure 4. Grafana - Edit Data Source

4.2 Grafana Dashboards

Sie importieren drei Dashboards.

Grafana Import Dashboard
Figure 5. Grafana - Import Dashboard

Zusammenfassung

Bilder sagen mehr als Worte…​

ntpstats-archive
Figure 6. Grafana - ntpstats-archive
ntpstats-archive_loopstats
Figure 7. Grafana - ntpstats-archive_loopstats
ntpstats-archive_peerstats
Figure 8. Grafana - ntpstats-archive_peerstats

Ausblick

ntpstats-ng Demo

ntpstats-ng © MMXV-MMXVII WOLfgang Schricker

results matching ""

    No results matching ""