HowTo Icinga2 Perfdaten mit Graphite und Grafana verdrahten

Installation

Icinga2, Graphite

Icinga2, Graphite Web und Graphite Carbon werden wie gewohnt über die Paketquellen installiert:

# apt install icinga2 graphite-web graphite-carbon

Grafana

Grafana kann man über eine externe Paketquelle in APT einbinden:

deb https://packages.grafana.com/oss/deb stable main

Dazu muss noch der HTTPS-Transport für APT installiert werden:

# apt install apt-transport-https

Leider hat das bei mir nicht funktioniert, also habe ich ein fertiges deb-Paket von der Projektseite heruntergeladen und installiert:

# dpkg -i grafana_6.6.2_amd64.deb

Konfiguration

Icinga2

In Icinga2 muss der Export nach Graphite aktiviert werden:

# icinga2 feature enable graphite

Danach sollte noch Icinga2 neugestartet werden, um die Konfiguration und das neue Feature zu laden:

# systemctl restart icinga2

Jeder Host/Service, dessen Checks Perfdaten liefern, die später im Grafana landen sollen, muss zudem enable_perfdata = true gesetzt haben. Am besten macht man das in einem Template, welches von jedem Host bzw. Service eingebunden wird.

Carbon Cache

Standardmäßig liegen unter Debian für Carbon gar keine Konfigurationsdateien in /etc/carbon. Im groben und ganzen kann man die default-Einstellungen nehmen. Anpassen sollte man noch, auf welchen Adressen der Carbon Cache lauscht:

# /etc/carbon/carbon.conf
[cache]
DATABASE = whisper
ENABLE_LOGROTATION = True
USER = _graphite
MAX_CACHE_SIZE = inf
MAX_UPDATES_PER_SECOND = 500
MAX_CREATES_PER_MINUTE = 50
MIN_TIMESTAMP_RESOLUTION = 1
LINE_RECEIVER_INTERFACE = 127.0.0.1
LINE_RECEIVER_PORT = 2003
ENABLE_UDP_LISTENER = False
UDP_RECEIVER_INTERFACE = 127.0.0.1
UDP_RECEIVER_PORT = 2003
PICKLE_RECEIVER_INTERFACE = 127.0.0.1
PICKLE_RECEIVER_PORT = 2004
PICKLE_RECEIVER_MAX_LENGTH = 1048576
USE_INSECURE_UNPICKLER = False
CACHE_QUERY_INTERFACE = 127.0.0.1
CACHE_QUERY_PORT = 7002
USE_FLOW_CONTROL = True
LOG_UPDATES = False
LOG_CREATES = False
LOG_CACHE_HITS = False
LOG_CACHE_QUEUE_SORTS = False
CACHE_WRITE_STRATEGY = timesorted
WHISPER_AUTOFLUSH = False
WHISPER_FALLOCATE_CREATE = True

[relay]
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2013
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2014
PICKLE_RECEIVER_MAX_LENGTH = 1048576
RELAY_METHOD = rules
REPLICATION_FACTOR = 1
DESTINATIONS = 127.0.0.1:2004
MAX_QUEUE_SIZE = 10000
MAX_DATAPOINTS_PER_MESSAGE = 500
QUEUE_LOW_WATERMARK_PCT = 0.8
TIME_TO_DEFER_SENDING = 0.0001
USE_FLOW_CONTROL = True
USE_RATIO_RESET=False
MIN_RESET_STAT_FLOW=1000
MIN_RESET_RATIO=0.9
MIN_RESET_INTERVAL=121

[aggregator]
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2023
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2024
FORWARD_ALL = True
DESTINATIONS = 127.0.0.1:2004
REPLICATION_FACTOR = 1
MAX_QUEUE_SIZE = 10000
USE_FLOW_CONTROL = True
MAX_DATAPOINTS_PER_MESSAGE = 500
MAX_AGGREGATION_INTERVALS = 5

In der /etc/carbon/storage-schemas.conf wird festgelegt, welche Perfdaten wie lange und in welcher Präzision gespeichert werden. Dazu definiert man mehrere Policies, die auf bestimmte Pattern matchen und bei einem Match die entsprechende Speicherungsregel (retentions) anwendet. Hier gilt, dass nur das erste Match von oben nach unten in der Datei wirksam wird. Die retentions sind Listen der Form Präzision:Speicherdauer. Faustregel ist: Je kleiner die Präzision, desto länger kann man speichern. Hier ein simples Beispiel:

[carbon]
pattern = ^carbon\.
retentions = 60:90d

[default]
pattern = .*
retentions = 10s:1d,60s:1w,5m:4w,30m:1y,1h:4y

Die nächste Datei, die man bearbeiten sollte, ist die storage-aggregation.conf. Diese legt fest, wie Perfdaten aggregiert werden, wenn sie gemäß retention policy zu einer geringeren Auflösung komprimiert werden sollen. Details dazu liest man am besten in der Dokumentation1) nach. Ich benutze eine einfache Policy, die einfach immer mit Durchschnittsbildung die Daten zusammenfasst:

[default]
pattern = .*
xFilesFactor = 0.0
aggregationMethod = average

Wichtig: Änderungen der Retention/Aggregation Policies werden nur bei neuen Whisper-Files wirksam, d.h. sobald einmal Perfdaten für ein bestimmtes Objekt aus Icinga2 gespeichert wurden, bleibt die alte Retention Policy auch dann wirksam, wenn man die Konfigurationsdatei ändert. Man sollte also alles richtig konfiguriert haben, bevor die ersten Perfdaten eingeliefert werden, wenn man nicht dazu bereit ist, seine Perfdaten nach einer Änderung der Konfiguration wieder zu löschen.

Generierung Graphite-DB

Als nächstes muss noch die Graphite-DB initialisiert werden. Das geschieht in bester Django-Manier:

# graphite-manage migrate

Mir ist es dabei passiert, dass die Datenbank dann dem Nutzer/Gruppe root:root gehört hat und nicht mehr von Carbon beschreibbar war. Das Problem lässt sich leicht händisch beheben:

# chown _graphite:_graphite /var/lib/graphite/graphite.db

Graphite Web

Graphite Web stelle ich über den bereits installierten Apache2 bereit. Dazu musste nebst Apache2 also noch das WSGI-Modul für Python 3 installiert werden:

# apt install libapache2-mod-wsgi-py3

Graphite-Web bietet eine fertige Apache2-Konfigurationsdatei an, die man kopieren und anpassen kann:

# cp /usr/share/graphite-web/apache2-graphite.conf /etc/apache2/sites-available/graphite.conf

Anzupassen gibt es hier normalerweise nichts. In meinem Fall habe ich noch einen alternativen Port genutzt, um das Graphite Web einfacher von außen abzusichern:

# /etc/apache2/sites-available/graphite.conf
Listen 3001

<VirtualHost *:3001>
        WSGIDaemonProcess _graphite processes=5 threads=5 display-name='%{GROUP}' inactivity-timeout=120 user=_graphite group=_graphite
        WSGIProcessGroup _graphite
        WSGIImportScript /usr/share/graphite-web/graphite.wsgi process-group=_graphite application-group=%{GLOBAL}
        WSGIScriptAlias / /usr/share/graphite-web/graphite.wsgi                              

        Alias /static/ /usr/share/graphite-web/static/                                       
        <Location "/static/">
                SetHandler None
        </Location>
        <Directory /usr/lib/python3/dist-packages>                                           
                Require all granted
        </Directory>
        <Directory /var/log/graphite>
                Require all granted
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/graphite-web_error.log                                    

        # Possible values include: debug, info, notice, warn, error, crit,                   
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/graphite-web_access.log combined                         

</VirtualHost>

Danach muss die Konfiguration noch aktiviert und der Apache2 neu geladen werden:

# a2ensite graphite
# systemctl reload apache2

Der Apache2 lauscht jetzt zusätzlich auf Port 3001 und man kann diesen jetzt für den Zugriff von außen abdichten:

# iptables -A INPUT -i lo -j ACCEPT
# iptables -A INPUT -p tcp --dport 3001 -j REJECT
# ip6tables -A INPUT -i lo -j ACCEPT
# ip6tables -A INPUT -p tcp --dport 3001 -j REJECT

Graphite-Web sollte auf dem localhost jetzt erreichbar sein und man sollte mit Graphite-Web auch in der Lage sein, sich Perfdaten zurechtzuklicken. Der Zugriff von außen sollte zudem nicht mehr möglich sein.

Grafana

Nach der Grafana-Installation sollte man die Firewall anpassen, damit der unverschlüsselte Grafana-Server (der standardmäßig auf TCP/3000 lauscht) nicht offen in der Welt hängt. Ich habe stattdessen einen Reverse Proxy, der für mich HTTPS macht, also sperre ich Zugriff von außen ab:

# iptables -A INPUT -p tcp -m tcp --dport 3000 -j REJECT --reject-with icmp-port unreachable
# ip6tables -A INPUT -p tcp -m tcp --dport 3000 -j REJECT --reject-with icmp6-port-unreachable

Erlangt man nun einen gesicherten Zugriff auf das Grafana über den eigenen Reverse Proxy oder durch einen lokalen SSH-Tunnel auf den Grafana-Server, kann man das Webinterface aufrufen. Die Standard-Zugangsdaten sind Nutzer „admin“ und Passwort „admin“.

Der Wizard ist recht leicht zu verstehen. Als Datenquelle muss Graphite auf http://localhost:3001 eingetragen werden. Grafana testet, ob die Verbindung klappt, und fährt dann fort.

Wenn man sich bis zur Startseite durchgeklickt hat, kann man dann anfangen, Dashboards und Graphen zu erstellen.