\subsubsection{Funktionsweise von Chef} \label{ssub:funktionsweise_von_chef} \href{http://www.getchef.com/chef/}{Chef} ist ein Framework, welches es ermöglicht automatisiert Server zu konfigurieren und zu verwalten. Der Endanwender beschreibt hierbei die Systemresourcen und ihre Zustände in der Programmiersprache \href{https://www.ruby-lang.org/}{Ruby}. Diese Definitionen werden von \emph{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 \emph{Chef-repo}. Diese untergliedert sich in mehrere \emph{Cookbooks}\label{cookbook}, welche die Grundverwaltungseinheit darstellt. Jedes dieser Cookbooks, erfüllt einen bestimmten Teilaspekt des Systems, (z.B. die Einrichtung eines Webservers \href{https://github.com/opscode-cookbooks/apache2}{Apache}). Coobooks können versioniert werden. Es können Abhängigkeiten zwischen mehreren Cookbooks angegeben werden. Eine physikalische oder virtuelle Maschine wird als \emph{node} bezeichnet. Einer Node können \emph{Attributes}, \emph{Roles} und Cookbooks zugewiesen werden. Roles und Cookbooks werden in eine sogenannte \emph{Run-list} eingefügt. Diese gibt die Reihenfolge angibt, in welche Roles und Cookbooks angewendet werden. Roles bieten eine Möglichkeit Nodes, welche die gleiche Aufgaben in einer Organisation besitzen, zu gruppieren (z.B. webserver). Es gibt mehrere Möglichkeiten \emph{Chef} zu betreiben: \begin{description} \item[chef-solo] Dies ist die einfachste Ausführungsform. Hierbei werden alle nötigen Daten aus einem lokalen Verzeichnis geladen. Im Gegensatz zu den anderen Methoden wird bei dieser das Programm \emph{chef-solo} gestaret. Diese Form wurde für die Umsetzung der Aufgabenstellung gewählt. \item[chef-server] Hierbei authentifiziert sich \emph{Chef-client} über eine \emph{REST-Api} zu einem \emph{chef-server} mittels eines privaten RSA-Keys. Auf diesem wird das Chef-repo zentral verwaltet. Der Chef-client bekommt von diesem alle nötigen für die zu provisionierende \emph{node}. Chef-server bietet eine Weboberfläche für die Administrierung an. Die Attribute aller Nodes sind über die eingebaute Suchemaschine \emph{Solr} durchsuchbar. \item[Enterprise Chef/Hosted Enterprise Chef] Ähnlich wie Chef-server aber bietet bessere Skalierbarkeit, rolenbasierte Benutzerverwaltung, bessere Überwachung, Push-Deployment und eine verbesserte Weboberfläche~\cite{chefenterprise} \end{description} \textbf{Aufbau eines Cookbook} \label{aufbau_eines_cookbook} Hier ist die Ordnerstruktur des Cookbook \href{https://github.com/opscode-cookbooks/apt}{apt} dargestellt: \begin{tikzpicture} \treeroot{apt-2.3.4} \altentry{attributes}{1} \altentry{default.rb}{2} \altentry{files}{1} \altentry{default}{2} \treeentry{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} \treeentry{acng.conf.erb}{3} \altentry{CHANGELOG}{1} \altentry{metadata.json}{1} \altentry{metadata.rb}{1} \altentry{README.md}{1} \end{tikzpicture} Die Verzeichnisnamen sind fest vorgeben. Jedes Verzeichnis hat seine eigene Funktion. Dies hat den Vorteil, das man sich schnell in neuen Cookbooks zurecht findet. Hier nochmal die einzelnen Verzeichnisse im Überblick: \begin{description} \item[attributes] setzt Standardwerte (Attribute) für das Cookbook. Dies können Strings, Zahlen oder Arrays sein. Die gesetzten Attribute können in Roles, Nodes oder anderen Cookbooks überschrieben werden. Hierfür gibt es die Prioritäten default, force\_default, normal und override um das überschreiben deterministisch zu machen. Attributes sind hierarchisch organisiert. In der Regel ist die höchste Ebene der Name des Cookbooks. (z.B. normal.mysql.client.packages) \item[files] Hier können statische Dateien eingefügt werden, welche dann auf dem Zielsystem in das entsprechende Verzeichnis kopiert werden können. \item[libraries] In diesem Verzeichnis 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 Packet sein. Man beschreibt, welchen Zustand (action in Chef genannt) diese Ressource haben soll und Chef versucht diesen Zustand herzustellen. Chef liefert von Haus viele wichtige Ressourcen mit. In Cookbooks kann man darüber hinaus eigene Ressourcen definieren. \item[providers] Während Ressourcen nur die Schnittstelle beschreiben, mit allen Attributen, die gesetzt werden können, ist der Provider eine konkrete Implementierung. Deswegen muss jede Ressource mindestens einen Provider besitzen. Es kann mehrere Provider für eine Ressource geben, um zum Beispiel um mehrere Plattformen/Betriebssysteme abzudecken (z.B. bei Packetmanagern oder Initsystemen). \item[recipes] In Recipes werden Ressourcen instantiiert, welche nötig sind um die gewünschte Aufgabe zu erreichen. Dabei können Abhängigkeiten zwischen diesen angegeben werden. \item[definitions] Ressourcen häufiger in verschiedenen Recipies auf ähnliche Art und Weise benötigt werden, können diese in eine \emph{Definition} ausgelagert werden. \item[templates] Häufig werden dynamisch generierte Dateien benötigt, um zum Beispiel Konfigurationsdateien zu erzeugen. Chef bindet hierfür die Templatesprache eRuby (Embedded Ruby) ein. Diese führt in den Templates Rubycode, der sich zwischen den Tags \emph{<\%} und \emph{\%>} befindet, aus. Dies erlaubt es Variablen zu interpolieren, sowie If-Statements und Schleifen. \item[metadata.rb] In dieser Datei kann der Name des Cookbook, die Version, eine Beschreibung sowie Abhängigkeiten zu anderen Cookbooks angeben werden. \end{description} Beispiel ERB-Template: \begin{lstlisting} Diese Zeile wird beim Render 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 der Node auf %> <% @node.block_device.each do |block_device, attributes| %> <%= block_device %>: <%= attributes.join(", ") %> <% end %> \end{lstlisting} \textbf{Ablauf einer Provisonierung} \label{ablauf_einer_provisionierung} Der genaue Ablauf wurde der Onlinedokumentation (~\cite{chefrun}) von Chef entnommen. Wie schon zu Beginn erwähnt wird die Provisonierung von einem Programm namens \emph{chef-client} durchgeführt. Je nach Umgebung wieder kann dieser periodisch vom Scheduler \emph{Cron} gestartet, permanent als Systemdienst laufen (z.B. bei Enterprise Chef) oder manuell gestartet werden (z.B. bei Vagrant). Als erstes lädt dieser seine Konfiguration aus der Datei \emph{client.rb}. In dieser stehen beispielsweise Informationen mit welchen Chef-Server der Client verbinden soll, an welcher Stelle temporäre Daten gespeichert werden soll und der Name der Node. Letzteres ist wichtig um die Node richtig von Chef einordnen zu können und die richtigen Einstellungen zuzuweisen. Alternativ kann der Name auch von der 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ück gegriffen wird. Ohai sammelt noch andere 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 Version, installierte Software) und die laufenden Prozesse. Diese Informationen sind durch eigene Ohai-Plugins erweiterbar und können dann 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, folgte im Falle von Chef-Server, die Authentifizierung mit diesem über den vorher auf der Node abgelegten RSA-Schlüssel. Für Adminstratoren gibt es für den \href{http://docs.opscode.com/knife\_bootstrap.html}{Bootstraprozess}, in welchem Chef initial auf der Node installiert wird, einen Validatorkey, mit dem eine Node auf dem Server registriert werden kann, umso einen Clientkey zu generieren. Anschließend werden alte gesetzte Attributes und die Run-list vom Server übertragen. Beim 1. Durchlauf oder im Falle Chef-Solo sind diese Daten nicht vorhanden (ausgenommen der voreingestellten Run-list von Chef-Server). Stattdessen kann eine Datei im JSON-Format angegeben werden, um die Attributes und der Run-list für diese Node zu spezifizieren. Durch Auswertung der eingebunden Rollen und Recipes wird eine Liste der benötigen Cookbooks ermittelt. Der Client fordert für diese eine Liste aller Dateien und deren Checksumme an. Alle geänderten oder neuen Dateien werden darauf hin heruntergeladen und im lokalen Cache gespeichert. Nun werden die Attribute zurückgesetzt und aus den Cookbooks, Roles und der Node neu generiert und entsprechend ihrer Priorität gesetzt. Die in den Cookbooks definierten Resources werden geladen und mit den von Chef mitgelieferten Resources in der Resourcecollection zusammengefasst. Nachdem alle Definitions und Libraries geladen wurden, werden schließlich die Recipes verarbeitet. In diesen werden Resourcen des Systems beschrieben und durch Actions deren Zustand festgelegt. Im nächsten Schritt folgt das sogenannte Converging. Es werden alle Resources in der Reihenfolge abgearbeitet. Dabei wird für jede Resource der für die Plattform zugehörige Provider ausgewählt. Dieser überprüft den aktuellen Zustand der Resource und verändert, wenn notwendig, das System um den Sollzustand zu erreichen. Zum Schluss überträgt Chef-client, die aktualisierten Attributes auf den Server, von welchem sie in Solr indexiert werden. Es besteht die Möglichkeit vor oder nach dem Provisioning Handler auszuführen. Diese können beispielsweise im Fehlerfall Benachrichtigungen an das Monitoringssystem oder per Email verschicken. In letzten Abschnitt (\ref{minitest_handler}) wird dieser Mechanismus genutzt um Tests auszuführen. \textbf{Vergleich mit puppet} \label{vergleich_mit_puppet} % vim: set spell spelllang=de_de