Icinga2 – check_mssql_health

Das check_mssql_health Modul kann in Icinga2, als auch in Nagios dazu verwendet werden, seine MSSQL Datenbank zu überwachen. Dabei können Checks von Verbindungszeiten, Deadlocks, angemeldete User, existierende Tabellen und viele weitere ausgewählt werden. So macht es das Modul zu einem starken Tool für die Datenbanken. Leider wird check_mssql_health nicht bei der icinga2 respektive nagios mit installiert und muss manuell nachgeholt werden. Ich rede hier von der Installation über den Packet Manager. Die Installation dabei ist aber relativ einfach. Ich gehe davon aus, dass Icinga aus dem Repository heruntergeladen und nach Standard Parametern installiert worden ist.

 

 

Vorbereitung

Um mssql_health vollständig und erfolgreich installieren zu können, müssen einige Vorbereitungen getroffen werden, die ich hier kurz erläutere. Zunächst müssen ein paar Pakete nachinstalliert werden.

apt install libdbd-sybase-perl freetds-common freetds-dev freetds-bin

Dann laden wir die aktuelle mssql_health Version mit wget runter, was in meinem Fall(10.11.2018) die Version 2.6.4.14 ist.

wget https://labs.consol.de/assets/downloads/nagios/check_mssql_health-2.6.4.14.tar.gz

Natürlich müssen wir die tar.gz jetzt noch entpacken und gehen direkt in das neu erstellte Verzeichnis hinein.

tar xvzf check_mssql_health_2.6.4.14
cd check_mssql_health_2.6.4.14

Sobald wir im Verzeichnis sind, fangen wir an mssql_health zu kompilieren. Ich benutze jeweils die default Parameter. Änderungen können sonst mit dem ./configure Command geändert werden.

./configure
make
make install

Wenn die Kompilierung abgeschlossen und das Modul installiert ist, sollten wir überprüfen, ob es nicht doch noch eigene Syntax Errors im Perl Code gibt. Wenn alles soweit in OK ist, kopieren wir das Script in das jeweilige Icinga Verzeichnis

cd plugin-scripts/
perl -c check_mssql_health
cp check_mssql_health /usr/lib/Nagios/plugins

Zuguterletzt müssen wir eine Datenbank-Instanz in der freetds.conf einfügen. Dort ist schon ein Beispiel vorhanden, welches wir einfach für unsere Einstellungen übernehmen können. Falls dieser Eintrag übersprungen wird, kann keine Verbindung mit der Datenbank hergestellt werden.

nano /etc/freetds/freetds.conf

Aus Sicherheitsgründen sollten wir das TDS Protokoll noch auf Version 8.0 ändern. Die anderen Versionen verschicken Username/Passwort im Klartext. Somit hätten wir die Installation + Einrichtung des Modules vollzogen. Machen wir weiter mit der Konfiguration der Datenbank.

 

 

Datenbank einrichten

Das schöne an der Datenbank Einrichtung ist, dass wir hier nicht viel machen müssen. Auf der Projekt Seite steht ein vorgefertigtes Script zur Verfügung. Es ist zu empfehlen sich einen SQL-Benutzer anzulegen und diesen in der dafür vorgesehenen Stelle im Script anzugeben.

declare @dbname varchar(255)
declare @check_mssql_health_USER varchar(255)
declare @check_mssql_health_PASS varchar(255)
declare @check_mssql_health_ROLE varchar(255)
declare @source varchar(255)
declare @options varchar(255)
declare @backslash int

/*******************************************************************/
SET @check_mssql_health_USER = '"icinga"'
SET @check_mssql_health_PASS = 'password'
SET @check_mssql_health_ROLE = 'icinga'
/******************************************************************

PLEASE CHANGE THE ABOVE VALUES ACCORDING TO YOUR REQUIREMENTS

- Example for Windows authentication:
  SET @check_mssql_health_USER = '"[Servername|Domainname]\Username"'
  SET @check_mssql_health_ROLE = 'Rolename'

- Example for SQL Server authentication:
  SET @check_mssql_health_USER = 'Username'
  SET @check_mssql_health_PASS = 'Password'
  SET @check_mssql_health_ROLE = 'Rolename'

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
It is strongly recommended to use Windows authentication. Otherwise
you will get no reliable results for database usage.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

*********** NO NEED TO CHANGE ANYTHING BELOW THIS LINE *************/

SET @options = 'DEFAULT_DATABASE=MASTER, DEFAULT_LANGUAGE=English'
SET @backslash = (SELECT CHARINDEX('\', @check_mssql_health_USER))
IF @backslash > 0
  BEGIN
    SET @source = ' FROM WINDOWS'
    SET @options = ' WITH ' + @options
  END
ELSE
  BEGIN
    SET @source = ''
    SET @options = ' WITH PASSWORD=''' + @check_mssql_health_PASS + ''',' + @options
  END

PRINT 'create Nagios plugin user ' + @check_mssql_health_USER
EXEC ('CREATE LOGIN ' + @check_mssql_health_USER + @source + @options)
EXEC ('USE MASTER GRANT VIEW SERVER STATE TO ' + @check_mssql_health_USER)
EXEC ('USE MASTER GRANT ALTER trace TO ' + @check_mssql_health_USER)
EXEC ('USE MSDB GRANT SELECT ON sysjobhistory TO ' + @check_mssql_health_USER)
EXEC ('USE MSDB GRANT SELECT ON sysjobschedules TO ' + @check_mssql_health_USER)
EXEC ('USE MSDB GRANT SELECT ON sysjobs TO ' + @check_mssql_health_USER)
PRINT 'User ' + @check_mssql_health_USER + ' created.'
PRINT ''

declare dblist cursor for
  select name from sysdatabases WHERE name NOT IN ('master', 'tempdb', 'msdb') open dblist
    fetch next from dblist into @dbname
    while @@fetch_status = 0 begin
      EXEC ('USE [' + @dbname + '] print ''GRANT permissions IN the db '' + ''"'' + DB_NAME() + ''"''')
      EXEC ('USE [' + @dbname + '] CREATE ROLE ' + @check_mssql_health_ROLE)
      EXEC ('USE [' + @dbname + '] GRANT EXECUTE TO ' + @check_mssql_health_ROLE)
      EXEC ('USE [' + @dbname + '] GRANT VIEW DATABASE STATE TO ' + @check_mssql_health_ROLE)
      EXEC ('USE [' + @dbname + '] GRANT VIEW DEFINITION TO ' + @check_mssql_health_ROLE)
      EXEC ('USE [' + @dbname + '] CREATE USER ' + @check_mssql_health_USER + ' FOR LOGIN ' + @check_mssql_health_USER)
      EXEC ('USE [' + @dbname + '] EXEC sp_addrolemember ' + @check_mssql_health_ROLE + ' , ' + @check_mssql_health_USER)
      EXEC ('USE [' + @dbname + '] print ''Permissions IN the db '' + ''"'' + DB_NAME() + ''" GRANTED.''')
      fetch next from dblist into @dbname
    end
close dblist
deallocate dblist

Haben wir das Script ausgeführt, können wir außerhalb von Icinga testen, ob unsere Einstellungen soweit korrekt sind. Hierzu führen wir eine erste Überprüfung durch.

./check_mssql_health –server=wpsql3 –port=1433 –username=icinga –password=<password> --mode=locks-deadlocks –commit

Wenn dieser Check erfolgreich war, haben wir die Datenbank und das mssql_health modul korrekt installiert und eingerichtet. Jedoch fehlen noch die Änderungen in Icinga, damit dieser die Checks überhaupt ausführen kann. Ich hab es soweit eingerichtet, dass ich jedem Host mehrere Serviceobjekte von mssql_health zuweisen kann. Diese Objekte führen unterschiedliche Checks aus. Dazu habe ich einen Command angelegt, der bestimmte Parameter erwartet, aber auch solche die schon fest zugewiesen sind, wie Benutzername und Passwort.

object CheckCommand "checkmssql_health" {
   import "plugin-check-command"

   command = [PluginDir + "/check_mssql_health"]

   arguments = {
   "--server" = "$mssqlhealth_server$"
   "--username" = "$mssqlhealth_username$"
   "--password" = "$mssqlhealth_password$"
   "--mode" = "$mssqlhealth_mode$"
   "--critical" = "$mssqlhealth_critical$"
   "--warning" = "$mssqlhealth_warning$"
   "--commit" = ""

   }

   vars.mssqlhealth_username = "icinga"
   vars.mssqlhealth_password = "passwort"

}

Der erstellte Service geht dabei durch jedes, im Host Objekt angegebene, mssql_health Objekt.

apply Service "mssql_check_health" for (mode => config in host.vars.mssqlhealth_modes){
  import "generic-service"

  check_command = "checkmssql_health"

  vars.mssqlhealth_mode = mode

  vars+=config

  vars.mssqlhealth_critical = config.mssqlhealth_critical
  vars.mssqlhealth_warning = config.mssqlhealth_warning

   assign where ((host.address || host.address6) && host.vars.mssql == "true")
}

Mein Host Objekt sieht dementsprechend so aus und ist gefüllt mit mehreren Modis des Modules.

vars.mssqlhealth_modes["connected-users"] = {
     mssqlhealth_modes = "connected-users"
     mssqlhealth_warning = "1100"
     mssqlhealth_critical = "1500"
  }
vars.mssqlhealth_modes["locks-waits"] = {
     mssqlhealth_modes = "locks-waits"
     mssqlhealth_warning = "1"
     mssqlhealth_critical = "2"
  }
vars.mssqlhealth_modes["locks-deadlocks"] = {
     mssqlhealth_modes = "locks-deadlocks"
     mssqlhealth_warning = "1"
     mssqlhealth_critical = "2"
  }
vars.mssqlhealth_modes["database-backup-age"] = {
     mssqlhealth_modes = "database-backup-age"
     mssqlhealth_warning = "24"
     mssqlhealth_critical = "48"
  }

In “modes” werden die verfügbaren Modis von mssql_health eingetragen, während die anderen beiden den jeweils kritischen und warnenden Zustand angeben.

Haben wir alles soweit eingerichtet muss selbstverständlich der Icinga Service neugestartet werden, damit die vollzogenen Änderungen überhaupt aktiv werden

service icinga2 restart

Fazit

Wenn alles geschafft ist, haben wir unser Monitoring Tool für MSSQL Datenbanken erweitert und können dementsprechend Checks ausführen. Die Installation von mssql_health an sich ist einfach nur die jeweilige Integration in Icinga bedarf etwas Überlegung. Natürlich kann das Modul auch auf andere Wege in Icinga implementiert werden. Dort stehen alle Möglichkeiten offen. Ich habe mich für diese Integration entschieden, da ich für mich hier die meisten Vorteile sehe. Mit dieser Art der Erstellung müssen nur noch im Host Objekt die einzelnen Modis mit ihren Werten eingeben werden.  So kann auf einfachste Weise ein neuer Check eingefügt werden, ohne den Service bzw. den Command anpacken zu müssen.

17 Gedanken zu „Icinga2 – check_mssql_health

  1. Hallo! Danke für die Anleitung.. Eine Frage.. Wo fügt man die Datenbank Einrichten script ein? auch im datei freetds.conf?? oder woanders..

          1. Hello
            sorry, I meant to ask that the database setup script must be executed on the icinga database or the remote database host to be monitored?

          2. Hi,

            the database setup script must be executed on the remote host. It grants icinga access to the Database and its basic needs. The only part you have to take care of is to align these variables to your environment.

            @check_mssql_health_USER = ‘”icinga”‘
            @check_mssql_health_PASS = ‘password’
            @check_mssql_health_ROLE = ‘icinga’

            This is the page where i got my information from. May help you as well: https://labs.consol.de/nagios/check_mssql_health/index.html.

            Best Regards
            stevie

  2. Hi Stevie
    ich benutze ‘check_mssql_health’ erfolgreich bei MSSQL DBs.
    Jetzt habe ich Project mit Sybase DB Überwachung. Von den allem Modis funktionieren nu 2:
    connection-time und connected-users.
    Alle andere bringen mir Meldung “Mode cpu-busy is not implemented for this type of device”

    Weißt Du vielleicht, was das bedeutet und die Lösung?
    Beim Foren habe ich auch nichts gefunden oder kein Antwort bekommen.

    Habe ich auch die aktuellste Plugin Version installiert ( 2.6.4.16 ), aber ohne Erfolg
    Thx

    1. Hallo monitoringjunkie,

      Ich kenne mich leider mit Sybase DB nicht aus und kann daher nur vermuten was da passiert.
      Dieses Plugin, welches ich in diesem Artikel beschreibe, ist für MSSQL DB erstellt worden. Ich kann mir vorstellen, dass die Anfragen in Sybase anders aussehen müssen, als wie in MSSQL und dementsprechend laufen diese ins leere oder erzeugen eine Fehlermeldung(Mode is not implemented…). Aussnahmen sind hier Connection-time und connected-users, die der Server beantworten kann. Kurz gesagt, das MSSQL Plugin ist inkompatibel zu Sybase Datenbanken.
      Ich verweise hier mal auf das Plugin, welches ich im Internet gefunden habe. Es ist zwar schon 2 Jahre alt, aber vielleicht hilft es weiter: https://github.com/john100001uk/icinga-sybase

      Viel Glück!

      Grüße
      stevie

        1. Hallo monitoringjunkie,

          interessantes Video, habe ich mir mal stückchenweise angeschaut. Leider, wie sie schon angemerkt haben, ist es von 2013. Da ist schon einige Zeit vergangen. Was ich dort soweit gehört habe und auch soweit recherchieren konnte, ist dass Sybos vor längerer Zeit mit Microsoft zusammengearbeitet hat, jedoch später beide ein eigenes DB System hatten. Wie in meinem ersten Kommentar schon erwähnt, ist es nur eine Vermutung meinerseits, dass Inkompatibilitäten die Fehler verusachen und das Plugin könnte durchaus immer noch funktionieren. Ich hoffe Ihnen gelingt das Monitoring der Sybos Datenbank.

          Viele Grüße
          stevie

  3. Hallo,
    danke für die Anleitung. Soweit bin ich damit zurecht gekommen, aber beim Starten des checks an der Kommandozeile scheitere ich mit folgender Fehlermeldung:
    UNKNOWN – Please specify hostname or server, username and password

    Mein Aufruf ist folgender:
    ./check_mssql_health –-server=dbserver –-port=1433 –-username=DOMAIN\icinga –-password=secretpassword –mode=connected-users

    [dbserver] ist auch in der freetds.conf eingetragen. Auch Versuche mit hostname, ohne Port und einem nicht Domänenbenutzer enden auch bei dieser Fehlermeldung.
    Eine Idee was hier bei mir schieft läuft?

    Danke,
    Chris

    1. Hallo Chris,

      soweit haben Sie schon alles ausprobiert, was ich vorgeschlagen hätte. Evtl. bringt es etwas den Username und Passwort zu quoten. Wie sieht den soweit die Instanz in der freetds.conf aus?

      mfg
      stevie

      1. Hi,
        danke für die schnelle Antwort. Quoten verändert leider nichts an der Fehlermeldung, die conf sieht so aus:
        [dbserver]
        host = dbserver.domain.nrw (=> hab es hier auch schon mit der IP probiert)
        port = 1433
        instance = SQLEXPRESS
        tds version = 8.0

        CaseSensitive Schreibweise beim Servernamen hatte ich schon ausprobiert.
        Im Icinga2 bekomme ich allerdings eine andere Fehlermeldung:
        CRITICAL – connection could not be established within 15 seconds
        bei folgendem Aufruf:
        ‘/usr/lib/nagios/plugins/check_mssql_health’ ‘–hostname’ ‘dbserver’ ‘–password’ ‘pwd’ ‘–port’ ‘1433’ ‘–mode’ ‘connected-users’ ‘–report’ ‘short’ ‘–username’ ‘domain\icinga’

        Wenn Du noch eine Idee hast nehme ich diese gerne noch ansonsten setze ich mit zwei Tagen zum alles vergessen nochmal neu auf…

        Grüße,
        Chris

        1. Hi Chris,
          ist die SQLEXPRESS Datenbank den soweit konfiguriert, dass diese Remotezugriffe entgegen nimmt? TCP/IP Verbindungen müssen generell erlaubt werden und der Port muss angegeben werden. Dies muss nach der Installation eigenständig in der Management Konsole vorgenommen werden.
          SQL Server-Netwerkkonfiguration TCP/IP -> Aktivieren + Rechtsklick auf TCP/IP -> Eigenschaften -> IP-Adressen-> IPAll-> TCP-Port 1433 eintragen.
          Ich habe das Plugin gerade auf meine PI installiert + neuer SQLEXPRESS(2017)-Umgebung und kann soweit eine Verbindung herstellen.

          Meine freetds.conf sieht so aus:
          [MSSQLSERVER]
          host = mssqlserver
          port = 1433
          tds version = 8.0

          In der /etc/hosts habe ich einen Eintrag für mssqlserver gemacht und die IP zugewiesen.

          Mein check mit Antwort sieht so aus:
          ./check_mssql_health –hostname=mssqlserver –port=1433 –username=icinga –password=password –mode=connection-time –commit
          OK – 0.06 seconds to connect as icinga | ‘connection_time’=0.06;1;5;;

          Wenn –commit nicht mit übergeben wird, kommt eine Fehlermeldung mit dem Result:
          ./check_mssql_health –hostname=mssqlserver –port=1433 –username=icinga –password=password –mode=connection-time
          OK – 0.06 seconds to connect as icinga | ‘connection_time’=0.06;1;5;;
          DBD::Sybase::db DESTROY failed: Server message number=3903 severity=16 state=1 line=2 server=WIN-BF9K56LPD1C\SQLEXPRESS text=The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION. Server message number=3903 severity=16 state=1 line=2 server=WIN-BF9K56LPD1C\SQLEXPRESS text=The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION. during global destruction.
          (in cleanup) (in cleanup) during global destruction.

          Bitte nicht das SQL-Script auf dem MSSQL Server vergessen, der den User für die Abfrage generiert und auf die Firewall von dem Server/Rechner schauen(testweise komplett abschalten).

          Viel Glück!

          Mfg
          stevie

          1. Hi,
            das will irgendwie nicht. Der SQL Server ist von außen erreichbar, hab inzwischen auch mal die IP6 noch zusätzich aktiviert, es nochmals mit dem sa User und deaktivierter Firewall probiert und ich bleiben bei den beiden Fehlern hängen (“Unknown …” im Terminal und “Connection could not ….” im Icinga. Ich lass das Thema jetzt mal zwei Tage liegen und vielleicht fällt mir dann sofort di eLösung auf 😉

            Danke erstmal,
            Chris

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert