post

Multienvironment Puppet

Im Puppet-Umfeld passiert immer noch relativ viel. Standards ändern sich und werden mit deprecated markiert. Daher hier eine Zusammenfassung für eine aktuelle Puppet-Umgebung.

Verzeichnisstruktur

Wer mit verschiedenen Umgebungen (production/testing) arbeitet und keinen external node classifier verwendet und node Definitionen lieber in klassisch in „node.pp“ Files ablegt, braucht eine Verzeichnisstruktur für die Unterscheidung der Umgebungen. Best Practice aktuell (Puppet v3.7.4) ist in der /etc/puppet/puppet.conf:

[main]
environmentpath = $confdir/environments
environment = testing

Die entsprechende Verzeichnisstruktur für die Ablage der Nodedefinitionen  sieht dann so aus:

/etc/puppet/environments/
├── example_env
│   ├── manifests
│   └── modules
├── testing
│   └── manifests
│       └── site.pp
└── production
    └── manifests
        └── site.pp

 Hiera

Wer dem Design Pattern „Separation Of Data And Code“ folgt (und ich kann nur empfehlen es zu tun) fragt sich früher oder später wie er die ganzen Default Werte und Übergabeparameter an Puppet Klassen aus dem Code oder aus den Nodedefinitionen wieder herausbekommt. Im ersten Schritt wird man eine params.pp (Siehe https://docs.puppetlabs.com/guides/module_guides/bgtm.html) bauen und da zumindest die ganzen Defaultwerte einbauen. Aber so richtig los wird man das Ganze mit Hiera.
Hier werden alle Daten, ob Defaultwerte oder speziellere Daten, die z.B. pro Umgebung/Betriebssystem/Rechner/… unterschiedlich sind, in YAML Files abgelegt. Wie der Name „Hiera“ schon sagt ist der Clou an der Sache das hierarchische Element. So kann man Werte mehrfach definieren. Hiera geht dann, ähnlich wie bei Firewallregeln, von oben nach unten durch und nimmt den ersten Treffer. Die Konfiguration ist trivial:

---
:backends: yaml
:yaml:
  :datadir: /etc/puppet/hieradata
:hierarchy:
  - "%{::clientcert}"
  - "%{::environment}"
  - common

Auf der Suche nach dem Wert einer Variable sucht Hiera in /etc/puppet/hieradata nach Files die auf den Rechnernamen, die Umgebung oder „common“ matchen und liest den Wert aus der ersten passenden Datei, welche die entsprechende Variable enthält. Im Puppet Code kann man Hiera auf zwei Arten nutzen.

1. Nutzung der Funktion hiera()

$pwd=hiera('db::pwd')

 2. Implizit über Übergabeparameter

Das ist mein Favorit. Ggf. benötigte Parameter werden als Übergabeparameter in der Puppetklasse definiert:

class web ($pwd) {
  # Benutze $pwd....
}

Diese werden dann automatisch ohne Angabe in der Nodedefinition in Hiera gesucht und genutzt, wenn vorhanden.

Beispiel

  • Rechnername: web01.domain.tld
  • Umgebung: production

Folgende Hieradateien sind abgelegt (hiera.yaml wie oben angegeben):

/etc/puppet/hieradata/
├── common.yaml
├── testing.yaml
├── production.yaml
└── web01.domain.tld.yaml

Somit wird eine Variable „$pwd“ der Klasse „web„, bzw. „hiera(‚web::pwd‘)“ zuerst in der „web01.domain.tld.yaml„, dann in der „production.yaml“ und falls sie noch nicht gefunden wurde in der „common.yaml“ gesucht. Die YAML Datei könnte wie folgt aussehen:

---
web::db: IchBinGanzGeheim!

Vorteil ist, dass nun sehr einfach in jeder Umgebung ein anderes Passwort gesetzt sein könnte und das passende einfach so ohne irgendwelche If-Abfragen im Puppet genutzt wird.

Schreibe einen Kommentar