\subsubsection{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. (TODO -
Provisionierung und Deployment) 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 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}.
Ein solches untergliedert sich in mehrere \emph{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 \emph{Nodes} 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 an, in welcher Roles und Cookbooks
angewendet werden. Roles bieten eine Möglichkeit, Nodes zu gruppieren, welche die
gleichen Aufgaben in einer Organisation erfüllen (z.B. Webserver).

Es gibt mehrere Möglichkeiten \emph{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
    \emph{Chef-Server} und \emph{Enterprise Chef} wird bei Chef-Solo das
    Programm \emph{chef-solo} an Stelle von \emph{chef-client} ausgeführt. 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
    Attributes aller Nodes sind über die eingebaute Suchmaschine
    \href{https://lucene.apache.org/solr/}{\emph{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 den Serverteil betreibt und die Skalierung des Dienstes
    übernimmt, ist bei Enterprise-Chef der Server in der eigenen
    Organisation~\cite{chefenterprise}.
\end{description}

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

Nachfolgend 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] Attributes 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.
    \emph{normal.mysql.client.packages}). Werte können Strings, Zahlen oder
    Arrays sein. Die gesetzten Attributes können in Roles, Nodes oder von
    anderen Cookbooks überschrieben werden. Hierfür werden die Attributes mit
    den verschiedenen Prioritäten default, force\_default, normal und override
    gesetzt (aufsteigender Wertigkeit) gesetzt, wobei eine höhere Priorität eine
    Niedrigere überschreibt.
  \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
    Resource 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
    Resources 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 Paketmanagern oder Initsystemen TODO - Initsystemen
    erklären). In eigenen Cookbooks erstellte Resources/Provider nennt man LWRP
    (Lightweight-Resource/Provider).
  \item[recipes] In Recipes werden Ressourcen instanziiert, welche nötig sind,
    um die gewünschte Ziel zu erreichen. Dabei können Abhängigkeiten zwischen
    Recipes angegeben werden.
  \item[definitions] Ressources, welche häufiger in verschiedenen Recipes in
    ähnlicher Form benötigt werden, können in eine \emph{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
    Rubycode ausgeführt, der sich zwischen den Tags \emph{<\%} und \emph{\%>}
    befindet. Dies erlaubt es einerseits den Inhalt von Variablen oder den
    Rückgabewert von Methoden zu interpolieren, andererseits können in Templates
    Kontrollstrukturen wie If-Statements und Schleifen verwendet werden.
  \item[metadata.rb] In der Datei \emph{metadata.rb} kann der Name des Cookbook,
    die eigene Version, eine Beschreibung sowie Abhängigkeiten zu anderen
    Cookbooks angegeben 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 gewählter 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 die URL des Chef-Server, in
welchem Pfad temporäre Dateien gespeichert werden und der Name der 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 Chef-Client mit
Chef-Server. Die Authentifizierung erfolgt über den vorher auf der Node
abgelegten RSA-Schlüssel. Für Administratoren gibt es einen Validator-Key. Im
\href{http://docs.opscode.com/knife\_bootstrap.html}{Bootstraprozess}, in
welchem Chef initial auf der Node installiert, kann mit diesem eine Node auf dem
Server registriert werden und ein Clientkey generiert werden.

Anschließend werden alte gesetzte Attributes 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 Attributes und der 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 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 Resource-Collection zusammengefasst. Nachdem alle Definitions
und Libraries geladen wurden, werden schließlich die Recipes verarbeitet. Die
darin erstellten Resources beschreiben das System. Für jede Resource wird eine
Action festgelegt, was gleichbedeutend mit deren Zustand ist.

Im nächsten Schritt folgt das sogenannte Converging (englisch für
\emph{Angleichen}). Es werden alle Resources Schritt für Schritt 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 Handler vor oder nach dem Provisioning 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.

\textbf{Vergleich mit puppet}
\label{vergleich_mit_puppet}\\
Ein anderes weiteres verbreitetes Konfigurationsmanagmentsystem ist Puppet. Es
ist das ältere der beiden Projekte. Während die erste Puppetrelease bereits im
Jahr 2005 von den Puppet Labs veröffentlicht wurde, erschien Chef erst 4 Jahre
später im Jahre 2009. Chef wurde stark beeinflusst von Puppet. Der Erfinder von
Chef Adam Jacob war selbst langjähriger Puppetnutzer bevor er Chef oder wie es
in den 1. Versionen hieß <TODO>, schrieb.
- Konsultantfirma: Infrastruktur bis zum Deployment
- mangelnde Abstraktionsmöglichkeiten
\cite{chefhistory}.

%- bei beiden Projekte ist Clientkomponente in Ruby geschrieben.
%- Chef: Konfigurations in Ruby
%- Puppet: eine auf Puppet optimierte, vereinfachte Sprache
%  -> einfacher für Einsteiger und Nicht-Programmieren
%  -> Grund für manche Firmen -> wird um Umschulung zu sparen
%  -> weniger flexible als Ruby (Grund bei Facebook, TODO youtube-Link, mehre Cluster mit mehr als 10.000 Nodes mit Chef provisionier)
%- Während die Regeln und Beschreibung in Chef standartmäßig in der Reihenfolge abgearbeitet
%  wird in der sie geladen werden, sortiert Puppet diese um. In beiden kann die
%  Reihenfolge durch Spezifikation von Abhängigkeiten umsortiert werden (Später
%  ein Beispiel)
%
%Note:
%- Puppet: eigene Sprache -> komplexere Codebasis
%- Um die Größe der Community abzuschätzen (schwierig): Suchtreffer für Repositories bei Github
%- Alter(Puppet) > Alter(Chef)
%- Chef Enterprise vs Puppet Enterprise: Hinter beiden Projekten stehen Firmen, Weiterentwicklung des Produkt, bieten Support und Hosting an
%- Resume: Ähnliche Projekte, lösen das gleiche Problem auf unterschiedliche
%  Weise

% vim: set spell spelllang=de_de
