Puppet: Ueberwachen von puppet agent und puppet master mit Nagios

puppet agent

Man kann mit Nagios gut pruefen ob der puppet agent sich regelmaessig mit dem puppet master abgeglichen hat. Das Plugin dafuer ist check_puppet_agent und ist auf NagiosExchange zu finden.

Eingebunden zum Beispiel per NSCA gibt es einem eine Warnung sobald etwas nicht mehr laeuft.

Bildschirmfoto vom 2014-04-26 14:15:13

puppet master

Auch kann man von extern pruefen ob der puppet master erreichbar ist. Das geht am besten ueber HTTP mit der REST API. Auf dem Nagios Server habe ich dafuer das folgende Kommando definiert:

define command{
command_name    check_puppetmaster
command_line    $USER1$/check_http -H $ARG1$ -S -p 8140 -u /production/status/puppetclient --header="Accept: yaml"
}

Den Check habe ich wie folgt eingerichtet:

define service{
use                             my-service
host_name                       server.example.org
service_description             puppet master
check_command                   check_puppetmaster!puppetmaster.example.org
}

Zu guter Letzt muss dem Nagios Server gestattet werden die Abfrage ueber die REST API auch durchzufuehren. Dafuer auf dem puppet master Server in der /etc/puppet/auth.conf die folgenden Zeilen hinzufuegen:

path /status/puppetclient
auth any
method find
allow 1.2.3.4

Und schon steht auch dem Monitoring des puppet masters nichts mehr im Wege:

Bildschirmfoto vom 2014-04-26 14:40:58

Puppet: Syntaxpruefung mit puppet-lint

Mit dem Tool puppet-lint kann man die Syntax seiner puppet manifest Dateien pruefen. Die Installation erfolgt aus den Repositories:

sudo aptitude install puppet-lint

Die Syntaxpruefung geht dann mit dem Aufruf:

puppet-lint --with-filename /etc/puppet/modules

Falls es Auffaelligkeiten gibt werden diese auf der Kommandozeile ausgegeben:

root@host:~# puppet-lint --with-filename /etc/puppet/modules/
foo/manifests/init.pp - WARNING: line has more than 80 characters on line 5
foo/manifests/init.pp - ERROR: tab character found on line 34
foo/manifests/init.pp - WARNING: => on line isn't properly aligned for resource on line 23
root@host:~#

Puppet: Das erste eigene Modul mit einer MOTD

Nachdem die puppet Infrastruktur steht moechte ich nun auf alle Server eine eigene, individuelle MOTD nach dem Ubuntu Vorbild verteilen. Damit alles funktioniert muessen verschiedene Bedingungen erfuellt sein:

  1. Auf allen Systemen muss /etc/motd ein Symlink nach /var/run/motd sein
  2. Auf allen Systemen muss das Verzeichnis /etc/update-motd.d/ existieren
  3. Auf allen Systemen muessen die Skripte von Nick Charlton im /etc/update-motd.d/ Verzeichnis existieren
  4. Auf allen Systemen muss das Paket ‚figlet‘ installiert sein.

Die perfekte Ausgangslage um ein eigenes Modul fuer puppet zu schreiben, dass automatisch alle Bedingungen sicherstellt. #

Ich habe unter /etc/puppet/modules/ die folgende Verzeichnisstruktur erzeugt:

└── motd
    ├── files
    │   └── etc
    │       └── update-motd.d
    │           ├── 00-header
    │           ├── 10-sysinfo
    │           └── 99-footer
    └── manifests
        └── init.pp

Die Skripte im Unterverzeichnis files habe ich von der Seite Debian/Ubuntu: Dynamic MOTD. Im Verzeichnis manifests ist eine init.pp abgelegt. Diese hat den folgenden Inhalt:

class motd {
 
  package { 'figlet':
    ensure => 'installed'
  }
 
 
 
  file { '/etc/motd':
    ensure => 'link',
    target => '/var/run/motd',
  }
 
 
 
  file { '/etc/update-motd.d/':
    ensure => 'directory',
    owner  => 'root',
    group  => 'root',
    mode   => '0755'
  }
 
 
 
  file { '/etc/update-motd.d/00-header':
    ensure => 'present',
    source => 'puppet:///modules/motd/etc/update-motd.d/00-header',
    owner  => 'root',
    group  => 'root',
    mode   => '0755'
  }
 
  file { '/etc/update-motd.d/10-sysinfo':
    ensure => 'present',
    source => 'puppet:///modules/motd/etc/update-motd.d/10-sysinfo',
    owner  => 'root',
    group  => 'root',
    mode   => '0755'
  }
 
  file { '/etc/update-motd.d/99-footer':
    ensure => 'present',
    source => 'puppet:///modules/motd/etc/update-motd.d/99-footer',
    owner  => 'root',
    group  => 'root',
    mode   => '0755'
  }
}

Ich denke sie ist relativ selbsterklaerend. Als erstes wird sichergestellt, dass das Paket figlet installiert ist. Danach wird der symbolische Link erzeugt falls er nicht existiert. Als drittes validiert, dass das Verzeichnis /etc/update-motd.d/ existiert und danach die Skripte an die richtige Stelle kopiert.

Damit dieses Modul auch an alle puppet nodes verteilt wird, habe ich einen default node definiert. Dieser greift immer dann, wenn ein node nicht explizit aufgelistet wurde. Dafuer wurde die Datei /etc/puppet/manifests/site.pp mit dem folgenden Inhalt angelegt:

node default {
  class { 'motd': }
}

Nach dem manuellen Aufruf des puppet agents auf dem node wird die Konfiguration uebernommen:

user@host:~# puppet agent --server puppetmaster.example.org --test
info: Caching catalog for host.example.org
info: Applying configuration version '1398539626'
info: FileBucket adding {md5}d41d8cd98f00b204e9800998ecf8427e
info: /Stage[main]/Motd/File[/etc/motd]: Filebucketed /etc/motd to puppet with sum d41d8cd98f00b204e9800998ecf8427e
notice: /Stage[main]/Motd/File[/etc/motd]/ensure: ensure changed 'file' to 'link'
notice: /Stage[main]/Motd/File[/etc/update-motd.d/]/ensure: created
notice: /Stage[main]/Motd/File[/etc/update-motd.d/10-sysinfo]/ensure: defined content as '{md5}684e660175b367c21bbf0bf5b4cb2475'
notice: /Stage[main]/Motd/File[/etc/update-motd.d/00-header]/ensure: defined content as '{md5}13ab41fc9d68d2e2b05c31185aecfab5'
notice: /Stage[main]/Motd/File[/etc/update-motd.d/99-footer]/ensure: defined content as '{md5}8609d989ae2538fbb15f9055c995d050'
notice: Finished catalog run in 1.16 seconds
user@host:~#

Anschliessend ist die MOTD zu sehen wenn ich mich mit dem Server verbinde:

Bildschirmfoto vom 2014-04-26 21:17:22

Puppet: Aufsetzen der Infrastruktur

Durch die Arbeit inspiriert, habe ich nun auch fuer mich Privat einen puppet Server zur Verwaltung meiner virtuellen Maschinen aufgesetzt.

Wikipedia schreibt zu puppet:

Puppet ist ein Tool zum Konfigurationsmanagement von Computern mit Betriebssystemen 
wie Unix, Linux und FreeBSD. Ein IT-Administrator kann damit an zentraler Stelle 
die Konfiguration von Rechnern in seinem Netzwerk verwalten. Puppet eignet sich 
sowohl für einzelne Rechner als auch für große Rechnerverbünde

Als erstes wurde die generelle Infrastruktur aufsetzen. Das bedeutet fuer mich:

  1. Einen puppet master Server zu haben
  2. Auf den Clients einen puppet agent laufen zu haben der mit dem Master verbunden ist.

Alles hier beschriebene passiert auf der Basis von Debian wheezy. Auf dem Server der als puppet master dienen soll habe ich zuerst das entsprechende Paket mit seinen Abhaengigkeiten installiert:

sudo aptitude install puppetmaster

Anschliessend habe ich in der /etc/default/puppetmaster den Parameter START=yes gesetzt. Wichtig ist nun noch sicherzustellen, dass der Port 8140 von den Clients aus erreichbar ist.

Danach habe ich auf den Clients den puppet agent installiert:

sudo aptitude install puppet

Auch hier habe ich in der /etc/default/puppet wieder den Parameter START=yes gesetzt. Weiter habe ich in den DAEMON_OPTS den Parameter zu dem Server angegeben. Beispiel:

--server puppetmaster.example.org

Dann habe ich probiert mich mit dem puppet agent an den puppet master Server zu verbinden:

puppet agent --server puppetmaster.example.org --test

Auf dem puppet master konnte ich danach das unsignierte Zertifikat des Clients mit dem folgenden Befehl sehen:

puppet cert list

Danach musste es mit dem folgenden Befehl signiert werden, wobei puppetclient.example.org der FQHN des puppet clients ist:

puppet cert sign puppetclient.example.org

Alle signierten Zertifikate kann man sich uebrigens mit dem folgenden Befehl anzeigen lassen:

puppet cert list --all

Danach konnte ich den puppet agent auf dem Client erneut laufen lassen und die Verbindung war erfolgreich. Zum Ende das neu starten des puppet agents auf den Clients nicht vergessen, damit der Prozess mit den neuen DAEMON_OPTS laeuft.

Notizen:

  • Wenn es zu einer „Connection refused“ Fehlermeldung wie unten gezeigt kommt, sicherstellen, dass der Port erreichbar ist. Eventuell auch erst einmal ausprobieren mit der IP Adresse auf dem Port zu verbinden (telnet IP PORT)
    root@host:~# puppet agent --test --server puppetmaster.example.org
    err: Could not retrieve catalog from remote server: Connection refused - connect(2)
    warning: Not using cache on failed catalog
    err: Could not retrieve catalog; skipping run
    err: Could not send report: Connection refused - connect(2)
    root@host:~#
    
  • Wenn es zu einer „Server hostname did not match server certificate“ Fehlermeldung kommt, dann kann es helfen fuer den Server einen entsprechenden Eintrag in die /etc/hosts zu packen
    root@host:~# puppet agent --test --server 192.168.1.100
    err: Could not retrieve catalog from remote server: Server hostname '192.168.1.100' did not match server certificate; expected one of puppetmaster.example.org, DNS:puppet, DNS:puppet.example.org, DNS:puppetmaster.example.org
    warning: Not using cache on failed catalog
    err: Could not retrieve catalog; skipping run
    err: Could not send report: Server hostname '192.168.1.100' did not match server certificate; expected one of puppetmaster.example.org, DNS:puppet, DNS:puppet.example.org, DNS:puppetmaster.example.org
    root@host:~#