\subsection{Funktionsweise von Chef} \label{ssub:funktionsweise_von_chef} \href{http://www.getchef.com/chef/}{Chef} ist ein Framework, welches eine automatisierte Serverkonfiguration und -verwaltung ermöglicht. Chef übernimmt dabei Aufgaben der Provisionierung (Installation der grundlegenden Dienste, Ressourcenverwaltung, Einrichtung und Konfiguration von Middleware) bis hin zum Deployment (Verteilung der eigentlichen Business-Anwendung). Der Endanwender beschreibt hierbei die Systemressourcen und ihre Zustände in der Programmiersprache \href{https://www.ruby-lang.org/}{Ruby}. Diese Definitionen werden von dem Programm \texttt{Chef-Client} eingelesen und in notwendige Aktionen übersetzt, welche ausgeführt werden müssen, um den beschriebenen Zustand umzusetzen. Die Gesamtheit aller Definitionen/Einstellungen nennt man das \texttt{Chef-Repo}. Ein solches untergliedert sich in mehrere \texttt{Cookbooks}\label{cookbook}. Ein Cookbook ist die Grundverwaltungseinheit in Chef. Es erfüllt einen bestimmten Teilaspekt des Systems (z.B. die Einrichtung eines Webservers \href{https://github.com/opscode-cookbooks/apache2}{Apache}). Cookbooks können versioniert werden. Es können Abhängigkeiten zwischen mehreren Cookbooks angegeben werden. Physikalische oder virtuelle Maschinen werden als \texttt{Nodes} bezeichnet. Der Node werden \texttt{Attribute}, \texttt{Rollen} und Cookbooks zugewiesen. Rollen und Cookbooks werden dazu in die sogenannte \texttt{Run-List} eingefügt. Diese gibt die Reihenfolge an, in welcher Rollen und Cookbooks angewendet werden. Rollen bieten eine Möglichkeit, Nodes zu gruppieren, welche die gleichen Aufgaben in einer Organisation erfüllen (z.B. Webserver). Es gibt mehrere Möglichkeiten \texttt{Chef} zu betreiben: \begin{description} \item[Chef-Solo] Chef-Solo ist die einfachste Ausführungsform. Alle nötigen Daten werden aus einem lokalen Verzeichnis geladen. Im Gegensatz zu \texttt{Chef-Server} und \texttt{Enterprise-Chef} wird bei Chef-Solo das Programm \texttt{chef-solo} an Stelle von \texttt{chef-client} ausgeführt. Diese Form wurde für die Umsetzung der Aufgabenstellung in Abschnitt~\ref{sub:einrichtung-der-netzwerkdienste} gewählt. \item[Chef-Server] Hierbei authentifiziert sich \texttt{Chef-Client} über eine \texttt{REST-Api} zu einem \texttt{Chef-Server} mittels eines privaten RSA-Keys. Der Server verwaltet zentral das Chef-Repo. Der Chef-Client bekommt von diesem alle nötigen Informationen für die zu provisionierende \texttt{Node}. Chef-Server bietet eine webbasierte GUI für die Administration an. Die Attribute aller Nodes sind über die eingebaute Suchmaschine \href{https://lucene.apache.org/solr/}{\texttt{Solr}} durchsuchbar. \item[Enterprise-Chef/Hosted-Enterprise-Chef] Enterprise-Chef bietet zusätzlich zu den Funktionen der Opensource-Version Chef-Server eine rollenbasierte Benutzerverwaltung, bessere Überwachung, eine verbesserte Weboberfläche sowie Push-Deployment an. Während bei Hosted-Enterprise-Chef die Firma Chef die Infrastruktur des Chef-Server betreibt und die Skalierung des Dienstes übernimmt, befindet sich im Falle von Enterprise-Chef der Server in der eigenen Organisation~\cite{chefenterprise}. \end{description} \subsubsection{Aufbau eines Cookbooks} \label{aufbau_eines_cookbook} \begin{figure}[h] \centering \caption{Ordnerstruktur eines Cookbooks am Beispiel des \href{https://github.com/opscode-cookbooks/apt}{apt}-Cookbooks dargestellt.} \begin{tikzpicture} \treeroot{apt-2.3.4} \altentry{attributes}{1} \altentry{default.rb}{2} \altentry{files}{1} \altentry{default}{2} \altentry{apt-proxy-v2.conf}{3} \altentry{libraries}{1} \altentry{helpers.rb}{2} \altentry{network.rb}{2} \altentry{providers}{1} \altentry{preference.rb}{2} \altentry{repository.rb}{2} \altentry{recipes}{1} \altentry{cacher-client.rb}{2} \altentry{cacher-ng.rb}{2} \altentry{default.rb}{2} \altentry{resources}{1} \altentry{preference.rb}{2} \altentry{repository.rb}{2} \altentry{templates}{1} \altentry{debian-6.0}{2} \altentry{default}{2} \altentry{01proxy.erb}{3} \altentry{acng.conf.erb}{3} \altentry{ubuntu-10.04}{2} \altentry{acng.conf.erb}{3} \altentry{CHANGELOG}{1} \altentry{metadata.json}{1} \altentry{metadata.rb}{1} \altentry{README.md}{1} \end{tikzpicture} \end{figure} Die Verzeichnisnamen und die Datei \texttt{metadata.rb} sind fest vorgeben. Jedes Verzeichnis hat seine eigene Funktion. Dies hat den Vorteil, das man sich schnell in neuen Cookbooks zurecht findet. \begin{description} \item[attributes] Attribute sind einfache Schlüssel-Wert-Beziehungen und setzen Standardwerte für das Cookbook. Die Schlüssel sind hierarchisch organisiert. In der Regel ist die höchste Ebene der Name des Cookbooks (z.B. \texttt{normal.mysql.client.packages}). Werte können Strings, Zahlen oder Arrays sein. Die gesetzten Attribute können in Rollen, Nodes oder von anderen Cookbooks überschrieben werden. Hierfür werden die Attribute mit den verschiedenen Prioritäten \texttt{default}, \texttt{force\_default}, \texttt{normal} und \texttt{override} (aufsteigender Wertigkeit) gesetzt. Attribute mit einer höheren Priorität überschreiben den Wert von Attributen mit einer niedrigeren Priorität. \item[files] In diesem Verzeichnis können statische Dateien eingefügt werden, welche auf dem Zielsystem in das entsprechende Verzeichnis kopiert werden können. \item[libraries] In diesem Pfad können Hilfsfunktionen und Spracherweiterungen definiert werden. \item[resources] Ressourcen beschreiben die Bestandteile eines Systems. Eine Ressource kann z.B. eine Datei, ein Prozess oder ein Paket sein. Man beschreibt, welchen Zustand (Action in Chef genannt) diese Ressource haben soll und Chef versucht, diesen Zustand herzustellen. Chef liefert bereits viele wichtige Ressourcen mit. In Cookbooks können darüber hinaus eigene Ressourcen definiert werden. \item[providers] Während Ressourcen nur die Schnittstelle mit allen Attribute beschreiben, die gesetzt werden können, ist der Provider eine konkrete Implementierung. Deswegen muss für jede Ressource mindestens ein Provider existieren. Es kann mehrere Provider für eine Ressource geben, um zum Beispiel mehrere Plattformenvarianten oder Betriebssysteme abdecken zu können (z.B. bei Paketmanagern oder Initsystemen - \ref{sec:initsysteme}). In eigenen Cookbooks erstellte Ressourcen/Provider nennt man LWRP (englische Abkürzung für \texttt{Lightweight Resources and Providers}). \item[recipes] In Recipes werden Ressourcen instantiiert, welche nötig sind, um das gewünschte Ziel zu erreichen. Dabei können Abhängigkeiten zwischen Recipes angegeben werden. \item[definitions] Ressourcen, welche häufiger in verschiedenen Recipes in ähnlicher Form benötigt werden, können in eine \texttt{Definition} ausgelagert werden. Ein Beispiel ist das Generieren eines SSH-Schlüssels für verschiedene Nutzer auf dem System. Für komplexere Konstrukte sollten jedoch LWRPs (siehe oben) bevorzugt werden. \item[templates] Häufig werden dynamisch generierte Dateien benötigt, um zum Beispiel Konfigurationsdateien zu erzeugen. In Chef wird für diesen Zweck die Templatesprache eRuby (Embedded Ruby) verwendet. In ERB-Templates wird Rubyquellcode ausgeführt, der sich zwischen den Tags \texttt{<\%} und \texttt{\%>} befindet. Dies erlaubt es einerseits den Inhalt von Variablen oder den Rückgabewert von Methoden einzufügen, andererseits können in Templates Kontrollstrukturen wie If-Statements und Schleifen verwendet werden. \item[metadata.rb] In der Datei \texttt{metadata.rb} kann der Name des Cookbook, die eigene Version, eine Beschreibung sowie Abhängigkeiten zu anderen Cookbooks angegeben werden. \end{description} \begin{lstlisting}[caption={Beispiel ERB-Template:},label={lst:erb-templates}] Diese Zeile wird beim Rendern ohne Aenderung uebernommen <%# Ein Kommentar%> Diese Node heisst: <%= @node.name %> <% if node[:platform] == "ubuntu" -%> <%# Bedingte Anweisung %> Diese Zeile erscheint auf Ubuntu-basierten Nodes. <% else %> Diese Zeile erscheint auf nicht Ubuntu-basierten Nodes. <% end -%> <%# Listet in einer Schleife alle Blockdevices des Node auf %> <% @node.block_device.each do |block_device, attributes| %> <%= block_device %>: <%= attributes.join(", ") %> <% end %> \end{lstlisting} \subsubsection{Ablauf einer Provisionierung} \label{ablauf_einer_provisionierung} Der genaue Ablauf wurde der Onlinedokumentation (\cite{chefrun}) von Chef entnommen. Wie schon zu Beginn erwähnt, wird die Provisionierung von einem Programm namens \texttt{Chef-Client} durchgeführt. Je nach gewählter Umgebung kann dieser unterschiedlich gestartet werden: \begin{itemize} \item periodisch vom Scheduler \texttt{Cron} \item permanent als Systemdienst (z.B. bei Enterprise Chef) \item manuell (z.B. bei Vagrant - siehe~\ref{sub:einrichtung-der-netzwerkdienste}) \end{itemize} Als erstes lädt dieser Prozess seine Konfiguration aus der Datei \texttt{client.rb}. In dieser stehen beispielsweise die URL des Chef-Server und der Name des Node. Letzteres ist wichtig, um die Node in Chef einordnen zu können und die richtigen Einstellungen zuzuweisen. Alternativ kann der Name auch von der Bibliothek \href{http://docs.opscode.com/ohai.html}{Ohai} gesetzt werden, in dem auf den Hostnamen oder der FQDN (Fully Qualified Domain Name) zurückgegriffen wird. Ohai sammelt systemrelevante Daten wie Details über Hardwarekomponenten (Anzahl der CPUs, Größe und Art des RAMs, Netzwerkanbindung, Festplatten/SSDs, \dots), Informationen über die Plattform (Art des Betriebssystems und sowie dessen Version, installierte Anwendungssoftware) und die laufenden Prozesse. Diese Informationen sind durch eigene Ohai-Plugins erweiterbar und können im Provisionierungsprozess genutzt werden, um weitere Entscheidungen zu treffen. Sie sind darüber hinaus auch auf dem Server gespeichert und für andere Clients abrufbar. Nach dem alle Einstellungen eingelesen sind, verbindet sich der Chef-Client mit dem Chef-Server. Die Authentifizierung erfolgt über dem vorher auf dem Node abgelegten RSA-Schlüssel. Für Administratoren gibt es einen Validator-Key. Mit diesem kann ein Node auf dem Server registriert werden und so ein Client-Schlüssel generiert werden. Anschließend werden zuvor gesetzte Attribute und die Run-List vom Server übertragen. Im 1. Durchlauf oder bei Verwendung von Chef-Solo sind diese Daten nicht vorhanden. Stattdessen kann eine Datei im JSON-Format angegeben werden, um die Attribute und die Run-List für die Node zu spezifizieren. Außerdem ist es möglich eine Run-List auf dem Chef-Server einzustellen, welche ausgeführt wird, wenn die Node keine eigene Run-List besitzt. Durch Auswertung der eingebunden Rollen und Recipes werden die benötigen Cookbooks ermittelt. Der Client fordert eine Liste aller darin enthaltenen Dateien und deren Checksumme an. Alle geänderten oder neuen Dateien werden heruntergeladen und lokal gespeichert. Nun werden die Attribute zurückgesetzt und aus den Cookbooks, Rollen und dem Node neu generiert und entsprechend ihrer Priorität gesetzt. Die Ressourcen aus den Cookbooks werden geladen und in der Ressource-Collection zusammengefasst. Nachdem alle Definitionen und Bibliotheken geladen wurden, werden schließlich die Recipes verarbeitet. Die darin erstellten Ressourcen beschreiben das System. Für jede Ressource wird der Zustand festgelegt. Im nächsten Schritt folgt das sogenannte \texttt{Converging} (englisch für Angleichen). Es werden alle Ressourcen Schritt für Schritt abgearbeitet. Dabei wird für jede Ressource der für die Plattform zugehörige Provider ausgewählt. Dieser überprüft den aktuellen Zustand der Ressource und verändert falls notwendig das System, um den Sollzustand zu erreichen. Zum Schluss überträgt Chef-Client die aktualisierten Attribute auf den Server, von welchem sie in \texttt{Solr} indexiert werden. Es besteht die Möglichkeit, Handler vor oder nach der Provisionierung auszuführen. Diese können im Fehlerfall Benachrichtigungen an das Monitoringssystem oder per Email verschicken. In letzten Abschnitt (\ref{minitest_handler}) wird dieser Mechanismus genutzt, um Tests auszuführen. \subsubsection{Vergleich mit puppet} \label{vergleich_mit_puppet} \paragraph{Historischer Kontext} Ein ebenfalls weit verbreitetes Konfigurationsmanagementsystem ist Puppet. Es ist das Ältere der beiden Projekte. Während das erste Puppet-Release bereits im Jahre 2005 von den Puppet Labs veröffentlicht wurde, erschien Chef erst 4 Jahre später im Jahr 2009. Chef wurde stark von Puppet beeinflusst. Der Erfinder von Chef, Adam Jacob, war selbst langjähriger Puppetnutzer, bevor er Chef schrieb. Seine damalige Firma betreute als Unternehmensberater mehrere Firmen bei der Provisionierung der Infrastruktur bis hin zum Deployment der Anwendung. Dabei kam Puppet zum Einsatz. Mit steigender Anzahl der Kunden, wuchs nach Aussagen von Adam Jacob der Aufwand bei der Verwaltung der Puppet-Konfiguration. Diese mussten häufig für jeden Kunden stark angepasst oder neu geschrieben werden. Aus diesem Grund begann er an ein neues Deploymentsystem zu schreiben. Damals trug es noch den Namen \texttt{Marionette}. Dabei verwendete er, wie schon bei Puppet, die Programmiersprache Ruby zur Implementierung des Clients. Ein wichtiges Designziel seines neuen System war es, bessere Abstraktionsmöglichkeiten zu schaffen, um damit die Wiederverwendbarkeit zu erhöhen (Quelle: \cite{chefhistory}). Anzumerken ist, dass seit der damals veröffentlichten Puppetversion (\href{https://github.com/puppetlabs/puppet/commit/ce964ecb6d6a38cb7fb9f0b13a7e6b2eb4c381c3}{0.24.5}) neue Funktionen und Spracherweiterungen zu Puppet hinzugefügt wurden, um dieses Problem zu adressieren. (\cite{puppetlanguagechangelog}) \paragraph{Sprache} Während bei Chef die Konfiguration in Ruby geschrieben wird, besitzt Puppet eine eigene Konfigurationssprache. Puppet's Sprache ist im Gegensatz zu allgemeinen verwendeten Sprachen (engl. General-Purpose-Languages, kurz GPL) wie Ruby, Java oder C/C++ eine domänspezifische Sprache (engl. Domain-Specific-Language - DSL). Eine DSL ist eine speziell für den Anwendungszweck geschriebene und optimierte Sprache. Sie enthält häufig Elemente und Ausdrücke, welche es erlauben, Probleme der Anwendungsdomäne effizient zu lösen. Es wird häufig auf umfangreiche Standardbibliotheken und Sprachkonstrukte verzichtet, die in GPLs üblich sind. Puppet's Sprache wurde an das Konfigurationsformat der Überwachungssoftware Nagios angelehnt (\cite{puppetlanguage}). Sie ist deklarativ gehalten und soll möglichst einfach erlernbar sein (auch für Administratoren ohne programmiertechnischen Hintergrund). Der Schwerpunkt liegt auf der Beschreibung von \texttt{Ressourcen}. Die Sprache besitzt Kontrollstrukturen wie Case- und If-Statements. Es gibt Datentypen wie \texttt{Strings}, \texttt{Booleans}, \texttt{Arrays}, \texttt{Reguläre Ausdrücke} und \texttt{Hashes}. Diese können in Variablen gespeichert werden. Die \href{https://forge.puppetlabs.com/puppetlabs/stdlib}{Standardbibliothek} von Puppet stellt Funktionen bereit, um auf diesen Datentypen einfache Operationen auszuführen. Allerdings ist es nicht möglich, Schleifen auszuführen. (Diese \href{http://docs.puppetlabs.com/puppet/latest/reference/experiments_lambdas.html}{Funktion} ist momentan als \texttt{experimentell} markiert). Funktionen können nicht direkt in Puppet's Sprache definiert werden. Stattdessen werden diese als Erweiterung des Parsers in Ruby implementiert, was wiederum den Nachteil hat, dass dafür eine weitere Sprachen erlernt werden muss. Manche Unternehmen und Organisationen greifen bevorzugt auf Puppet zurück, weil es einfacher ist, neue Mitarbeiter ohne Rubykenntnisse in diesem Framework zu schulen. Andere wiederum bevorzugen die Flexibilität von Ruby. Facebook gab dies als einen der Grund an für einen Umstieg im Jahre 2013 von \texttt{CFEngine2} auf \texttt{Chef 11} \cite{facebooklikeschef}. \paragraph{Communities} Das strukturelle Gegenstück zu \texttt{Cookbooks} in Chef ist das \texttt{Modul} in Puppet. Diese werden in der Nutzergemeinschaft entwickelt. Da Puppet älter ist, ist anzunehmen, dass hierfür mehr Module zur Verfügung stehen, als Cookbooks für Chef. Die primäre Distributionsquelle ist \href{https://forge.puppetlabs.com/}{Puppet-Forge}, in dem \textbf{2206} \href{https://forge.puppetlabs.com/modules?supported=yes}{Modul} zur Verfügung stehen (Stand: 31.03.2014). Für Chef gibt es eine ähnliche \href{http://community.opscode.com/}{Community-Seite} mit \textbf{1368} Modulen, (Stand: 31.03.2014 - ermittelt über die \href{https://cookbooks.opscode.com/api/v1/cookbooks?start}{API}). Zu einer weiteren wichtigen Quelle hat sich die Plattform \href{https://github.com}{Github} für beide Projekte entwickelt. Für einen Vergleich wurde die Anzahl der Suchtreffer für Projekte, die die Begriffe ``Chef'' und ``Puppet'' in der Suchmaschine auf Github herangezogen. Github filtert Forks (Abspaltungen) von Projekten aus den Suchergebnissen heraus und schlüsselt die Ergebnisse nach Programmiersprache auf. Es wurden alle Sprachen in beiden Projekte mit weniger als 100 Suchtreffer aus Übersichtlichkeitsgründen nicht in das Diagramm übernommen (siehe Tabelle~\ref{tab:rohdaten}). Eine Stichproben der Ergebnisse, dass die Suchtreffer sich überwiegend mit den eigentlichen Projekten Chef und Puppet beschäftigen. Anzumerken ist, dass Zielgruppe von Puppet überwiegend Systemadminstratoren aus besteht, während Chef auch von vielen Entwicklern genutzt wird. Letztere verwenden bevorzugt Github. \begin{figure}[h] \pgfplotstableread{ Puppet Ruby Shell Python Javascript Perl Andere 0 9902 321 148 124 42 260 7315 3108 751 207 157 137 211 }\dataset \definecolor{bblue}{HTML}{4F81BD} \definecolor{rred}{HTML}{C0504D} \definecolor{ggreen}{HTML}{9BBB59} \definecolor{ppurple}{HTML}{9F4C7C} \begin{tikzpicture} \begin{axis}[ybar stacked, width=12cm, enlarge x limits=0.5, height=10cm, ymin=0, ymax=13500, scaled x ticks = false, scaled y ticks = false, ylabel={Anzahl der Suchtreffer}, xtick=data, xticklabels = { \strut Chef (Gesamt: 10797), \strut Puppet (Gesamt: 11749) }, major x tick style = {opacity=0}, every node near coord/.append style={ anchor=west, rotate=90 }, legend entries={Puppet, Ruby, Shell, Python, Javascript, Perl, Andere}, legend columns=13, ] \addplot[draw=black,fill=rred] table[x index=0,y index=0] \dataset; \addplot[draw=black,fill=ggreen] table[x index=0,y index=1] \dataset; \addplot[draw=black,fill=bblue] table[x index=0,y index=2] \dataset; \addplot[draw=black,fill=ppurple] table[x index=0,y index=3] \dataset; \addplot[draw=black,fill=magenta] table[x index=0,y index=4] \dataset; \addplot[draw=black,fill=yellow] table[x index=0,y index=5] \dataset; \addplot[draw=black,fill=black] table[x index=0,y index=6] \dataset; \end{axis} \end{tikzpicture} \caption{Anzahl der Suchtreffer auf Github aufgeschlüsselt nach Programmiersprache für die Begriffe ``Chef'' und ``Puppet''.} \label{tab:rohdaten} \end{figure} \begin{table}[h] \caption{Ausgangsdaten für das Diagramm} \begin{tabular}{l|c|c|c|c|c|c|c|c|c|c|c|c} Sprache & \textbf{Ruby} & \textbf{Puppet} & \textbf{Shell} & \textbf{Python} & \textbf{Javascript} & \textbf{Perl} & PHP & Java & VimL & CSS & C & C++ \\\hline \textbf{Chef} & 9,902& - & 321 & 148 & 124 & 42 & 56 & 88 & - & 31 & 48& 37 \\\hline \textbf{Puppet} & 3,108& 7,315 & 751 & 207 & 157 & 137 & 82 & 42 & 64 & 23 & - & - \\ \end{tabular} \end{table} \vspace{0.5cm} Eine weitere wichtige Statistik für Opensource-Projekte ist die Anzahl der Abonnenten auf den jeweiligen Mailinglisten. Engagierte und aktive Nutzer/Entwickler abonnieren häufig diese, wodurch sich die Größe der Community qualitativ vergleichen lassen. \begin{description} \item[chef@lists.opscode.com] Community-Mailingliste, 1620 Abonnenten, Quelle:~\cite{chefcommunitylist}, Stand: 31.03.2014 \item[chef-dev@lists.opscode.com] Entwickler-Mailingliste, 652 Abonnenten, Quelle:~\cite{chefdeveloperlist}, Stand: 31.03.2014 \item[puppet-users@googlegroups.com] Community-Mailingliste, \textasciitilde{}7000 Abonnenten, Quelle:~\cite{puppetcommunitylist}, Stand: 01.04.2014 \end{description} Die Anzahl der verfügbaren Module, veröffentlichte Githubprojekte und der Abonnenten auf den Mailinglisten weisen darauf hin, dass Puppet nach wie vor eine größere Community hat. \paragraph{Funktionsweise} Anstelle von Recipes werden in Puppet Manifeste geschrieben. Das sind Dateien, die auf den Suffix .pp enden und sich in dem Ordner \texttt{manifests} im Modul befinden. Jedes Manifest definiert eine Klasse, eingeleitet durch das Schlüsselwort \texttt{class}. Der Namen dieser Klasse wird aus dem Modulnamen und dem Manifest-Namen gebildet. Wenn das Modul \texttt{foo} das Manifest \texttt{bar} enthält, ist der Name der Klasse \texttt{foo::bar}. Eine Ausnahme bildet das Manifest \texttt{init.pp}, bei dem die Klasse nur \texttt{bar} lauten würde. Diese Benennungskonvention wurde in Chef übernommen, um Recipes in Cookbooks zu referenzieren. Allerdings werden in Recipes keine separaten Objekt definiert und der ganze Inhalt der Datei bildet das Recipe. Eine Klasse in Puppet kann über Parameter konfiguriert werden. Parameter werden im Kopfteil der Klasse deklariert und können Standardwerte besitzen. Chef besitzt mit \texttt{Attributen} ein vergleichbares Konzept. Allerdings werden Attribute getrennt von den Recipes definiert und sie werden dem Node-Objekte zugewiesen. Die Attribute stehen somit allen Recipes zu Verfügung und können an verschiedenen Stellen überschrieben werden. In Puppet 3 wurde diese Trennung von Code und organsationsspezifischen Daten durch die Erweiterung \texttt{Hiera} ebenfalls eingeführt. Klassenparameter werden automatisch in der \texttt{HieraDB} gesucht und gegebenenfalls überschrieben. In älteren Versionen von \texttt{Puppet} wurden Einstellungen für die Nodes in der zentralen \texttt{site.pp}-Manifest verwaltet. Hiera ersetzt die \texttt{site.pp} weitest gehend. Durch die Funktion \texttt{hiera\_include} können Klassen im Hiera-Backend gesetzt werden (ähnlich der Run-List in Chef). Ressourcen heißen in Puppet \texttt{Types}. Puppet liefert wie Chef bereits eine Reihe von Types mit. Diese werden Core-Types genannt. Wie auch in Chef können Types in Puppet mehrere plattformspezifische Provider besitzen. Es ist möglich, eigene Types zu definieren, auch Custom-Types genannt (Ähnlich LRWP in Chef). Die Implementierung der Types/Provider erfolgt in Ruby im Verzeichnis \texttt{lib/puppet}. Die Zustände einer Ressource können in Puppet über das Setzen des Parameters \texttt{ensure} festgelegt werden (vergleichbar mit \texttt{action} in Chef). Ein weiteres häufig genutztes Entwurfsmuster, um Ressourcen zu gruppieren, ist der \texttt{Defined-Type}. Dieser ist das Äquivalent zur aus Chef bekannten \texttt{Definition}. Ein Defined-Type kann im Gegensatz zum Custom-Type auch direkt in der Puppet-Sprache mit dem Schlüsselwort \texttt{define} erstellt werden. Vor der eigentlichen Provisionierung werden Informationen über das System zu gesammelt. Dabei wird auf die Bibliothek \href{http://puppetlabs.com/facter}{Facter} zurückgegriffen. In frühen Versionen von Chef wurde die gleiche Bibliothek verwendet, bevor später \href{http://docs.opscode.com/ohai.html}{Ohai} integriert wurde. Puppet nutzt die gleiche Template-Syntax wie Chef, welche in Quellcodelisting~\ref{lst:erb-templates} vorgestellt wurde, um Dateien auf dem System zu generieren. Der einzige Unterschied bei Chef ist die Funktion für verschiedene Plattformen und -versionen verschiedene Template-Varianten der gleichen Datei im Cookbook vor halten zu können. Die Varianten werden durch Unterordner im Verzeichnis \texttt{templates/} unterschieden (z.B. \texttt{templates/windows} oder \texttt{templates/ubuntu-12.04}). Falls kein der Plattform entsprechende Ordner existiert sucht Chef im Verzeichnis \texttt{templates/default}. Ein wesentlicher Unterschied zwischen Puppet und Chef ist die Reihenfolge der Ausführung von Ressourcen. Chef überprüft die Ressourcen in der Reihenfolge, in der sie in der Run-List und in den Recipes geladen werden. Puppet sortiert Ressourcen derartig um, dass möglichst wenig Veränderungen am System vorgenommen werden müssen um den gewünschten Zustand zu erreichen. Zum Beispiel, wenn an mehreren Stellen eine Konfiguration für einen Dienst verändert wird, sollte dieser nur einmal neu gestartet werden müssen. Bei Puppet spricht man von modellbasiertem Konfigurationsmanagement, während Chef ein \href{http://www.getchef.com/solutions/configuration-management/}{codebasiertes Konfigurationsmanagement} ist. Da manche Ressourcen voneinander abhängen, kann durch die Angabe der Parameter \texttt{before} und \texttt{require} die Reihenfolge festgelegt werden. Über die Parameter \texttt{notify} und \texttt{subscribe} können darüber hinaus Ressourcen aktualisiert werden, wenn sich eine Abhängigkeit geändert hat (z.B. kann ein Dienst neu gestartet werden, wenn sich die dazu gehörige Konfiguration verändert hat). In Chef kann Letzteres über die Parameter \texttt{notifies} und \texttt{subscribes} angegeben werden. \paragraph{Architektur} Wie auch Chef bietet Puppet verschiedene Betriebsmodi. Im einfachsten Fall wird mit dem Befehl \texttt{puppet apply} ein lokales Manifest geladen werden (vergleichbar mit Chef-Solo). Das Äquivalent zum Chef-Server in Chef ist bei Puppet der Puppet-Master, zu welchem sich der Client \texttt{Puppetd} verbindet und mittels SSL-Zertifikaten authentifiziert. In der Standarteinstellung setzt Puppetmaster auf den verhältnismäßig einfachen Webserver \texttt{WEBrick} Dieser skaliert allerdings nicht auf mehrere CPU-Kerne, da nur ein Prozess und Thread gestartet wird. Für Installationen mit mehr als 10 Knoten werden Passenger oder Mongrel als Applikationsserver empfohlen, wobei Nginx als Load-Balancer fungiert. Ein beliebter Ansatz zum Skalieren größerer Cluster ist das Verwalten der Manifeste in einem Git-Repository, wobei ein Cron-Job periodisch die Manifeste vom Git-Server lädt und Puppet ausführt. Während Chef-Server bis zur Version 10 wie Puppetmaster in Ruby geschrieben war, wurde der API-Teil von Chef-Server in Version 11 in der Programmiersprache Erlang neu geschrieben. Die Zahl der Nodes, die von einem Server bedient werden, soll sich dabei vervierfacht haben und kann somit bis zu 10.000 Nodes bedienen (Quelle: \cite{chefscale}). Für Puppet wurden keine Statistiken gefunden, die eine Aussage darüber treffen, wie viele Nodes pro Server betreut werden können. Allerdings ist anzunehmen, dass die Anzahl der Server, bedingt durch die genutzte Architektur, kleiner ist als bei Chef. Zu den, von offiziell von Chef unterstützten, Plattformen gehören Windows, Mac OS X, verschiedene Linuxderivate (Debian, Ubuntu, Redhat, \ldots) und Solaris. Puppet bietet breiteren Support und unterstützt zusätzlich Free- und OpenBSD sowie HP-UX und AIX. \paragraph{Résumé} Zusammenfassend lässt sich feststellen, dass Chef und Puppet den gleichen Funktionsumfang bieten. Die Grundkonzepte sind ähnlich, so ein Anwender des einen Systems mit wenig Aufwand auch das andere System lernen kann. Die beiden Firmen, Puppet Labs und Chef, entwickeln beide ihr Produkt stetig weiter und bieten kommerziellen Support. Während Puppet auf den klassischen Systemadministrator abzielt, Chef spricht den Trend der \href{http://www.getchef.com/solutions/devops/}{DevOps}-Kultur an, bei welcher Administration und Entwicklung stärker ineinander über gehen. % vim: set spell spelllang=de_de