24 März 2015

[Howto] PuppetDB Installation

Kategorien: HowTos
Tags: Puppet

Dieser Blog Eintrag ist ein Tutorial, um die Benutzung von PuppetDB aufzuzeigen und ein paar Beispiele für die Benutzung zu geben.

Was ist PuppetDB

PuppetDB ist ein Backend für Puppet, um verschiedene Informationen aus dem Puppetmaster heraus zu speichern und wieder verfügbar zu machen. Sie ist der Nachfolger der ActiveRecord basierten Storeconfigs.

PuppetDB kann Fakten, Reports, Events und andere Informationen sammeln. Auf diese Daten kann dann über eine REST ähnliche Schnittstelle zugegriffen werden. Zusätzlich gibt es ein Puppetmodul mit dem andere Module auf diese Daten zugreifen zu können. Da PuppetDB weitestgehend mit dem alten „storeconfig“ Mechanismus kompatibel ist, kann Puppet genutzt werden um Ressourcen zu exportieren und anderen Knoten verfügbar zu machen. So können beispielsweise alle bekannten Hostschlüssel von den Knoten gesammelt und in /etc/ssh/ssh_known_hosts gespeichert werden.

Die Installation

Installation der Pakete

Bei der Installation gehen wir davon aus das der Puppetmaster und die PuppetDB auf dem selben Host installiert werden sollen. Zur PuppetDB Installation wird das Puppetlabs APT Repository benötigt. Dieses lässt sich ganz einfach in das System einbinden:

# wget https://apt.puppetlabs.com/puppetlabs-release-<RELEASE>.deb
# sudo dpkg -i puppetlabs-release-<RELEASE>.deb
# sudo apt-get update

<RELEASE> ist hierbei durch den Releasenamen der verwendeten Distribution zu ersetzen. Im Falle von Debian 7 wäre dies puppetlabs-release-wheezy.deb. Eine Liste der verfügbaren Releases kann man unter https://apt.puppetlabs.com einsehen.

Anschliessend kann das puppetdb Paket installiert werden:

# sudo puppet resource package puppetdb ensure=latest
# sudo puppet resource service puppetdb ensure=running enable=true

Anschliessend ist das PuppetDB Paket in der letzten Version installiert und aktiviert. In der Standardkonfiguration ist PuppetDB so konfiguriert das sie auf localhost:8080 unverschlüsselt und auf *:8081 mit SSL lauscht.

Im nächsten Schritt installieren wir den Puppetsupport für PuppetDB:

# sudo puppet resource package puppetdb-terminus ensure=latest

Danach sind alle Komponenten installiert, die Puppet benötigt um mit der PuppetDB zu kommunizieren.

Einbindung in Puppet

Damit Puppet weiss wo er die PuppetDB findet müssen wir die Datei /etc/puppet/puppetdb.conf anlegen:

[main]
server = <fqdn des puppetdb servers>
port = 8081

Es ist wichtig in der Konfigurationsdatei den Hostnamen des PuppetDB Servers zu verwenden. Das Puppetmodul prüft hier den Namen des Zertifikats und wenn dies nicht mit dem Servernamen in der puppetdb.conf zusammenpasst wird ein Fehler generiert.

Damit der Puppetmaster die Daten auch Richtung PuppetDB schickt müssen wir in der Datei /etc/puppet/puppet.conf folgende Zeilen in der [master] Sektion ergänzen:

[master]
storeconfigs = true
storeconfigs_backend = puppetdb

Wenn man die Reports auch in der PuppetDB speichern möchte, muss die puppet.conf zusätzlich um folgendes ergänzt werden:

[master]
reports = store,puppetdb

Damit die Informationen in der PuppetDB auch innerhalb von Puppet verwendet werden können, muss noch eine letzte Datei angelegt werden. /etc/puppet/routes.yaml:

---
master:
  facts:
    terminus: puppetdb
    cache: yaml

Damit zieht Puppet für Fakten die PuppetDB als Quelle heran. Die Fakten werden in yaml Dateien zwischengespeichert um die Datenbank zu entlasten.

Wenn alles funktioniert hat sollte ein puppet agent -t ohne Fehlermeldungen durchlaufen:

# puppet agent -t
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for foreman.novalocal
Info: Applying configuration version '1427207789'
Notice: Finished catalog run in 0.23 seconds

In der Logdatei der PuppetDB sollte daraufhin Meldungen erscheinen das die Informationen eingeliefert und gespeichert wurden:

tail -n 3 /var/log/puppetdb/puppetdb.log
2015-03-24 16:45:48,145 INFO  [c.p.p.command] [2af3b94d-7ec6-49e0-802d-3dec939dd5ab] [replace facts] foreman.novalocal
2015-03-24 16:45:48,958 INFO  [c.p.p.command] [25546f85-25b4-43b8-91f0-98d386a7d36f] [replace catalog] foreman.novalocal
2015-03-24 16:45:50,079 INFO  [c.p.p.command] [b223b4db-a3d9-4ab5-b50e-0f31f92ac4b8] [store report] puppet v3.7.4 - foreman.novalocal

Die Benutzung

Zugriff via curl

Nachfolgend wird anhand von ein paar Beispielen der Zugriff auf die HTTP API mittels curl gezeigt. Die Antworten werden von PuppetDB im JSON Format zurückgeliefert. Die vollständige Dokumentation der API findet man unter https://docs.puppetlabs.com/puppetdb/2.3/api/index.html.

Die API unterstüzt verschiedene Endpunkte um auf Informationen in der PuppetDB zuzugreifen.

Wenn man sich alle aktiven Knoten anzeigen lassen möchte kann man folgendes Query verwenden:

curl -X GET http://localhost:8080/v3/nodes  --data-urlencode 'query=["=", ["node", "active"], true]'

PuppetDB liefert daraufhin JSON formatiert eine Liste aller Knoten zurück (gekürzt):

[ {
  "name" : "foreman.novalocal",
  "deactivated" : null,
  "catalog_timestamp" : "2015-03-24T16:45:48.918Z",
  "facts_timestamp" : "2015-03-24T16:45:48.022Z",
  "report_timestamp" : "2015-03-24T16:45:48.462Z"
}...]

Der Parameter query weist PuppetDB an unsere Daten anhand des querys zu filtern. Die Dokumentation zu den Filtern findet man in in der PuppetDB Dokumentation.

Eine Liste aller verwendeten Betriebssysteme kann man mit dem Facts Endpunkt abfragen:

# curl -X GET http://localhost:8080/v3/facts --data-urlencode 'query=["=", "name", "operatingsystem"]'

Auch hier kommt wieder ein JSON formatiertes Objekt zurück:

[ {
  "value" : "Debian",
  "name" : "operatingsystem",
  "certname" : "foreman.novalocal"
} ]

Das Ganze lässt sich auch kürzer schreiben:

curl -X GET http://localhost:8080/v3/facts/operatingsystem

Oder wenn ich das ganze auf Debian Systeme einschränken möchte:

curl -X GET http://localhost:8080/v3/facts/operatingsystem/Debian

Der Reports Endpunkt liefert die letzten Reports. Dieser beinhaltet allerdings nicht die eigentlichen Informationen sondern nur die Metadaten zum Report:

curl -X GET http://localhost:8080/v3/reports
 
[ {
  "hash" : "050d4697b9aff4ae48e1b0c1e5102487a7f8db8d",
  "puppet-version" : "3.7.4",
  "receive-time" : "2015-03-24T13:15:38.866Z",
  "report-format" : 4,
  "start-time" : "2015-03-24T13:15:33.083Z",
  "end-time" : "2015-03-24T13:15:34.705Z",
  "transaction-uuid" : "ee73330d-e031-450d-8f4e-cde317ca22c7",
  "configuration-version" : "1427199788",
  "certname" : "foreman.novalocal"
} ... ]

Wenn man herausfinden möchte was sich während eines Puppetdurchlaufes geändert hat, dann können wir dazu den Hash des Reports nehmen. Der Events Endpunkt kann nun alle Events liefern die zu einem bestimmten Report gehören:

curl -X GET http://localhost:8080/v3/events --data-urlencode 'query=["=", "report", "050d4697b9aff4ae48e1b0c1e5102487a7f8db8d"]'
[ {
  "containment-path" : [ "Stage[main]", "Ntp::Config", "File[/etc/ntp.conf]" ],
  "new-value" : "{md5}96de9ac4d747c521ce12a111ff24fb66",
  "containing-class" : "Ntp::Config",
  "report-receive-time" : "2015-03-24T13:15:38.866Z",
  "report" : "050d4697b9aff4ae48e1b0c1e5102487a7f8db8d",
  "resource-title" : "/etc/ntp.conf",
  "property" : "content",
  "file" : "/etc/puppet/modules/ntp/manifests/config.pp",
  "old-value" : "{md5}27060798ca930cc9fa4c6a7a9d798f75",
  "run-start-time" : "2015-03-24T13:15:33.083Z",
  "line" : 20,
  "status" : "success",
  "run-end-time" : "2015-03-24T13:15:34.705Z",
  "resource-type" : "File",
  "timestamp" : "2015-03-24T13:15:36.045Z",
  "configuration-version" : "1427199788",
  "certname" : "foreman.novalocal",
  "message" : "content changed '{md5}27060798ca930cc9fa4c6a7a9d798f75' to '{md5}96de9ac4d747c521ce12a111ff24fb66'"
} ]

In diesem Beispiel wurde z.B. die ntp.conf vom NTP Modul editiert.

Die Benutzung in Puppet

Kommen wir auf das Beispiel mit den SSH-Hostkeys zurück: Hierzu kann ein Mechanismus namens „Exported Resources verwendet werden. Dabei wird jeder Knoten angewiesen bestimmte Informationen als Objekt in der PuppetDB zu speichern. Diese Objekte können dann benutzt werden um z.B. eine Konfigurationsdatei zu realisieren. Genaue Informationen dazu finden sich unter https://docs.puppetlabs.com/guides/exported_resources.html

class ssh {
  # Deklaration:
  @@sshkey { $hostname:
    type => dsa,
    key => $sshdsakey,
  }
  # Collect:
  Sshkey <<| |>>
}
 
include 'ssh'

Hier verwenden wir die sshkey Ressource um die SSH Hostkeys aller Clients in der PuppetDB zu speichern. Der Aufruf von Sshkey <<| |>> „realisiert“ diese SSH Hostkeys dann auf dem Clientsystem.

cat /etc/ssh/ssh_known_hosts 
# HEADER: This file was autogenerated at 2015-03-24 14:41:24 +0000
# HEADER: by puppet.  While it can still be managed manually, it
# HEADER: is definitely not recommended.
foreman ssh-dss AAAAB3NzaC1kc3MAAACBAPU8MHiLvP44gGW4KnUHZ0ikEV/OteJVPCmpi6+odRiWXmzFEcWZrIDPAeusb+9JnPsYUgrDKe5ZxIRWVkZPCFV+A5DwJbOzPLd2s3sngtUvPD8yDjx1fiqsBWaWV3TtRBdGOsgPnEHI8kTEF2rk3tzSQOAmfRdTEIRbSjyJIx93AAAAFQDW1m3d6uedEpk7jqfl/Q8VKaL5wQAAAIB9z4Kg7SgJGEfoMz42rCT6nsfz3CIk5MPlkNQaGKz2nxI6BvxhrqOHpYNuIrZqy75Z/PaStRfztr+Ks7VAD7yUxB0++Rm1iXfh/laapk/sa9L5V53g6notB5ux3aBzUYzfIckiJlifGUkxodpTlOdHKFfvRdStvGNzUfaoV1tJYQAAAIEAoBsiK8y65Mp7XJRria6lXDGhB326r+DVZsohBYI4O72Gfx71loBwCye/6pvezy+96B838qpJaYvHUk+x3/8NH8pvaRnb/qrWlg1WEbQQ9LBD03ea/hSEIpGySnOZs8zbgV/gUWFy939p4G6SxUiUSKQHcqm/POMTyneQvXX0+pE=
puppetclient ssh-dss AAAAB3NzaC1kc3MAAACBAN14x/OOcU5uLng13pszxQLwyuEcN9rsAaBKEh33t4/BrrBWIiM7XUQ86tToH4LeJwmQMXtZHEojXcsi1XD3N9qnluQ4u6K3zIdqrqQzJoFHnsLYDU4zF9FSeBw47m/0/4DL/BohczhJJ88W00Kfj6ItFP4mNCfEw7iMOLKY+gP5AAAAFQC7Wivw9jUjJ/9nMXCUVbh/ZeIIZwAAAIEAye4plFIRpcVnflmZQmDwCg6BNd5m5g1NkqI9Qz7HTbYzyJars9qzB3BZiVBpz0waX+KjUlcWfGDsDnNCl0RMOuhfTnzfW2JeBILoArEjaY0thkkeDUtgPD6XYM3/xKPusXf61AqapAfRU1HFrT3EMxYicfPLwUDFGmZoc7nDUxEAAACBALjkr8py08gfWaIhPrJXlh7FIs9RdP8mIW9p0QsgW7zRFKrXixnS77d6brabM9/TGcxcRtbvwk2LQM/px8YIfJhGMoW/SP5lc7tsWvrhLjcxTNnI4PcfCbMda2RrM53oUBjd7pRpIV6K1MIFmR6yMqj0FGMHTOIgH3sWTYL6JLQd

Weiterführendes

Um PuppetDB Queries in puppet auszuführen gibt es das puppetdbquery modul. Damit kann man auch komplexe Abfragen in Puppetmodulen ausführen und mit den zurückgelieferten Daten arbeiten.

Dies ermöglicht zum Beispiel Dinge wie:

$nodes = query_nodes('Class[Apache]')
$nodes.each { |$node|
  nagios_service {
    ...
  }
}

Das Modul enthält auch ein Hiera Backend, mit dem Daten aus der PuppetDB direkt in Hiera verwendet werden können:

ntp::servers::_nodequery: 'Class[Ntp::Server]'

In diesem Beispiel wird die ntp::servers Variable mit allen Hostnamen gefüllt, die die Klasse Ntp::Server verwenden. Sollte man also einen neuen NTP Server benötigen, so muss man ihm nur die entsprechende Klasse zuweisen und alle Nodes werden den neuen Server automatisch verwenden.

Tuning

In der Standardeinstellung verwendet PuppetDB eine integrierte Datenbank. In großen Umgebungen empfiehlt es sich eine externe PostgreSQL Datenbank einzusetzen. Nähere Informationen dazu findet man in der PuppetDB Dokumentation zur Datenbankeinrichtung

Kategorien: HowTos
Tags: Puppet


Beitrag teilen: