Part two in the series about Cyso's DevOps related projects, focusing on automatic deployment of machines. Part one is here. The article is in Dutch, because this post has also been posted to Cyso's blog.

Waar waren we gebleven

In het vorige deel heb ik de concepten achter mijn visie over Automated Deployment uitgelegd. Kortgezegd zijn er drie stappen: aanmaken, installeren en configureren. Afhankelijk van het doel van de uiteindelijk beoogde machine kan voor elke stap de beste tool gekozen worden. De configuratie stap bepaalt ook in hoeverre het uiteindelijke systeem zal worden bewaakt door de Configuration Management Tool, waar ik onderscheid maak tussen volledig beheer van applicatie en hun configuratie, of het klaarzetten van applicatie voor handmatige configuratie achteraf.

Dit artikel beschrijft hoe we het bovenstaande hebben toegepast om de development machines binnen Cyso te stroomlijnen, zodat elke developer in controle is over zijn omgeving.

Developers en hun omgeving

Developers hebben een omgeving nodig om hun software op te schrijven en te testen. De beste keuze hiervoor is een omgeving die qua gebruikte software en versies zoveel mogelijk overeenkomt met de live omgeving waar het uiteindelijk op komt te draaien. Daarnaast is het zaak dat deze omgeving up-to-date wordt gehouden en het liefst iets voorloopt op de uiteindelijke live omgeving, zodat updates getest kunnen worden voordat deze worden uitgerold.

Van developers kan je niet verwachten dat ze hun eigen omgeving up-to-date houden of goede keuzes kunnen maken over hoe de machine opgezet wordt. Waarom zouden ze ook, aangezien er collega's zijn die dit de hele dag doen. De developer wil focussen op zijn eigen taak, niet op de infrastructuur die daarvoor nodig is. Wat een developer wel wil aangeven is wat zijn omgeving moet kunnen. Er moet dus onderscheid gemaakt worden tussen wat de omgeving moet kunnen (zogenaamde rollen) en hoe de machine opgezet wordt. Het eerste wordt bepaald door de developer, het laatste door de deployment tool.

Het belangrijkste is dus dat de developer zijn omgeving kan beheren op een manier die simpel is, zodat bereikt wordt wat hij wil, en goed opgezet wordt, zodat hij daarna (automatisch) te beheren is.

VMware vCloud

Simpel is het keyword. Van de twee virtualisatie technieken die ik tot mijn beschikking had (Vmware vSphere en vCloud), is vCloud het simpelst. Het biedt een webinterface waar een gebruiker op een afgeschermd deel van de infrastructuur zijn ding kan doen. De interface is zo opgebouwd dat een beginner simpele acties uit kan voeren (bijvoorbeeld een VM aan- of uitzetten), en een gevorderde gebruiker ook beschikking heeft tot krachtige tools (bijvoorbeeld netwerken beheren). Voor onze development omgevingen was vCloud mede hierom de juiste keuze.

Een ander sterk punt van vCloud is dat het een goede en vooral abstracte API aanbiedt. Concepten als “maak een VM aan” zijn in de API makkelijk te bereiken. Dit is in contrast met VMware vSphere API, waarbij de focus sterk gelegd wordt op maximale flexibiliteit. Nadeel van de vCloud API is echter dat bepaalde acties niet (of ongedocumenteerd) mogelijk zijn, bijvoorbeeld het vergroten van een virtuele disk. De development machines zijn echter vrij simpel qua opzet, en hebben deze extra features niet nodig, waardoor de eenvoud van de vCloud API de doorslag geeft in deze keuze.

Anders nog iets?

Tot zover de gedachtes en beweegredenen voor dit project, tijd voor de technische details. Zoals uit het eerste artikel bleek hebben we bij Cyso gekozen voor Chef voor onze Configuration Management tool. Omdat we met Chef op onze development omgevingen onze eigen projecten zullen uitrollen, kunnen wij hierbij kiezen om Chef de volledige configuratie te laten beheren. De uiteindelijke development omgevingen zullen dus de applicatie bevatten, inclusief configuratie en de benodigde tools en dependencies. Dit zorgt ervoor dat zodra de machine klaar is, de developer direct via zijn browser bij het project kan en kan beginnen met developen.

Uitrollen van de machine

De machines worden aangemaakt op vCloud, wat dus betekent dat er een manier nodig is om dit te doen. De webinterface is een optie, maar die is niet te automatiseren. De vSphere API wel, dus we hebben hiervoor een tool geschreven genaamd vcloud-client. vcloud-client maakt het mogelijk om met simpelweg

$ vcloud-client -c dev.conf --add-vm

een machine aan te maken in vCloud. Het meegegeven configuratiebestand bepaalt welke specificaties de machine zal krijgen, zoals CPU, geheugen, disk en naam. Een voorbeeld hiervan kan zijn:

username=<vcloud username>
password=<vcloud password>
server=<vcloud server>
organization=Cyso
vdc=Development
vapp=dev.cyso.com
catalog=cyso-dev images
template=Ubuntu 12.04 LTS AMD64 Dev
fqdn=nick.dev.cyso.com
description=Nick's development machine
network=dev.cyso.com-routed
ip=10.0.0.123

Dit kan als volgt verder onderverdeeld worden:

username=<vcloud username>
password=<vcloud password>
server=<vcloud server>

Gegevens voor de connectie met vCloud.

organization=Cyso
vdc=Development
vapp=dev.cyso.com

Waar de VM terecht moet koment binnen vCloud, In dit geval in de Organization van Cyso, het Virtual Datacenter van Development, in de vApp dev.cyso.com. De bronnen die beschikbaar zijn voor de development machines kunnen op Virtual Datacenter niveau worden geregeld.

catalog=cyso-dev images
template=Ubuntu 12.04 LTS AMD64 Dev

Hier wordt bepaald welke template er gebruikt wordt voor de machine. In dit geval is het een template van een Ubuntu 12.04 LTS installatie, die is voorbereid op Chef en vmware-tools bevat. De configuratie die de gemaakte machine krijgt wordt ook op template niveau geregeld, dit kan eventueel later worden aangepast. Indien er update beschikbaar zijn voor Ubuntu 12.04, hoeft enkel deze template geupdate te worden. Alle machines die hierna worden uitgerold zullen dan voorzien zijn van deze updates.

fqdn=nick.dev.cyso.com
description=Nick's development machine
network=dev.cyso.com-routed
ip=10.0.0.123

De FQDN is de naam van de machine zoals hij bekend is bij vCloud. Network en IP bepalen binnen welk afgescherm vCloud netwerk de machine een netwerkinterface krijgt en met welk IP adres. We kiezen hier voor een routed/NAT-enabled netwerk, waardoor we binnen vCloud gebruik kunnen maken van de ingebouwde firewall en routing opties. Dit zorgt er direct voor dat wij het interne netwerk van de development machines kunnen afschermen van de buitenwereld.

Het resultaat

Nadat vcloud-client -c dev.config --add-vm gedraaid heeft is de machine in vCloud aangemaakt. De volgende stap is de machine aanzetten. Direct hierna zal vCloud “Guest customizations” loslaten op de machine. Dit proces zorgt ervoor dat vCloud via de geïnstalleerde vmware-tools het volgende uitvoert:

  • De hostname wordt ingesteld, en is gelijk aan de naam van de VM (in dit geval dus nick.dev.cyso.com).
  • Het netwerk wordt ingesteld, en het geconfigureerde IP-adres wordt toegevoegd aan de netwerkinterface.
  • Het root wachtwoord wordt gereset en is beschibaar via de vCloud API.
  • De machine wordt gereboot.

Dit mechanisme neemt een aantal stappen uit handen en zorgt ervoor dat de machine in de basis goed is ingesteld qua hostname en netwerk, voordat hij aan Chef overgedragen wordt.

Configureren van de machine

De machine zou op dit punt al gebruikt kunnen worden, hij is alleen nog vrijwel leeg. De aanmaak- en installatiestap zijn door het uitrollen van een template in vCloud en de daarna geactiveerde Guest Customizations volledig uitgevoerd. Het enige wat nu nog rest is de configuratiestap, zodat de machine gebruikt kan worden waar de developer hem voor bedoeld heeft.

Bepalen van een baseline

Elke development machine is anders, tegelijk is elke development machine is ook gelijk aan alle andere. Bij het bepalen van een baseline wordt geïndentificeerd wat er nodig is voor elke development machine. In ons geval is dat:

  • Instellen van het netwerk. Dit is al deels gedaan door vCloud; we laten dit echter borgen door Chef door de configuratie bestanden in beheer te nemen.
  • Instellen van de SSH daemon. Doordat we templates gebruiken heeft elke uitgerolde VM dezelfde SSH server keys. Dit is onwenselijk, dus deze laten we eenmalig hergenereren.
  • Instellen van SSH toegang. Chef weet wat de SSH keys zijn van alle developers, en we zorgen ervoor dat alle developers toegang krijgen tot de development machine.
  • Installeren van SCM tools. Git en Subversion worden geïnstalleerd, zodat broncode kan worden uit- en ingechecked.
  • Installeren van editors. Vim wordt geïnstalleerd als default editor, alsmede de screen en tmux terminal multiplexers.
  • Installeren van SSH lockdown tools ( gitprompt en git-ssh-user). Deze combinatie zorgt ervoor dat we via de Bash prompts informatie over Git checkouts kunnen weergeven, en ervoor kunnen zorgen dat commits automatisch met de goede user gebeuren op basis van SSH key.
  • Installeren van Apache2 en PHP. Veel van onze projecten maken hier gebruik van, dus het is onderdeel van de baseline.
  • Installeren van database client libraries. MySQL en PostgreSQL clients en libraries worden geïnstalleerd.

Deze worden samengevoegd tot een development_baseline rol in Chef, zodat deze makkelijk kunnen worden toegewezen aan nieuwe VMs.

Bepalen van andere rollen

Met alleen de baseline eindigen we met een VM die voldoet aan onze eisen aan development machines, maar nog geen code bevat. Er zijn gevallen waarbij dit wenselijk is, bijvoorbeeld voor een volledig nieuw project waar nog geen rollen voor zijn, of voor het snel maken van een testmachine. Meestal wil een developer echter werken aan een al bestaand project. Hiervoor dient code uitgechecked te worden en configuratiebestanden aangemaakt te worden. Als het project gebruik maakt van Apache2 dan zal deze ook geconfigureerd moeten worden. Dit zijn slechts een aantal voorbeeld van randvoorwaarden aan een project, en we gebruiken Chef om dit voor ons te configureren.

Een gebruikelijk formaat voor een recept is:

  • Libraries en dependencies installeren, bijvoorbeeld modules voor PHP en Apache2.
  • Het aanmaken van een nieuwe gebruiker.
  • Het neerzetten van deploy keys waarmee Chef code uit kan checken.
  • Code uitchecken via Git of Subversion.
  • Aanmaken van configuratie bestanden voor de code.
  • Neerzetten van (self-signed) SSL certificaten.
  • Aanmaken van log directories en logrotated configuratie.
  • Aanmaken en activeren van Apache2 VirtualHosts.
  • Aanmaken van database users en het kopiëren van database templates.
  • Opruimen van deploy keys.

Bovenstaande stappen zijn gedefinieërd in een Chef recept. In de regel is er één recept per development project, welke wordt toegevoegd aan een gelijknamige rol. Aan deze rol kunnen extra dependencies worden toegevoegd, hier een voorbeeld:

  • role[development_baseline]: om te borgen dat de baseline aanwezig is.
  • role[development_anderproject]: een ander project dat aanwezig moet zijn voordat hoofdproject geïnstalleerd wordt.
  • recipe[development::extrarecept]: een los recept dat nodig is voor hoofdproject.
  • recipe[development::hoofdproject]: het project dat we aan het installeren zijn.

Chef zal op deze manier ervoor zorgen dat de recepten op de goede manier geïnstalleerd worden. Als een recept in meerdere rollen voorkomt zal hij slechts éénmaal uitgevoerd worden.

De praktijk

Het resultaat van het definiëren van de baseline en projecten als rollen, is dat een developer simpelweg uit een keuzemenu kan selecteren wat hij geïnstalleerd wil hebben. Chef heeft vervolgens alle instructies tot zijn beschikking om alle stappen uit te voeren, en een werkend geheel achter te laten.

Zodra Chef de gewenste rollen geïnstalleerd heeft is de configuratie stap afgerond, en is de machine klaar voor gebruik.

En nu makkelijk

De stappen hierboven beschrijven wat er nodig is om tot een werkend resultaat te worden. Echter, het zijn nogal wat stappen:

Rendering prettier diagram, hold on...
+------------------------------------+
| Selecteren van rollen              |
+----------------*-------------------+
                 |
+----------------*-------------------+--------------+
| Aanmaken van machine in vCloud     | Aanmaken &   |
| Aanzetten van machine              | Installatie  |
+----------------*-------------------+--------------+
                 |
+----------------*-------------------+
| Ophalen van root wachtwoord        |
+----------------*-------------------+
                 |
+----------------*-------------------+--------------+
| Chef bootstrap loslaten op machine.| Configuratie |
| Chef de machine laten configuren.  |              |
+------------------------------------+--------------+

Ons uitgangspunt was eenvoud voor de developer. We hebben ook nog het probleem dat de developer of één of andere manier makkelijk moet kunnen aangeven welke rollen hij op zijn machine wil hebben. En om het allemaal in goede banen te leiden is er een mechanisme nodig dat de bovenstaande stappen in de goede volgorde aanroept en stuurt waar nodig. Om deze reden heb ik een systeem geschreven genaamd autoprov, een simpel menu-based tool die alle stappen uit handen neemt van de developer.

De developer kan simpelweg via SSH inloggen op de provisioning server:

chaos@helix ~  $ ssh -A provisioning@master.dev.cyso.com

Om vervolgens de menu's door te lopen:

autoprov stap 1
Stap 1: machine selecteren.

Elke developer heeft zijn eigen machine.

autoprov stap 2
Stap 2: actie selecteren.

Rebuild verwijdert een eventuele bestaande machine en maakt een nieuwe aan. Reconfigure kan rollen toevoegen aan bestaande machines zonder ze te verwijderen. Destroy doet precies wat het zegt: de machine verwijderen.

autoprov stap 3
Stap 3: rollen selecteren.

Een developer kan de rollen selecteren die hij geconfigureerd wil hebben. Indien een kale machine gewenst is dwingt autoprov af dat in ieder geval de baseline rol geconfigureerd wordt.

autoprov stap 4
Stap 4: confirmatie.

Nadat de developer bevestiging geeft dat dit de gewenste acties zijn, kan het proces beginnen.

autoprov stap 5
autoprov stap 5
autoprov stap 5
autoprov stap 8
Stap 5: wachtwoord overzicht.

Zodra het proces klaar is, zal autoprov alle gegenereerde wachtwoorden voor de nieuwe machine ophalen en weergeven.

Wat hebben we bereikt?

Ons uitgangspunt was een simpel systeem maken waarmee een developer in een paar acties een volledig werkende development omgeving kan aanmaken. Hiervoor hebben we gebruik gemaakt van het model dat besproken is in het eerste deel, bestaande uit drie stappen. De eerste twee stappen hebben we voldaan voor gebruik te maken van VMware vCloud en templates, waardoor een machine binnen een paar minuten aangemaakt en geïnstalleerd wordt. Vervolgens wordt via Chef de laatste stap uitgevoerd: het configureren van de machine. Het enige wat de developer ziet van dit process is de autoprov tool, of als hij in een avontuurlijke bui is, de webinterface van VMware vCloud.

De tijd die het hele proces duurt is afhankelijk van de gekozen rollen. Voor sommige rollen zal er ook een kopie van een testdatabase worden aangemaakt, terwijl andere recepten slechts een code checkout en wat packages zijn. Echter, de meest uitgebreide machine kost ongeveer 15 minuten, wat in mijn ogen erg snel is. Een developer kan dus besluiten om zijn development omgeving opnieuw aan te maken, het proces starten, koffie halen, en binnen ongeveer twintig minuten weer aan het werk zijn.

Het volgende deel zal beschrijven hoe wij ons productieplatform hebben opgebouwd met VMware vSphere en Chef. Dit systeem houdt zich ook aan het model uit het eerste deel, maar is qua uitgangspunten en resultaat erg verschillend van de development omgevingen.