Wenn man sich – so wie ich – mit einer Großzahl an zu überwachenden Servern beschäftigt, macht man sich ziemlich schnell Gedanken darüber, wie man das ganze einfach, schnell und nachvollziehbar etabliert.
Ich begann in einem früheren Post bereits über meine Erfahrungen zu schreiben und möchte hiermit fortfahren.

Diesmal geht es um die Grundinstallation des icinga2-Core mittels puppet.
Hilfreich sind dabei Grundkenntnisse in puppet, der Konfiguration und dem logischen Aufbau von hiera.
Des weiteren nutzen wir ein Ruby Feature namens deep_merge. Das müsste ggf. noch mittels gem install deep_merge / emerge dev-ruby/deep_merge installiert werden.
Ich gehe bewusst nicht auf die von mir genutzte hiera-Struktur ein, da jeder seinen eigenen Weg verfolgt.
So bald ich das ganze hier aber herunter geschrieben habe, werde ich eine lauffähige Konfiguration in meinem github Account packen. Versprochen! ;)

Zum installieren von icinga2 über puppet nutze ich das dazu passende github Repository.
Das kann man einfach als git submodule in sein eigenes puppet Repository einfügen und los gehts.

Um den Icinga2-Core betreiben zu können benötigen wir noch eine zusätzliche Datenbank für die IDO Funktionalität. Ich wähle hier der Einfachheit halber eine MySQL.

Zur Installation

Innerhalb von puppet nutze ich (auch eigene) puppet-Module, die über hiera konfiguriert werden.
Damit trenne ich strikt die Logik des puppet-Moduls und dessen Konfiguration, die in eine yaml-Datei ausgelagert wird.

Datenbank

Wir installieren im ersten Schritt ersteinmal eine MySQL Datenbank.
Da wir die Zugangsdaten auch später benötigen, verpacken wir diese in Variablen, die wir über hiera-Mitteln auslesen können.

# --------------------------------------------------------------------------
# == Variablen Definitions
icinga2::ido_db       : 'mysql'
icinga2::ido_type     : 'mysql'
icinga2::ido_db_host  : 'localhost'
icinga2::ido_db_port  : 3306
icinga2::ido_db_user  : 'icinga2'
icinga2::ido_db_pass  : 'password'
icinga2::ido_db_name  : 'icinga2_data'

icinga2::web_db       : 'mysql'
icinga2::web_type     : 'mysql'
icinga2::web_db_host  : 'localhost'
icinga2::web_db_port  : 3306
icinga2::web_db_user  : 'icinga2'
icinga2::web_db_pass  : 'password'
icinga2::web_db_name  : 'icinga2_auth'
icinga2::web_db_prefix: 'icingaweb_'

# --------------------------------------------------------------------------

# --------------------------------------------------------------------------
# = MySQL Server
mysql::server::remove_default_accounts: false
mysql::server::service_enabled: true
mysql::server::restart: true
mysql::server::purge_conf_dir: false
mysql::server::override_options:
  mysqld:
    bind-address: 127.0.0.1
    max_connections: 15
    long_query_time: 10
    query_cache_limit: '8M'
    join_buffer_size: '4M'
    tmp_table_size: '32M'
    max_heap_table_size: 32M'

# --------------------------------------------------------------------------
# = MySQL - Databases
mysql::databases:
  icinga2_data:
    ensure  : present
    user    : "%{hiera('icinga2::ido_db_user')}"
    password: "%{hiera('icinga2::ido_db_pass')}"
    host    : "%{hiera('icinga2::ido_db_host')}"
  icinga2_auth:
    ensure  : present
    user    : "%{hiera('icinga2::web_db_user')}"
    password: "%{hiera('icinga2::web_db_pass')}"
    host    : "%{hiera('icinga2::web_db_host')}"

ACHTUNG: Die MySQL hätte keinerlei Passwortschutz!

In unserem puppet-Module fügen wir anschließend folgende Zeilen ein, um den MySQL-Datenbank Service zu installieren und die beiden Datenbank-Schemas zu erzeugen:

include mysql::server
include mysql::client

$databases = hiera_hash('mysql::databases', undef)
if( $databases ) { create_resources( mysql::db, $databases ) }

$backup = hiera_hash('mysql::server::backup', undef )
if( $backup ) { include mysql::server::backup }

Das include mysql::client stellt sicher, dass die benötigten Client Tools ebenfalls mit installiert werden. Zusätzlich habe ich hier bereits ein Backup der Datenbanken eingeplant.

Icinga2 Core

Die Installation des Icinga2-Cores hat sich drastisch vereinfacht und die ursprünglich beschriebene Vorgehensweise ist mittlerweile auch als depricated gekennzeichnet worden.
Daher hier ein Update:

# --------------------------------------------------------------------------
# == install icinga2-Core and manage there databases
icinga2::manage_database: true
icinga2::db_type: "%{hiera('icinga2::ido_db')}"
icinga2::db_name: "%{hiera('icinga2::ido_db_name')}"
icinga2::db_pass: "%{hiera('icinga2::ido_db_pass')}"
icinga2::db_user: "%{hiera('icinga2::ido_db_user')}"
icinga2::db_schema: /usr/share/icinga2-ido-mysql/schema/mysql.sql

In unserem puppet-Modul könnte ein simples include icinga2 bereits ausreichen, doch das ist etwas zu kurz gedacht.
Puppet stellt zwar sicher, dass das gewünschte Ergebniss zustande kommt, der Weg dahin ist allerdings eher zufällig gewählt.
Es kann also vorkommen, dass Puppet erst den Icinga2-Core installieren und konfigurieren will, bevor die benötigten Datenbanken erzeugt wurden.
Daher müssen wir hier etwas mehr mit der Puppet Magie arbeiten:

class { 'icinga2':
  require => [
    Class['mysql::server'],
    Class['mysql::client'],
    Mysql::Db[ hiera('icinga2::ido_db_name') ]
  ]
}

Mit Hilfe von require stellen wir sicher, dass die Klassen für den MySQL Server und die Client Tools vor icinga2 aufgerufen werden.

Das wars dann auch schon mit der Grundinstallation!

Icinga2 Features

Icinga2 bietet einiges an Features, die man gerne mitnehmen möchte, die muss man allerdings auch gezielt aktivieren.
Mit der obigen Grundinstallation werden schon die Basisfeatures (checker, notification mainlog) aktiviert.
Wir aktivieren für uns noch 2 weitere:

  • command und
  • syslog
# == add some icinga2-Core Features
icinga2::features:
  command:
    manage_file: true
  syslog:
    manage_file: true

Hier reicht dann ein einfaches include nicht mehr aus, hier müssen wir innerhalb von puppet dynamisch eine Resource erzeugen.
Wir erweitern also unser puppet-Modul um folgende Zeilen:

$icinga2_feature = hiera_hash( icinga2::features, undef )
if( $icinga2_feature ) { create_resources( icinga2::feature, $icinga2_feature ) }

Icinga2 LiveStatus

Der LiveStatus ermöglicht es, alte von Nagios bekannte, Kommandos auch an Icinga2 zu schicken.
LiveStatus ist seit der Veröffentlichung von v2.4.0 von Icinga2 für mich veraltet, da seit dem eine API zur Verfügung steht, die deutlich mehr kann und auch deutlich lesbarer ist.
Ich werde das einrichten des LiveStatus hier aber trotzdem noch kurz anreissen.

Die hiera Komponente ist wieder relativ kurz:

# == add LiveStatus Listener for Icinga2-Core
icinga2::object::livestatuslistener:
  socket:
      socket_type: 'unix'
      socket_path: '/var/run/icinga2/cmd/livestatus'
  network:
      socket_type: 'tcp'
      bind_host  : '0.0.0.0'
      bind_port  : '8080'

Hier erzeugen wir 2 verschiedene Wege um mit der LiveStatus Komponente kommunizieren zu können. Einmal als Socket, die zweite Variante über eine TCP Verbindung.
Der LiveStatus wird in unserem puppet-Modul dann folgendermaßen integriert:

$icinga_listener = hiera_hash( 'icinga2::object::livestatuslistener', undef )
if( $icinga_listener ) { create_resources( icinga2::object::livestatuslistener, $icinga_listener ) }

Damit sollte bereits alles erledigt sein und der icinga2 Service sollte laufen.

Es ist durchaus sinnvoll sich die Logfiles unter /var/log/icinga2 anzusehen!

Beide Codeteile befinden sich auch in meinem GitHub Account.

Im nächsten Teil geht das weiter mit dem einrichten von Host- und Servicechecks.