Aufbauend auf dem vorherigen Teil, möchte ich hier beschreiben, wie man Host- und Servicechecks über puppet definiert und ausrollt.

Das zusammenführen von Host- und Servicechecks ist mittels apply Regel in icinga2 geradezu kinderleicht geworden.
Da haben sich die Jungs echt was tolles ausgedacht!

Aber genug des Smalltalks!

Im vorherigen Blog-Post habe ich ja kurz angerissen, wie einfach man sich einen Icinga2-Core mit puppet provisionieren lassen kann.
Aber damit haben wir ja auch nur einen blanko Core, der nicht anderes macht, als sich selber zu prüfen.
Wir wollen aber mehr!

Hostcheck

Ein Hostcheck prüft nur, ob ein Host erreichbar ist.
Das wird – per default – durch ein simples ping erreicht, was man aber ebenso einfach ändern lassen kann.

Wir erweitern unsere vorherige hiera Konfiguration durch folgenden Part:

# -------------------------------------------------------------------------- 
# == Hostchecks
icinga2::object::hosts:
  node-01:
    display_name: 'Node 01'
    ipv4_address: "node-01.DOMAIN.TLD"
    notes: 'Testnode zur Demonstration'
    notes_url: 'https://docu.domain.tld/nodes/node-01.html'
    vars:
      os: 'Linux'
      memcache: true
    target_file_name: 'node-01.conf'
  node-02:
    display_name: 'Node 02'
    ipv4_address: "node-02.DOMAIN.TLD"
    notes: 'Testnode zur Demonstration'
    notes_url: 'https://docu.domain.tld/nodes/node-02.html'
    vars:
      os: 'Linux'
      memcache: true
    target_file_name: 'node-02.conf'

Wenn wir z.B. jetzt ein SSL-Zertikat prüfen wollen, richten wir ebenso einen Hostcheck ein. Dort allerdings ohne das default ping.
Stattdessen lautet hier unser Check Kommando http:

icinga2::object::hosts:
  . . .
  ssl-DOMAIN.TLD:
    display_name: 'SSL - Certificate - www.DOAMIN.TLD'
    address: 'www.DOAMIN.TLD'
    notes_url: 'https://docu.domain.tld/nodes/ssl-cert.html'
    check_command: 'http'
    vars:
      zone: 'ssl'
      http_certificate: 25

Im entsprechenden Puppet-Modul reichen dann nur wenige Zeilen um diese Hosts zu übernehmen:

# = Hosts
$h          = hiera_hash( 'icinga2::object::hosts', undef )
$h_defaults = hiera_hash( 'icinga2::object::hosts::defaults', undef )
if( $h ) {
  if( $h_defaults ) { create_resources( icinga2::object::host, $h, $h_defaults ) }
  else              { create_resources( icinga2::object::host, $h ) }
}

Ich nutze sehr gern notes, notes_url und action_url.
In umfangreicheren Setups kann man dort bereits kurze, aber wichtige Informationen (notes) hinterlegen, oder einen direkten Link in einer Online- (notes_url) bzw. Bereitschaftsdokumentation (action_url) anbieten.
Bei entsprechend konsequenter Vorarbeit kann man sich damit auch schon selbst (bzw. Kollegen) dazu zwingen, entsprechende Informationen zu erstellen und zu pflegen.
Diese 3 Informationen werden allerdings nur in einem entsprechenden Frontend (wie z.B icingaweb2) angezeigt und sind zum jetzigen Zeitpunkt noch völlig unsichtbar.

Mittels des vars Blockes kann man jedem Host einen Satz von individuellen Konfigurationsvariablen mitgeben, die man im späteren Verlauf (verknüpfen mit Services, einrichten von Hostgroups) nutzen kann.

Neben den Hostchecks benötigen wir noch …

Servicechecks

Servicechecks prüfen lokale Services auf den einzelnen Hosts.
Diese werden in der Regel über nrpe ausgeführt und werden durch den icinga2-Server aufgerufen.

Wir nehmen unsere hiera Konfiguration und definieren unsere ersten Checks.

# --------------------------------------------------------------------------
# == Servicecheck
icinga2::object::apply_service:
  nrpe-load:
    display_name: 'current load'
    check_command: 'nrpe'
    vars:
      nrpe_command: 'check_load'
    assign_where: 'host.vars.os == "Linux"'
    ignore_where: 'host.vars.zone == "uri" || host.name == "localhost"'
  nrpe-zombie:
    display_name: 'procs / Zombie',
    check_command: 'nrpe',
    vars:
      nrpe_command: 'check_zombie_procs',
    assign_where: 'host.vars.os == "Linux"'
    ignore_where: 'host.vars.zone == "uri" || host.vars.zone == "ssl" || host.name == "localhost"'

Damit erzeugen wir 2 einfache Checks, welche mittels nrpe remote auf den Hosts ausgeführt werden.

Mittels der assign_where Regel können wir jetzt diesem Servicecheck frei Hosts zuordnen.
Die ignore_where Regel bildet dagegen eine Blacklist-Funktion um bestimmte Hosts auszuschließen.
Mit intelligent designten Serviceschecks, kann man so problemlos Host hinzufügen die sofort nach ihrem Deployment alle wichtigen Servicechecks erhalten.
Flexibler in der Zuordnung geht es kaum noch!

Die konfigurierten Servicechecks können jetzt leicht ins puppet-Modul integriert werden:

# = Services
$s          = hiera_hash( 'icinga2::object::apply_service', undef )
$s_defaults = hiera_hash( 'icinga2::object::apply_service::defaults', undef )

if( $s ) {
  if( $s_defaults ) { create_resources( icinga2::object::apply_service, $s, $s_defaults ) }
  else              { create_resources( icinga2::object::apply_service, $s ) }
}

Auch bei den Servicechecks kann man wieder mit notes, notes_url und action_url arbeiten.

icinga2::object::apply_service:
  . . .
  nrpe-cache-memcache:
    display_name: 'Memcache Cluster'
    check_command: 'nrpe'
    vars:
      nrpe_command: 'check_memcache'
    assign_where: 'host.vars.memcache'
    notes: 'Prueft den verfuegbaren Memcached. Im Fehlerfall den betroffenen Memcached neu starten!'
    notes_url: 'https://docu.domain.tld/services/memcache.html'
    action_url: 'https://docu.domain.tld/operation/memcache.html' 

Host- bzw. Servicechecks kann – und sollte man auch – gruppieren.
Sollte … um nicht den Überblick zu verlieren und einen einfachen Filter zu bekommen.

Host- und Servicegroups

Hostgroups fassen Hosts in bestimmten Gruppen zusammen.
Hier lässt sich auch wunderbar mittels assign_where arbeiten:

# --------------------------------------------------------------------------
# == Hostgroups
icinga2::object::hostgroups:
  nodes-memcache:
    display_name: 'MEMCACHES'
    assign_where: 'host.vars.memcache'

Und Servicegruppen sind ganz ähnlich aufgebaut:

# --------------------------------------------------------------------------
# == Servicegroups
icinga2::object::servicegroups:
  apache:
    display_name: 'Webserver'
    assign_where: 'match("*apache*", service.name)'

Die integration ins das puppet-Modul erfolgt ähnlich wie den Host- oder Servicechecks:

# = Hostgroups
$hg          = hiera_hash( 'icinga2::object::hostgroups', undef )
$hg_defaults = hiera_hash( 'icinga2::object::hostgroups::defaults', undef )

if( $hg ) {
  if( $hg_defaults ) {
    $hg_dir = hiera( 'icinga2::object::hostgroups::defaults::target_dir', '/etc/icinga2/objects/hostgroups' )
    file { $hg_dir:
      ensure => directory
    }
    create_resources( icinga2::object::hostgroup, $hg, $hg_defaults )
  } else {
    create_resources( icinga2::object::hostgroup, $hg )
  }
}

# = Servicegroups
$sg          = hiera_hash( 'icinga2::object::servicegroups', undef )
$sg_defaults = hiera_hash( 'icinga2::object::servicegroups::defaults', undef )

if( $sg ) {
 if( $sg_defaults ) {
    $sg_dir = hiera( 'icinga2::object::servicegroups::defaults::target_dir', '/etc/icinga2/objects/servicegroups' )
    file { $sg_dir:
      ensure => directory
    }
    create_resources( icinga2::object::servicegroup, $sg, $sg_defaults )
  } else {
    create_resources( icinga2::object::servicegroup, $sg )
  }
}

Und damit bin ich erstmal fertig soweit.

Zum Schluß

Mein derzeitige Stage-Projekt beinhaltet 58 Hostchecks und um die 1000 Servicechecks.
Produktiv rechne ich mich ~160 Host- und ~1500 Servicechecks …
Wobei ich dabei aber weit mehr Services prüfe als der üblich Standard-Kram, wie ping, load oder procs.

Eine sinnvolle Überwachung von Tomcat-Containern und den darin laufenden Anwendungen ist etwas anspruchsvoller. Hier bietet sich die Integration von jolokia an, was ich ja in einem früheren Post schon mal andeutete.