Verbesserung unserer Bereitstellungsstrategie

12

Wir haben eine E-Commerce-App, die wir in unserem Unternehmen entwickeln. Es ist eine recht normale LAMP-Anwendung, die wir seit ungefähr 3 Jahren ein- und ausschalten. Wir entwickeln die Anwendung auf einer Testdomäne, fügen hier neue Funktionen hinzu und beheben Fehler usw. Unsere Fehlerverfolgung und Funktionsentwicklung werden alle in einer gehosteten Subversion-Lösung (unfuddle.com) verwaltet. Wenn Fehler gemeldet werden, nehmen wir diese Korrekturen in der Testdomäne vor und schreiben dann Änderungen an svn fest, wenn wir zufrieden sind, dass der Fehler behoben wurde. Wir folgen demselben Verfahren mit der Hinzufügung neuer Funktionen.

Es lohnt sich, auf die allgemeine Architektur unseres Systems und unserer Anwendung auf allen Servern hinzuweisen. Jedes Mal, wenn eine neue Funktion entwickelt wird, wird dieses Update mit unserer Anwendung (immer ein von uns gesteuerter Server) auf alle Sites verteilt. Jede Site, die unser System verwendet, verwendet für 95% der Codebasis im Wesentlichen genau dieselben Dateien. Wir haben eine Reihe von Ordnern innerhalb jeder Site, die auf diese Site zugeschnittene Dateien enthalten - CSS-Dateien / Bilder usw. Abgesehen davon werden die Unterschiede zwischen den einzelnen Sites durch verschiedene Konfigurationseinstellungen innerhalb der jeweiligen Site-Datenbank definiert.

Dies führt zur eigentlichen Bereitstellung. Wenn wir bereit sind, ein Update irgendeiner Art herauszubringen, führen wir einen Befehl auf dem Server aus, auf dem sich die Testsite befindet. Dies führt einen Kopierbefehl aus (cp -fru / testsite / / othersite /) und durchläuft jede vhost-Force, die die Dateien basierend auf dem Änderungsdatum aktualisiert. Jeder zusätzliche Server, auf dem wir hosten, verfügt über einen vhost, mit dem wir die Produktionscodebasis synchronisieren. Anschließend wiederholen wir den Kopiervorgang auf allen Sites auf diesem Server. Während dieses Vorgangs verschieben wir die Dateien, die nicht überschrieben werden sollen, zurück, wenn der Kopiervorgang abgeschlossen ist. Unser Rollout-Skript führt eine Reihe anderer Funktionen aus, z. B. das Anwenden von SQL-Befehlen zum Ändern jeder Datenbank, das Hinzufügen von Feldern / neuen Tabellen usw.

Wir haben zunehmend Bedenken, dass unser Prozess nicht stabil genug, nicht fehlertolerant und auch ein bisschen brachial ist. Wir sind uns auch bewusst, dass wir Subversion nicht optimal nutzen, da wir eine Position haben, in der die Arbeit an einer neuen Funktion verhindern würde, dass wir eine wichtige Fehlerbehebung einführen, da wir keine Verzweigungen oder Tags verwenden. Es scheint auch falsch, dass wir so viele Replikationen von Dateien auf unseren Servern haben. Wir sind auch nicht in der Lage, ein Rollback für das, was wir gerade eingeführt haben, durchzuführen. Wir führen vor jedem Rollout einen Diff durch, damit wir eine Liste der Dateien erhalten, die geändert werden, damit wir wissen, was danach geändert wurde, aber der Vorgang zum Rollback weiterhin problematisch ist. In Bezug auf die Datenbank habe ich angefangen, dbdeploy als mögliche Lösung in Betracht zu ziehen. Wir möchten jedoch eine allgemeine Anleitung, wie wir die Dateiverwaltung und -bereitstellung verbessern können. Idealerweise möchten wir, dass die Dateiverwaltung enger mit unserem Repository verknüpft ist, damit ein Rollout / Rollback stärker mit svn verbunden ist. So etwas wie die Verwendung des Befehls export, um sicherzustellen, dass die Site-Dateien mit den Repo-Dateien identisch sind. Es wäre jedoch auch gut, wenn die Lösung möglicherweise auch die Dateireplikation auf unseren Servern stoppen würde.

Wenn wir unsere derzeitigen Methoden ignorieren, wäre es wirklich gut zu hören, wie andere Leute sich dem gleichen Problem nähern.

zusammenfassen ...

  • Wie lassen sich Dateien auf mehreren Servern am besten mit svn synchronisieren?
  • Wie sollen wir die Dateireplikation verhindern? Symlinks / noch etwas?
  • Wie sollten wir unser Repo strukturieren, damit wir neue Funktionen entwickeln und alte reparieren können?
  • Wie sollen wir Rollouts / Rollbacks auslösen?

Danke im Voraus

BEARBEITEN:

Ich habe in letzter Zeit eine Menge guter Dinge über die Verwendung von Phing und Capistrano für diese Art von Aufgaben gelesen . Kann jemand weitere Informationen über sie geben und wie gut sie für diese Art von Aufgabe sein würden?

robjmills
quelle

Antworten:

6

Mein Rat für Releases ist, Feature Releases und Maintenance Releases zu haben. Feature Releases sind die Releases, die neue Funktionen erhalten. Diese werden Ihrem Subversion-Trunk hinzugefügt. Wenn Sie glauben, dass diese Funktionen vollständig sind, verzweigen Sie diese in einen Release-Zweig. Sobald Ihr QA-Prozess mit dieser Version zufrieden ist, markieren Sie die Version und stellen den Code auf Ihren Servern bereit.

Wenn Sie jetzt einen Fehlerbericht erhalten, übertragen Sie diesen Fix in den Zweig und portieren ihn in den Trunk. Wenn Sie mit der Anzahl der behobenen Fehler zufrieden sind, können Sie ein Maintenance Release kennzeichnen und bereitstellen.

Es ist wichtig, dass Sie einen Zweig Ihrer Live-Codebasis haben (oder die Möglichkeit haben, einen Zweig zu erstellen, indem Sie die Live-Revision kennen), der von Ihrem Entwicklungszweig getrennt ist, damit Sie Fixes für Ihren Live-Code bereitstellen können, ohne dies zu müssen Bereitstellen neuer Funktionen oder nicht getesteten Codes.

Ich würde empfehlen, das native Paketsystem Ihrer Distribution für die Bereitstellung von neuem Code zu verwenden. Wenn Sie ein Paket haben, das Ihre gesamte Codebasis enthält, wissen Sie, dass Ihr gesamter Code in einer Art atomarer Operation implementiert wurde. Sie können auf einen Blick erkennen, welche Version installiert ist. Sie können Ihre Codebasis anhand der Prüfsumme Ihrer Pakete überprüfen. Ein Rollback ist nur ein Fall der Installation der zuvor installierten Version des Pakets.

Die einzige Hürde, die ich sehen kann, ist, dass Sie offenbar mehrere Kopien der Codebasis für verschiedene Kunden haben, die auf einem einzigen Server ausgeführt werden. Ich würde versuchen, Ihren Code so zu gestalten, dass alle Kunden dieselben Dateien ausführen und keine Kopien verwenden. Ich weiß nicht, wie einfach das für Sie sein würde, aber wenn Sie die Anzahl der Exemplare reduzieren, mit denen Sie sich befassen müssen, werden Ihre Kopfschmerzen massiv reduziert.

Ich gehe davon aus, dass Sie, wie Sie bereits erwähnt haben, PHP oder eine andere Skriptsprache verwenden, für die kein Kompilierungsprozess erforderlich ist. Dies bedeutet, dass Ihnen wahrscheinlich ein wunderbarer Prozess namens Continuous Integration entgeht. Dies bedeutet im Grunde, dass Ihr Code kontinuierlich getestet wird, um sicherzustellen, dass er sich noch in einem freigegebenen Zustand befindet. Jedes Mal, wenn jemand neuen Code eincheckt, wird dieser von einem Prozess verwendet und der Erstellungs- und Testprozess ausgeführt. Bei einer kompilierten Sprache würden Sie diese normalerweise verwenden, um sicherzustellen, dass der Code noch kompiliert ist. Bei jeder Sprache sollten Sie die Gelegenheit nutzen, Komponententests (Ihr Code ist in prüfbaren Einheiten, nicht wahr?) Und Integrationstests durchzuführen. Für Websites ist Selen ein gutes Werkzeug zum Testen von Integrationstests. In unseren Java-Builds messen wir auch die Codeabdeckung und Codemetriken, um zu sehen, wie wir uns im Laufe der Zeit entwickeln. Der beste CI-Server, den wir für Java gefunden haben, ist Hudson, aber Buildbot funktioniert möglicherweise besser für andere Sprachen. Sie können Pakete mit Ihrem CI-Server erstellen.

David Pashley
quelle
Vielen Dank. Ja, wir verwenden PHP. Ich muss zugeben, dass ich mich nicht zu sehr mit kontinuierlicher Integration beschäftige. Soweit ich weiß, ist es dem Testen von Einheiten sehr ähnlich, aber darüber weiß ich nicht viel mehr. Wir sind scharf auf Unit-Tests, aber unsere Codebasis enthält immer noch eine Menge veralteter Prozedurcodes, die sich nicht wirklich für Unit-Tests eignen. Einige interessante Ideen sind jedoch hilfreich, wenn Sie wissen, wie unser Code besser organisiert werden kann, um die Replikation zu verhindern.
Robjmills
Kontinuierliche Integration ist buchstäblich nur das Ausführen automatisierter Tests bei jedem Einchecken, jeder Stunde oder jedem Tag. Nur solange Sie es regelmäßig und automatisiert tun, ist das so ziemlich CI.
David Pashley
Ich habe heute diesen Artikel über die Verwendung von Hudson neben PHP und Phing gesehen - toptopic.wordpress.com/2009/02/26/php-and-hudson
robjmills
1

Wir haben mit Puppet (Flaggschiffprodukt von Reductive Labs) begonnen. Es ist ein Ruby-basiertes Framework zur Automatisierung von Sys-Admin-Jobs. Ich war vor ein paar Wochen im Puppetcamp und hier sind die Videolinks:

Luke Kanies Presenting - Puppet Intro

Wenn Sie alle Präsentationen sehen möchten, die im Puppenlager in San Francisco gemacht wurden, ist dies der Link:

Präsentationen darüber, wie andere Puppet verwendeten

Genießen.

Nikolas Sakic
quelle