Trick 42 mit dem Director – Jobs in Reihenfolge

Nachdem wir unseren Trick 17 mit dem Director veröffentlichten, schiebe ich Trick 42 direkt hinterher. Wie im Blogpost von Markus beschrieben, sind Schnittmengen aus mehreren Importquellen eine geniale Lösung um beispielsweise Hosts aus mehreren Quellen mit Informationen anzureichern. Konfiguriert man nun eine Vielzahl solcher Importquellen die für die Schnittmenge dienen sollen, bekommt man evtl. im Ablauf gewisse Probleme mit der Reihenfolge.

Zur genauen Erklärung unser Ausgangsszenario:

  • CMDB 1: Quelle für die Basisdaten des Hosts (Name, IP, FQDN, …)
  • CMDB 2: Quelle für den OS-Type (CentOS, OpenSuSE, Debian, …)
  • CMDB 3: Quelle für den Ansprechpartner (Hr. Müller, Hr. Maier, …)

Damit die Hosts aus CMDB 1 angereichert erstellt (Import + Sync) werden können müssen zuerst CMDB 2 und CMDB 3 abgearbeitet werden. Logisch – wenn der OS-Type und der Ansprechpartner des Hosts dem Director nicht bekannt sind wird es mit Hilfe von Trick 17 auch nicht möglich sein den Host aus CMDB 1 mit Daten anzureichern.

Hauptsächlich fällt dieses Problem beim initialen Import + Sync der Daten auf. Je nachdem wie oft sich eure Importquellen ändern kann dies “gar nicht schlimm” (Hr. Müller ist für den Server 3 Jahre zuständig) oder auch “sehr unglücklich” (Ihr importiert die Kontaktdaten einer ständig wechselnden Rufbereitschaft) sein.

Für den Fall das die Reihenfolge der Importquellen wichtig ist gibt es eine denkbar simple Lösung.

Ihr legt für jeden Import und Sync einen Job im Director an…

 

…und notiert euch jeweils die ID des Director Jobs (die Zahl an der letzten Stelle der URL).

Mit Hilfe dieser ID könnt ihr nun die im Director konfigurierten Jobs von der Kommandozeile aus ausführen. Der Job mit der ID 1 (Import Job für CMDB1) kann mit dem Kommando “icingacli director jobs run 1” gestartet werden.

Am Ende bauen wir uns dazu noch ein kleines Skript:

#!/bin/bash

# set paths and vars
ICINGA_CLI=`which icingacli`
JOB_CMD=${ICINGA_CLI}" director jobs run"

# execute jobs
echo "import and sync..."

echo -e "\tcmdb1"
${JOB_CMD} 1
${JOB_CMD} 2

echo -e "\tcmdb2";
${JOB_CMD} 3
${JOB_CMD} 4

echo -e "\tcmdb3";
${JOB_CMD} 5
${JOB_CMD} 6

Und voilà – wir haben die Imports und Syncs in einer Reihenfolge 🙂

Tobias Redel

Autor: Tobias Redel

Tobias hat nach seiner Ausbildung als Fachinformatiker bei der Deutschen Telekom bei T-Systems gearbeitet. Seit August 2008 ist er bei NETWAYS, wo er in der Consulting-Truppe unsere Kunden in Sachen Open Source, Monitoring und Systems Management unterstützt. Insgeheim führt er jedoch ein Doppelleben als Travel-Hacker, arbeitet an seiner dritten Millionen Euro (aus den ersten beiden ist nix geworden) und versucht die Weltherrschaft an sich zu reißen.

Icinga 2 – Monitoring automatisiert mit Puppet Teil 7: Objekte aus Hiera erzeugen

This entry is part 7 of 7 in the series Icinga 2 Monitoring automatisiert mit Puppet

Vor einiger Zeit trat der Wunsch auf mit dem aktuellen Icinga-2-Modul für Puppet beliebe Objekte aus Hiera heraus zu erzeugen. Zum Beispiel aus folgender Hiera-Datei sollen ein Host-Objekt und zwei Service-Objekte gebaut werden.

---
monitoring::object:
  'icinga2::object::host':
    centos7.localdomain:
      address: 127.0.0.1
      vars:
        os: Linux
  'icinga2::object::service':
    ping4:
      check_command: ping4
      apply: true
      assign: 
        - host.address
    ssh:
      check_command: ssh
      apply: true
      assign:
        - host.address && host.vars.os == Linux

In Puppet 4 lässt sich dies nun sehr einfach mit zwei Schleifen realisieren:

class { 'icinga2':
  manage_repo => true,
}

$default = lookup('monitoring::default')

lookup('monitoring::object').each |String $object_type, Hash $content| {
  $content.each |String $object_name, Hash $object_config| {
    ensure_resource(
      $object_type,
      $object_name,
      deep_merge($default[$type], $object_config))
  }
}

Hierbei sind sogar für jeden Objekt-Type auch noch Defaults in Hiera gesetzt, z.B. in einer Datei common.yaml, die immer gelesen wird.

---
monitoring::default:
  'icinga2::object::host':
    import:
      - generic-host
    target: /etc/icinga2/conf.d/hosts.conf
  'icinga2::object::service':
    import:
      - generic-service
    target: /etc/icinga2/conf.d/services.conf

Dieses Verfahren ist mit dem selben Code auf Objekte mit allen möglichen Objekt-Typen erweiterbar. Passt man den Funktionsaufruf von lookup entsprechend an, kann auch über die Hiera-Struktur gemerged werden.

Lennart Betz

Autor: Lennart Betz

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.

Icinga 2 Best Practice Teil 6: Service-Checks auf Agenten schedulen

This entry is part 6 of 6 in the series Icinga 2 Best Practice

In Teil 1 dieser Blogserien beschäftigten wir uns mit Zonen, Agenten und wie man zentral angetriggert Plugins auf diesen Agenten ausführt. Nun im aktuellen Teil soll es darum gehen, das einplanen und ausführen dem Agenten selbst zu überlassen, damit werden auch während eines Verbindungsausfalls weiter Daten gesammelt und später, wenn die Verbindung wieder besteht, nachträglich übertragen.

In dem hier folgenden verdeutlichen wir, wie dies zu konfigurieren ist, mit einem Beispiel von einer Zone master, einer globalen Zone global-templates und einer Zone zu einem Beispiel Agenten agent.example.org.

Die Zonen- und Endpoint-Definitionen des Agenten auf Seite des Masters müssen in einer Datei in der Master-Zone oder in zones.conf hinterlegt werden. Leider ist es hier nicht möglich die jeweiligen Host-, Zonen- und Endpoint-Objekte in einer Datei zusammen zufassen, da wir das Host-Objekt agent.example.org zum Agenten selbst synchronisieren müssen und diese Definition in der Agenten-Zone abgelegt sein muss, z.B. in der Datei zones.d/agent.example.org/agent.conf:

object Host "agent.example.org“ {
 import "generic-host"

 address = "10.0.10.42"
 zone = get_object(Zone, name).parent

 vars.os = "Linux“
}

Durch die Ablage an genau diesem Ort, wird das Objekt zum Agenten synchronisiert. Mit setzen des Attributes zone auf die eigene Parent-Zone sorgen wir jedoch wieder dafür, dass das Host-CheckCommand sowie alle an diesen Host gebundenen Services auf einem Endpoint der Parent-Zone ausgeführt werden, hier die Zone master.

Damit wird der hostalive vom Master ausgeführt, was gewünscht ist, da sonst der Host seine Erreichbarkeit von sich selbst aus testen würde. D.h. alle Services, die auf den Agenten über das Netzwerk zugreifen sollen, bleiben wie sie sind und wir müssen keine Anpassungen vornehmen. Ganz im Gegensatz zu Services, die ein Plugin lokal auf dem Agenten ausführen sollen.

apply Service "load“ {
 import "generic-service“

 check_command = "load“
 if ( get_object(Zone, host.name) ) {
   zone = host.name
 }

 assign where host.vars.os == "Linux"
}

Auch Objekte vom Typ Service besitzen das Attribut zone mit dem wir hier nun die umgekehrten Weg beschreiten, existiert zum Host eine Zone selben Namens, wird die Zone zur Ausführung des zugeordneten Plugins in die eigene Agenten-Zone verlegt.

Lennart Betz

Autor: Lennart Betz

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.

Apply Service for im Icinga Director

Mit den Icinga 2 Apply Rules ist es spielend einfach möglich Services zu erstellen. Möchte man mehrere, gleiche Services erstellen (z. B. mehrere Port-Checks oder SNMP-Counteer) kommt Apply For zum Einsatz.

Im Zusammenhang mit dem Icinga Director erhalten wir ab und an Fragen zur Konfiguration von Apply For und sehr oft stellt sich dabei heraus das die Erklärung dieser Konfiguration per E-Mail oder Telefon sehr umständlich ist. Daher habe ich ein kleines Video für euch vorbereitet.

 

Schönes Wochenende! 🙂

Tobias Redel

Autor: Tobias Redel

Tobias hat nach seiner Ausbildung als Fachinformatiker bei der Deutschen Telekom bei T-Systems gearbeitet. Seit August 2008 ist er bei NETWAYS, wo er in der Consulting-Truppe unsere Kunden in Sachen Open Source, Monitoring und Systems Management unterstützt. Insgeheim führt er jedoch ein Doppelleben als Travel-Hacker, arbeitet an seiner dritten Millionen Euro (aus den ersten beiden ist nix geworden) und versucht die Weltherrschaft an sich zu reißen.

Icinga 2 – Monitoring automatisiert mit Puppet Teil 6: Agenten

This entry is part 6 of 7 in the series Icinga 2 Monitoring automatisiert mit Puppet

Nachdem Lennart sich bereits mit vielen Aspekte des Moduls befasst hat, will ich dieses Mal auf die Installation von Icinga 2 als Agenten eingehen. Neben einem generellen Einstieg mit zu beachtenden Konfigurationsoptionen, will ich hierbei auf die verschiedenen Möglichkeiten für die benötigten Zertifikate und Anbindung an die übergeordnete Zone eingehen.

Puppet-Icinga2

Die Installation und Feature-Konfiguration erfolgt wie Lennart dies in den ersten beiden Teilen der Serie beschrieben hat. Hierbei möchte ich beim Agent sicherstellen, dass keine lokale Konfiguration angezogen wird, da ich für die Verteilung der CheckCommands die Konfigurationssynchronisation von Icinga 2 nutzen möchte. Alternativ können diese zwar auch über Puppet verteilt werden, da ja auch die Plugins installiert werden müssen, aber in den meisten Umgebungen trenne ich an dieser Stelle Konfiguration der Monitoring-Infrastruktur von der eigentlichen Monitoring-Konfiguration. Der Start meines Agenten-Profils sieht also meist so aus:

  class { 'icinga2':
    confd       => false,
    manage_repo => true,
    features    => ['checker','mainlog'],
  }

(more…)

Dirk Götz

Autor: Dirk Götz

Dirk ist Red Hat Spezialist und arbeitet bei NETWAYS im Bereich Consulting für Icinga, Nagios, Puppet und andere Systems Management Lösungen. Früher war er bei einem Träger der gesetzlichen Rentenversicherung als Senior Administrator beschäftigt und auch für die Ausbildung der Azubis verantwortlich.

Icinga 2 – Monitoring automatisiert mit Puppet Teil 5: Konfiguration II

This entry is part 5 of 7 in the series Icinga 2 Monitoring automatisiert mit Puppet

Heute werden wir uns die Define Resource icinga2::object::host zum konfigurieren eines Host-Objekts anschauen und auch Services via apply-Regeln an diesen Host binden.

::icinga2::object::host { 'NodeName':
  target  => '/etc/icinga2/example.d/my_hosts.conf',
  import  => [ 'generic-host' ],
  address => '127.0.0.1',
}

Generell kann bei Objekten mit target angegeben werden in welche Datei sie geschrieben werden. Auch lässt sich mit dem Parameter order Einfluss auf die Reihenfolge der einzelnen Objekte in der jeweiligen Datei nehmen. Der Defaultwert für Host-Objekte ist 50, möchte man nun ein weiteres Host-Objekt davor einfügen, ist bei diesem order auf einen Wert kleiner 50 zu setzen. Das funktioniert mit anderen Objekttypen auf die gleiche Weise. So werden z.B. Hostgruppen oder Services mit einer order von 55 bzw. 60 standardmäßig hinter Hosts einsortiert. Um das mittels import eingebundene Template generic-host vor dem Host in die Datei zu schreiben muss im folgenden Codebeispiel order explizit gesetzt werden, da auch ein Host-Template aus icinga2::object::host erzeugt wird und damit den Defaultwert 50 hat.

::icinga2::object::host { 'generic-host':
  template           => true,
  target             => '/etc/icinga2/example.d/my_hosts.conf',
  order              => '47',
  check_interval     => '1m',
  retry_interval     => 30,
  max_check_attempts => 3,
  check_command      => 'hostalive',
}

Der Titel, also der Name des Objektes, und Werte aller Attribute werden durch einen einfachen Parser ausgewertet. So werden Zahlen als solche erkannt, auch wenn sie in Puppet als String geschrieben sind. Das gilt auch für Zeitabstände wie 1h, 1m oder 1s. Auch Konstanten werden erkannt, dadurch wird NodeName als solche erkannt und in der Icinga-Konfiguration nicht gequotet als Konstanten geschrieben. Die erzeugte Konfigurationsdatei sieht dann wie folgt aus:

template Host "generic-host" {
  check_interval = 1m
  retry_interval = 30
  max_check_attempts = 3
  check_command = "hostalive"
}

object Host NodeName {
  import "generic-host"
  address = "127.0.0.1"
}

Ein einzelnes Service-Objekt wird äquivalent erstellt. Möchte man jedoch mittels Apply den Service mehreren Hosts zuordnen geht dies mit Puppet ebenfalls, der Parameter apply muss hier lediglich auch true gesetzt werden.

::icinga2::object::service { 'ping4':
  target        => '/etc/icinga2/example.d/services.conf',
  apply         => true,
  import        => [ 'generic-service' ],
  check_command => 'ping4',
  assign        => [ 'host.address' ],
}

Die Assign- bzw. Ignore-Ausdrücke werden über die Parameter assign bzw. ignore definiert. Die Werte müssen als Array zugewiesen werden. Aus den einzelnen Elemente werden jeweils Assign- bzw. Ignore-Ausdrücke erzeugt.

apply Service "ping4" to Host {
  import "generic-service"

  check_command = "ping4"
  assign where host.address
}

Custom-Attribute können in beliebiger Anzahl dem Parameter vars als Dictionary-Elemente zugewiesen werden. So erzeugt dieser zusätzlich Puppet-Code für das oben beschriebene Host-Objekt,

  vars => {
    os     => 'Linux',
    disks  => {
      'disk /' => {
        disk_partition => '/',
      },
    },

die folgenden Zeilen Icinga-Konfiguration:

  vars.os = "Linux"
  vars.disks["disk /"] = {
    disk_partition = "/"
  }

Der Parser kann auch komplexere Ausdrücke korrekt bearbeiten, wie in assign des folgenden Services ssh.

::icinga2::object::service { 'ssh':
  target        => '/etc/icinga2/example.d/services.conf',
  apply         => true,
  import        => [ 'generic-service' ],
  check_command => 'ssh',
  assign        => [ '(host.address || host.address6) && host.vars.os == Linux' ],
}

Attribute aus dem Host-Kontext wie auch die Operatoren werden korrekt erkannt, das Wort Linux ist nicht bekannt und damit gequotet dargestellt. Alle bekannten Wörter werden ohne Quotes geschrieben. Bekannte Wörter sind neben dem Objekt-Titel, alle Objekt-Attribute, Custom-Attribute, die Konstanten der Icinga-Instanz und eine in icinga2::params::globals definierte Liste.

apply Service "ssh" to Host {
  import "generic-service"

  check_command = "ssh"
  assign where (host.address || host.address6) && host.vars.os == "Linux"
}

Um nun via Puppet auch die folgende Konfiguration modellieren zu können,

apply Service for (fs => config in host.vars.disks) to Host {
  import "generic-service"

  check_command = "disk"
  vars = vars + config
}

Hierzu setzt man den Parameters apply auf einen String, der dem Zuweisungsteil einer Icinga-Foreach-Schleife für Services entspricht. Wichtig hier zu beachten ist, das fs und config nun auch bekannte Wörter sind und nicht gequotet werden. Nähme man anstatt fs z.B. disk, hätte das zur Folge, das die Zeile check_command, mit disk ohne Quotes geschrieben wird. Damit ist dann aber leider die Konfiguration nicht korrekt, die Validierung schlägt fehl und ein Neustart von Icinga wird nicht ausgeführt.

::icinga2::object::service { 'disk':
  target        => '/etc/icinga2/example.d/services.conf',
  apply         => 'fs => config in host.vars.disks',
  import        => [ 'generic-service' ],
  check_command => 'disk',
  vars          => 'vars + config',
}

Zu den bisher erschienen Artikel dieser Serie geht es hier.

Lennart Betz

Autor: Lennart Betz

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.