Buildout para instalar de todas las partes de un sitio

Descripción general

Buildout permite no solamente instalar Zope y Plone, sino cualquier parte de la arquitectura de un sitio, desde el servidor web de front end hasta el balanceador de carga o la base de datos. Un sitio plone poderoso requiere muchas partes distintas y mediante buildout podemos instalarlas todas de una sola vez. El beneficio adicional de esto es que obtenemos un solo script de configuración con el cual se puede repetir la instalación completa de todas las partes del sitio. Para conocer ejemplos de esto de una manera práctica, revisaremos paso por paso un script completo de buildout, comentando las diferentes partes que utilizaremos.

Arquitectura en Plone de Alta Disponibilidad

Transformaciones visuales

Lo primero es definir las secciones de construcción del software necesario. Lxml y diazo son componentes que forman parte de deliverance, que es un mecanismo para generar los temas visuales de los sitios de Plone mediante reglas de XSLT, evitando que el diseñador requiera conocer a fondo Plone y sus mecanismos de temas. Lxml tiene su propia receta y diazo utiliza la receta básica de instalación de paquetes de Python:

[lxml]
recipe = z3c.recipe.staticlxml
egg = lxml
force = false

[diazo]
recipe = zc.recipe.egg
eggs =
   lxml
   PasteScript
   diazo
scripts =
   paster
   diazocompiler

Configuraciones de Transformaciones visuales

Las transformaciones del tema visual con Deliverance se realizan configurando un servidor adicional de Nginx que ejecuta las reglas de los temas:

[transform-config]
recipe = collective.recipe.template
input = ${buildout:directory}/production/transform.conf.template
output = ${buildout:directory}/production/transform.conf

Zope y ZEO

La construcción de Zope y el servidor de ZEO utilizan así mismo sus propias recetas. Algunas declaraciones es mejor definirlas como variables para poder reutilizarlas en otras partes del buildout sin tener que definirlas más de una vez. Estas definiciones de variables constan de una cadena encerrada entre llaves y precedida por el símbolo $, de esta manera: ${parte:nombre}. En esta sintaxis, parte se refiere a la sección del buildout definida entre corchetes [] donde se define la variable y nombre corresponde a la variable definida dentro de esa sección:

[zope2]
recipe = plone.recipe.zope2install
fake-zope-eggs = true
additional-fake-eggs =
   ZConfig
   pytz
skip-fake-eggs =
   zope.testing
   zope.i18n
url = ${downloads:zope}

[zeoserver]
recipe         = plone.recipe.zeoserver
zeo-address    = ${hosts:zeoserver}:${ports:zeoserver}
# Packing
pack-days      = 0
# Customization
eggs =
    ZODB3
    mailinglogger
# If we try to start as root, Zope will switch to the user below
effective-user = ${buildout:effective-user}
# Process
zeo-var = ${buildout:directory}/var
# Set storage
blob-storage   = ${buildout:var-dir}/blobstorage
shared-blob    = on
# Logging
# Put the log, pid and socket files in var/zeoserver
zeo-log        = ${zeoserver:zeo-var}/${:_buildout_section_name_}/zeoserver.log
pid-file       = ${zeoserver:zeo-var}/${:_buildout_section_name_}/zeoserver.pid
socket-name    = ${zeoserver:zeo-var}/${:_buildout_section_name_}/zeo.zdsock

Clientes ZEO

Como según nuestro diagrama de arquitectura del sitio deseamos tener cuatro clientes en un cluster, lo mejor es utilizar la receta existente para generar cluster de Plone en lugar de la típica receta de zope2instance. La parte importante aquí es la definición de instance-clone, que representa una definición de molde que contendrá valores de configuración que serán utilizados por los cuatro clientes. Siempre se recomienda utilizar variables para la definición de hosts y puertos, de tal forma que puedan configurarse en una sección separada:

[client1]
recipe = collective.recipe.zope2cluster
instance-clone = instance-settings
http-address = ${hosts:client1}:${ports:client1}
zope-conf-additional =
   <icp-server>
      address ${ports:client1-icp}
   </icp-server>

[client2]
recipe = collective.recipe.zope2cluster
instance-clone = instance-settings
http-address = ${hosts:client2}:${ports:client2}
zope-conf-additional =
   <icp-server>
      address ${ports:client2-icp}
   </icp-server>

[client3]
recipe = collective.recipe.zope2cluster
instance-clone = instance-settings
http-address = ${hosts:client3}:${ports:client3}
zope-conf-additional =
   <icp-server>
      address ${ports:client3-icp}
   </icp-server>

[client4]
recipe = collective.recipe.zope2cluster
instance-clone = instance-settings
http-address = ${hosts:client4}:${ports:client4}
zope-conf-additional =
   <icp-server>
      address ${ports:client4-icp}
   </icp-server>

Instancia de depuración

Es recomendable también incluir una instancia de debug que no sea iniciada automáticamente para poder conectarse al sitio sin interferir con el cluster de producción:

[client-debug]
recipe = collective.recipe.zope2cluster
instance-clone = instance-settings
http-address = ${hosts:client-debug}:${ports:client-debug}
debug-mode = on
verbose-security = on

Servidor web

nginx, es un servidor web de alto desempeño, que es cada vez más utilizado en el mundo de Plone. La receta cmmi que se utiliza baja el paquete, lo configura, lo compila y lo instala. Esto significa que dicha receta puede utilizarse en realidad para instalar cualquier paquete de Unix que utilice este mecanismo de compilación e instalación:

[nginx-build]
recipe = hexagonit.recipe.cmmi
url = ${downloads:nginx}
patches =
   ${buildout:directory}/patches/nginx-xslt.patch
   ${buildout:directory}/patches/nginx-xslt-options.patch
   ${buildout:directory}/patches/nginx-xslt-conf.patch
configure-options =
   --with-http_xslt_module
   --with-http_stub_status_module
   --with-libxml2=${buildout:directory}/parts/libxml2
   --with-libxslt=${buildout:directory}/parts/libxslt
   --conf-path=${buildout:directory}/production/nginx/default.conf
   --error-log-path=${buildout:directory}/var/log/main-error.log
   --pid-path=${buildout:directory}/var/main.pid
   --lock-path=${buildout:directory}/var/main.lock

Configuraciones de servidor web

La configuración del servidor web principal de Nginx se hace utilizando como template un archivo almacenado en el buildout.

[main-config]
recipe = collective.recipe.template
input = ${buildout:directory}/production/main.conf.template
output = ${buildout:directory}/production/main.conf

[compile-theme]
recipe = plone.recipe.command
command = ${buildout:directory}/bin/diazocompiler -t ${theme:theme} -r ${theme:rules} -a ${theme:absolute-prefix} ${theme:output-xslt}
update-command = ${compile-theme:command}

Motor de cacheo

Varnish, es un motor de cacheo que guarda las respuestas de las peticiones dinámicas que se hacen a Plone y las sirve directamente de disco para mejorar el desempeño:

[varnish-build]
recipe = hexagonit.recipe.cmmi
url = ${downloads:varnish}

Configuraciones de Motor de cacheo

La configuración de Varnish funciona de la misma manera:

[cache-config]
recipe = collective.recipe.template
input = ${buildout:directory}/production/cache.conf.template
output = ${buildout:directory}/production/cache.conf

[cache]
recipe = plone.recipe.varnish
daemon = ${buildout:directory}/parts/varnish-build/sbin/varnishd
mode = foreground
bind = ${hosts:cache}:${ports:cache}
cache-size = 1G
user = ${users:cache}
config = ${buildout:directory}/production/cache.conf

Balanceador de carga

HAProxy, es un balanceador de carga que distribuye las peticiones al sitio entre los cuatro clientes definidos:

[haproxy-build]
recipe = plone.recipe.haproxy
url = http://dist.jarn.com/public/haproxy-1.3.15.7.zip
cpu = ${build:cpu}
target = ${build:target}

Configuraciones de balanceador de carga

El balanceador de carga también utiliza un archivo de template ubicado dentro del buildout:

[balancer-config]
recipe = collective.recipe.template
input = ${buildout:directory}/production/balancer.conf.template
output = ${buildout:directory}/production/balancer.conf

Administrador de procesos

Supervisor es un administrador de procesos que se encarga de mantener funcionando todas las piezas del sitio y proporciona un punto único de control para iniciar y detener los servicios, así como consultar su status y logs:

[supervisor]
recipe = collective.recipe.supervisor
port = ${ports:supervisor}
user = ${supervisor-settings:user}
password = ${supervisor-settings:password}
serverurl = http://${hosts:supervisor}:${ports:supervisor}
programs =
#  Prio Name      Program                                      Params
   10   zeo     ${zeoserver:location}/bin/runzeo true ${users:zope}
   20   client1 ${buildout:directory}/parts/client1/bin/runzope true ${users:zope}
   20   client2 ${buildout:directory}/parts/client2/bin/runzope true ${users:zope}
   20   client3 ${buildout:directory}/parts/client3/bin/runzope true ${users:zope}
   20   client4 ${buildout:directory}/parts/client4/bin/runzope true ${users:zope}
   30   balancer ${buildout:directory}/bin/haproxy [-f ${buildout:directory}/production/balancer.conf -db] true ${users:balancer}
   40   transform ${nginx-build:location}/sbin/nginx [-c ${buildout:directory}/production/transform.conf] true ${users:transform}
   50   cache ${buildout:directory}/bin/cache true ${users:cache}
   60   main ${nginx-build:location}/sbin/nginx [-c ${buildout:directory}/production/main.conf] true

eventlisteners =
# Check every 60 seconds that no child process has exceeded. it's like a RSS memory quota
MemoryMonitor TICK_60 ${buildout:bin-directory}/memmon [-p client1=200MB -p client2=200MB -p client3=200MB -p client4=200MB -m macagua+leonardocaballero@gmail.com]
# Check every 60 seconds whether the plone instance is alive
HttpOk1 TICK_60 ${buildout:bin-directory}/httpok [-p client1 -t 20 http://127.0.0.1:${ports:client1}/${plone-sites:main}]
HttpOk2 TICK_60 ${buildout:bin-directory}/httpok [-p client2 -t 20 http://127.0.0.1:${ports:client2}/${plone-sites:main}]
HttpOk3 TICK_60 ${buildout:bin-directory}/httpok [-p client3 -t 20 http://127.0.0.1:${ports:client3}/${plone-sites:main}]
HttpOk4 TICK_60 ${buildout:bin-directory}/httpok [-p client4 -t 20 http://127.0.0.1:${ports:client4}/${plone-sites:main}]

Rotar archivos con logrotate

Se genera una configuración de logrotate para poder incluirla fácilmente en el directorio de configuración de esta herramienta en Unix:

[logrotate.conf]
recipe = collective.recipe.template
input = ${buildout:directory}/production/logrotate.conf.template
output = ${buildout:directory}/production/logrotate.conf

Herramientas de desarrollo

Un intérprete de Python y algunas otras herramientas de desarrollo se incluyen en las siguientes secciones. El intérprete de Python es especial porque en su path de ejecución están todos los paquetes utilizados en el buildout:

[zopepy]
recipe = zc.recipe.egg
eggs = ${instance-settings:eggs}
interpreter = zopepy
extra-paths = ${zope2:location}/lib/python
scripts = zopepy

[omelette]
recipe = collective.recipe.omelette
eggs = ${instance-settings:eggs}
products = ${instance-settings:products}
packages = ${zope2:location}/lib/python ./

[diazo-setup]
recipe = collective.recipe.template
input = ${buildout:directory}/devel/server.ini.template
output = ${buildout:directory}/devel/server.ini

Secciones de buildout de producción

Esta configuración de construcción se integra después en una configuración base del sitio. La base contiene la mayoría de los servicios y configuraciones compartidas entre las demás configuraciones buildout. El buildout contiene los siguientes servidores:

main
el servidor web Nginx que puede correr en el puerto principal
cache
un cache Varnish configurado para servir un sitio Plone
transform
un servidor web Nginx que realiza transformaciones
balancer
un cluster de HAproxy que balancea los clientes ZEO
client1
Cliente de ZEO 1
client2
Cliente de ZEO 2
client3
Cliente de ZEO 3
client4
Cliente de ZEO 4
client-debug
un cliente ZEO que no forma parte del cluster y esta siempre en modo de desarrollo.
zeoserver
un servidor ZEO para la base de datos de Zope común

Se incluye la configuración para rotación de logs con logrotate, excepto para Varnish. La configuración queda en el directorio production/logrotate.conf y debe integrarse a la configuración general de logrotate usando un symlink.

En la configuración de transformación de Nginx, solo se incluye un servidor Plone, pero es posible agregar mas si es necesario.

Para controlar todos los servicios, se incluye Supervisor:

$ ./bin/supervisord

En http://localhost:9001 puede consultarse el estado de los servicios. Desde ahí es posible iniciar o detener cualquiera de ellos.

La configuración esta contenida enteramente en este buildout, con patrones para los archivos de configuración en production/*.template. Los nombres de servidores, puertos y otras opciones comunes pueden cambiarse en las secciones que se encuentran al inicio de este archivo. Estos son los valores que se utilizan en la sección de construcción definida arriba:

[buildout]
extensions = buildout.dumppickedversions
# Copiar las versiones mas recientes de los paquetes utilizados a un archivo,
# para poder "congelarlas" después en producción.
dump-picked-versions-file = versions/known-good-versions.cfg

# Extender la configuración de versiones para obtener la versión de Plone
# requerida, desde http://dist.plone.org/release/<version>/versions.cfg
extends =
   build.cfg
   versions/plone-3.3rc4.cfg

newest = false
unzip = true
versions = versions

# Las partes del buildout son todos los servicios que se instalaran
parts =
   lxml
   diazo
   zope2
   zeoserver
   client1
   client2
   client3
   client4
   client-debug
   nginx-build
   varnish-build
   haproxy-build
   cache
   main-config
   cache-config
   transform-config
   balancer-config
   compile-theme
   logrotate.conf
   supervisor
   zopepy
   omelette
   backup
   cron-pack
   cron-backup

develop =
   src/*

# Se requieren versiones especificas de algunos proyectos
[versions]
zc.buildout = 1.2.1
zc.recipe.testrunner = 1.1.0
elementtree = 1.2.6-20050316
ZODB3 = 3.8.1
z3c.blobfile = 0.1.2
lxml = 2.1.5

###
# URLs de las versiones de Zope, Varnish y Nginx que se utilizaran
[downloads]
zope = ${versions:zope2-url}
varnish = http://downloads.sourceforge.net/varnish/varnish-2.0.4.tar.gz
nginx = http://sysoev.ru/nginx/nginx-0.7.43.tar.gz

# configuración básica de los clientes ZEO
[instance-settings]
eggs =
#   mynamespace.policy
   Plone
   plone.app.blob
   plone.app.ldap
   Products.CacheSetup
zcml =
# mynamespace.policy
# mynamespace.policy-meta
# mynamespace.policy-overrides
   plone.app.ldap
   plone.app.blob
products =
user = admin:admin
zodb-cache-size = 10000
zeo-client-cache-size = 300MB
debug-mode = off
zope2-location = ${zope2:location}
zeo-client = true
shared-blob = on
blob-storage = ${zeoserver:zeo-var}/blobstorage
zeo-address = ${zeoserver:zeo-address}
effective-user = ${users:zope}

# configuración básica de supervisor
[supervisor-settings]
user = admin
password = admin

# Nombre del sitio Plone que se usara para configurar virtual hosting
[plone-sites]
main = plone-site

# Nombres o ips de los diversos servidores, main es el principal
[hosts]
main = 127.0.0.1
cache = 127.0.0.1
supervisor = 127.0.0.1
balancer = 127.0.0.1
transform = 127.0.0.1
client1 = 127.0.0.1
client2 = 127.0.0.1
client3 = 127.0.0.1
client4 = 127.0.0.1
client-debug = 127.0.0.1
diazo = 127.0.0.1
syslog = 127.0.0.1

# Puertos de los servidores, main es el principal
[ports]
main = 8000
cache = 8101
balancer = 8201
transform = 8301
client1 = 8401
client2 = 8402
client3 = 8403
client4 = 8404
client1-icp = 8401
client2-icp = 8402
client3-icp = 8403
client4-icp = 8404
client-debug = 8499
zeo-server = 8501
supervisor = 9001
diazo = 5000

# Usuarios del sistema a los que se asignaran los servicios
[users]
main = www
cache = www
transform = www
balancer = www
zope = www
supervisor = www

# configuración del tema
[theme]
root = ${buildout:directory}/theme
theme = ${theme:root}/theme.html
rules = ${theme:root}/rules/default.xml
absolute-prefix = /static
output-xslt = ${theme:root}/theme.xsl

# configuración de compilación
[build]
cpu = i686
target = linux26

# Creación de scripts para backup
[backup]
recipe = collective.recipe.backup

# Compresión semanal de la base de datos
[cron-pack]
recipe = z3c.recipe.usercrontab
times = 0 2 1 * *
command = ${buildout:directory}/bin/zeopack

# Backups diarios
[cron-backup]
recipe = z3c.recipe.usercrontab
times = 0 1 * * *
command = ${buildout:directory}/bin/backup

Descarga código fuente

Para descargar el código fuente de este ejemplo ejecute el siguiente comando:

$ git clone https://github.com/plone-ve/buildout.plone.highavailability.git

Conclusiones

Este ejemplo demuestra las capacidades del zc.buildout como herramienta para la construcción de la las diversas partes del sitio web en entornos de producción.

Artículos relacionados

Ver también

Artículos sobre replicación de proyectos Python.

Referencias

los comentarios son proporcionados por Disqus

Editar este documento

El código fuente de este archivo esta hospedado en GitHub. Todos pueden actualizar y corregir errores en este documento con unos clic - sin necesidad de descargar.

  1. Vaya hacia el articulo Buildout para instalar de todas las partes de un sitio en GitHub.
  2. Presione el botón Fork. Este creara su propia copia personal de la documentación.
  3. Edite los archivos usando el editor de texto de GitHub desde su navegador Web
  4. Rellene en la caja de texto Commit message al final de la pagina indicando por que usted realizo estos cambios. Presione el botón Propose file change próximo a ese cuando haya finalizado.
  5. Luego diríjase a la página Send a pull request (no será necesario rellenar ningún texto adicional). Sólo tiene que pulsar el botón Send pull request.
  6. Sus cambios serán consultados por un revisor dentro de la pestaña Pull requests del proyecto en Github.

Para mas información básica acerca de como actualizar este manual y referencia a sintaxis Sphinx, por favor consulte la guía Escribiendo y actualizando el manual.