Ein Buch über Icinga 2

Erscheint am 27. Juni 2016

 
41suqaLOyCL._SX336_BO1,204,203,200_April 2015, nach Monaten des Schwankens machten sich dann zwei verbliebene Möchtegernautoren doch auf ein Buch zum Thema Icinga 2 zu verfassen. Wir wollten ein sehr praxisnahes Werk mit vielen Beispielen wie und mit welchen Plugins etwas zu überwachen ist. Herausgekommen sind 344 Seiten von denen sich 100 mit Plugins und deren Verwendung in Icinga 2 befassen. Vorweg erfolgt eine generelle Einführung, die Vorstellung des neuen Webinterfaces Icingaweb 2 als auch eine ausführliche Erläuterung wie man lokale Werte wie Load bzw. CPU bei Windows oder Disk Usage mit NRPE/NSClient++, SSH und selbstverständlich mit dem neuen Icinga Agenten ermittelt.
Dem Kapitel über Plugins ist noch die Vorstellung einer fiktiven Firma vorangestellt. Diese betreibt ein zweigeteiltes Netzwerk mit einem internen Netz und eine durch Perimeter abgetrennte DMZ. Anhand dieses Beispiels wird eine verteilte Überwachung implementiert. Im internen Netz ist ein Icinga-Server (Master) für die Überwachung der dortig angesiedelten Server und Dienste zuständig. Für die DMZ wird ein weiterer Icinga-Server (Satellit) verwendet, der die ermittelten Ergebnisse an den Master meldet.
Diese Icinga-2-Infrastruktur wird dann im Folgenden benutzt, um eine Vielzahl von Diensten zu überwachen:

  • Host Erreichbarkeit
  • Zeitserver und lokale Zeit
  • Webservices incl. Apache und Ngnix
  • Domain Name Services
  • DHCP
  • Kerberos
  • Mailempfang und -versand
  • Proxy-Server
  • Generische Portüberwachung am Beispiel von Jabber
  • Javabasierte Application-Server
  • SAP
  • Kibana
  • Microsoft-Infrastrukturdienste: CIFS, Terminalservice, Domaincontroller, Exchange
  • Datenbanken: MySQL, PostgreSQL, MS SQL, Oracle
  • LDAP
  • Redis
  • Elasticsearch
  • VMware vSphere
  • Hardware: IPMI, HP, Oracle Solais, Thomas Krenn, Netzwerk, Festplatten
  • NetApp
  • Qnap

Das letzte Drittel ist Graphing mit PNP4Nagios und Graphite, Logmangement, Reporting und Businessprozessen gewidmet.
Teilbereiche werden von den beiden Autoren in einem Workshop vor der diesjährigen Open Source Monitoring Conference mit den Teilnehmern zusammen praktisch umgesetzt.

Lennart Betz
Lennart Betz
Senior Consultant

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.

Weekly Snap: Galera & Icinga 2 Clusters, Puppet for Tomcat & Nagios

weekly snap11 – 15 August featured clusters, Puppet automation and a new OSMC workshop.
Eva counted 106 days to the OSMC with Bernd and Sasha’s talk on how “Puppet automatically configures Nagios”.
Bernd followed by announcing a new Advanced Windows Monitoring workshop on NSClient++ to be held by Michael Medin at this year’s OSMC.
On clusters, Enrico looked at Galera as Michael gave an update on his work with Icinga 2 cluster vagrant boxes and the various Icinga 2 webinars and training courses.
Finally, Lennart shared his Puppet module for Tomcat installation and configuration.

Einmal bitte Tomcat oder zweimal oder dreimal…

tomcatHeute möchte ich euch ein Puppet-Modul zur Installation und Konfiguration von Tomcat vorstellen. Es verwaltet entweder einen Standalone Tomcat-Server oder aber eine Vielzahl von Server-Instanzen, z.Z. jedoch lediglich auf Red Hat Systemen. Mit einem

# puppet module install lbetz/tomcat

installieren wir das Module auf unserem Puppet-Server, respektive auf unserem Test-System. Mit folgendem Puppet Code wird aus den konfigurierten Repositories eine Tomcat 6 installiert und für den Multi-Instanz-Betrieb konfiguriert.

class { 'tomcat':
   version => '6',
}

Die einzelnen Instanzen bzw. deren Konfiguration sind standardmäßig unter /var/tomcat zu finden. Der Übersichtlichkeit in diesem Blog geschuldet, definieren wir uns einige Variablen, zuerst für die von uns verwendeten Connectors, Listeners und Resources.

$connectors = {
   'http' => {
      port => '8080',
      protocol => 'HTTP/1.1',
   },
   'ajp' => {
      port => '8009',
      protocol => 'AJP/1.3',
   },
}
$listeners = {
   'org.apache.catalina.core.AprLifecycleListener' => { 'ssl_engine' => 'On', },
   'org.apache.catalina.core.JasperListener' => {},
   'org.apache.catalina.core.JreMemoryLeakPreventionListener' => {},
   'org.apache.catalina.mbeans.GlobalResourcesLifecycleListener' => {},
}
$resources = {
  'UserDatabase' => {
     'auth' => 'Container',
     'type'        => 'org.apache.catalina.UserDatabase',
     'extra_attrs' => {
        'description' => 'User database that can be updated and saved',
        'factory'     => 'org.apache.catalina.users.MemoryUserDatabaseFactory',
         'pathname'    => 'conf/tomcat-users.xml',
      },
   },
}

Als nächstes definieren wir uns ein Hostobjekt localhost und mit diesem als Default Host eine Engine der Bezeichnung Catalina.

$hosts = {
   'localhost' => {
      'app_base'            => 'webapps',
      'unpack_wars'         => true,
      'auto_deploy'         => true,
      'xml_validation'      => false,
      'xml_namespace_aware' => false,
   },
}
$engine = {
   'Catalina' => {
      'default_host' => 'localhost',
      'realms'       => {
         'org.apache.catalina.realm.LockOutRealm' => {
         'realms' => {
            'org.apache.catalina.realm.UserDatabaseRealm' => {
               'attrs' => {
                  'resource_name' => 'UserDatabase',
               },
            },
         },
      },
      hosts = $hosts,
   },
}

Die eigentlich Instanz mayapp1 lässt sich nun wie folgt deklarieren:

tomcat::server { 'myapp1':
   ensure   => 'running',
   enable   => false,
   port     => '8005',
   services => {
      'Catalina' => {
         'connectors' => $connectors,
         'engine'     => $engine,
      },
   },
   resources => $resources,
   listeners => $listeners,
}

Mit dem zusätzlichen Parameter java_home ließe sich auch eine alternative Java Engine wählen.
Möchte man nun einen weiteren Host der Engine hinzufügen, kann natürlich der Hash $hosts entsprechend erweitert werden oder wie hier nachträglich deklarieren:

tomcat::host { 'myapp1:Catalina:Catalina:shop.netways.de':
  $app_base            => 'webapps',
  $auto_deploy         => true,
  $unpack_wars         => true,
  $xml_validation      => false,
  $xml_namespace_aware => false,
}

Über den Resource-Titel wird hier der XML-Pfad in der server.xml angegeben. Damit wird in diesem Beispiel der Host shop.netways.de der Instanz myapp1 zugeordnet und dort wiederum der Engine Catalina, die zum Service Catalina gehört. Äquivalent lassen sich auch andere Konfigurationsobjekte wie Services und Realms hinzufügen .
Für den Standalone-Betrieb, wenn man nicht mehrere Instanzen benötigt, reicht folgende Deklaration:

class { 'tomcat':
   version => '6',
   config  => {
      port     => '8005',
      services => {
         'Catalina' => {
            'connectors' => $connectors,
            'engine'     => $engine,
         },
      },
      resources => $resources,
      listeners => $listeners,
   }
}

War-Dateien können nun im Nachgang via File-Resource in die entsprechenden Ordner gelegt werden, danach ist dann nur noch ein notify auf den Tomcat-Service nötig. Im Standalone-Betrieb ist dieses z.Z. jedoch noch an Tomcat::Server[‘tomcat6’] bzw. Tomcat::Server[‘tomcat’] (Version 7) zu senden.

Lennart Betz
Lennart Betz
Senior Consultant

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.

Puppenschnur im XML-Baum verheddert

Wer sich schon mal mit Puppet und XML-Konfigurationsdateien beschäftigt hat, weiß das dies ein schwer umzusetzendes Vorhaben in Puppet ist. Es gibt zwar eine Linse für Augeas, wer aber eine komplette XML-Datei mit Puppet verwalten möchte, wird damit schnell wahnsinnig.
Ich hatte vor einigen Wochen das Glück, mich bei einem Kunden, näher mit der Konfiguration vom Tomcat beschäftigen zu dürfen. Dabei stand ich vor dem Problem, z.B. folgende Struktur als server.xml mit Puppet erzeugen zu müssen.

<Server>
  <Service name=Catalina>
    <Engine name=Catalina>
      <Host name=...>
        ...
      </Host>
      <Host name=...>
        ...
      </Host>
    </Engine>
  </Service>
</Server>

Wobei in den Host-Sektionen natürlich auch nochmals Schachtelungen vorkommen. Mein erster Lösungsansatz war, mit XML Referenzen auf eigenständige Dateien zu verweisen, die damit eingebunden werden. Dies führt nun aber zu einem recht unübersichtlichen Datei-Tohuwabohu.
Die jetzige Lösung macht sich die Eigenschaften des Puppet concat-Moduls zu nutze. Die einzelnen Fragmente werden auf dem Puppet-Agent jeweils als separate Datei in ein temporäres Verzeichnis geschrieben, z.B. nach /var/lib/puppet/concat/_etc_tomcat_server.xml/fragments. Das Attribut order von concat::fragment dient hierbei als Prefix für den Dateiname des entsprechenden Fragments. Sind alle Fragmente geschrieben, liest ein Skript alle Dateien mittels find, sortiert lexikalisch nach Dateinamen und fügt die Fragmente abschließend mittels cat in die Zieldatei zusammen, hier /etc/tomcat/server.xml.
Schaut man sich dieses find näher an, stellt man fest, dass es nicht tiefenbeschränkt ist, d.h. es durchsucht auch weitere Unterverzeichnisse. Diese können vorab mit einer files-Resource angelegt werden und im order-Attribut mit angegeben werden.

concat { '/etc/tomcat/server.xml':
  mode => '0644',
} ->
file { '/var/lib/puppet/concat/_etc_tomcat_server.xml/50_host_A':
  ensure => directory,
}
concat::fragment { 'engine-header':
  target => '/etc/tomcat/server.xml',
  content => "\n",
  order => '40',
}
concat::fragment { 'engine-footer':
  target => '/etc/tomcat/server.xml',
  content => "\n",
  order => '60',
}
concat::fragment { 'host_A-header':
  target => '/etc/tomcat/server.xml',
  content => "\n",
  order => '50_host_A/00',
  require => File['/var/lib/puppet/concat/_etc_tomcat_server.xml/50_host_A'],
}
concat::fragment { 'host_A-footer':
  target => '/etc/tomcat/server.xml',
  content => "\n",
  order => '50_host_A/99',
  require => File['/var/lib/puppet/concat/_etc_tomcat_server.xml/50_host_A'],
}

Analog für weitere Hosts. Zusätzliche Fragmente für Host A lassen sich nun zwischen dem Header und Footer einordnen. Dies soll erstmal nur die Idee vergegenwärtigen. Ein komplexeres Anwendungsbeispiel findet sich unter https://github.com/lbetz/netways-tomcat.
Auch ist zu bedenken, das auf unterschiedlichen Hosts das temporärere concat-Verzeichnis nicht immer am selben Ort zu finden ist. Hier schaft ein selbstgeschriebener Fact Abhilfe.

# vardir.rb
Facter.add(:vardir) do
  setcode do
    Puppet[:vardir]
  end
end
Lennart Betz
Lennart Betz
Senior Consultant

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.