Check_MK: MRPE-Optimierung durch Intervall bezogene Checks [UPDATE]

30. April 2013 | Von | Kategorie: Monitoring | Availability

Der Einsatz von Check_MK bietet viele Vorteile: automatische Inventarisierung der zu überwachenden Systeme, mitgelieferte Templates für PNP4Nagios, eine Vielzahl an vorgefertigten Checks … Du findest weitere Informationen zum Einsatz von Check_MK in verschiedenen Artikeln auf diesem Blog oder auf der Seites des Check_MK-Projektes.

In diesem Artikel soll es um die Möglichkeiten gehen die Ausführung von Nagios-Plugins auf dem lokalen System flexibler zu gestalten. Bei allen Vorteilen die Check_MK bietet hat es aber auch einen entscheidenen Nachteil. Es gibt nur ein Zeitintervall in dem immer alle Checks ausgeführt werden müssen. Per Voreinstellung werden alle Checks im Abstand einer Minute durchgeführt. Bei einem Kunden hatten wir jedoch das Problem, dass er mehrer lokalen Checks durchführen musste. Dies hatte jedoch negative Auswirkungen auf die Latenzzeiten der Check-Ausführungen insgesamt.

Bei diesem Kunden dauerte die Ausführung einer Prüfung mittels Check_MK rund 15 Sekunden.

$ check_mk -nv kvm2
Check_mk version 1.1.8b3
CPU load             OK - 15min Load 0.00 at 4 CPUs
CPU utilization      OK - user: 0.4%, system: 0.3%, wait: 0.0%
...
sg10                 OK: no SMART errors detected
sg11                 OK: no SMART errors detected
sg12                 OK: no SMART errors detected
sg4                  OK: no SMART errors detected
sg5                  OK: no SMART errors detected
sg6                  OK: no SMART errors detected
sg9                  OK: no SMART errors detected
OK - Agent Version 1.1.8b3, processed 39 host infos in 15.1 sec|execution_time=15.052

Die lange Ausführungszeit resultierte aus den Checks, die durch den Einsatz von MRPE ausgeführt wurden. Hierbei werden reguläre Nagios-Plugins in der Datei /etc/check_mk/mrpe.cfg konfiguriert und bei der Abfrage von Check_MK auch jedesmal ausgeführt. Nun ist das Problem, dass dies jedoch im Abstand von einer Minute geschieht.

Für den Kunden ist dieses Zeitintervall für einge seiner Checks jedoch völlig überdimensioniert. So würde ein Test auf Festplattenfehler mit den smartmontools auch im Abstand einer Stunde ausreichen. Nun gab es zunächst die Überlegung neben Check_MK auch den Nagios Remote Plugin Executor (NRPE) einzusetzen. Dies wurde jedoch schnell wieder verworfen, weil es zum einen auf dem zu überwachenden System einen zusätzlichen Daemon erfordert hätte, als auch eine separate Konfiguration und Überwachung eines dieses Daemon. Der Kunde wünschte sich aber auch die Möglichkeit einer automatischen Inventarisierung von Systemen, was zumindest beim  Einsatz von NRPE nicht möglich ist. Also war die Frage geklärt und es musste eine Lösung auf der Basis von Check_MK gefunden werden.

Die Lösung dieses Problem war dann jedoch gar nicht so kompliziert. Zunächst stand die Überlegung an, die Ausführung der Checks von der Ausführung des check_mk_agent zu entkoppeln, aber dennoch über diesen die Checkergebnisse an die Nagios- oder Icinga-Instanz zu übergeben. Die Entkoppelung war schnell gelöst, dazu wird der Crond für die zeitgesteuerte Ausführung verwendet. Da wir uns auf die Zeitintervalle hourly, daily und weekly beschränkt haben musste in die entsprechenden /etc/cron.*/-Verzeichnisse zunächst ein Skript hinterlegt werden, welches sich um die Ausführung der Plugins kümmert.

# cat /etc/cron.hourly/check_mk_hourly.sh
#!/bin/bash

# Ausfuehren der stuendlichen Checks
FILES=/etc/check_mk/hourly/*

for f in $FILES
do
$f
done

Die stündlichen Checks werden nun durch den Cron-Daemon ausgeführt. Dieser führt in den entsprechenden Intervallen alle ausführbaren Skripte im Verzeichnis /etc/check_mk/hourly/ aus. Angepasste Skripte gibt es dann auch in den Verzeichnissen /etc/crond.daily/ und /etc/cron.weekly/.   Damit wir diese Checkergebnisse auch per Check_MK an das Monitoring-System übertragen können, wenden wir einen Trick an.

Schauen wir uns hierzu zunächst eines der Skripte an, die im Rahmen des Cron-Job ausgeführt werden.

#!/bin/bash

# Auszufuehrendes Plugin
CMD="/usr/local/libexec/nagios-plugins/check_smart -d /dev/sg12 -i scsi"
# Plugin-Beschreibung
DESCR="sg12"
#Ausfuehrungsintervall: hourly, daily, weekly
INTERVAL=hourly

# Ab hier nicht mehr editieren!
TEMPFILENAME=$(date +%s)
MV=$(which mv)
PLUGIN=${CMD%% *}
OUTPUT=$(eval "$CMD")

echo "(${PLUGIN##*/}) $DESCR $? $OUTPUT" > /tmp/check_mk/$TEMPFILENAME.$DESCR

$MV -f /tmp/check_mk/$TEMPFILENAME.$DESCR /tmp/check_mk/$INTERVAL/$DESCR.mk

Was macht dieses Skript? Zunächst definieren wir in der Variablen CMD den konkreten Aufruf des Nagios-Plugins mit allen Parametern, die für dieses Plugin erforderlich sind. In der Variable DESCR hinterlegen wir die Beschreibung, wie dieser Check später inventarisiert werden soll und wie er anschließend im Nagios benannt wird. Zusätzlich definieren wir in einer Variablen den Interval, in dem das Plugin ausgeführt werden soll. Wofür die letzte Variable notwendig ist erkläre ich später.

Auf die Definition der drei Variablen wird im wesentlichen das Plugin ausgeführt und die Ausgabe in eine temporäre Datei gespeichert. Abschließend wir die Temporäre Datei noch in eine Datei mit der Bezeichung des Checks verschoben. Die Ausgabe erfolgt in einer Form, in der sie auch bei einer direkten Ausführung durch MRPE präsentiert würde.

(check_smart) sg4 0 OK: no SMART errors detected|defect_list=0 temperature=20;;65

Der Aufbau der Ausgabe folgt einem bestimmten Muster: geklammert wird zunächst das ausgeführte Nagios-Plugin ausgegeben – diese Information ist für die spätere Auswahl eines PNP4Nagios-Templates erforderlich. Darauf folgt die service_description, mit dem der Check eine bestimmte Bezeichnung erhält. Daran schließt sich der Rückgabe-Wert der Plugin-Ausführung an, hieran erkennt Nagios später, den Zustand des Checks. Und abschließend wird der normale Output des Plugins angehangen.

Durch die Zwischenspeicherung in eine temporäre Datei und anschließendes verschiebenes dieser Datei soll eine Racecondition verhindert werden, wenn später der check_mk_agent und das Skript, welches das Plugin aufruft, zeitgleich auf die Datei zugreifen sollten. Das Verschieben der Datei ist eine atomare Aktion, die einen exklusiven Zugriff erfordert und damit eine Racecondition verhindert.

Die Datei wird in das Verzeichnis /tmp/check_mk/hourly/ verschoben und erhält die Endung, *.mk. Wird ein Check nicht stündlich sondern nur täglich vorgenommen, so wird diese Datei in das Verzeichnis /tmp/check_mk/daily/ verschoben. Und so weiter.

Damit die Daten nun übertragen werden ist eine kleine Anpassung des check_mk_agent erforderlich. Wir haben die Ausgabe der Nagios-Plugins in einem Format, welches dem MRPE-Format entspricht, in eine Datei umgelenkt. Diese Dateien werden nun durch den Agent lediglich an der entsprechenden Stelle in den Datenstrom eingefügt.
Im MRPE-Abschnitt wurden hierzu die folgenden Codezeilen ergänzt, die über die Dateien iterieren und die Ausgaben in den Agent-Datenstrom einfügen.

$ diff check_mk_agent /usr/bin/check_mk_agent
56c56
< echo Version: 1.1.8
---
> echo Version: 1.1.8b3
344a345,353
>    if [ -d /tmp/check_mk/ ]
>    then
>     FILES="/tmp/check_mk/daily/*.mk /tmp/check_mk/hourly/*.mk /tmp/check_mk/weekly/*.mk"
>     for f in $FILES
>     do
>         cat $f
>     done
>    fi
>

Der wesentliche Unterschied ist nun jedoch, dass die Nagios-Plugins in unserem Falle nicht mehr jede Minute ausgeführt werden, sondern in festen Intervallen per Cron-Job. Der check_mk_agent verwendet jedoch bei jedem Aufruf die Werte aus den zwischengespeicherten Dateien und prüft somit auch weiterhin jede Minute unser System, wobei unsere testergebnisse nicht immer „aktuelle“ Werte enthalten.

Auch eine Inventraisierung ist weiterhin möglich. Sobald die Nagios-Plugins per Cron oder manuell einmalig ausgeführt wurden existieren die temporären Dateien und diese werden vom Agenten ausgeliefert.

Die aufmerksame Leserin wird nun schnell merken, dass es aber einen Haken an diesem Vorgehen gibt. Werden die Nagios-Plugins – warum auch immer – nicht mehr korrekt ausgeführt. Ist das Checkergebnis in den Ergebnisdateien nicht mehr aktuell. Check_MK geht aber weiterhin davon aus, dass alles in Ordnung ist. Um dieses Problem zu lösen löschen wir automatisch alle Ergebnisdateien, die älter sind als das jeweilige Cron-Intervall, in dem die Nagios-Plugins ausgeführt werden.

Daher ist das Skript in /etc/cron.hourly/ entsprechend erweitert:

#!/bin/bash

# Loeschen zu alter Dateien
TMPWATCH=$(which tmpwatch)
$TMPWATCH --mtime 62m /tmp/check_mk/hourly/
$TMPWATCH --mtime 1500m /tmp/check_mk/daily/
$TMPWATCH --mtime 10140m /tmp/check_mk/weekly/

# Ausfuehren der stuendlichen Checks
FILES=/etc/check_mk/hourly/*

for f in $FILES
do
$f
done

Die Löschung zu alter Dateien wird mit dem Befehl tmpwatch kontrolliert. Hierbei sind die Werte immer ein wenig größer, als das Intervall selbst, damit es nicht zu Überschneidungen kommt.

Der normale Einsatz von MRPE funktioniert weiterhin wie gehabt. Bei unserem Kunden führte diese Umstruktierung der Checkausführung zu einer enormen Beschleunigung  der Prüfung. Vor der Umstruktrierung benötigte ein check_mk-Aufruf rund 15 Sekunden nachher waren es lediglich noch 0.3 Sekunden.

# check_mk -nv kvm2
Check_mk version 1.1.8b3
CPU load             OK - 15min Load 0.00 at 4 CPUs
CPU utilization      OK - user: 0.6%, system: 0.5%, wait: 0.0%
...
sg9                  OK: no SMART errors detected
OK - Agent Version 1.1.8b3, processed 41 host infos in 0.3 sec|execution_time=0.279

Für die Einrichtung müssen zunächst die folgenden Verzeichnisse erstellt werden:

  • /etc/check_mk/hourly/
  • /etc/check_mk/daily/
  • /etc/check_mk/weekly/
  • /tmp/check_mk/hourly/
  • /tmp/check_mk/daily/
  • /tmp/check_mk/weekly/

Zusätzlich muss die oben aufgeführte Anpassung am check_mk_agent vorgenommen werden. Und zu guter Letzt müssen für den CronDaemon die Dateien in die entsprechenden Verzeichnisse /etc/cron.hourly/ … eingespielt werden. Das Skript für die stündliche Ausführung ist bereits weiter oben aufgeführt, die beiden anderen Skripte findest du hier:

# cat /etc/cron.daily/check_mk_daily.sh
#!/bin/bash

# Ausfuehren der taeglichen Checks
FILES=/etc/check_mk/daily/*

for f in $FILES
do
$f
done
# cat /etc/cron.weekly/check_mk_weekly.sh
#!/bin/bash

# Ausfuehren der taeglichen Checks
FILES=/etc/check_mk/weekly/*

for f in $FILES
do
    $f
done

[UPDATE]
Ich hab die Anpassungen mal in Skripte zusammengefasst. Auf dem System, welches du überwachen möchtest, muss das folgende Skript einmalig ausgeführt werden.

#!/bin/bash</pre>
mkdir -p /etc/check_mk/hourly
mkdir -p /etc/check_mk/daily
mkdir -p /etc/check_mk/weekly

mkdir -p /var/run/check_mk/hourly
mkdir -p /var/run/check_mk/weekly
mkdir -p /var/run/check_mk/daily
if [ -d /usr/lib/check_mk_agent/plugins/ ];
then
cat > /usr/lib/check_mk_agent/plugins/mk_mrpe_cron << EOF
#!/bin/sh
if [ -d /var/run/check_mk/ ]
then
# Delete old Buffer-Files
find /var/run/check_mk/hourly/* -mmin +62 -exec rm -f {} \;
find /var/run/check_mk/daily/* -mmin +1500 -exec rm -f {} \;
find /var/run/check_mk/weekly/* -mmin +10140 -exec rm -f {} \;
echo '<<<mrpe_cron>>>'
FILES="/var/run/check_mk/daily/*.mk /var/run/check_mk/hourly/*.mk /var/run/check_mk/weekly/*.mk"
for f in \$FILES
do
cat \$f
done
fi
EOF
chmod 755 /usr/lib/check_mk_agent/plugins/mk_mrpe_cron
fi

#for INTER in 1 2 3
#do
# touch /tmp/$INTER
#done

for INTER in "hourly" "daily" "weekly"
do
if [ -d /etc/cron.$INTER ];
then
cat > /etc/cron.$INTER/check_mk_$INTER << EOF
#!/bin/bash
INTERVAL=$INTER
MV=\$(which mv)
TEMPFILENAME=\$(date +%s)
if [ -d /etc/check_mk/\$INTERVAL/ ]
then
grep -hEv '^:space:*(\$|#)' /etc/check_mk/\$INTERVAL/*.cfg | \
while read descr cmdline
do
PLUGIN=\${cmdline%% *}
OUTPUT=\$(eval "\$cmdline")
echo "(\${PLUGIN##*/}) \$descr.\$INTERVAL \$? \$OUTPUT" > /tmp/\$TEMPFILENAME.\$descr
if [ -d "/var/run/check_mk/\$INTERVAL" ]; then
\$MV -f /tmp/\$TEMPFILENAME.\$descr /var/run/check_mk/\$INTERVAL/\$descr.mk
else
/bin/mkdir -p /var/run/check_mk/\$INTERVAL
fi
done
fi
EOF
chmod 755 /etc/cron.$INTER/check_mk_$INTER
fi
done
<span style="font-family: Consolas, Monaco, monospace; font-size: 12px; line-height: 18px;">

Danach kannst du einfach in den neuen Verzeichnissen unterhalb von /etc/check_mk/ jenachdem im Stunden-, Tages- oder Wochenintervall Checks ausführen lassen.

Musst du den folgenden Inhalt in die Datei /usr/share/check_mk/checks/mrpe_cron ablegen. Das Skript basiert auf einer regulären Check_MK-Installation (nicht auf OMD!). Für OMD müssten die Pfadangaben entsprechend angepasst werden.

#!/usr/bin/python

# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Thorsten Robers 2011   <a href="mailto:thorsten@opensource-training.de">thorsten@opensource-training.de</a> |
# | based on mrpe from Mathias Kettner                               |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at <a href="http://mathias-kettner.de/check_mk">http://mathias-kettner.de/check_mk</a>.
#
# check_mk is free software;  you can redistribute it and/or modify it
# under the  terms of the  GNU General Public License  as published by
# the Free Software Foundation in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# tails.  You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.

def inventory_mrpe_cron(checkname, info):
items = []
for line in info:
# New Linux agent sends (check_name) in first column. Stay
# compatible with MRPE versions not providing this info
if line[0].startswith("("):
item = line[1]
else:
item = line[0]
items.append((item, None))
return items

def check_mrpe_cron(item, params, info):
for line in info:
if line[0].startswith("("):
check_name = line[0][1:-1]
line = line[1:]
else:
check_name = None
if line[0] == item:
state = int(line[1])
rest = " ".join(line[2:])
parts = rest.split("|", 1)
# replace first line break with "<a href="smb://n">\\n</a>" -> Nagios expects it like this
output = parts[0].replace("\1", "<a href="smb://n">\\n</a>", 1).replace("\1", "<br>")
            perfdata = []
if len(parts) > 1: # found pipe symbol
perftxt = parts[1].strip()
for perfinfo in perftxt.split(" "):
try:
varname, valuetxt = perfinfo.split("=", 1)
values = valuetxt.split(";")
perfdata.append(tuple( [varname] + values) )
except:
pass

# name of check command needed for PNP to choose the correct template
if check_name:
perfdata.append(check_name)
return (state, output, perfdata)
return (3, "Check output not found in mrpe_cron checks")

check_info['mrpe_cron'] = (
check_mrpe_cron,
"%s",
1,
inventory_mrpe_cron)

Ich hoffe die Skripte machen es dir ein wenig einfacher. Check_MK auch intervallbezogen zu betreiben. Über Rückmeldungen würde ich mich freuen.

Post to Twitter Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to Ping.fm Post to Reddit

Tags: | | | | | |

Schreibe einen Kommentar

Fühle dich ermuntert einen Kommentar, Anmerkungen, Hinweise oder deine Ideen zum Thema zu hinterlassen. Wir freuen uns über deine Rückmeldung.