Mit etwas Glück und Disziplin schaffe ich es vielleicht, etwas über unsere Reise mit Saltstack zu berichten, und wie wir uns dem "Infrastructure as Code" Thema nähern. Wir haben mittlerweile einiges an Erfahrung mit Saltstack gesammelt, und ich hoffe, diese Erfahrungen weiter geben zu können. Ob alles, was wir machen, Best-Practise ist, bleibt abzuwarten, aber ich werde versuchen, darüber zu schreiben.
In einem ersten Post will ich über unsere Wahl zwischen Puppet und Saltstack berichten, und welche Gründe letztlich dazu geführt haben, Saltstack den Vorzug vor Puppet zu geben.
Warnung: Mitunter waren die Entscheidungsgründe hoch subjektiv!
Wir kommen aus einem Umfeld, in welchem scVenus ein Jahrzehnt lang für das Configuration Management zuständig war. 2005 war scVenus ein ausgereiftes, zuverlässiges Werkzeug einer deutschen Firma, mit welchem wir ein konkretes Problem (Umstellung vieler Server auf ein neues OS in kurzer Zeit) lösen konnten. Auch in den Jahren danach leistete scVenus gute Dienste. Es gab allerdings ein paar grundlegende Probleme:
scVenus ist ein Nieschenprodukt, das außer den Kunden von s&c niemand nutzt,
wenn man ein Problem hat, kann man nicht einfach googlen, um eine mögliche Lösung zu finden,
scVenus hat keine eigene, wirkliche DSL,
es gibt auch keinen wirklichen Resource Abstraction Layer
Anders ausgedrückt: Man merkt scVenus sein Alter an. Neuere Produkte haben auch neue Wege zur Lösung der Automatisierung gedacht und implementiert.
Irgendwann wurde es Zeit, sich auf dem Markt nach Alternativen umzusehen.
"Puppet? Wie geil ist das denn?!"
Anfang 2014 wollten wir im Rahmen eines kleinen Projektes ein neues Automatisierungstool testen und stolperten über einen Vortrag zweier Google Admins, die darüber berichteten, wie sie +40K Laptops mit Puppet administrieren.
Das klang sehr vielversprechend!
Also haben wir anhand einer Anwendung ein PoC mit Puppet erstellt und die Installation und Konfiguration vollständig in Puppet abgebildet.
Das Resource Abtraction Layer in Puppet (kurz RAL genannt) und die DSL waren eine deutliche Erleichterung gegenüber den Shell Skripten, aus denen scVenus-Methoden bestanden und ein wesentlicher, konzeptioneller Unterschied war, dass man mit modernen Configuration Management Systemen (CMS )keine Installationsanleitungen mehr schreibt, sondern Systemzustände definiert - ein kleiner, aber wesentlicher Unterschied.
Nachdem wir das Konzept von Hiera verstanden hatten, wurden auch unsere Manifeste flexibler, der Code effizienter (und übersichticher) und allgemein waren wir an einem Punkt, an welchem wir fanden, man müsste Puppet großflächiger einsetzen und damit scVenus ablösen.
"Warum muss das alles so kompliziert sein?" - erster Frust mit Puppet
Von scVenus kannten wir das nützliche Werkzeug scprdo, mit welchem man vom Master-Server aus beliebige Kommandos an eine Gruppe von Servern schicken kann, welche das Kommando dann ausführen.
Verwundert stellten wir fest, dass es bei Puppet nichts Vergleichbares gibt. Jedenfalls nicht von Hause aus.
"Aber es gibt doch MCollective!"
MCollective ist das Orchestrierungstool von Puppet, welches man aber extra installieren muss.
Wenn man die Inhaltsangabe der Installationsanleitung liest, ahnt man, dass das kein großer Spaß wird, erst recht nicht, wenn die eigene Infrastruktur hinter einer Firewall sitzt und man keinen direkten Internetzugang hat.
Und wenn man es dann erst mal installiert hat, dann kann es kaum etwas. Dann kann man vielleicht Services starten und den puppet-agent antriggern, aber dann ist auch bald schon Schluß. Um MCollective so richtig nutzen zu können, muss man dann eigene Agenten schreiben (was nicht sonderlich intuitiv ist).
Kurzum: Wir ließen von MCollective die Finger.
Ein anderer Punkt, der uns mitunter bitter traf: Hiera löste die Daten anders auf, als wir es angenommen hatten und folgerichtig liefen Installationen und Konfigurationen nicht so, wie wir das erwartet hätten.
Das war kein Bug in Hiera, sondern eine falsche Implementierung unsererseits, aber was uns Nerven kostete, waren die fehlenden Debugging-Möglichkeiten.
Wie löst man für einen speziellen puppet-agent seine für ihn gültigen Hiera Daten auf?
Auf dem Client kann man das nicht tun, weil der Client offenbar selber keine Hieradaten kennt, und erst während des puppet-runs selbige übermittelt bekommt.
Auf dem Master kann man Hieradaten nur zuverlässig für den Master selbst auflösen.
Ist dieser bspw. in einem "prod" Environment und der zu testende Server in einem "dev" Environment, dann kann man keine korrekte Hiera Data Auflösung mehr durchführen, weil die Envs nicht stimmen, bzw. nicht gleich sind. Und wenn das doch gehen sollte, so schweigt sich die Doku darüber aus.
Dependency Cycles. Eine kleine Änderung im Code und PENG! - Puppet sieht sich gegenseitig bedingende Abhängigkeiten, die einen Kreis bilden und aus dem es nicht mehr rausfindet.
Das es sich dabei um eine fehlerhafte Implementierung unsererseits handelte, war klar, aber Puppet selbst war nicht sonderlich hilfreich, wenn man dieses Problem lösen wollte: Es verwies auf Graph-Tools mit denen man seinen Code analysieren sollte, um den DC zu finden. Und wenn man einmal diesen nicht ganz einfachen Prozess des Importierens der entsprechenden Daten hinter sich hatte, dann bekam man einen Graphen zu sehen, dessen Komplexität und Umfang einem auch nicht half, das Problem zu lösen.
Einfacher war es, in Git die letzten Änderungen nachzuvollziehen und so dem Problem auf die Spur zu kommen.
Ab und an will man, dass Puppet mal inne hält und nichts macht. Also müsste man den Puppet Agenten stoppen.
Da es kein einfaches Orchestrierungswerkzeug gibt, muss man sich also doch mit den Servern per ssh verbinden und Puppet stilllegen (und später wieder in Betrieb nehmen).
Das ist unpraktisch und führt doch wieder zu MCollective, welches aber, wie oben beschrieben, auch nur weh tut, wenn man nicht gerade die Enterprise Variante von Puppet installiert, welche MCollective von Hause aus mitbringt.
Am Ende waren wir so weit, dass wir uns fragten, ob es nicht Alternativen zu Puppet geben könnte, die besser unsere Bedürfnisse abdecken würden.
"Probiert doch mal Saltstack"
Wir bekamen den Tipp, einen Blick auf Saltstack zu werfen.
Zu diesem Zeitpunkt waren die Schmerzen mit Puppet schon ziemlich akut und infolgedessen die Bereitschaft, sich umzusehen, entsprechend groß.
Die erste Anlaufstelle war Youtube, der bequemste Weg, sich in einer Mittagspause zu einem Thema berieseln zu lassen und einen ersten Eindruck zu verschaffen. Das erste Video, das wir uns ansahen, war eines von Thomas Kramm.
Wenn man sich erst einmal an seine Stimme gewöhnt hatte, war der erste Eindruck von Saltstack wirklich beindruckend: So leicht ließ sich ein Master aufsetzen? So einfach waren die Clients (Minions) eingerichtet? Und Salt brachte die Orchestrierung einfach gleich mit?
Eine weitere interessante erste Informationsquelle war ein Blogpost von Ryan D Lane, der Ansible mit Saltstack verglich. Nach dem Studium dieses Posts wussten wir zumindest, dass wir nicht unbedingt Ansible als erstes würden betrachten wollen.
Einige Videos später waren wir ermutigt genug, eine Saltstack Testumgebung zu bauen und erste Versuche darin zu unternehmen.
Mit wachsener Erfahrung im Betrieb von Puppet und der Kenntnis über unsere Infrastruktur, hatten wir in etwa folgende Anforderungen an ein CMS:
Einfache Installation aller benötigten Komponenten (Master- und Clientsoftware)
Eine aktive, umgängliche und hilfsbereite Community
Eine Orchestrieungskomponente
Möglichst geringer Resourcenbedarf des Masters und der Clients (wegen Sandboxing von Entwicklungsumgebungen mithilfe von VMs)
Während wir also damit begannen, Slatstack näher in Augenschein zu nehmen, behielten wir unsere Anforderungen im Hinterkopf und verglichen sie mit unseren Erfahrungen.
Saltstack wartete zu Beginn schon mit einer ungewohnten Hürde auf: Das Vokabular.
States, Modules, Pillars, Grains, Minions, Master, Highstate, Lowstate und was nicht alles noch.
Gottseidank hat ein sympathischer Typ namens Peter Baumgartner dazu auf der PyCon 2014 einen informativen Vortrag gehalten.
Am Ende, wenn man einmal die wesentlichen Unterschiede verstanden (Unterschied Module und State sowie Grain und Pillar) und man das Konzept der top.sls verinnerlicht hat, kann man auch schon anfangen und mit Saltstack sinnvolle Dinge tun.
Und sinnvolle Dinge kann man eigentlich sofort mit Saltstack anstellen.
"Das ist ja irre!" - Erste Erfolge mit Saltstack
Schon während der ersten Versuche, irgendetwas Sinnvolles mit Saltstack anzustellen, stießen wir auf salt cmd.run. Ein einfacher Befehl, mit dem man alles mögliche auf all seinen Servern gleichzeitig erledigen lassen kann - das scprdo Äquivalent von scVenus - wofür es nicht mal bei Puppet Enterprise etwas Vergleichbares gibt.
Und dann warfen wir mal einen genaueren Blick auf die Builtin-Modules von Saltstack - also Funktionalität, die von Hause aus schon mit dabei ist - und waren baff: 200+ Module, die man einsetzen konnte, ohne ein einziges Manifest (oder in Salt-Sprech: State) schreiben zu müssen.
Puppet ist nach der Grundinstallation noch völlig wertlos, bei Salt hat man nach der Erstinstallation bereits einen prall gefüllten Werkzeugkastern zur Verfügung.
Das war sehr vielversprechend!
Also überlegten wir, testweise unsere Servergrundkonfiguration in Saltstack zu implementieren.
Das würde uns ein Gefühl vermitteln, wie flexibel und intuitiv Saltstack im Betrieb wäre.
Wenn man mit der DSL von Puppet vertraut ist, fällt der Umstieg nach Saltstack nicht so schwer.
Allerdings schreibt man States (Puppet = Manifests) jetzt in YAML, was eine saubere Formatierung des Codes voraussetzt.
Das ist gut! Es zwingt alle beteiligten zu einer einheitlichen Schreibweise und vielleicht können wir das später auch linten.
Allerdings muss man erst das Prinzip der State-IDs begreifen und sich insbesondere mit der Definition von Bedingungen anfreunden, ebenso mit der Template-Engine Jinja.
Es war definitiv ein initialer Aufwand nötig, sich mit dem Templating, den States, Pillars, top.sls und Environments auseinanderzusetzen, um Saltstack sinnvoll und effizient einsetzen zu können.
Aber mit den Vorkenntnissen von Puppet war das in einem akzeptablen Zeitrahmen machbar.
Innerhalb von vielleicht 10 PT war unsere Severgrundkonfiguration implementiert und es war bereits erkennbar, dass vieles deutlich einfacher, flexibler und schneller funktionierte, als mit scVenus (und auch im Vergleich zu Puppet).
Währenddessen hatten wir jedoch auch einige Bugs in Saltstack gefunden und auch hier immer wieder mal das Bedürfnis, den Kopf auf die Tischplatte zu schlagen.
Trotzdem gab es deutlich weniger Bauchweh als mit Puppet und innerhalb kurzer Zeit fingen wir an, die Module regelmäßig zu nutzen und uns immer weniger per SSH mit den Servern zu verbinden.
Und das war ein gutes Zeichen!
Pro & Cons Puppet vs. Saltstack
Vielleicht noch einmal etwas gesammelt die Vor-und Nachteile der beiden CMS, wie wir sie wahrgenommen haben:
Standard-Tool. Jeder kennt es, so ziemlich jeder aus dem Ops-Umfeld hat damit Erfahrungen.
Ausgereift. Alle Fallstricke, Probleme sind irgendwo dokumentiert, Google führt recht zuverlässig zu den gängigsten Lösungen zu den gängigsten Problemen.
Eine sinnvolle Enterprise-Edition, die ggü. der OSS Edition einen echten Mehrwert bietet (das Dashboard, einfachere Installation der Einzelkomponenten).
Man findet viele Schulungsanbieter, externen Support, externe Expertise.
Puppet Forge ist eine Quelle für eine sehr große Anzahl an sehr guten Modulen/Manifests.
Man merkt, das Hiera und MCollective dazu gekauft worden sind. Die Integration ist miunter hackelig.
Es ist nahezu unmöglich, Mergerequests durchzubekommen, selbst bei Bugfixes. So wurde es uns zumindest von einem unserer externen Dienstleister berichtet, welcher Fixes für die Kerberos Authentfizierung des Clients am Master eingereicht hatte, welche abgelehnt wurden ("Sorry, aber das ist Code aus dem Core, und zwar welcher, dessen Entwickler nicht mehr da ist und den wir selber nicht so genau verstehen. Deswegen können wir deinen Fix nicht annehmen!").
Puppet und Debugging ist schwieriger, als es sein sollte.
Die Installation aller Komponenten (inklusive MCollective) ist nur in der Enterprise-Edition einfach, während es in der Community Edition weh tun kann. Auch ist die Anzahl der Abhängigkeiten der Puppet Pakete zu anderen Pakteten im Vergleich zu Salt sehr hoch. Man muss sehr viel an Overhead in Kauf nehmen.
Orchestrierung ist nur mit einigem Aufwand vernünftig zu realisieren.
Ohne Manifests ist Puppet nutzlos.
Saltstack ist schnell installiert, die Abhängigkeiten sind überschaubar, ebenso der Resourcenbedarf.
Nach der Installation hat man auch ohne States bereits eine ganze Reihe nützlicher Werkzeuge zur Administration und Orchestrierung zur Hand. Man ist ist gleich von null auf 100.
Pillars im Zusammenhang mit Grains (was bei Puppet in etwa Hieradaten und Facts entspricht) und der top.sls sind ein mächtiges Werkzeug, variable Daten Hosts zuzuweisen und so die States möglichst modular zu halten. Pillars lassen sich kumulativ zuweisen, was großartig ist, wenn man beispielsweise mit Rollen arbeitet und innerhalb der Rollen unterschiedliche Variablen dynamisch zusammensetzen möchte. Hiera in Puppet ist hierarchisch organisiert, was Limitierungen mit sich bringt, Saltstack hingegen organisiert seine Pillars so, dass sie sich gegenseitig ergänzen können.
Probleme mit Pillars lassen sich ziemlich einfach debuggen - zumindest im Vergleich zu Puppet. Das CLI bietet hierzu das passende Werkzeug.
Grains (Puppet: Facts) lassen sich zentral vom Master aus einem Host oder einer Hostgruppe zuweisen, ohne dass es dafür extra einen State braucht. In Puppet benötigt man hierfür ein Manifest und Hiera.
Saltstack ist in Python geschrieben, die States in YAML. Das ist irgendwie cooler als Ruby (das ist höchst subjektiv, jaja)
Wenn man einen Bug findet und einen Fix dazu als Pullrequest auf Github einstellt, stehen die Chancen gut, dass dieser akzeptiert wird.
Formulas haben bei weitem nicht den Umfang und die Qualität der Module auf Puppet Forge.
Die Designpattern für Formulas scheinen nicht zu Ende gedacht. Man könnte auch sagen, sie existieren eigentlich nicht.
Manchmal funktioniert einfach etwas nicht wie erwartet. Man merkt mitunter, dass Saltstack eben doch noch nicht so alt ist wie Puppet.
Es gibt kaum Schulungsanbieter, externe Expertise ist schwer zu kaufen. Im Zweifel leisten wir auch so etwas wie Pionierarbeit (was aber vielleicht auf der Pro-Seite stehen sollte).
Es gibt keine wirkliche Enterprise Variante, bei der man die inhaltlichen Vorteile sehen würde, kein Dashboard etc. Wobei man auch hier streiten kann, ob es das dringend braucht.
Die Windowsunterstützung soll weniger umfangreich sein als beispielsweise bei Chef - wobei Chef hier auch als Marktführer gilt.
Ich habe mit Leuten gesprochen, die sich negativ über die ZeroMQ geäußert haben und dies als Sicherheitsproblem benannten. Andererseits waren das Ausnahmen, und ich konnte im Netz keine prinzipiellen Bedenken finden, welche diese Kritik gestützt hätte.
Jinja kann manchmal ganz schön nerven und schwer lesbar sein.
Auch wenn Puppet der etablierte Marktführer ist, hatten wir nicht das Gefühl, dass er das beste Produkt anbietet. Saltstack hat mitunter Probleme, wenn etwas mal anders funktioniert als erwartet, aber die Basis ist vielversprechend und wirkt runder, vollständiger und die Komponenten untereinander sauberer zusammengesetzt.
Insgesamt hatten wir das Gefühl, dass Saltstack eine rosige Zukunft vor sich hat und unseren Anforderungen vollständiger genügt, als das bei Puppet der Fall wäre.
Saltstack fühlt sich mehr nach scVenus an als Puppet, und das erhöht auch die Akzeptanz bei den alteingesessenen Ops-Leuten.
Am Ende entschied auch eine gehörige Portion Bauchgefühl zwischen beiden CMS. Und bisher haben wir es nicht bereut, auf unsere Intuition gehört zu haben.
Trotzdem sind wir gespannt, was passieren wird, je komplexer unsere Salt Architektur wächst.
In den nächsten Postings will ich etwas über Organisation reden:
Wie organisieren wir den Code,
wie wollen wir die Zusammenarbeit der Admins untereinander koordinieren,
wie soll die Code Qualität gehalten, bzw. verbessert werden,
welche Ideen haben wir, schnell, flexibel und trotzdem zuverlässig unsere Infrastruktur wachsen zu lassen...
Bleiben Sie also an den Hörfunkgeräten!