Dit topic is tegelijk geopend met mijn blogpost over de voorbeeld code 
Boudewijns blogje: Waarom configuratie-management met Puppet cool is!
Boudewijns blogje: Waarom configuratie-management met Puppet cool is!
Puppet? | ||||||||||||||||||||||||||
Puppet is een bekend configuration management (CM) systeem dat in Ruby is geschreven , en ook van een Ruby DSL (domain specific language) gebruik maakt voor zijn configuraties. CM is een techniek waarmee je op een gestructureerde manier systeemconfiguraties kunt centraliseren. Puppet is FOSS, alhoewel er ook een enterprise versie is. | ||||||||||||||||||||||||||
Wat heb ik eraan? | ||||||||||||||||||||||||||
Je configuraties worden overzichtelijker, minder werk om uit te rollen, minder foutgevoelig en je kunt makkelijker configuraties tussen machines verplaatsen/syncen. offtopic: Uiteraard is er ook een bescheiden leercurve te doorlopen...maar dat mag geen naam hebben Het spreekt voor zich dat in een omgeving met veel machines je het meeste aan puppet hebt (1 maal instellen, x maal uitrollen), maar op een enkele machine kan het ook al heel nuttig zijn. Je hebt namelijk overzicht, en je kunt je changes aan je systeem ook terugdraaien als je je puppet configuratie in een versiebeheer-tool (git, svn) stopt. | ||||||||||||||||||||||||||
Waar werkt het op? | ||||||||||||||||||||||||||
| ||||||||||||||||||||||||||
Hoe werkt het? | ||||||||||||||||||||||||||
Je hebt een puppetmaster waar je systeemdefinities op staan, en deze machine kan verschillende puppet-nodes als client hebben. Dit is dus een klassieke client-server architectuur. Een client controleert elke X (standaard in debian 30) minuten zijn systeemstaat met de staat zoals deze volgens de puppetmaster moet zijn en zal eventuele aanpassingen uitrollen. Je statements zijn opgebouwd uit klassen: een client kan tot een classe behoren en zal dan die eigenschappen overnemen. Binnen de klassen kun je templates (defines in puppet termen) definieren die in feite te vergelijken zijn met een functie als je in object-oriented-programming taal denkt. Hier zijn zelfs grafische interfaces voor (Foreman, puppet dashboard). In je klasse (en in je defines) kun je een aantal standaard resource types gebruiken om aan te geven hoe je systeem eruit ziet. Voorbeelden hier van zijn:
Van elk van deze types kun je een aantal dingen aangeven,bijvoorbeeld of de service geinstalleerd moet zijn (of juist niet!), of hij moet draaien, en waar het initscript staat. Voor de overige resources zijn er ook dergelijke eigenschappen. Omdat we het hier over systeemstaten hebben is Puppet een declaratief framework: je beschrijft hoe het systeem eruit moet komen te zien. Goed, genoeg info... tijd voor een voorbeeld. Dit voorbeeld is vast niet perfect (commentaar is altijd welkom) maar bedoeld om te laten zien hoe cool puppet is in de praktijk zonder daarbij heel complex te worden. Ook is het geen complete stap voor stap tutorial, maar meer een showcase van de mogelijkheden zonder al te complex te worden. Wel is onderstaande code de daadwerkelijke code zoals ik die gebruik voor mijn servers. Als mensen willen weten hoe ze puppet hier op kunnen zetten, of dit voorbeeld in de praktijk kunnen gebruiken zijn ze welkom om om meer informatie te vragen. Ik heb zelf een aantal webservers waarop ik vhosts configureer in apache. Dat kan prima met de hand, maar via puppet is het makkelijker. Hiervoor heb ik een recipe gemaakt.. Hierin regel ik:
De klasse hier is apache, en de functie "simple-vhost". Er kan vast ooit nog een complex-vhost komen. Mijn code heb ik gebaseerd op diverse informatiebronnen/tutorials en voor mijn eigen gebruik ingericht. Het is deels creatief knippen en plakken, en deels van mezelf. Je mag deze code vrij gebruiken. Alle onderstaande code staat in het recipe, en het hele recipe is te vinden op: http://pastebin.com/J2AaMAev De code: code:
Hier geef ik aan dat apache2 en awstats geinstalleerd moeten zijn. Puppet zoekt zelf uit of dat via apt, yum of wat anders moet gebeuren. code:
Hetzelfde geldt voor php, waarbij ik echter ook meteen aangeef dat de package 'apache2' eerst geinstalleerd moet zijn. Dit zorgt er namelijk voor dat de php configuratie meteen in apache wordt gezet door APT. Het maakt niet uit of ik php in mijn klasse voor of na apache2 definieer, maar hij moet wel netjes aangemaakt worden. code:
Als de package apache is gestart, wil ik ook dat de daemon wordt gestart. In het geval van apache zijn de initscripts en dergelijke goed in orde dus hoef ik weinig anders aan te geven dan dat de daemon moet starten (ensure running), hij bij boot moet starten (enable) en dat de apache package geinstalleerd moet zijn. Dat laatste klinkt zeer logisch, maar je weet bij Puppet niet in welke volgorde je definities gesynchroniseerd worden. Hiermee voorkom ik dat een systeem eerst apache probeert aan te zwengelen en daarna de package gaat installeren. Nu komen we bij het interessante deel: ik heb een sjabloontje gemaakt voor virtual hosts... deze roep ik voor elke virtualhost een keer aan buiten mijn recipe: code:
Dit is te vergelijken met een functie. Sowieso moet je een naam opgeven voor je vhost (omdat het een declaratieve omgeving is...) waardoor dat geen aparte parameter wordt. Daarnaast kun je een attribuut voor de admin (het mailadres in geval van storing), een array (maak hier even een mental note van) van aliassen en een documentroot opgeven. Dit is optioneel, als je geen mailadres opgeeft wordt mijn default mailadres (beheer@foo.bar) gebruikt. De documentroot wordt anders op "" (een lege string) gezet, dit komt later nog aan bod. code:
In de define body definieer ik vervolgens een file (deze file wordt dus voor elke keer dat de define wordt gebruikt, en dus een vhost wordt aangemaakt gecreeerd). De variabele $name wordt door puppet automatisch gezet op naam van de instantie van de vhost. Zo'n vhost definitie ziet trouwens als volgt uit: code:
Hierbij heet de vhost in kwestie (en dus de $name variabele!) "www.foo.bar" respectievelijk "test.foo.bar". www.foo.bar heeft een Alias op foo.bar. Goed, terug naar de puppet code: Het aanmaken van de virtualhost file verijst de definitie voor de apache2 package en service al toegepast zijn, met andere woorden apache moet geinstalleerd zijn en de daemon moet draaien. Vrij logisch. Vervolgens zien we deze regel: code:
Hier wordt eigenlijk een extern bestand van de puppetmaster gebruikt, (in apache/vhost.conf) wat de vhost-file definieert: code:
Dit is een standaard vhost file, waarbij opvalt dat op een aantal plekken Ruby-code staat( in de <% en <%= tags ). De <%= foo %> tags worden door puppet vervangen door de waarde van de variabele foo in de define. Dit zien we terug in de name (de naam van de vhost) en de admin (die standaard beheer@foo.bar is) variabele. De name wordt vervolgens ook gebruikt voor de documentroot. We zagen ook dat de aliassen in array vorm waren opgegeven bij declaratie van een vhost. We zien nu waarom: een we iteren met gewone ruby syntax door die array en maken voor elk element een ServerAlias tag aan in de vhost-configuratie. Dit gebeurt door het aliases.each statement. Is de array leeg? dan wordt er geen ServerAlias regel aangemaakt. Met de <% end -%> geef ik aan dat de each-lus is afgelopen. Voor de logging gebruik ik wederom de name variabele. Een vhost voor www.foo.bar met als alias foo.bar en test.foo.bar komt er dan zo uit te zien: code:
De ServerAliassen kunnen ook op 1 regel, maar je moet daarbij tussen alle elementen een , hebben. Hierbij zou je het alias neer moeten zetten en als geldt het alias niet het laatste in de array is een komma. Dat is lastiger qua puppetcode, daarom heb ik voor deze vorm gekozen. De file in puppet is gedeclareerd als: code:
Dit betekent dat de configuratie die met die template is aangemaakt dan ook meteen in /etc/apache2/sites-available/www.foo.bar wordt gezet... wat exact de bedoelign is Hierna willen we de site enablen, en hiervoor gebruiken we een exec-resource. Exec voert shell-commando's uit (verrassing!). code:
De resource zelf zal uitvoeren "/usr/sbin/a2ensite $name; /usr/sbin/apache2ctl graceful", dit enablet de site en herstart apache. Echter willen we dit in verband met de performance niet elke puppetrun doen. Daarom gebruiken we de subscribe-eigenschap: dit zorgt ervoor dat de resource (in dit geval de exec) alleen wordt uitgevoerd als de resources waarop de eerste resource is gesubscribet veranderen. Met andere woorden: de puppetclient kijkt of de configuratiefile van de vhost op de client is aangepast, en herstart dan apache als dat zo is. Is de file niet aangepast... dan herstart hij apache niet. Erg handig dus! Nu hebben we een vhost gedefinieerd in apache, en apache herstart maar nog geen webroot: code:
offtopic: Ik weet dat dit in 1x moet kunnen maar moet dat nog een keer uitpluizen. We maken hier de directories aan met het file resource type, waarbij we met ensure => directory zorgen dat het een directory is. Ik denk dat wel duidelijk is hoe bovenstaande werkt. Als laatste heb ik ook een aw-stats configuratie die aangemaakt wordt zodat klanten op www.foo.bar/cgi-bin/awstats.pl hun awstats kunnen bekijken. code:
Ook hier gebruik ik een template zoals bij de vhost. De template is niet erg boeiend en zal ik hier ook niet neerzetten tenzij men hier behoefte aan heeft. De extra accolades sluiten de klasse die we in de eerste code-snippet zijn begonnen weer netjes af. Op de puppetmaster kan ik met 1 enkele regel code een vhost aanmaken en inrichten op servers. Wil ik een vhost van server1 naar server2? Dan copy-paste ik de regel (en moet ik mijn DNS aanpassen) en ik ben klaar. Supermooi dus. Andere dingen die ik in puppet heb zitten:
Ik zie op GitHub bijna voor alles wel een recipe: KVM virtual machines, Nagios monitoring, Mysql DB's, firewalls, asterisk, noem maar op. | ||||||||||||||||||||||||||
Waarom dit topic? | ||||||||||||||||||||||||||
Nou het valt eerlijk gezegd op dat hier op GoT weinig mensen over Puppet praten terwijl het toch echt booming business is. Ook is het, wat mij betreft, de fijnste configuration management tool, alhoewel Chef ook heel aardig schijnt te zijn. Ik heb echter om niet-technische redenen voor puppet gekozen. Het doel van dit topic is fijn over puppet in het algemeen en technische tips en trucs te praten. Ook hoop ik dat wat meer mensen hun coole (of juist heel simpele) recipes showen. Ook zou het leuk zijn als mensen wat informatie geven over hun setup, of bijvoorbeeld Foreman. | ||||||||||||||||||||||||||
Toffe links? | ||||||||||||||||||||||||||
|
Ik heb elektra-inbouwmaterialen over? Kopen? Zie: hier