25 Februar 2010

[Howto] Einstieg in Puppet

Kategorien: HowTos
Tags: Puppet

Bei der Administration einer großen Zahl von Servern ist ein zentrales Konfigurations-Management irgendwann unabdingbar. Dieser Artikel beschreibt in einer ersten Einführung das in Ruby geschriebene Framework Puppet.

Einführung

Teil unseres Tagesgeschäfts ist es, beliebig große Server-Installationen zu verwalten und zu warten. Gerade bei großen Clustern heißt dies, eine Vielzahl von Maschinen mit fast identischer Konfiguration nebeneinander zu betreiben. Ohne eine zentralisierte, automatisierte Konfigurations-Verteilung ist dies kaum machbar – an dieser Stelle tritt Puppet auf den Plan.
Wie auch andere Konfigurations-Management-Werkzeuge greift Puppet auf einen zentralen Server zurück, der die Konfiguration verwaltet. Dort fragen die „Clients“ verschlüsselt die Konfiguration ab, und spielen Sie gemäß der Vorgaben des Servers ein, verändern Rechte, führen Befehle aus, etc. Die Vorteile liegen auf der Hand:

  • Arbeitsschritte müssen unabhängig von der Rechner-Zahl nur einmal umgesetzt werden, unnötige Wiederholungen werden vermieden.
  • Für alle Rechner vereinheitlicht sich die Konfiguration zwangsweise – und wird damit einfach wartbar.
  • Die zentrale Infrastruktur ermöglicht einen schnellen Überblick an einer Stelle – ein „Rumlaufen“, entfällt.
  • Der zentrale Konfigurationsbaum ermöglicht damit eine Versionierung: das Zurückspielen der Konfiguration für alle Rechner eines Netzwerkes z.B. auf den Stand „PRE-UPDATE“ geht mit wenigen Befehlen, für das ganze Netzwerk!

Technische Arbeitsweise

Puppet besteht aus einem zentralen Server, Puppet-Master genannt, und den Clients, genannt Nodes. Diese melden sich beim Master an, und fragen dort nach der aktuellen Konfiguration. Der Master gibt diese an die Nodes weiter – die Möglichkeiten der Anweisungen des Masters sind schier unbegrenzt:

  • Der Server kann Dateien übergeben, die an bestimmte Orte kopiert werden.
  • Die Node kann angewiesen werden, Dateirechte zu prüfen und notfalls zu korrigieren.
  • Je nach Betriebssystem kann erzwungen werden, dass die Node prüft, ob bestimmte Dienste aktiv sind, oder ob bestimmte Pakete auch in der neuesten Version installiert sind.
  • Der Server kann die Node anweisen, bestimmte Befehle auszuführen.
  • usw.

Im Prinzip kann alles mit der Übergabe von Dateien vom Server an die Node erledigt werden, doch ist dies in komplexen Setups weder übersichtlich noch vereinfachend. Gerade die Abstraktion von System-Aufgaben (Dienste neu starten, Paket-Versionen sicherstellen, Nutzer einrichten, etc.) ohne das direkte Überschreiben von Dateien hilft ungemein beim Konfigurieren komplexer Systeme.

Installation

Für die Installation benötigt man einen zentralen Puppet-Master, der die Konfiguration verwaltet: apt-get install puppetmaster Puppet geht davon aus, dass alle beteiligten Rechner FQDNs haben, dies sollte in einem korrekt gewarteten Netzwerk aber eh der Fall sein!
Auf jedem zu verwaltenden Rechner wird ein Puppet-Client mit apt-get install puppet installiert.

Konfiguration von Puppet

Die Puppet-Nodes suchen automatisch nach dem Rechner, der auf den Namen puppet auflöst, so lange der Name korrekt auf den Hauptserver zeigt, brauchen sie nicht weiter konfiguriert werden.
Beim Puppet-Master muss der Dateiserver noch korrekt konfiguriert werden, der wie oben beschrieben Dateien an die Nodes übergeben kann. Je nach Anspruch können die Dateien dabei nah bei der weiteren Konfiguration gehalten werden, oder aber zentral in einem externen Archiv untergebracht werden. Für unser Beispiel werden wir die zu verteilenden Dateien nah bei der eigentlichen Konfiguration halten, ganz so, wie es auch im Best Practice Guide und in der Anleitung Module Configuration der Puppet-Dokumentation beschrieben wird.
Daher reicht es, in der Datei /etc/puppet/fileserver.conf folgende Konfiguration vorzunehmen:

[modules]
allow 192.168.0.1/24
allow *.credativ.de

Konfiguration der Konfiguration – Module

Um eine Server-Konfiguration durch Puppet erledigen zu lassen, ist es am Besten, diese in Aufgabenbereiche oder Themen zu unterteilen, wie zum Beispiel „ssh“, „logs“, „apache“, etc. Diese Bereiche werden in Puppet als „Module“ bezeichnet, und sind der Kern von Puppets Konfigurationsverwaltung. Den Aufbau eines Modules beschreiben wir hier anhand einer fiktiven SSH-Konfiguration und halten uns dabei eng an den Best Practice Guide.
Es sei angemerkt, dass die tatsächliche Konfiguration von SSH durch Puppet an einigen Stellen dynamischer wäre, hier wird nur ein vereinfachter Weg gezeigt.

Das SSH-Modul

Der Anspruch des SSH-Moduls ist:

  1. Das openssh-server-Paket soll in neuester Version installiert sein.
  2. Die Datei sshd_config soll der entsprechen, die im Puppet-Master hinterlegt ist.
  3. Falls die Datei sshd_config installiert wird, soll der sshd neu gestartet werden.
  4. Der Nutzer credativ soll bestimmte Dateien in seinem Verzeichnis $HOME/.ssh haben.

Um diesen Ansprüchen gerecht zu werden, erstellen wir die notwendigen Verzeichnisse des Moduls:

mkdir -p /etc/puppet/modules/ssh/manifests
mkdir -p /etc/puppet/modules/ssh/files

Der Ordner Mainfests enthält die eigentlichen Konfigurations-Anweisungen des Moduls, der Ordner files hält Dateien vor, die an die Nodes ausgeliefert werden sollen.
Die Konfigurations-Anweisungen des Modules finden sich in der Datei init.pp im Ordner manifests. Die Gruppe von Anweisungen, um die obigen Ziele 1.-4. zu erfüllen, wird dort als „Klasse“ zusammen gefasst. Die Klasse enthält selbst wiederum Untersektionen, sogenannte Types. In unserem Fall findet sich für jedes vorher definierte Ziel ein Type:

class ssh{
        package { "openssh-server":
                 ensure => latest,
        }
        file { "/etc/ssh/sshd_config":
                owner   => root,
                group   => root,
                mode    => 644,
                source  => "puppet:///ssh/sshd_config",
        }
        service { ssh:
                ensure          => running,
                hasrestart      => true,
                subscribe       => File["/etc/ssh/sshd_config"],
        }
        file { "/home/credativ/.ssh":
                path    => "/home/credativ/.ssh",
                owner   => "credativ",
                group   => "credativ",
                mode    => 600,
                recurse => true,
                source  => "puppet:///ssh/ssh",
                ensure  => [directory, present],
        }
}

jeder Type setzt eine gänzlich andere Aktion auf dem Node um:
package
Hier wird sicher gestellt, dass das Paket openssh-server in der neuesten Version installiert ist.
file
Eine Datei auf der Node wird durch die Version vom Server überschrieben und mit entsprechenden Rechten versehen.
service
Der Dienst sshd muss laufen, und wird notfalls gestartet. Falls außerdem die Datei /etc/ssh/sshd_config aktualisiert wird, wird auch der Dienst neu gestartet.
file
Hier taucht noch einmal der Type „file“ auf – es wird aber nicht eine einzelne Datei übertragen, sondern gleich ein ganzes Verzeichnis.

Damit das Modul auch korrekt arbeitet, müssen die beim Type „file“ definierten Dateien und Verzeichnisse auch unter /etc/puppet/modules/ssh/files/ zu finden sein.

Nodes und Module

Wir haben nun drei Elemente: den Puppet-Master, die Nodes, und die Module. Nun muss die Zuweisung erfolgen, welche Nodes welche Module aufrufen sollen. Dafür muss zuerst das Modul in der Datei /etc/puppet/manifests/modules.pp aktiviert werden:

import "ssh"

Die Zuweisung zu den einzelnen Nodes erfolgt in der Datei /etc/puppet/manifests/nodes.pp. Diese legt für jede Node fest, welches Modul geladen wird. Außerdem gibt es für alle nicht weiter spezifizierten Nodes einen Default-Eintrag, und zu guter Letzt können auch Einträge von anderen abgeleitet werden. Um also für alle Nodes das Modul „rsyslog“ zu laden, aber nur für die Node „external“ das Modul „ssh“, sieht der Eintrag wie folgt aus:

node default {
   include rsyslog
}
 
node 'external' inherits default {
  include ssh
}

Damit ist Puppet fertig konfiguriert, und nimmt sofort seine Arbeit auf.

Zertifikate – Sichere Kommunikation zwischen Node und Master

Die Kommunikation zwischen Master und Node verläuft verschlüsselt. Um dies zu gewährleisten, müssen Nodes auf dem Master zertifiziert werden. Dies ist möglich, nachdem ein Node das erste Mal eine Anfrage an den Master gestellt hat – der Master setzt diesen Node dann auf wait, und stellt ihm so lange keine Daten zur Verfügung. Erst, wenn die Node durch einen Admin verifiziert wurde, wird die Node frei geschaltet. Mit # puppetca --list wird die Liste der noch zu verifizierenden Nodes angezeigt, verifiziert wird mit: # puppetca --sign external.example.com Bei Bedarf kann dieser Prozess weiter verfeinert werden.

Abschließende Worte

Die hier vorgestellten Beispiele sind natürlich stark vereinfacht. Im Real-Betrieb würde die SSH-Konfiguration komplexer sein, und Schlüssel würden nicht gerade mit dem Type „file“ statisch verteilt werden. Aus diesen Beispielen lassen sich aber leicht weitere Module ableiten, und die an vielen Stellen verlinkte Konfiguration tut ihr Übriges, damit der geneigte Leser sich tiefer in die Materie einarbeiten kann.
Wir hier bei credativ haben mit Puppet mittlerweile sehr umfangreiche und sehr gute Erfahrungen gemacht, leisten an vielen Ecken Support und Beratung für Puppet und merken, wie die Nachfrage steigt. Puppet ist derzeit auf der Überholspur, und es wird spannend sein zu beobachten, wie sich der Platzhirsch cfengine angesichts dieser Konkurrenz verhält.

 

Dieser Artikel wurde ursprünglich geschrieben von Roland Wolters.

Kategorien: HowTos
Tags: Puppet

SH

über den Autor

Sascha Heuer


Beitrag teilen: