Déploiement et backup

Author:Vincent Fretin
Contributors:Thomas Desvenain
Version:1.0.0

Copyright (C) 2010 Vincent Fretin <vincentfretin AT ecreall.com>.

Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http://creativecommons.org/licenses/by-nc-sa/2.0/fr

Le code source présent dans ce document est soumis aux conditions de la « Zope Public License », Version 2.1 (ZPL).

THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED “AS IS” AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.

Définition

Le déploiement d’un site Plone requiert des options particulières. Par exemple, nous voulons être sûr qu’une configuration d’un buildout produit la même chose aujourd’hui ou dans un an.

Vous avez également des environnements différents, donc vous aurez un fichier de configuration par environnement (développement, intégration, production, ...). Chaque fichier principal development.cfg, deployment.cfg, deployment-backup.cfg étant une extension d’une configuration de base buildout.cfg intégrant tous les modules applicatifs.

Savoir

  • Profil buildout de déploiement
  • Mettre en place un backup de la ZODB
  • Apache
  • Varnish
  • HAproxy
  • plone.app.caching
  • Supervisor

Profil de déploiement

Vous pouvez récupérer l’exemple complet de buildout sur le collective :

$ git clone git://github.com/collective/collective.trainingmanual.git
$ cd collective.trainingmanual/examples/buildout

Le buildout.cfg du chapitre précédent est légèrement modifié :

buildout.cfg

[buildout]
extends =
    http://dist.plone.org/release/4.2.4/versions.cfg
    sources.cfg
    checkouts.cfg
    versions.cfg
    tests.cfg
parts +=
    instance1
    zopepy
    backup
    omelette
extensions =
    mr.developer
    buildout.dumppickedversions
versions = versions
allow-hosts =
    pypi.python.org
    effbot.org

find-links =
#    http://devagile:8080/site/products/simple
    http://dist.plone.org/release/4.2.4

eggs +=
    Pillow

[instance1]
recipe = plone.recipe.zope2instance
user = admin:admin
http-address = 8280
eggs =
#    formation.policy
    ${buildout:eggs}
environment-vars =
    PYTHON_EGG_CACHE ${buildout:directory}/tmp
    TMPDIR ${buildout:directory}/tmp
    zope_i18n_compile_mo_files true
zcml =
event-log-custom =
  <logfile>
    level info
    path ${buildout:directory}/var/log/${:_buildout_section_name_}.log
    max-size 1MB
    old-files 720
  </logfile>
  <logfile>
    level error
    path ${buildout:directory}/var/log/error.log
    max-size 1MB
    old-files 720
  </logfile>
access-log-custom =
  <logfile>
    path ${buildout:directory}/var/log/${:_buildout_section_name_}-Z2.log
    max-size 1MB
    old-files 720
  </logfile>
mailinglogger =
#  <mailing-logger>
#    level error
#    flood-level 10
#    smtp-server localhost:9025
#    from somebody@example.com
#    to somebody@example.com
#    subject [Error on MyApp] [%(hostname)s] %(line)s
#  </mailing-logger>

[zopepy]
recipe = zc.recipe.egg
eggs = ${instance1:eggs}
interpreter = zopepy
scripts = zopepy

[backup]
recipe = collective.recipe.backup
keep = 2
keep_blob_days = 14
full = false
gzip = true

[omelette]
recipe = collective.recipe.omelette
eggs =
    ${instance1:eggs}
    ${test:eggs}

Créez un fichier deployment.cfg :

deployment.cfg

[buildout]
extends =
    buildout.cfg
parts +=
    zeoserver
    instance1
    instance2
    instance3
    instance4
    varnish-build
    varnish-conf
    varnish
    haproxy
    haproxy-conf
    supervisor
    munin1
    munin2
    munin3
    munin4

eggs +=
    plone.app.caching

[hosts]
zeoserver   = 127.0.0.1
instance1   = 127.0.0.1
instance2   = 127.0.0.1
instance3   = 127.0.0.1
instance4   = 127.0.0.1
varnish     = 127.0.0.1
haproxy     = 127.0.0.1
supervisor  = 127.0.0.1

[ports]
zeoserver   = 8100
instance1   = 9880
instance2   = 9881
instance3   = 9882
instance4   = 9883
varnish     = 8000
haproxy     = 5501
supervisor  = 9001

[users]
zope        = vincentfretin
varnish     = vincentfretin
haproxy     = vincentfretin

[zeoserver]
recipe = plone.recipe.zeoserver
zeo-address = ${hosts:zeoserver}:${ports:zeoserver}

[instance1]
shared-blob = on
zeo-client = true
zeo-address = ${zeoserver:zeo-address}
effective-user = ${users:zope}
zodb-cache-size = 30000
zeo-client-cache-size = 128MB
zserver-threads = 1
http-address = ${hosts:instance1}:${ports:instance1}

[instance2]
<= instance1
http-address = ${hosts:instance2}:${ports:instance2}
#ftp-address = 9821

[instance3]
<= instance1
http-address = ${hosts:instance3}:${ports:instance3}

[instance4]
<= instance1
http-address = ${hosts:instance4}:${ports:instance4}

[supervisor]
recipe = collective.recipe.supervisor
port = ${ports:supervisor}
user = admin
password = admin
plugins = superlance
supervisord-conf = ${buildout:directory}/etc/supervisord.conf
serverurl = http://${hosts:supervisor}:${ports:supervisor}
programs =
    10 zeoserver ${zeoserver:location}/bin/runzeo ${zeoserver:location} true ${users:zope}
    20 instance1 ${buildout:bin-directory}/instance1 [console] ${instance1:location} true
    30 instance2 ${buildout:bin-directory}/instance2 [console] ${instance2:location} true
    40 instance3 ${buildout:bin-directory}/instance3 [console] ${instance3:location} true
    50 instance4 ${buildout:bin-directory}/instance4 [console] ${instance4:location} true
    60 haproxy ${buildout:bin-directory}/haproxy [-f ${buildout:directory}/etc/haproxy.conf -db] true
    70 varnish (autorestart=true) ${buildout:bin-directory}/varnish ${varnish:location} true
eventlisteners =
#    memmon TICK_60 ${buildout:bin-directory}/memmon [-p instance1=600MB -p instance2=600MB -p instance3=600MB -p instance4=600MB -m development+demo@example.com]
#    crashmail PROCESS_STATE ${buildout:bin-directory}/crashmail [-m development+demo@example.com]

[varnish-build]
recipe = zc.recipe.cmmi
url = ${varnish:download-url}

[varnish-conf]
recipe = collective.recipe.template
input = ${buildout:directory}/templates/varnish.vcl.in
output = ${buildout:directory}/etc/varnish.vcl

[varnish]
recipe = plone.recipe.varnish
daemon = ${buildout:parts-directory}/varnish-build/sbin/varnishd
bind = ${hosts:varnish}:${ports:varnish}
#backends = ${haproxy-conf:bind}
config = ${varnish-conf:output}
cache-size = 256M
user = ${users:varnish}
mode = foreground

[haproxy]
recipe = plone.recipe.haproxy
#cpu = i686
target = linux26
pcre = 1

[haproxy-conf]
recipe = collective.recipe.template
input = ${buildout:directory}/templates/haproxy.conf.in
output = ${buildout:directory}/etc/haproxy.conf
maxconn = 32000
ulimit-n = 65536
user = ${users:haproxy}
group = ${users:haproxy}
bind = ${hosts:haproxy}:${ports:haproxy}

[munin1]
recipe = zc.recipe.egg
eggs = munin.zope
scripts = munin=munin1
arguments = ip_address='${hosts:instance1}', http_address='${ports:instance1}', user="${instance1:user}"

[munin2]
recipe = zc.recipe.egg
eggs = munin.zope
scripts = munin=munin2
arguments = ip_address='${hosts:instance2}', http_address='${ports:instance2}', user="${instance2:user}"

[munin3]
recipe = zc.recipe.egg
eggs = munin.zope
scripts = munin=munin3
arguments = ip_address='${hosts:instance3}', http_address='${ports:instance3}', user="${instance3:user}"

[munin4]
recipe = zc.recipe.egg
eggs = munin.zope
scripts = munin=munin4
arguments = ip_address='${hosts:instance4}', http_address='${ports:instance4}', user="${instance4:user}"

Vous allez créer un utilisateur zope qui servira pour lancer le proxy cache varnish, le load balancer HAproxy et les instances zope.

$ sudo adduser zope

Note

Si vous avez installé un Plone en root avec l’unified installer, vous pouvez utiliser le compte plone au lieu de créer un compte zope. Pour cela remplacer zope par plone dans la section [users] du fichier deployment.cfg.

Note

Il faut que les fichiers appartiennent à l’utilisateur zope ou plone ou vous aurez des problèmes pour démarrer le zeoserver par exemple. Donc vérifiez que les fichiers ont bien le bon propriétaire :

$ sudo chown -R zope:zope votre_buildout

Relancez le buildout en tant qu’utilisateur zope avec bin/buildout -c deployment.cfg.

Supervisor

Le buildout génère le fichier etc/supervisord.conf.

Tous les processus sont gérés par supervisor.

Pour lancer supervisor, lancez le daemon en tant que super utilisateur qui lancera tous les processus ayant autostart=true (par defaut) :

$ sudo bin/supervisord

(varnish et haproxy ont besoin d’être démarrés en root pour activer certaines options. Les processus sont ensuite forkés pour utiliser l’utilisateur zope)

Vous pouvez voir l’état des processus avec :

$ bin/supervisorctl status

Pour redémarrer un processus par exemple instance1 :

$ bin/supervisorctl restart instance1

Pour stopper : stop, pour démarrer : start.

Pour tout redémarrer :

$ bin/supervisorctl restart all

Pour arrêter supervisor et donc tous les processus :

$ bin/supervisorctl shutdown

Support des backups

Les backups sont configurés dans la section backup.

[backup]
recipe = collective.recipe.backup
keep = 2
keep_blob_days = 14
full = false
gzip = true

[omelette]
recipe = collective.recipe.omelette
eggs =
    ${instance1:eggs}
    ${test:eggs}

Vous avez par défaut les options suivantes :

location = ${buildout-directory}/var/backups
snapshotlocation = ${buildout-directory}/var/snapshotbackups

Plus d’informations sur les options de la recipe

Pour exécuter la sauvegarde toutes les nuits, vous pouvez ajouter un cron job (crontab -e), ici à 3h du matin :

00 3 * * *      /home/zope/MyProject/bin/backup -q

Vous allez voir dans la suite une configuration de buildout qui s’occupe de créer le cron job à votre place.

Pour faire une restauration :

$ bin/restore

Si vous voulez faire un backup de la production pour travailler ensuite en local, utilisez plutôt la commande :

$ bin/snapshotbackup

qui créera une sauvegarde dans le dossier var/snapshotbackups/, utile pour ne pas perturber les sauvegardes normales qui se font la nuit. Vous récupérez ensuite la sauvegarde (les fichiers .fsz et .dat) via scp et vous placez la sauvegarde dans votre dossier var/snapshotbackups/ en local et exécutez bin/snapshotrestore en local.

Cron job pour zeopack et backup

Voici un exemple de configuration qui étend deployment.cfg pour réaliser un pack de la database avec la commande bin/zeopack et faire un backup avec la commande bin/backup vue précédemment.

Il synchronise également les dossiers backup/ et log/ sur un autre serveur.

Tout cela est réalisé par un job cron à 4h du matin.

deployment-backup.cfg

[buildout]
extends = deployment.cfg
parts +=
    backup-template
    backup-schedule
    zeopack-schedule

[backup-template]
recipe = collective.recipe.template
inline =
    #!/bin/bash
    ${buildout:bin-directory}/backup -q
    rsync -a --delete ${backup:location}/ save@serveur1.example.com:/home/save/Plone/backups/
    rsync -aH --delete ${backup:blobbackuplocation}/ save@serveur1.example.com:/home/save/Plone/blobstoragebackups/
output = ${buildout:bin-directory}/backup.sh
mode = 755

[backup-schedule]
recipe = z3c.recipe.usercrontab
times = 0 4 * * *
command = ${backup-template:output}

# every sunday
[zeopack-schedule]
recipe = z3c.recipe.usercrontab
times = 0 1 * * 0
command = ${buildout:bin-directory}/zeopack -B ${buildout:directory}/var/blobstorage/

Dans cet exemple, la synchronisation se fait sur le serveur de secours/backup serveur1.example.com avec le login save. Il vous faut préalablement partager une clé publique entre ces deux serveurs pour que la commande rsync ne demande aucun mot de passe.

Pour utiliser cette configuration, exécutez bin/buildout -c deployment-backup.cfg. Le cron job sera automatiquement ajouté dans le crontab de l’utilisateur.

Configuration d’Apache

Création d’un certificat autosigné :

$ sudo mkdir -p /etc/apache2/ssl/
$ sudo make-ssl-cert /usr/share/ssl-cert/ssleay.cnf \
  /etc/apache2/ssl/server.crt

/etc/apache2/sites-available/devagile :

NameVirtualHost 127.0.0.1

<VirtualHost 127.0.0.1:80>
    ServerName devagile
    ServerAdmin anthony.sombris@devagile.fr
    ErrorLog /var/log/apache2/devagile_error.log
    TransferLog /var/log/apache2/devagile_access.log
    LogLevel warn
    RewriteEngine On
    RewriteRule ^/(.*) https://ssl.devagile/$1 [NC,R=301,L]

</VirtualHost>

/etc/apache2/sites-available/ssl.devagile (dans la RewriteRule, changez Plone par le nom de votre site plone) :

NameVirtualHost 127.0.0.1:443

<VirtualHost 127.0.0.1:443>
    ServerName ssl.devagile
    ServerAdmin anthony.sombris@devagile.fr
    ErrorLog /var/log/apache2/devagile_error.log
    TransferLog /var/log/apache2/devagile_access.log
    LogLevel warn

    SSLEngine On
    SSLCertificateFile /etc/apache2/ssl/server.crt
    #SSLCertificateKeyFile /etc/apache2/ssl/server.key

    RewriteEngine On
    RewriteRule ^/(.*) http://localhost:8000/VirtualHostBase/https/%{SERVER_NAME}:443/Plone/VirtualHostRoot/$1 [L,P]

    <IfModule mod_proxy.c>
        <Proxy proxy:http://localhost:8000>
            Order deny,allow
            Allow from localhost
        </Proxy>
    </IfModule>
</VirtualHost>

Activez les sites :

$ a2ensite devagile
$ a2ensite ssl.devagile

Activez les modules :

$ a2enmod ssl
$ a2enmod dav
$ a2enmod proxy
$ a2enmod proxy_http
$ a2enmod rewrite

Activation de la compression

Activez le module deflate :

$ a2enmod deflate

et éditez le fichier de configuration /etc/apache2/mods-enabled/deflate.conf (ce n’est plus nécessaire avec Ubuntu 10.04 et plus) :

<IfModule mod_deflate.c>
        # these are known to be safe with MSIE 6
        AddOutputFilterByType DEFLATE text/html text/plain text/xml

        # everything else may cause problems with MSIE 6
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
        AddOutputFilterByType DEFLATE application/rss+xml
</IfModule>

Redémarrez Apache :

$ /etc/init.d/apache2 restart

Configuration des DNS

Pour configurer vos DNS ou pour tester en local, éditez /etc/hosts :

127.0.0.1 devagile ssl.devagile

Redémarrez Firefox pour qu’il relise le fichier.

Vous accéderez à votre site à partir de maintenant avec l’adresse http://devagile.

Installation et configuration de plone.app.caching

plone.app.caching propose une interface graphique pour gérer les règles de cache HTTP pour Plone 4. Il est construit sur z3c.caching, plone.caching et plone.cachepurging.

Installation

plone.app.caching est livré avec Plone mais n’est pas activé. Vous avez donc juste à activer le module dans la gestion des modules.

Le panneau de configuration de la gestion de cache

Une fois activé vous allez trouver au niveau de la configuration de votre site un lien pour configurer les règles de cache de votre site.

_images/liencaching.png

Cette interface graphique est constituée de trois onglets :

_images/3onglets.png
  1. Changer la configuration (Change settings) : pour gérer le comportement du cache HTTP
  2. Importer une configuration (Import settings) : vous permet d’importer des politiques de cache prédéfinies
  3. RAM cache : fournit des informations statistiques sur le cache en RAM et son éventuelle purge.

Configuration

Dans notre exemple, nous avons un cache proxy varnish derrière Apache. Pour configurer cette chaine, faire ce qui suit :

  • Cliquer sur Import settings, sélectionner With caching proxy, cliquer sur Import
  • Retourner dans Change settings, dans Global settings, cocher Enable caching
  • Dans l’onglet Caching proxies, cocher Enable purging
  • Ajouter http://127.0.0.1:8000 dans les Caching proxies.
  • Cocher Virtual host rewriting takes place front of the caching proxy car les adresses sont réécrites par Apache avec le RewriteRule.
  • Dans Externally facing domains, mettre https://ssl.devagile:443
  • Cliquer sur Save

Le mieux après est d’exporter cette configuration dans formation.policy. Pour cela aller dans portal_setup, export, Export the configuration registry schemata. Ajouter le fichier registry.xml dans votre dossier profiles/default/. Eventuellement nettoyer ce fichier, seules les clés commencant par plone.app.caching nous intéressent.

Pour aller plus loin : http://pypi.python.org/pypi/plone.app.caching

Tester

Vous pouvez tester que votre configuration fonctionne bien en inspectant les requêtes HTTP avec l’extension Firebug de Firefox par exemple.

Exercice

Geler toutes les versions des eggs utilisés dans le buildout.

Ajout de la recipe collective.recipe.backup dans le buildout pour réaliser un backup régulier de la base de données.


blog comments powered by Disqus