Perl in the Cloud - OpenShift Express by Red Hat - Installation, Initialisierung und Konfiguration

Veröffentlicht von Thomas Fahle am (Permalink)

OpenShift by Red Hat soll die Entwicklung von Open-Source-Anwendungen für die Cloud vereinfachen. Dieser Plattform-as-a-Service stellt eine Infrastruktur für verschiedene Programmiersprachen und Web-Frameworks zur Verfügung.

Red Hat unterscheidet zwischen den Produktvarianten Express, Flex und Power.

Die kostenlose Express Variante (Registrierung erforderlich) erlaubt u.a. die Verwendung der dynamischen Programmiersprache Perl in Version 5.10.1, der Datenbanken MySQL in Version 5.1 oder SQLite in Version 3 und (ganz wichtig) die Installation von CPAN-Modulen.

Die bekannten und beliebten Perl Web-Frameworks Dancer, Mojolicious und Catalyst können verwendet werden.

 

Schritt für Schritt

Dieser Beitrag geht zuerst Schritt für Schritt durch die Installation, Initialisierung und Konfiguration von OpenShift Express. Danach wird ein betont einfaches, aber nützliches Perl-Programm erstellt und gezeigt, wie dieses in die Cloud ausgeliefert (deployed) wird.

 

Registrierung

Zur Verwendung von OpenShift Express ist eine Registrierung mit einer gültigen E-Mail-Adresse erfoderlich. Alternativ kann auch ein bestehender RHN-Account verwendet werden.

 

Installation der Client-Tools

OpenShift funktioniert unter Mac OSX, Linux und Windows - für diesen Beitrag verwende ich CentOS 6 (64-Bit in einer eigenen virtuellen Maschine).

Für die Client-Tools bietet RedHat eine eigenes YUM-Repository an, das wie folgt installiert wird.

# wget https://openshift.redhat.com/app/repo/openshift.repo
# mv openshift.repo /etc/yum.repos.d

Damit alle Paket-Abhänigkeiten aufgelöst werden, musste ich auch die EPEL- und RPMForge-Repositories hinzufügen.

Nun können die Client-Tools installiert werden:

# yum install rhc

 

Initialisierung

Alle Apps eines Users werden in einen eigenen Namensraum (Domain) installiert. Apps sind dann nach dem Schema http://$app-$domain.rhcloud.com öffentlich erreichbar. Dazu gleich mehr.

Das Kommando rhc-create-domain erzeugt einen neuen Namensraum, die Konfigurationsdatei express.conf und SSH-Schlüssel (libra_id_rsa) zur Git-Authentifizierung.

$ rhc-create-domain -n yourdomain -l user@example.com
Password: <user password>

Generating Openshift Express ssh key to /home/UserName/.ssh/libra_id_rsa
Generating public/private RSA key pair.
Created directory '/home/UserName/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/UserName/.ssh/libra_id_rsa.
Your public key has been saved in /home/UserName/.ssh/libra_id_rsa.pub.
.
.
Contacting https://openshift.redhat.com
Adding rhlogin to /home/UserName/.openshift/express.conf
Creation successful

You may now create an application.  Please make note of your local config file
in /home/UserName/.openshift/express.conf which has been created and populated for
you.

Jetzt noch Git (minimal) konfigurieren

$ git config --global user.name "Your Name"
$ git config --global user.email you@example.com

und dann kann endlich die erste App erstellt werden.

 

Appgerüst erzeugen

Das Kommando rhc-create-app erzeugt das Gerüst der neuen App. Über die Option -a wird der Name der Applikation angegeben. Die Option -t legt den Typ der Applikation, hier perl-5.10, fest. Typen werden in der Dokumentation auch gerne als cartridge bezeichnet.

$ rhc-create-app -a X1 -t perl-5.10 
Password: 

Attempting to create remote application space: X1
Now your new domain name is being propagated worldwide (this might take a minute)...
Pulling new repo down
Warning: Permanently added 'x1-thomasfahle.rhcloud.com,184.73.107.7' (RSA) to the list of known hosts.
Confirming application 'X1' is available
  Attempt # 1

Success!  Your application 'X1' is now published here:

      http://X1-thomasfahle.rhcloud.com/

The remote repository is located here:

    ssh://ce3eb6cc3b1942a2a61a76db6ff63274@X1-thomasfahle.rhcloud.com/~/git/X1.git/

To make changes to 'X1', commit to X1/.

Successfully created application: X1

Die neu erstellte Applikation mit dem Namen X1 innerhalb des Namensraumes thomasfahle ist sofort unter der URL http://x1-thomasfahle.rhcloud.com/ erreichbar.

Welcome-to-OpenShift-klein.png

Wer lieber seine eigene Domain verwenden möchte und über einen eigenen Nameserver verfügt, kann einen DNS Alias einrichten.

 

Orientierung im Gelände

Die neu erstellte Applikation befindet sich im Verzeichnis $app, hier X1.

$ tree X1
X1
|-- deplist.txt
|-- libs
|-- misc
|-- perl
|   |-- health_check.pl
|   `-- index.pl
`-- README

Das Verzeichnis perl ist die DocumentRoot der Webapp. Alle hier abgelegten Dateien sind öffentlich. Die Datei index.pl dient als DirectoryIndex.

Die Datei deplist.txt nimmt eine Liste der zu installierenden CPAN-Module auf, pro Zeile ein Modul ohne Versionsnummer.
Beispiel:

Test::Base
YAML
Dancer
Plack::Handler::Apache2

Das Verzeichnis misc ist nicht öffentlich und kann für eigene Zwecke genutzt werden.

Das Verzeichnis libs ist ebenfalls nicht öffentlich und dient als Speicherort für eigene Module.

Sinn und Zweck der Datei health_check.pl ist mir nicht ganz klar geworden.

Weiterhin gibt es noch ein verstecktes Verzeichnis .openshift zur Steuerung des Build-Prozesses. Dazu später mehr.

 

Das erste Programm: Umgebungsvariablen

Einige Konfigurationseinstellungen, z.B. für Datenbanken, sind als Umgebungsvariablen abgelegt.

Daher erstellen wir als erstes einfaches Beispiel keine Hallo-Welt-App, sondern eine nützliche App, welche die Umgebungsvariablen anzeigt.

Das Programm wird unter dem Namen printenv.pl im Ordner perl abgelegt.

#!/usr/bin/perl
use strict;
use warnings;

#  printenv -- demo CGI program which just prints its environment
print "Content-type: text/plain\n\n";

foreach my $key ( sort( keys(%ENV) ) ) {
    my $val = $ENV{$key};
    $val =~ s|\n|\\n|g;
    $val =~ s|"|\\"|g;
    print qq~$key = $val\n~;
}
exit();

Zur Veröffentlichung (Deployment) der App verwendet OpenShift Git. Sobald die Datei hinzugefügt und commited wurde, kann diese per git push in die Cloud ausgeliefert werden.

$ git add printenv.pl
$ git commit -m 'Umgebungsvariablen App'
$ git push

Counting objects: 6, done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 594 bytes, done.
Total 4 (delta 1), reused 0 (delta 0)
remote: Stopping application...
remote: Waiting for stop to finish
remote: Done
remote: Running .openshift/action_hooks/pre_build
remote: strict is up to date. (1.04)
remote: skipping F/FL/FLORA/perl-5.15.4.tar.gz
remote: Running .openshift/action_hooks/build
remote: Running .openshift/action_hooks/deploy
remote: Starting application...
remote: Done
remote: Running .openshift/action_hooks/post_deploy
To ssh://ce3eb6cc3b1942a2a61a76db6ff63274@X1-thomasfahle.rhcloud.com/~/git/X1.git/
   ee74341..e31f2ec  master -> master

Das Programm ist nun unter der URL http://x1-thomasfahle.rhcloud.com/printenv.pl erreichbar.

Hinweis: Alle Daten innerhalb des Git-Repositories werden dabei auf dem OpenShift Express Server zunächst gelöscht und dann neu eingespielt.

Hinweis: Da Umgebungsvariablen auch Benutzernamen und Passwörter enthalten können, sollte dieses Programm nicht auf dem Cloud-Server verbleiben.

Zum Bau und zur Auslieferung der Applikation werden die Programme im Ordner .openschift/action_hooks/ ausgeführt. Um sich die Umgebungsvariablen anzeigen zu lassen, genügt es in die Datei build die Anweisung export einzufügen. Dann werden die Umgebungsvariablen bei jedem push angezeigt.

$ cat .openshift/action_hooks/build 
#!/bin/bash
# This is a simple build script and will be executed on your CI system if 
# available.  Otherwise it will execute while your application is stopped
# before the deploy step.  This script gets executed directly, so it
# could be python, php, ruby, etc.
export

Eigene Umgebungsvariablen können derzeit nicht gesetzt werden.

 

Logfiles

Das Kommando rhc-tail-files ermöglicht den Zugriff auf die Logdateien auf dem Cloud-Server.

$ rhc-tail-files -a X1 
Password: 

Attempting to tail files: X1/logs/*
Use ctl + c to stop

==> X1/logs/error_log-20111122-000000-EST <==
[Tue Nov 22 16:43:18 2011] [notice] Apache/2.2.15 (Unix) mod_perl/2.0.4 Perl/v5.10.1 configured -- resuming normal operations

==> X1/logs/access_log-20111122-000000-EST <==
xx.xxx.xxx.IP - - [22/Nov/2011:16:47:04 -0500] "GET /printenv.pl HTTP/1.0" 200 2323 "-" "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.24) Gecko/20111107 Ubuntu/10.04 (lucid) Firefox/3.6.24"

Der Zugriff auf die error_log Dateien erleichert das Debuggen erheblich.

 

Snapshots

Das Kommando rhc-snapshot erstellt einen Snapshot der Applikation und liefert diesen als gezippte tar Datei zurü:

$ rhc-snapshot  -a X1 
Password: 

Pulling down a snapshot to X1.tar.gz

Stopping application...
Waiting for stop to finish
Done
Creating and sending tar.gz
Starting application...
Done

Wenn man die Datei X1.tar.gz auspackt, sieht man alle Verzeichnisse und Dateien der Applikation.

$ tar -xzvf X1.tar.gz
$ cd app-verzeichnis

$ tree
.
|-- git
|   `-- X1.git
|       |-- branches
|       |-- config
|       |-- description
|       |-- HEAD
|       |-- hooks
|       |   |-- applypatch-msg.sample
|       |   |-- commit-msg.sample
|       |   |-- post-commit.sample
|       |   |-- post-receive
|       |   |-- post-receive.sample
|       |   |-- post-update.sample
|       |   |-- pre-applypatch.sample
|       |   |-- pre-commit.sample
|       |   |-- prepare-commit-msg.sample
|       |   |-- pre-rebase.sample
|       |   |-- pre-receive
|       |   `-- update.sample
|       |-- info
|       |   |-- exclude
|       |   `-- refs
|       |-- objects
|       |   |-- 0a
|       |   |   `-- bed1546ab3d6aee5b42c68f57100f52949b4bf
|       |   |-- 10
|       |   |   `-- cd54466b8f66bb40d6c50ab5519bf7727e51dd
|       |   |-- 1d
|       |   |   `-- b60ffa4e6b41be6ed92a6a2b3343c70b301fb6
|       |   |-- 2f
|       |   |   `-- a0243ca6abb34233618e9ea809871be855a225
|       |   |-- 40
|       |   |   |-- 0b36608e5e4405636bf7394c546ec18de53252
|       |   |   `-- c24d558d8a1196d4170f56182b8f69fbe6741f
|       |   |-- 5e
|       |   |   `-- 1c48b299eb8c1fd204b69e520236d3a2a3217e
|       |   |-- 6a
|       |   |   `-- e37b40a1cd342e2661bdf06b65fc4731e1af1e
|       |   |-- 9b
|       |   |   `-- 594ba566f5036940fd00dfeca9cd38e51579a8
|       |   |-- a5
|       |   |   `-- 7d1f5806d714a998130b9517a4240de0c39fe3
|       |   |-- b5
|       |   |   `-- 3bde9fe6346b3d54d39b9d970308cc25080cbe
|       |   |-- c0
|       |   |   `-- df17bb0b3dbdb4da6c06ad6fe4e070e3061485
|       |   |-- c1
|       |   |   `-- d6344439cdc822df02c54bb39aabb5ccd4a7de
|       |   |-- d5
|       |   |   `-- 64d0bc3dd917926892c55e3706cc116d5b165e
|       |   |-- df
|       |   |   `-- 8d841a9e8c1afd175e0061bb7b762d708b0c58
|       |   |-- e3
|       |   |   `-- 1f2ec741b91b2d4ddc9500991cc660a8cf037d
|       |   |-- e6
|       |   |   `-- 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
|       |   |-- ed
|       |   |   `-- 5eb993715da4af89ce517eedb2c3879994e10e
|       |   |-- ee
|       |   |   `-- 74341ac408153e9bfe02fe55669533ccdfdbba
|       |   |-- f1
|       |   |   `-- 25e7fa5f3603669e173695b284d170ddd7b62f
|       |   |-- info
|       |   |   `-- packs
|       |   `-- pack
|       |       |-- pack-e8aca9b5d216bb7c5a7ac884d5cdcb6c0a9faabe.idx
|       |       `-- pack-e8aca9b5d216bb7c5a7ac884d5cdcb6c0a9faabe.pack
|       |-- packed-refs
|       `-- refs
|           |-- heads
|           |   `-- master
|           `-- tags
`-- X1
    |-- ci
    |-- conf
    |   `-- magic -> /etc/httpd/conf/magic
    |-- conf.d
    |-- data
    |-- logs
    |   |-- access_log-20111122-000000-EST
    |   |-- access_log-20111123-000000-EST
    |   |-- error_log-20111122-000000-EST
    |   `-- error_log-20111123-000000-EST
    |-- modules -> /usr/lib64/httpd/modules
    |-- perl5lib
    |-- repo -> runtime/repo
    |-- run
    |-- runtime
    |   `-- repo
    |       |-- deplist.txt
    |       |-- libs
    |       |-- misc
    |       |-- perl
    |       |   |-- health_check.pl
    |       |   |-- index.pl
    |       |   `-- printenv.pl
    |       `-- README
    `-- tmp

45 directories, 53 files

 

Persistent Storage

Wie oben bereits erwähnt, werden bei der Auslieferung (git push) alle Dateien, die sich innerhalb des Git-Repositories befinden, auf dem Cloud-Server gelöscht und neu eingespielt.

Persistente Daten, z.B. SQLite Dateien, müssen daher ausserhalb des Git-Repositories auf dem Server aufbewahrt werden. Dazu stellt OpenShift Express den Ordner data zur Verfügung.

Der Pfad zum Ordner data kann aus der Umgebungsvariablen OPENSHIFT_DATA_DIR ermittelt werden.

#!/usr/bin/perl
use strict;
use warnings;

print "Content-type: text/plain\n\n";

my $data_dir = $ENV{OPENSHIFT_DATA_DIR};
my $file = 'test.txt';

open (OUT, ">" , "$data_dir/$file" ) or die $!;

for ( 1 .. 10 ) {
        print OUT "$_\n";
}
close(OUT) or die $!;
exit();

Die im Ordner data gespeicherten Daten lassen sich per rhc-snapshot vom Cloud-Server holen.

$ tree
.
|-- ci
|-- conf
|   `-- magic -> /etc/httpd/conf/magic
|-- conf.d
|-- data
|   `-- test.txt
|-- logs
|   |-- access_log-20111122-000000-EST
|   |-- access_log-20111123-000000-EST
|   |-- error_log-20111122-000000-EST
|   `-- error_log-20111123-000000-EST
|-- modules -> /usr/lib64/httpd/modules
|-- perl5lib
|-- repo -> runtime/repo
|-- run
|-- runtime
|   `-- repo
|       |-- deplist.txt
|       |-- libs
|       |-- misc
|       |-- perl
|       |   |-- health_check.pl
|       |   |-- index.pl
|       |   |-- printenv.pl
|       |   |-- read.pl
|       |   `-- write.pl
|       `-- README
`-- tmp

 

Siehe auch

Weitere Posts