\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 dem Program \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}). Cookbooks
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 dazu in die sogenannte \emph{Run-list} der
Node 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 heißt bei dieser das auszuführende Programm
    \emph{chef-solo} statt \emph{chef-client}. Diese Form wurde für die
    Umsetzung der Aufgabenstellung in
    Abschnitt~\ref{ssub:einrichtung-der-netzwerkdienste} 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 Informationen für die zu provisionierende \emph{Node}.
    Chef-server bietet eine webbasierte GUI für die Administration an. Die
    Attribute aller Nodes sind über die eingebaute Suchemaschine \emph{Solr}
    durchsuchbar.
  \item[Enterprise Chef/Hosted Enterprise Chef] Ähnlich wie Chef-server bietet
    aber eine bessere Skalierbarkeit, rolenbasierte Benutzerverwaltung, bessere
    Überwachung, eine verbesserte Weboberfläche sowie Push-Deployment an.
    Während Hosted Enterprise Chef die Firma Chef den Serverteil betreibt, ist
    bei Enterprise Chef der Server in der eigenen
    Organisation~\cite{chefenterprise}
\end{description}

\textbf{Aufbau eines Cookbook}
\label{aufbau_eines_cookbook}

Hier ist die Ordnerstruktur eines Cookbooks am Beispiel von
\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 von anderen Cookbooks überschrieben werden. Hierfür gibt
    es die Prioritäten default, force\_default, normal und override um die
    Reihenfolge zu beeinflussen. Attributes sind hierarchisch organisiert. In
    der Regel ist die höchste Ebene der Name des Cookbooks. (z.B.
    \emph{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 können man darüber hinaus eigene
    Ressourcen definiert werden.
  \item[providers] Während Ressourcen nur die Schnittstelle mit allen Attributes
    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 um mehrere Plattformenvarianten oder Betriebssysteme abdecken zu
    können (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, welche häufiger in verschiedenen Recipes auf
    ähnliche Art und Weise benötigt werden, können 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 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 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 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 - siehe~\ref{ssub:einrichtung-der-netzwerkdienste}).

Als erstes lädt dieser Prozess seine Konfiguration aus der Datei
\emph{client.rb}. In dieser stehen beispielsweise Informationen mit welchen
Chef-Server der Client sich 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 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, folgt 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, dafür einen Validatorkey.
Mit diesem kann eine Node auf dem Server registriert werden, 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
