1. Code
  2. PHP

Vagrant: Was, warum und wie

In diesem Artikel erfahren Sie, wie Sie Vagrant zur Verwaltung Ihrer Instanzen virtueller Maschinen verwenden und wie Sie Puppet nutzen können, um verschiedene Ressourcen wie PHP und PostgreSQL bereitzustellen.
Scroll to top
11 min read

German (Deutsch) translation by Alex Grigorovich (you can also view the original English article)

In diesem Artikel erfahren Sie, wie Sie Vagrant zur Verwaltung Ihrer Instanzen virtueller Maschinen verwenden und wie Sie Puppet nutzen können, um verschiedene Ressourcen wie PHP und PostgreSQL bereitzustellen.


Einführung

Entwickler haben eine große Auswahl an Möglichkeiten, ihre Webentwicklungsumgebung zu erstellen.

Die Entwickler haben viele Möglichkeiten, um ihre Webentwicklungsumgebung zu erstellen. Sie können "lokale" Optionen verwenden, z. B. die Installation vorgefertigter "All-in-One" -Server-Stacks wie Zend Server, XAMPP, MAMP, WAMP usw., oder Sie können die Komponenten selbst von der Quelle oder über installieren Paketverwaltungssysteme wie Homebrew, Apt und Yum.

Das kann sich aufbauen, wenn Sie an verschiedenen Projekten mit PHP 5.3 und PHP 5.4, MySQL, SQLite, MongoDB, Postgres, PEAR, PHPUnit, Rails 3.1, Memcached, Redis, Gearman, NodeJS usw. arbeiten. Wenn Sie ein Upgrade durchführen oder Ihr Computer stirbt, müssen Sie von vorne beginnen.

Sie können ein "Remote"-Einrichten mit einem Server im Netzwerk mit Samba-Freigaben oder einem SSH-Server mit einem Werkzeug wie ExpanDrive durchführen. Die letztere Option kann zu einer Latenz beim Lesen/Schreiben von Dateien führen, was äußerst ärgerlich ist. Sie können SSH + Vim für alles verwenden, was schnell geht, aber das funktioniert nur, wenn Sie Vim für alles verwenden möchten.


Entwicklung vs. Produktion

Während Sie vielleicht zufrieden sind, wie Sie die Dinge gerade tun, haben wie viele von Ihnen gehört (oder gesagt) "Nun, es funktioniert auf meinem Computer". Dies ist schrecklich häufig und passiert, wenn sich Umgebungen selbst durch die trivialsten Details unterscheiden.

Es ist äußerst wichtig sicherzustellen, dass Ihre Entwicklungsumgebung mit der Produktionsumgebung identisch ist und mit Staging- und Testservern übereinstimmt, wenn Sie diese ebenfalls haben.

Es klingt einfach, wenn Sie nur an die Installation von Apache, PHP und einer Kopie von MySQL denken, aber es gibt eine Million Faktoren, über die Sie nachdenken müssen. Wenn Sie unter OSX entwickeln und auf einem Ubuntu-System bereitstellen, werden Sie lustige Probleme mit der Großschreibung von Dateien bemerken. Dies ist in CodeIgniter üblich, wenn jemand eine Bibliothek mit einem Kleinbuchstaben hat. Es wird unter OSX einwandfrei geladen, bricht jedoch bei der Bereitstellung in der Produktion. Ihr Entwicklungsprozess hat Ihnen möglicherweise nur einiges an Geschäft verloren, und zwar aufgrund eines geringfügigen Unterschieds im Betriebssystem, an den niemand gedacht hat, bis es zu spät war.


Entwicklung = Produktion

Die Verwendung des gleichen Betriebssystems durch Entwickler führt zu Problemen.

Was ist die Lösung? Lassen Sie alle Ihre Entwickler verschiedene Tools aufgeben und auf einem Laptop-Modell entwickeln? Wenn Ihre Entwickler alle brandneue Macbooks erhalten, werden Sie möglicherweise nicht zu viele Beschwerden erhalten, aber dann müssen Sie OSX Server für alles verwenden.

Sie könnten Linux für alles verwenden, aber dann müssen Sie sich streiten, welche Distribution Sie verwenden möchten. Die Verwendung des gleichen Betriebssystems durch Entwickler wird zu Problemen führen, die Produktivität verringern und den Kampf gegen Nerds fördern.

Virtualisierung ist die Antwort und nichts Neues, aber wenn Menschen an Virtualisierung denken, denken sie oft an Leistungsprobleme und ihre Fans drehen sich wild, während ihr Laptop verzweifelt versucht, zwei Betriebssysteme auszuführen.

Das kann immer noch der Fall sein, wenn jemand versucht wird, Windows auf einem Computer mit geringem Stromverbrauch auszuführen. Heute verfügt ein Mac über 4 GB RAM, was mehr als genug ist, um eine Ubuntu-Serverinstallation im Befehlszeilenmodus mit Strom zu versorgen und alle Ihre üblichen EntwicklungsWerkzeugs (IDE, Browser, Debugging-Werkzeugs usw.). Es gibt einige Optionen für die Virtualisierung, aber ich bevorzuge VirtualBox von Oracle (kostenlos). Diese Software erledigt das ganze schwere Heben für die Virtualisierung, dann verwaltet ein Werkzeug namens Vagrant die Instanzen.


Schritt 1 - VirtualBox installieren

Laden Sie zuerst VirtualBox herunter und installieren Sie es. Auf *nix-Systemen (Mac OSX, Linux usw.) müssen Sie Ihr .bash_profile (oder .zsh_profile) ändern, um Ihre Variable $PATH zu erweitern:

1
PATH=$PATH:/Applications/VirtualBox.app/Contents/MacOS/
2
export PATH

Auf diese Weise kann Vagrant erkennen, wo VirtualBox installiert ist, und kann natürlich für verschiedene Betriebssysteme variieren.


Schritt 2 - Installieren Sie Vagrant

Sie können einen vagrant Build für Ihr Betriebssystem herunterladen oder als Gem installieren, falls einer nicht verfügbar ist:

1
$ gem install vagrant

Schritt 3 - Erstellen Sie eine Instanz

Machen Sie einen Ort, an dem Ihre Vagrant-Setups sein können:

1
mkdir -p ~/Vagrant/test
2
cd ~/Vagrant/test

Wir werden Ubuntu 12.04 LTS (Precise Pangolin) verwenden, für das bereits eine "Box" eingerichtet ist.

1
vagrant box add precise32 http://files.vagrantup.com/precise32.box

Sie sehen hier das Argument "precise32", das ein Spitzname für die URL ist. Sie können jetzt eine Instanz erstellen, die diese .box herunterlädt.

1
vagrant init precise32
2
vagrant up

Es wird jetzt ausgeführt. Einfach! Wenn Sie über SSH in diese Instanz gelangen möchten, verwenden Sie diesen Befehl:

1
vagrant ssh

Schritt 5 - Konfiguration

Sie haben eine Datei namens Vagrantfile, die die Konfiguration für diese Instanz enthält:

1
# -*- mode: ruby -*-

2
# vi: set ft=ruby :

3
4
Vagrant::Config.run do |config|
5
6
    config.vm.box = "precise32"
7
    config.vm.box_url = "http://files.vagrantup.com/precise32.box"
8
9
    # Assign this VM to a host-only network IP, allowing you to access it

10
    # via the IP. Host-only networks can talk to the host machine as well as

11
    # any other machines on the same network, but cannot be accessed (through this

12
    # network interface) by any external networks.

13
    config.vm.network :hostonly, "192.168.33.10"
14
15
    # Set the default project share to use nfs

16
    config.vm.share_folder("v-web", "/vagrant/www", "./www", :nfs => true)
17
    config.vm.share_folder("v-db", "/vagrant/db", "./db", :nfs => true)
18
19
    # Forward a port from the guest to the host, which allows for outside

20
    # computers to access the VM, whereas host only networking does not.

21
    config.vm.forward_port 80, 8080
22
23
    # Set the Timezone to something useful

24
    config.vm.provision :shell, :inline => "echo \"Europe/London\" | sudo tee /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata"
25
26
    # Update the server

27
    config.vm.provision :shell, :inline => "apt-get update --fix-missing"
28
29
    # Enable Puppet

30
    config.vm.provision :puppet do |puppet|
31
        puppet.facter = { "fqdn" => "local.pyrocms", "hostname" => "www" } 
32
        puppet.manifests_path = "puppet/manifests"
33
        puppet.manifest_file  = "ubuntu-apache2-pgsql-php5.pp"
34
        puppet.module_path  = "puppet/modules"
35
    end
36
37
end

Das ist, wenn Sie es nicht bemerkt haben, die Ruby-Syntax. Sie können also mit dieser Datei ziemlich kreativ werden, aber das sind die Grundlagen.

Es wird angezeigt, welcher Spitzname verwendet werden soll, und es wird die URL angegeben, falls der Spitzname nicht lokal eingerichtet ist (gut zum Teilen).

Die Zeilen share_folder sind sehr nützlich, um einen Ordner in der Instanz einem lokalen Ordner zuzuordnen. Mit nfs => true kann die Instanz Berechtigungen für die Dateien schreiben und ändern. Dies ist hilfreich, wenn Sie beispielsweise versuchen, dort ein CMS zu installieren.

Mit der Portweiterleitung können Sie unter http://localhost:8080 auf Ihre Instanz zugreifen und diese bei Konflikten natürlich in einen anderen Port ändern.

Diese Konfigurationsdatei setzt auch die Zeitzone auf Europa/London und führt dann das apt-get update aus, wodurch Ihr System beim Booten auf dem neuesten Stand sein sollte. Wenn Sie dieses Konfigurationselement überspringen, werden möglicherweise mehrere Pakete nicht installiert, da die Referenzen jetzt veraltet sind.

Wenn Sie die Konfiguration ändern, können Sie die Instanz neu laden, um sie zu verwenden:

1
vagrant reload

Jetzt, da unsere Server laufen und betriebsbereit sind, müssen wir einige Software installieren. Wir werden nicht nur eine apt-get install Reihe von Paketen über die Befehlszeile installieren, sondern auch unsere Server "bereitstellen".


Schritt 4 - Bereitstellung

Über die Serverbereitstellung müssen viele Entwickler nicht nachdenken.

Über die Serverbereitstellung müssen viele Entwickler nicht nachdenken, da sie normalerweise den Systemadministratoren überlassen bleibt. Die Idee ist, aufzuzeichnen, welche Software und Konfiguration auf einem Server vorgenommen wurde, damit Sie neue Entwicklungsumgebungen, neue Staging-Server, die die Produktion replizieren, oder einen anderen Produktionsserver erstellen können, um den Lastausgleich zwischen beiden zu gewährleisten.

Old-School-Bereitstellung

Wie Sysadmins damit umgehen, ist unterschiedlich, aber in der Vergangenheit wurden alle Arten von Lösungen verwendet - von der Ausführung eines Wiki mit Befehlen (die schnell groß und veraltet sein können) bis hin zu dem großartigen Ansatz, ein "Multi-Terminal" zu haben, in dem Sie tippen Befehle in ein Fenster und es repliziert dieselben Befehle gleichzeitig auf anderen 7 Servern. Diese Methoden sind alle schrecklich.

Eine Lösung wäre, eine eigene .box-Datei zu erstellen oder .iso-Backups zu erstellen, damit neue Server darauf basieren können. Die Pflege dieser Images erfordert jedoch viel zusätzliche Arbeit, und unabhängig davon, wie sehr Sie sich bemühen, werden diese Entwicklungsmaschinen dies tun im Laufe der Zeit nicht mehr synchron sein.

Moderne Versorgung

Es gibt zwei beliebte Systeme, Puppet und Chef.

Es gibt zwei beliebte Systeme, Puppet und Chef. Beide gibt es schon seit Jahren, aber mit der Zunahme der DevOps-Entwicklungsmethode werden sie immer beliebter. Die Ideen für beide sind ähnlich und Sie sollten beide Systeme untersuchen, aber dieses Tutorial konzentriert sich ausschließlich auf Puppet.

Anstatt eine Reihe von Befehlen auszuführen und zu hoffen, dass alles gut funktioniert, erstellen Sie im Wesentlichen ein Manifest für Puppet, in dem alles erklärt wird, was Sie benötigen, um sicherzustellen, dass es erledigt wurde. Wenn Sie einen Befehl im Terminal ausführen, sagen Sie dem Computer im Grunde:

"Apache installieren"

Mit Puppet würden wir sagen:

"Stellen Sie sicher, dass Apache installiert ist"

Oder statt:

"Erstellen Sie einen neuen Ordner mit dem Namen /var/www und setzen Sie die Berechtigungen auf www-data:www-data"

Mit Puppet würden wir sagen:

"Stellen Sie sicher, dass /var/www vorhanden ist und über Berechtigungen verfügt, die mit übereinstimmen www-data:www-data"

Der Unterschied besteht darin, dass diese Manifeste mehrmals ausgeführt werden können (stündlich oder täglich bei einem Cron-Job), um die Dinge auf dem neuesten Stand zu halten, und dass es keine unerwarteten Ergebnisse gibt, wenn versucht wird, zweimal zu installieren.

Es hilft Ihnen auch zu testen, ob alles wie erwartet ausgeführt wird, da jede dieser fehlgeschlagenen Regeln Fehler auslöst, die einfacher zu verfolgen sind, als eine große Menge von Bash-Befehlsergebnissen abzurufen. Puppet wirft große rote Fehler aus, die Sie darauf hinweisen, dass PHP nicht installiert wurde oder ein bestimmtes Modul nicht konfiguriert werden konnte.

Manifeste und Module

Manifeste sind zunächst etwas verwirrend, aber nach einer Weile beginnen sie Sinn zu machen.

So überprüfen Sie ein einfaches Beispiel:

1
file {'testfile':
2
  path    => '/tmp/testfile',
3
  ensure  => present,
4
  mode    => 0640,
5
  content => "I'm a test file.",
6
}

Sie müssen nicht erklären, was hier passiert, oder?

Diese Datei kann später in Ihrem Manifest als "testfile" bezeichnet werden, was bedeutet, dass sie als Abhängigkeit für andere Aktionen aufgeführt werden kann.

Weitere Beispiele finden Sie in den PyroCMS Puppet-Manifesten auf GitHub.

1
include apache
2
3
$docroot = '/vagrant/www/pyrocms/'
4
$db_location = "/vagrant/db/pyrocms.sqlite"
5
6
# Apache setup

7
class {'apache::php': }
8
9
apache::vhost { 'local.pyrocms':
10
    priority => '20',
11
    port => '80',
12
    docroot => $docroot,
13
    configure_firewall => false,
14
}
15
16
a2mod { 'rewrite': ensure => present; }

Dies beinhaltet das "apache"-Modul, richtet einige Variablen ein, führt das zusätzliche "apache::php"-Manifest im Apache-Modul aus, richtet einen virtuellen Host ein und stellt dann sicher, dass "mod_rewrite" aktiviert ist.

Alle diese Klassen sind in dem von uns enthaltenen Apache-Modul definiert.

Weiter möchten wir auch PHP installieren:

1
include php
2
3
php::module { ['xdebug', 'pgsql', 'curl', 'gd'] : 
4
    notify => [ Service['httpd'], ],
5
}
6
php::conf { [ 'pdo', 'pdo_pgsql']:
7
    require => Package['php5-pgsql'],
8
    notify  => Service['httpd'],
9
}

Dieser Teil des Manifests installiert die benötigten PHP-Erweiterungen. Mit der notify -Option wird Apache darüber informiert, dass Sie eine neue Konfiguration installiert haben, was bedeutet, dass sie neu gestartet wird.

1
include postgresql
2
3
class {'postgresql::server': }
4
5
postgresql::db { 'pyrocms':
6
    owner     => 'pyrocms',
7
    password => 'password',
8
}

Dadurch wird ein Postgres-Server eingerichtet, eine Datenbank mit dem Namen "pyrocms" erstellt und sichergestellt, dass ein Benutzer mit dem Namen "pyrocms" mit dem angegebenen Kennwort vorhanden ist.

Fast fertig! Der letzte Schritt besteht darin, sicherzustellen, dass die beschreibbaren Dateien und Ordner richtig eingestellt sind:

1
file { $docroot:
2
    ensure  => 'directory',
3
}
4
5
file { "${docroot}system/cms/config/config.php":
6
    ensure  => "present",
7
    mode    => "0666",
8
    require => File[$docroot],
9
}
10
11
$writeable_dirs = ["${docroot}system/cms/cache/", "${docroot}system/cms/config/", "${docroot}addons/", "${docroot}assets/cache/", "${docroot}uploads/"]
12
13
file { $writeable_dirs:
14
    ensure => "directory",
15
    mode   => '0777',
16
    require => File[$docroot],
17
}

Dadurch wird sichergestellt, dass das Apache-Dokumentstammverzeichnis vorhanden ist, die Konfigurationsdatei auf 0666 festgelegt ist und einige beschreibbare Ordner auf 777 festgelegt sind.

Da haben wir es!

Um all dies auszuführen, starten Sie einfach Ihre Vagrant Instanz neu oder führen Sie Folgendes aus:

1
vagrant provision

Wenn alles richtig funktioniert hat, sollte viel blauer Text darauf hinweisen, dass alles installiert wird. Wenn jedoch etwas schief geht, wird rot angezeigt. Google diese Fehler und versuche es erneut.

Die hier verwendeten Module sind: Apache, Postgres, PHP und Sie können das Ganze in Aktion sehen, indem Sie das PyroCMS Vagrant-Repo klonen:

1
git clone --recursive git://github.com/pyrocms/devops-vagrant.git ~/vagrant/pyrocms
2
cd ~/vagrant/pyrocms
3
vagrant up

Zeigen Sie mit Ihrem Browser auf http://localhost:8089/, und Sie sollten das Installationsprogramm sehen. Einfaches Zeug, oder?

Hinweis: Dies wird mit MySQL installiert, da sich die Postgres- und SQLite-Unterstützung von PyroCMS noch in der Entwicklung befindet und darauf wartet, dass einige CodeIgniter PDO-Funktionen abgeschlossen werden. Wenn Sie interessiert sind, können Sie experimentieren, indem Sie die Vagrant-Datei so ändern, dass das Manifest ubuntu-apache2-pgsql-php5.pp verwendet wird. Zerstören Sie die Instanz und starten Sie sie erneut. Das Pyrocms-Submodul muss auch auf feature/pdo überprüft werden


Zusammenfassung

In diesem Artikel haben wir Vagrant, VirtualBox und Puppet verwendet, um nicht nur eine Serverinstanz für die Arbeit festzulegen, sondern auch eine Testsuite für unseren Server zu erstellen, um sicherzustellen, dass alles ordnungsgemäß ausgeführt, installiert und konfiguriert wird.

Wir haben auch eine Checkliste für Anforderungen erstellt und können in Zukunft beliebig viele identische Server in Minuten und nicht in Stunden erstellen!