Continuous Deployment in Windows Azure

Beim letzten Mal haben wir gesehen wie man MongoDB in Windows Azure betreiben kann. Heute möchte ich in eine andere Richtung gehen, die ich auch im letzten Jahr in einer vierteiligen Videoserie in Zusammenarbeit mit der Developer Platform Evangelism Group von Microsoft Deutschland aufgenommen habe. Es soll um Continuous Deployment in Windows Azure gehen. Die Videoserie damals beinhaltete die schnelle und sichere Bereitstellung von Webanwendung auf Windows Azure und setzte sich aus folgenden Teilen zusammen

Heute möchte ich das Thema erneut aufgreifen, da auf der einen Seite das Thema immer noch sehr aktuell ist und auf der anderen Seite hat sich Windows Azure in dieser Hinsicht stark weiterentwickelt. Wenn ich sage “stark weiterentwickelt” heißt das nicht, dass Microsoft alles über den Haufen geworfen hat, was vor einem Jahr noch aktuell ist. Ganz im Gegenteil: Alles, was damals möglich war ist es heute immer noch. Durch die großartige Arbeit des Team Foundation Server- und Windows Azure-Teams haben wir heute aber noch bessere und einfachere Möglichkeiten. Aber zuerst die Grundlagen!

Was ist Continuous Deployment?

Diese Frage zu beantworten ist schwieriger als es auf den ersten Blick scheint. Woran liegt das? Es liegt primär am Begriff selber. Um diesen Begriff schwirren weitere wie Continuous Integration oder Continuous Delivery. Meistens werden diese in einem Atemzug zusammen genannt, aber es gibt doch feine Unterschiede. Beginnen wir zuerst mit dem Unterschied zwischen Continuous Deployment und Continuous Delivery. Carl Caum von Puppet Labs hat den hauptsächlichen Unterschied sehr schön und knapp zusammengefasst:

Continuous Delivery doesn’t mean every change is deployed to production ASAP. It means every change is proven to be deployable at any time.

Kurz gefasst: Im Continuous Delivery sollte man jederzeit eine Version haben, die man live schalten könnte. Das Go-Live erfolgt aber manuell. Im Continuous Deployment wird jede Änderung, die die automatisierten Tests erfolgreich besteht, in die Produktionsumgebung deployt.
Ähnlich sieht die Unterscheidung zwischen Continuous Deployment and Continuous Delivery aus.

Kann man sich auf dieses Wording verlassen? Nicht zwangsweise. Microsoft bevorzugt in der Regel das Ganze Continuous Delivery zu nennen. Andere Firmen und Autoren nennen es anders. Ich persönlich bevorzuge den Begriff Continuous Deployment, da meiner Meinung nach nicht die Details, sondern die große Idee dahinter wichtig und entscheidend ist.

Wie sieht diese Idee aus? Beginnen wir mit dem Bereich, der am weitesten weg von Azure ist, dem Repository. Das Repository ist unsere zentrale Codeverwaltung. Es kann ein TFS, Git Repository, ein SVN oder ein andersartiges zentrales Repository sein. Als Entwickler nutzen wir dieses Repository um unsere lokalen Änderungen am Projekt mit anderen zu teilen. Sobald wir Änderungen in das zentrale Repository eingecheckt haben geht unser Code auf große Reise in Richtung Windows Azure. Der erste Schritt ist das Erstellen einer lauffähigen Version unseres Codes. Dies kann je nach eingesetzter Technologie unterschiedlich geschehen. Im Falle einer .NET-Anwendung würde der Code kompiliert werden.
An diesem Punkt könnten wir diesen Code bereits an Windows Azure weitergeben und es deployen lassen. In kleineren Projekten mit einer begrenzten Anzahl von Anwendern wäre dies unter Umständen kein Problem, aber was können wir machen wenn wir ein größeres Publikum bedienen oder die Anwendung sogar erfolgskritisch für ein Unternehmen ist?
In diesem Fall möchten wir die Reise unseres Codes noch um ein paar Schritte verlängern. Je nach Typ der Anwendung und Publikum können diese Schritte stark variieren. Ein paar gemeinsame Nenner lassen sich aber in den meisten Fällen finden.
Ganz oben auf der Liste stehen Unit und Integration Tests. Während erstere die Funktionsweise in einer abgeschlossenen Einheit auf Herz und Nieren prüfen, testen letztere die Zusammenwirkung mit anderen Komponenten des Systems (bspw. einer Datenbank). Weiterhin können Quality Builds ein Zwischenstopp auf der Reise sein. Diese testen den Code in der Regel anhand von statischen Code Tests, ob (meist wissenschaftliche) Richtlinien bezüglich der Qualität des Codes eingehalten wurden. Hierzu gehören durchaus aber auch Style Guide-Regeln, wie sie bspw. von StyleCop vorgeschrieben werden.
Wie man wahrscheinlich schon ahnen kann, könnte ich diese Liste weiter fortsetzen. Um eine lange Geschichte kurz zu fassen: Die Reise unseres Codes zwischen Repository und Deployment kann durchaus sehr lang sein. Der letzte Schritt ist aber meistens immer der selbe. Der Code (und wir als Entwickler) haben sehnsüchtig warten müssen auf das was folgt: Das Deployment in die Live-Umgebung.

Wie kann ich Continuous Deployment auf Windows Azure nutzen?

Der letzte Abschnitt wirkte sicherlich teilweise sehr langatmig. Wir wollen doch eigentlich nur unseren Code deployt sehen, oder? Außerdem scheint das Aufsetzen dieser Deployment-Pipeline doch ziemlich kompliziert zu sein, richtig?
Frage Nummer 1 kann ich definitiv mit “JA” beantworten. Darauf wartet jeder Entwickler. Als Entwickler haben wir aber auch einen gewissen Anspruch an uns selber und die Systeme, die wir entwickeln. Es lohnt sich durchaus ein paar Minuten bis Stunden länger zu warten.
Die zweite Frage bringt aber den Übergang zu Windows Azure und den Technologien, die wir für das Continuous Deployment brauchen. Die Antwort ist ein eindeutiges “Es kommt darauf an”. Wollen wir eine komplette Infrastruktur haben, wo ein Build in den nächsten übergeht? Dann kann es durchaus schon kompliziert werden, aber insbesondere der Team Foundation Server hat sich hier in den letzten Jahren stark entwickelt. Wenn wir aber ein simples Deployment unseres Codes in die Live-Umgebung nach einem Check-In in das Repository haben möchten, ist die Antwort “Nichts leichter als das”.

Was brauchen wir als Setup? Als erstes brauchen wir ein Projekt, dass wir für unser Deployment nutzen können. Hier reicht für Demonstrationszwecke eines der Standardtemplates von Visual Studio.
Als zweites brauchen wir ein Repository. Hier haben wir auf Azure die Qual der Wahl der Provider, die standardmäßig bedient werden können. Die bekanntesten sind der Team Foundation Server und Git. Meine erste Wahl an dieser Stelle ist in der Regel der TFS. Dies liegt nicht daran, dass ich Git nicht mag. Im Gegenteil, ich bin ein großer Fan. Der Grund ist, dass der TFS uns allerhand Möglichkeiten gibt, was das Customizing der Deployment Pipeline angeht (was aber durchaus durch die Integration weiterer Systeme, wie bspw. einem Jenkins, möglich ist). Für dieses Beispiel wähle ich dennoch eine Git-Variante, GitHub. Warum? Das Deployen von einem On-Premise Team Foundation Server kann mit einigem Aufwand verbunden sein, je nachdem, ob bereits ein TFS vorhanden ist. Ein kurzer Abriss hierzu kann im Tutorial Continuous Delivery for Cloud Services in Windows Azure  gefunden werden. Ein weiterer guter Punkt für Git ist die Integration in den Team Foundation Server 2013 und Visual Studio Online. Mit Git ist es um einiges einfacher das darunter liegende Codeverwaltungssystem zu wechseln. Außerdem lassen sich auch Projekte, die nicht auf .NET basieren, sehr einfach bedienen.
Zum Schluss fehlt uns noch ein Ziel für das Deployment. Hier können wir generell zwischen den Cloud Services und den Windows Azure Web Sites wählen. Im Enterprise-Umfeld wird man eher auf die Cloud Services treffen, aber um Sachen einfach zu halten (und den Standardfall abzudecken) wird das Deployment Richtung Windows Azure Web Sites gehen.

Erstellen des Projektes

Beginnen wir mit dem Erstellen unserer Webanwendung. Ich bediene mich hier dem Single Page Application von Visual Studio 2013.

New project

Damit wäre der erste Schritt geschafft. Schauen wir uns an wie unsere spätere Cloud-Anwendung lokal aussieht:

Site local

Erstellen des Repositories

Für unser Repository bedienen wir uns einer der bekanntesten und einflussreichsten Git Provider, GitHub. Beginnen wir mit dem Erstellen unseres Repositories:

Create GitHub Repository

Erstellen der Windows Azure Web Site

Machen wir direkt weiter mit dem nächsten Schritt: Dem Erstellen unserer Windows Azure Web Site im Windows Azure Portal.

Create website

Nachdem unsere Webseite erstellt ist lohnt es sich einen Blick auf die “Get Started”-Sektion zu werfen.

WAWS Get Started

Neben den Links für die Tools finden wir den für uns interessanten Bereich, das Aufsetzen des Codeverwaltungssystems. Wenn man dem Link folgt, sieht man dass das Windows Azure-Team sehr viel Aufwand investiert hat um nicht nur die eigenen Systeme bedienen zu können. Wir haben (zurzeit) die Auswahl zwischen:

  • Visual Studio Online
  • Einem lokalen Git Repository
  • GitHub
  • Dropbox
  • Bitbucket
  • CodePlex
  • Händisches Einbinden anderer Systeme

Wie sinnvoll jedes System für die Quellcodeverwaltung ist, ist jedem selber überlassen. Glücklicherweise steht für unseren Fall GitHub schon Gewehr bei Fuß. Nach der Auswahl von GitHub als unser Quellcodeverwaltungssystem folgt in der Regel das Autorisieren des jeweiligen GitHub-Accounts. Sobald dieser Schritt abgeschlossen ist, wählen wir unser Repository und den Branch, den wir Deployen wollen, aus.

Choose project

Nach dem Bestätigen wird das Repository verlinkt und der derzeitige Stand des entsprechenden Branches deployt.

First fetch

Viel zu sehen gibt es zum derzeitigen Zeitpunkt noch nicht. Das wird sich schnell ändern.

Das Deployment

Beginnen wir mit der GitHub-Integration für unser Projekt. Bisher sieht unser GitHub-Projekt noch ziemlich leer aus. Füllen wir es mit unserem Projekt. Hierfür gibt es mehrere Varianten, unter anderem den GitHub-Client für Windows oder die GitHub Shell. Da die Shell wenig vor uns versteckt, bediene ich mich in diesem Beispiel der Shell.

Für das Aufsetzen unseres lokalen Repositories folgen wir drei einfachen Schritten:

  1. Erstellen des Repositories
  2. Hinzufügen einer gitignore-Datei
  3. Commiten unseres Projektes in das lokale Repository.

Schritt 1 dauert nicht länger als das Tippen des folgenden Befehls

git init

Hierdurch wird ein .git-Ordner auf unserem aktuellen Verzeichnis hinzugefügt, was sehr simpel gesagt unser zentrales Repository ist.

Das Hinzufügen einer .gitignore-Datei (Schritt 2) von Hand ist notwendig, da wir unser GitHub-Projekt nicht direkt geclont haben, sondern bereits ein Projekt hatten bevor überhaupt das GitHub-Projekt erstellt war.

Wozu brauchen wir diese Datei überhaupt? Die .gitignore-Datei informiert Git darüber welche Dateien wir nicht in unserem Repository haben möchten. Ein typisches Beispiel in einer .NET-Anwendung ist der bin-Ordner oder nutzerspezifische Einstellungen, die bei anderen Entwicklern ein böses Erwachen hervorrufen können.

Glücklicherweise müssen wir die .gitignore-Datei nicht selber erstellen. Ein kurzer Blick auf GitHub und das gitignore-Projekt und schon finden wir sehr einfach eine passende .gitignore-Datei. Für unser Beispiel passend ist VisualStudio.gitignore. Da es unter Windows leider nicht so einfach möglich ist eine .gitignore-Datei anzulegen bedienen wir uns eines kleine Workarounds. Wir erstellen eine gitignore.txt und kopieren den Inhalt der VisualStudio.gitignore in diese Datei. Um diese Datei nun entsprechend umzubenennen bedienen wir uns wieder der Shell und folgendem Befehl

ren gitignore.txt .gitignore

Fertig ist die .gitignore-Datei! Nun sind wir bereit unser Projekt in unser lokales Repository zu commiten. Hierfür fügen wir zuerst alle Dateien zum Index hinzu, gucken kurz wie der aktuelle Status aussieht und commiten sie anschließend.

git add .
git status
git commit -m "initial commit"

Jetzt sind wir an dem Punkt, wo es lokal ziemlich gut aussieht, wir aber immer noch nicht unser GitHub-Projekt auf dem aktuellen Stand haben. Da wir, wie bereits erwähnt, das Projekt nicht geclont haben, fehlt uns noch der entsprechende Remote. Dies ist nichts anderes als ein Alias bzw. Pointer auf unser GitHub-Repository.

git remote add github https://github.com/HorizonNet/CD.Demo.git

Schlussendlich fehlt nur noch das Pushen in unser Repository

git push github master

Sollten während des Pushes Probleme auftreten lassen sich diese in der Regel über

git pull github master

und einem simplen Merge lösen.

Bereits kurze Zeit nach dem Push sollte unsere Webseite deployt sein.

New deployment

Die Erfahrung zeigt, dass dies meistens innerhalb einer Minute geschieht und um einiges schneller ist als ein TFS Deployment.

Ein kurzer Blick auf unsere deployte Webseite:

Site cloud

Sieht genauso aus wie unsere lokale Webseite, läuft nun aber auf Windows Azure.

Customizing der Build Pipeline

Bis hierhin haben wir den Deployment-Prozess betrachtet wie er auch in verschiedenen MSDN-Artikeln beschrieben wird. Wie können wir diesen nun aber unseren Bedürfnissen anpassen? Wie eingangs schon erwähnt, es hängt vieles davon ab welches Codeverwaltungssystem wir wählen und was unser eigentliches Deployment-Ziel ist.

Im Team Foundation Server können wir mit etwas extra Aufwand eine längere Release Pipeline aufbauen. Unter Git können wir Ähnliches durch die Integration eines Jenkins erreichen. Die einfachste Variante ist aber das Branching. Wie wir beim Verlinken des GitHub-Repositories mit der Windows Azure Web Site gesehen haben, können wir den Branch auswählen von dem aus deployt wird. Um nicht jede kleine Änderung zu deployen, sondern erst ab einem Stand, der auch wirklich produktionsreif ist (Stichwort Continuous Delivery), können wir einen Branch develop erstellen. Auf diesem wird primär gearbeitet und commited. Sobald ein guter Stand erreicht sein, wird dieser Branch in den master branch gemergt und damit der aktuelle Stand deployt.

Bezüglich des eigentlichen Deployment-Ziels gibt es auch feine Unterschiede, die man beachten sollte. Im Gegensatz zu den Cloud Services kennen die Windows Azure Web Sites kein Production- und Staging-Deployments. Dies kann aber sehr leicht nachgebaut werden, indem man neben der Production-Webseite eine Staging-Webseite erstellt und diese auf den entsprechenden Branch verlinkt.

Für weitere Szenarien und Möglichkeiten sind der Fantasie (fast) keine Grenzen gesetzt.

Zusammenfassung

In diesem Artikel haben wir uns mit den Grundlagen des Continuous Deployments auf Windows Azure beschäftigt. Wir haben die kleinen, aber feinen Unterschiede der verschiedenen Begriffe kennengelernt und wir haben besprochen wie komplex eine Release Pipeline werden kann.

Im praktischen Teil haben wir unsere eigene Release Pipeline aufgebaut und ein Standardtemplate von Visual Studio nach Windows Azure deployt.

An dieser Stelle ist natürlich noch nicht Schluss. Wer sich tiefergehend mit dem Thema beschäftigen möchte, dem kann ich Martin Fowlers (von wem sollte so ein Buch auch sonst kommen) Continuous Delivery ans Herz legen. Außerdem sollte man den Blog von Brian Harry in seine Leseliste hinzufügen. Weiterhin ein paar kurze Stichwörter, die man sich bei Gelegenheit zu Gemüte führen kann:

  • Team Foundation Server Build Template Customizing
  • Visual Studio Online
  • Deployment aus anderen Repositories (Stichwort Git)
  • Production- und Staging-Deployment

– Jan (@Horizon_Net)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s