Berny's Knowledgebase als Newsfeed

Einführung

Das Konzept von Puppet fasziniert mich schon seit langem: Definiere nicht was das Tool tun soll sondern den Zielzustand.

Ersters entspricht dem, was man oft in der Praxis antrifft: Der System-Administrator - da von Natur aus faul - hilft sich damit für gewisse Tätigkeiten Scripts zu schreiben. Vor allem, wenn man eine größere Anzahl von Maschinen verwaltet, hat aber der zweite Ansatz (der Puppet-Ansatz) deutliche Vorteile, da die Scripts im Lauf der Zeit komplex werden. Man kann sich ja nicht immer darauf verlassen, dass das System einem bestimmten (erwarteten) Ausgangszustand entspricht, also baut man dutzende if-Abfragen ein und versucht so, sich durchzumogeln. Das Script soll möglichst von jedem Ausgangszustand den man sich vorstellen kann, zum Zielzustand führen. Leider läßt sich das recht schlecht testen… Und dann fangen die Probleme erst richtig an :-(

Puppet gibt man dagegen einfach nur den Zielzustand vor:

  • stelle sicher, dass folgende Zeile in folgendem Config-File enthalten ist

  • stelle sicher, dass User xy angelegt ist

  • stelle sicher, dass Paket abc installiert ist

Puppet macht dann. Zentraler Konfigurationsserver inclusive. Die Absicherung der Netzwerkverbindung erfolgt über SSL. Client und Server authentifizerien sich gegenseitig, d. h. es kommen auch Client-Zertifikate zum Einsatz. Security-Gesichtspunkte sind also auch schon recht gut berücksichtigt.

Wie eine Aktion auf der Zielplattform auszuführen ist, abstrahiert Puppet zudem sehr gut. Ob jetzt zur Installation des Pakets apt-get, yum oder zypper aufgerufen werden muss, darum muss man sich nicht mehr kümmern.

Eine Möglichkeit um Konfigurationsdateien auf die Zielsysteme zu verteilen ist auch gleich inclusive. Diese dürfen noch dazu Variablen enthalten, die dann auf dem Zielsystem durch den dort zutreffenden Wert ersetzt werden. Auch ein großartiges Feature.

Ein Produkt mit so beeindruckenden Fähigkeiten muss man einfach mal live ausprobiert haben. Inzwischen fand ich dazu endlich mal die Zeit.

http://www.linux-magazin.de/Heft-Abo/Ausgaben/2008/10/Puppenspiel hilft erst mal für das grundlegende Verständnis.

Die Installation geht flott von der Hand, da alle nennenswerten Linux-Distributionen fertige Pakete mitbringen. Meine Testumgebung besteht aus zwei virtuellen Maschinen, eine als zentrale Puppet-Instanz (Server) unter Kubuntu 8.04 und eine als zu konfigurierende Maschine (Client) unter Kubuntu 9.10.

Und: Puppet scheint wirklich eine relativ flache Lernkurve zu haben: Innerhalb weniger Stunden hatte ich die beiden Maschinen verbunden und wechselseitig authentifiziert, ein eigenes Modul gebaut und damit Puppet dazu gebracht auf dem Client den SSH-Server nach meinen Vorgaben umzukonfigurieren.

Seiten im Web, die dabei hilfreich waren:

Zwei Vorträge hatte ich zu Puppet schon gehört. Diese hatten bei mir die Neugier geweckt:

Die Folien kann man sich auf jeden Fall auch mal anschauen.

Einen weiteren sehr Interessanten Vortrag hatte David Roetzel bei den CLT 2009 gehalten, Video-Aufzeichnung steht zur Verfügung:

Integration mit Subversion

Ok, so weit, so gut. Macht Spass, funktioniert und in der täglichen Arbeit kann sich der Admin mit dem Tool echt viel Arbeit sparen.

Und dann kommt der logische Step 2: Integration mit Subversion wie von Michael in seinem Vortrag am Linux-Tag 2010 vorgeschlagen: Folien

Es macht absolut Sinn, in die Versionshaltung der Konfigurationsdateien eine gewisse Nachvollziebarkeit reinzubringen und ggf. auch mal einfach zurückrollen zu können. In der Praxis funktioniert das Tandem aus Puppet und Subversion sehr gut.

David Roetzel hat dazu einen sehr praktischen Ansatz: Im Pre-Commit-Hook von Subversion wird ein Syntax-Check von Puppet durchgeführt. D. h. wenn die Files syntaktisch nicht korrekt sind, klappt der Commit schon gleich gar nicht erst. "Kaputte" Dateien im Repository ausgeschlossen. In einem Post-Commit-Hook macht er dann gleich einen Update am Puppet-Master. Dort werden in diesem Zuge die Konfigurationsdateien und Manifests gleich wieder ausgecheckt. Der Puppet-Master hat somit ab sofort die geänderte Konfiguration und verteilt fortan diese an seine Clients. Für den Admin besteht also nur ein Arbeitsschritt: Konfigurationsdateien und Manifests anpassen, einchecken und fertig.

In der Praxis lässt sich das selbst dann recht gut umsetzen, wenn Puppet-Master und Subversion Repository auf unterschiedlichen Servern laufen. Der Syntax-Check kann direkt auf dem Subversion-Server gemacht werden. Einzige Voraussetzung dafür ist, dass auf der Maschine auch das Paket Puppet installiert ist. Beispiele siehe z. B. http://projects.puppetlabs.com/projects/1/wiki/Subversion_Commit_Hooks_Patterns

Beim Post-Commit-Hook muss der Subversion-Server im Prinzip auf dem Puppet-Master-Server ein Script anstossen. Das Script kann dabei ziemlich einfach sein: Es muß nur einen Checkout von allen Files durchführen und diese an der richtigen Stelle ablegen, wo Puppet sie erwartet. Zur Kommunikation über das Netz eignet sich SSH mit Key-Authentifizierung. Am besten erzeugt man sich dazu am Puppet-Master-Server einen eigenen User-Account, dem nur die Puppet-Manifest-Dateien, -Templates und zu verteilende Dateien gehören. Recht viel mehr sollte er aus Sicherheitsgründen auch nicht unbedingt dürfen. Insbesondere empfielt es sich daher eben gerade nicht den Puppet-User zu verwenden, unter dem schon der Puppet-Master läuft, sondern einen separaten User anzulegen. Für diesen User erzeugt man ein SSH Key-Pair. Den Private-Key benötigt der Subversion Server. Der Public-Key kommt am Puppet-Master-Server in die authorized_keys. Es empfielt sich in diesem File eine Command-Restriction zu setzen, so dass damit nur genau das Checkout-Script ausgeführt werden kann. So kann der User-Account und der Key im Zweifelsfall nicht mißbraucht werden.

Ein kleiner Nachteil ergibt sich durch diese Automatik: Das Checkout Script läuft einfach eine gewisse Zeit. Vielleicht 20 oder 30 Sekunden. Bei bei entsprechend vielen Dateien und Modulen vielleicht auch länger. Einchecken im Subversion dauert damit nicht mehr - wie vielleicht gewohnt - 1 Sekunde, sondern verlängert sich um die Zeit, die der Post-Commit-Hook braucht. Vorher kommt das svn-Kommando nicht zurück. Admins die gern und häufig einchecken stört diese Verlängerung der Wartezeit ziemlich. Es scheint also sinnvoll, hier noch nach einer Lösung zu suchen, wo der Post-Commit-Hook auf Seiten des Puppet-Master-Servers einfach nur triggert, der eigentliche Checkout aber asynchron abläuft.

Auch der Syntax-Check im Pre-Commit-Hook fängt - auch das soll hier nicht verschwiegen werden - nicht 100% aller Fehler ab. Er prüft eben nur - wie der Name schon sagt - ob die Manifests syntaktisch korrekt sind. Korrekte Semantik bleibt nach wie vor dem Menschen überlassen. So kann man z. B. problemlos ein Manifest einchecken, in dem zwei File-Resourcen für ein und die selbe Datei angelegt sind. Wenn Puppet die Konfiguration gemäß diesem Manifest später ausführen will, klappt das entsprechend nicht und Puppet bricht ab. Es passiert dabei dann natütlich erst mal nichts schlimmes, das zu konfigurierende System bekommt die neue Konfiguration nur nicht ab. Ärgerlich kann das allemal sein. Der Admin ist also nach wie vor gefordert, in sinnvoller Weise mitzudenken…

Puppet 2.7 auf Ubunutu 10.04 LTS (Lucid Lynx)

Puppet zu installieren, ist meist kein Problem, die Distributoren bringen Pakete mit, die in vielen Fällen hinreichend aktuell sind. Ubunutu 12.04 LTS (Precise Pangolin) bringt z. B. die stabile Version 2.7 mit.
Wo das nicht der Fall ist, nutzt man die Repositories von Puppetlabs unter http://apt.puppetlabs.com/ bzw. http://yum.puppetlabs.com/ (dazu mehr im nächsten Abschnitt)

Dort ist natürlich immer die aktuellste Version der Pakete verfügbar, im Moment (Dezember 2012) die brandneue Version 3.0.x
Will oder kann man diese noch nicht nutzen, muss man mit Version-Pinning arbeiten.

Konkretes Beispiel: Ubunutu 10.04 LTS (Lucid Lynx), das ja dank LTS nach wie vor gepflegt und damit eingesetzt wird.
Hier hat man in den Repos des Distributors nur die extrem gut abgehangene Version 0.25 verfügbar. Um auf 2.7 zu kommen geht man wie folgt vor:

wget http://apt.puppetlabs.com/puppetlabs-release-lucid.deb
dpkg -i puppetlabs-release-lucid.deb

Für das Version-Pinning legt man dann unter /etc/apt/preferences.d ein neues File an, das man z. B. puppet nennt und das mindestens folgenden Inhalt haben sollte:

Package: puppet puppet-common vim-puppet
Pin: version 2.7.*
Pin-Priority: 1000

Oder in schneller:

wget -O /etc/apt/preferences.d/puppet http://stroessenreuther.info/pub/puppet/etc/apt/preferences.d/puppet

Nach einem kurzen

aptitude update

führt ein

aptitude install puppet

zum Ziel, was sich dann auch noch schnell überprüfen lässt mit:

root@dunno:~# dpkg -l | grep puppet
ii  facter                               1.6.16-1puppetlabs1                             Ruby module for collecting simple facts abou
ii  puppet                               2.7.20-1puppetlabs1                             Centralized configuration management - agent
ii  puppet-common                        2.7.20-1puppetlabs1                             Centralized configuration management
ii  puppetlabs-release                   1.0-5                                           "Package to install Puppet Labs gpg key and

Puppet 2.7 auf RHEL 5.x bzw. Cent-OS 5.x

funktioniert im Prinzip ähnlich, leider ist Yum aber da unflexibler als Apt: Man kann nur genau eine Version pinnen, d. h. kriegt ab dem Zeitpunkt nie mehr Sicherheitupdates, ausser man schaut manuell im Repo von Puppetlabs nach.

Im einzelnen ist das Vorgehen beschrieben unter: http://docs.puppetlabs.com/guides/upgrading.html#yum-versionlock-example Kurzzusammenfassung:

yum install yum-versionlock yum-plugin-versionlock
install puppet-2.7.20
yum versionlock puppet

Das Eintragen in Versionlock-Liste mit dem letzten Kommando hat bei mir unter Cent-OS 5 leider nicht funktioniert, daher habe ich als Workaround den Eintrag in /etc/yum/pluginconf.d/versionlock.list manuell vorgenommen. Er muß dabei folgendes Format haben:

0:puppet-2.7.20-1.el5.noarch

Eine Liste mit allen installierten Paketen in diesem Format kann mit repoquery (aus dem Paket yum-utils) erzeugt werden mit:

repoquery --quiet --envra --pkgnarrow=installed -a

oder auch mit

rpm -qa --qf "%|epoch?{%{epoch}}:{0}|:%{name}-%{version}-%{release}.%{arch}\n"

Einen neuen Client an Puppet anbinden: Kurzanleitung

Kurze Checkliste, damit nichts vergessen wird:

Richtige Version von Puppet installieren, aus Distributor-Repositories oder aus Puppetlabs-Repositories (siehe weiter oben):

aptitude install puppet
dpkg -l puppet

Im Output prüfen, ob die richtige Version installiert ist, z. B. Version 2.7.x

In puppet.conf die Einstellung pluginsync = true setzen und ggf. environment setzen.
Für Environment "production" (default):

wget -O /etc/puppet/puppet.conf http://stroessenreuther.info/pub/puppet/client/production/puppet.conf

bzw. für Environment "test":

wget -O /etc/puppet/puppet.conf http://stroessenreuther.info/pub/puppet/client/test/puppet.conf

Ersten Lauf den Agent starten mit Zertifikatsgenerierung:

puppetd --test

Am Puppet-Master: Zertifikat signieren (als root):

puppetca --list
puppetca --sign -a

Ggf. dem neuen Client noch Puppet-Module zuordnen bzw. erben, z. B. in nodes.pp:

node 'dunno.example.com' inherits example-com-clients { }

Zurück am Client: Ersten vollständigen Lauf den Agent starten:

puppetd --test

Patterns for Puppet and Facter

Wenn man gerade vor der Herausforderung steht, etwas bestimmtes mit Hilfe von Puppet konfigurieren zu wollen, ist es meist ganz hilfreich, vorher mal im Wiki von Puppetlabs nachzuschauen, dort gibt es schon eine umfangreiche Sammlung von Patterns for Puppet and Facter. Wenn dort schon was passendes für die gewünschte Aufgabe dabei ist, spart man sich Zeit.

Weitere Schritte

Was ich sonst noch so mit Puppet ausprobieren will, dazu habe ich noch keine konkreten Pläne. Wenn aber was sinnvolles dabei abfällt, wird es sicher auch wieder hier zu lesen sein…

neues von den Puppetlabs

Auch firmenpolitisch bleibt es spannend, da Puppetlabs das Open-Source-Projekt MCollective übernommen hat, was wohl einfach dadurch geschah, dass man den Projektgründer eingestellt hat. MCollective bietet Werkzeuge an, um effizient mit großen und dynamisch wachsenden Server-Farmen (man nennt das heute wohl neudeutsch "dynamic cloud") umzugehen. Eine Kombination, die sicher interessante Konzepte und Tools hervorbringen wird.