Vous êtes sur la page 1sur 47

TRABAJO FIN DE GRADO

Título

Mejores practicas de despliegue continuo para


aplicaciones Symfony2
Autor/es

Fernando Arconada Orostegui

Director/es

Eloy Javier Mata Sotés


Facultad

Facultad de Ciencias, Estudios Agroalimentarios e Informática


Titulación

Grado en Ingeniería Informática

Departamento

Curso Académico

2012-2013
Mejores practicas de despliegue continuo para aplicaciones Symfony2, trabajo
fin de grado
de Fernando Arconada Orostegui, dirigido por Eloy Javier Mata Sotés (publicado por la
Universidad de La Rioja), se difunde bajo una Licencia
Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported.
Permisos que vayan más allá de lo cubierto por esta licencia pueden solicitarse a los
titulares del copyright.

© El autor
© Universidad de La Rioja, Servicio de Publicaciones, 2013
publicaciones.unirioja.es
E-mail: publicaciones@unirioja.es
Mejores prácticas de despliegue continuo para aplicaciones
Symfony2
Fernando Arconada Orostegui
5 de junio de 2013

Índice general

Índice general i

Índice de guras iii

1 Resumen 1

2 Abstract 1

3 Introducción 2
3.1. Antecedentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3.2. Problema que se quiere solucionar . . . . . . . . . . . . . . . . . . . . 2
3.3. Elementos a conseguir . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3.4. Flujos de trabajo habituales . . . . . . . . . . . . . . . . . . . . . . . 3

4 DevOps 6
4.1. Inculcar una cultura de DevOps . . . . . . . . . . . . . . . . . . . . . 6
4.2. Puntos a tener en cuenta para implantar con éxito una cultura de
DevOps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.3. Cómo crear una cultura de DevOps . . . . . . . . . . . . . . . . . . . 9

5 Infraestructura como código 12


5.1. Ventajas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
5.2. Herramientas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
5.3. Conguración con Puppet . . . . . . . . . . . . . . . . . . . . . . . . 13
5.4. Plataforma de producción . . . . . . . . . . . . . . . . . . . . . . . . 14

6 Entornos de producción, pruebas y desarrollo comparables 18


6.1. Diferentes entornos en Sistemas . . . . . . . . . . . . . . . . . . . . . 18
6.2. Entorno de producción . . . . . . . . . . . . . . . . . . . . . . . . . . 18
6.3. Gestión de máquinas virtuales con Vagrant . . . . . . . . . . . . . . . 22
6.4. Entorno de pruebas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

i
7 Sistema de control de versiones 24
7.1. Modelo de Ramas para Git . . . . . . . . . . . . . . . . . . . . . . . 24
7.2. Release Candidates . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
7.3. Estado de commit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

8 Despliegue como proceso automático 28


8.1. Herramientas de despliegue . . . . . . . . . . . . . . . . . . . . . . . 28
8.2. Alternativas a un script . . . . . . . . . . . . . . . . . . . . . . . . . 28
8.3. Capifony . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

9 Mantener la calidad del software 31


9.1. Qué es la integración continua . . . . . . . . . . . . . . . . . . . . . . 31
9.2. Métricas y reglas de integración contínua . . . . . . . . . . . . . . . . 31
9.3. Phing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

10 Monitorización 35
11 Plan B 36
11.1. Los datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
11.2. Rollback con capifony . . . . . . . . . . . . . . . . . . . . . . . . . . 37
11.3. Página de mantenimiento con capifony . . . . . . . . . . . . . . . . . 37

12 Conclusiones 39
Bibliografía 40

ii
Índice de guras

1. Flujo de trabajo 1.0 (empresa ágil) . . . . . . . . . . . . . . . . . . . . . . 4


2. Flujo de trabajo 2.0 (empresa burocrática) . . . . . . . . . . . . . . . . . . . 6
3. Actitud normal ante los problemas . . . . . . . . . . . . . . . . . . . . . . . 7
4. Actitud buena ante los problemas . . . . . . . . . . . . . . . . . . . . . . . . 7
5. Áreas de Desarrollo y Sistemas . . . . . . . . . . . . . . . . . . . . . . . . . 9
6. Áreas de aplicación de DevOps . . . . . . . . . . . . . . . . . . . . . . . . . 10
7. AMIs de Ubuntu Cloud en Amazon AWS . . . . . . . . . . . . . . . . . . . 15
8. Pasos para la creación del entorno de producción . . . . . . . . . . . . . . . 21
9. Pasos para la creación del entorno de pruebas y desarrollo . . . . . . . . . . 24
10. Modelo de ramas para Git propuesto por NVIE . . . . . . . . . . . . . . . . 25
11. Detalle de ramas de develop y master . . . . . . . . . . . . . . . . . . . . . 26
12. Ejemplo de gráco generado con PHP Depend . . . . . . . . . . . . . . . . 33
13. Ejemplo de gráco de métricas en pirámide generado con PHP Depend . . . 33

iii
1 Resumen
Poner un proyecto de software en marcha comprende más cosas que desarrollar código.
El software es algo vivo, normalmente una vez que se pone online o se entrega al cliente
se sigue desarrollando y generando nuevas versiones. En la mayor parte de las empresas, la
puesta en producción de una nueva versión es un momento crítico por las incertidumbres
que genera. Dentro de las empresas de IT hay dos grupos marcados que creen tener obje-
tivos distintos, desarrollo (dev) y sistemas (ops). Cambiar la mentalidad de estos grupos,
automatizar todas las tareas posibles y establecer políticas de calidad y control claras son
fundamentales para que el proceso de trasladar valor a los clientes (implementar cambios)
sea un proceso frecuente, sencillo y seguro.

2 Abstract
Start a software project is more than develop code. Software is alive. You will deploy new
releases after run it online for rst time or deliver it to the customer. Most times every
software deployment it's a critical moment cause of uncertainty generated. IT rms use to
have two kind of teams, developers (devs) and operators (ops). Both think that they goals
are dierent but this is not true. Change their minds, automate every task and establish a
clear quality policy with checkpoints is something vital to increase the value perceived by
our customers (in the end, implement change). So this will become a frequent task, easy
and reliable.

1
3 Introducción
3.1. Antecedentes
Hasta la actualidad, son muchas las empresas que se han dedicado a crear software sin
una reexión seria sobre cómo poner y mantener ese software en producción. El software
está vivo y en constante evolución, no sólamente porque esté extendido el modelo de difun-
dir y parchear, sino porque el mercado exige evolucionar y aplicar cambios con celeridad.
En los modelos de desarrollo de software se ha ido pasando de metodologías en las que se
abordaba la totalidad de las funcionalidades del software en cascada a metodologías ágiles.
El desarrollo ágil de software son métodos de ingeniería del software basados en el desa-
rrollo iterativo e incremental, donde los requerimientos y soluciones evolucionan mediante
la colaboración de grupos auto organizados y multidisciplinarios. Existen muchos métodos
de desarrollo ágil; la mayoría minimiza riesgos desarrollando software en lapsos cortos. El
software desarrollado en una unidad de tiempo es llamado una iteración, la cual suele durar
de 1 a 4 semanas. Ha habido mucho debate respecto a cómo desarrollar software, pero sólo
recientemente se está planteando cómo debemos poner el software en manos de los usuarios,
tanto en la primera puesta en producción como en cada una de las iteraciones o parches
ofrecidos. Además, los usuarios son cada vez más exigentes y más globales, y por lo tanto
toleran peor los problemas de disponibilidad. El objetivo de este documento es ofrecer un
ejemplo de modelo de despliegue de aplicaciones en el que se reexione sobre las que pueden
ser las mejores prácticas para poner en producción de forma ágil las nuevas versiones de
las aplicaciones. Como el modelo de despliegue está muy ligado a la tecnología que utiliza
para desarrollar, en el presente trabajo n de grado nos vamos a centrar en aplicaciones
desarrolladas con el framework de desarrollo PHP Symfony2.
3.2. Problema que se quiere solucionar
El objetivo es encontrar una forma de trabajo en el desarrollo integral de software que
no sea el caos típico de la empresa ágil ni tan lento como la empresa burocrática. Hay
que encontrar un ujo integral que no implique cruzar los dedos cada vez que se hace
un despliegue ni que tenga que pasar una semana para que los usuarios puedan usar las
nuevas funcionalidades. Subir cambios a producción debe implicar una garantía de éxito.
La infraestructura debe estar al servicio del software, debe ser fácilmente reproducible y
gestionable. En el ciclo de vida del software hay 3 etapas claras: desarrollo, pruebas y
producción. Desarrollo y producción son inevitables. El entono de pruebas es altamente
recomendable. El objetivo de estos entornos es:
Desarrollo: entorno donde el equipo de desarrollo crea el software, normalmente es
su propio PC, que ellos suelen denominar local. Se suelen realizar muchos cambios
al día, del orden de decenas o incluso cientos. También es común ver entornos de
desarrollo compartidos entre miembros del equipo de desarrollo.
Producción: es el entorno donde se ejecutan las aplicaciones y pueden usarlas los
clientes nales. Normalmente este entorno suele ser, al menos, un servidor dedicado,
si no un cluster, y lo normal es que tenga un sistema operativo diferente al entorno de
desarrollo e incluso una arquitectura diferente. Debe permanecer estable. Suele estar
gestionado por el equipo de Sistemas.

2
Pruebas: Se congura prácticamente igual al de producción y sirve para validar cam-
bios e intentar reproducir los errores de producción.

3.3. Elementos a conseguir


Para lograr el objetivo de establecer un ujo de despliegue continuo que mantenga la
estabilidad del sistema nos proponemos implementar los siguientes elementos:
Inculcar una cultura de DevOps, porque esto no se puede lograr sin la implicación de
todas las partes, esto es, el departamento de desarrollo y el departamento de sistemas.
Desplegar una infraestructura gestionable como código
Tener entornos de producción, pruebas y desarrollo comparables para evitar la frase
funciona en mi local
Utilizar un sistema de control de versiones que sirva para gestionar las diferentes ver-
siones del software tanto desde el punto de vista de desarrollo como de la infraestrutura
Hacer que el despliegue de cada cambio sea un proceso automático
Vericar que en el código se mantenga una calidad mínima a lo largo del tiempo
Establecer un plan B de marcha atrás que se pueda ejecutar de manera automatizada
o al menos claramente procedimental.

3.4. Flujos de trabajo habituales


Podemos agrupar a las empresas de desarrollo de software en dos grupos según su forma de
trabajo, que llamaremos Flujo de trabajo 1.0 y Flujo de trabajo 2.0 El Flujo 1.0 es el propio
de empresas que acaban de empezar o de tamaño reducido, normalmente sin diferenciación
de funciones. Este ujo se caracteriza por la agilidad y la desorganización formal. El Flujo
2.0 es la forma que han optado numerosas empresas según han ido creciendo para ser capaces
de contener el caos. Se caracteriza por la separación de funciones y la burocratización de los
procesos. En el presente trabajo intentaremos mostrar una nueva forma de trabajo basada
en la entrega continua pero que no por ello cae en la desorganización ni la inestabilidad.

Flujo de trabajo 1.0 (empresa ágil)


Es el ujo de trabajo más ágil, y también el menos pensado. Se tiene una idea, se desarrolla
y se despliega en producción. Suele ser lo habitual en empresas pequeñas y nuevas. El
mayor problema es que según avanza el tiempo el caos se apodera de la empresa, aparecen
conictos entre los compañeros de diferentes departamentos y empiezan a aparecer, cada
vez con más frecuencia errores. Cuando se arregla algo, de repente comienza a fallar una
funcionalidad que nadie había tocado hace meses. La infraestructura de servidores acaba
tan personalizada que son verdaderas piezas únicas de artesanía informática. El código
está escrito de tal manera y tan poco testeado que es difícil que alguien que no sea el autor
pueda mantenerlo, suponiendo que no haya pasado mucho tiempo desde que lo escribió.
Caracteísticas típicas de este ujo de trabajo son:
No hay nada por escrito

3
controlar la complejidad, pero a cambio se ha sacricado la agilidad para hacer llegar los
cambios a los usuarios. Las modicaciones sencillas pueden tardar semanas en aplicarse e
implican tiempo de muchas personas. El Departamento de Infraestructuras o Sistemas es
el responsable de mantener los ratios de disponibilidad de los servicios y por lo tanto no
es proclive a realizar cambios. El Departamento de Desarrollo es el responsable de crear
las nuevas funcionalidades demandadas por los usuarios lo antes posible y por lo tanto su
trabajo es modicar los programas. La burocracia es el pegamento que hace que ambos
departamentos se pongan de acuerdo. Estas empresas suelen tener, incluso por escrito, los
formularios que debe cumplimentar una aplicación para que sea puesta en producción. Un
ejemplo de este ciclo puede ser:

En el entorno de desarrollo se despliega cada hora y se utiliza para que los cambios se
aprueben internamente.

En el entorno de pruebas se despliega una vez al día y se emplea como sistema de


validación por parte del usuario nal, en el que verica la funcionalidad, usabilidad
etc.

En el entono de producción se despliega una vez a la semana, siempre el mismo día y


a la misma hora. Siempre se hace el despliegue por una persona autorizada y se exige
que el software haya pasado por los entornos de desarrollo y pruebas. Por lo tanto,
los cambios tardan en llegar al usuario nal cerca de una semana. Si comparamos la
simplicidad de la Figura 1 del Flujo 1.0 con la correspondiente al Flujo 2.0 vemos que
ahora hay multitud de estaciones por las que ir pasando desde que tenemos una gran
idea hasta que el desarrollo de esa idea llega al usuario nal.

5
4.2. Puntos a tener en cuenta para implantar con éxito una
cultura de DevOps
Difuminar la distinción entre programadores y administradores de sistemas. Si el pro-
gramador no tiene experiencia en sistemas se produce el típico en mi local funciona,
por ejemplo derivado de que en el servidor la fecha está en formato MM/DD/YYYY
porque está congurado en inglés, que es diferente de su PC Windows 7 en español
DD/MM/YYYY
El procedimiento de paso a producción debe ser plenamente seguro. Hacer los desplie-
gues en producción debe estar plenamente automatizado. Hacer despliegues a mano,
aunque estén todos los pasos por escrito en un manual de procedimiento es la forma
más fácil de cometer algún error.
El código no debe tener bugs. Es prácticamente imposible que el software no tenga fa-
llos, pero hay que incentivar que los programadores adopten técnicas de programación
defensiva y apliquen continuamente test unitarios y funcionales. De esta forma, no
sólo se evitan errores, sino que mejora la implicación entre los equipos de desarrollo y
sistemas, ya que si estos últimos encuentran que cada vez el software es más conable
tienen menos excusas para oponerse al cambio.
Hay que empezar por el producto mínimo viable. Citando al padre de C++ un sistema
grande y complejo que no ha evolucionado a partir de otro más pequeño no funciona y,
además, es imposible arreglarlo para que funcione. Por lo tanto el software debemos
concebirlo como pequeñas iteraciones frecuentes y trataremos de huir de las grandes
versiones con muchos cambios.
El diseño debe estar planicado para poder crecer en pequeños trozos. Si la programa-
ción se debe hacer en pequeños trozos el diseño debe ser pensado de forma ambiciosa.
Un elemento fundamental para lograr este objetivo es reducir el acoplamiento para
que determinadas piezas puedan ser fácilmente substituibles sin afectar a otras partes
del programa.
El sistema debe ser muy fácilmente auditable y depurable. Dado que se van a producir
cambios continuamente, hay que poder trazar lo que está sucediendo en cada instante.
En este punto el software libre juega un papel muy importante.
El sistema debe tener resiliencia. El sistema debe poder funcionar aunque se degraden
las condiciones del entorno.
Debe existir una política de contención de daños. Antes de pasar nada a producción
hay que intentar determinar qué es lo peor que podría pasar e intentar tener un plan
B por si se produce el desastre.
La organización debe aceptar que el software es algo vivo. Como tal, crece y evoluciona.
Cada día aparecen nuevas funcionalidades, y, por contra, alguna que otra desaparece o
deja de funcionar temporalmente. De igual forma los plazos se vuelven algo deslizante,
el software no se desarrolla, evoluciona y, como todas las evoluciones, su velocidad de
cambio y la dirección que tomen pueden ser muy variables en función del entorno.
Debe existir un sistema de documentación continua. Si al software se le añaden co-
sas todos los días, llega un momento en el que evoluciona hasta un punto en el cual
8
Sistemas tiene información sobre el entorno de ejecución. Actualmente Sistemas esta inun-
dado de información y agrega esta información como parte de su propio sistema de monitori-
zación. Sin embargo si esta información no uye hacia Desarrollo se pierde una oportunidad
de que éstos aprendan y mejoren.

Área 3
Desarrollo solo aporta nuevas funcionalidades sin tener en cuenta otros objetivos no
funcionales La idea de este área es integrar al equipo de Desarrollo dentro del equipo de
Sistemas. No se trata sólo de juntar los equipos sino también los objetivos y las actividades
de desarrollo dentro del área de sistemas. Desarrollo debe tener en cuenta no solamente
objetivos funcionales sino que tienen que considerar otros objetivos como la estabilidad y la
capacidad como parte del propio desarrollo.
Práctica: Poner la estabilidad y la capacidad como objetivos de Desarrollo.
Objetivos:
Alinear objetivos
Compartir incentivos

Área 4
Mientras se desplegaba el software en producción por primera vez se descubre que van a
ser necesarias nuevas máquinas para poder ejecutar el software. Hay que tratar de integrar al
equipo de Sistemas dentro del departamento de Desarrollo. Ambos equipos deben trabajar
juntos para conseguir la mejor solución posible. El equipo de Sistemas está sumamente
implicado en el desarrollo consultando y aportando ideas a la solución a desarrollar, no
apareciendo solamente cuando la funcionalidad ya está programada.
Práctica: Sistemas aporta feedback sobre el diseño de la aplicación en desarrollo de
manera temprana y frecuente.
Objetivos:
Desarrollo gana feedback sobre si la funcionalidad a desarrollar es factible.
Compartir conocimiento.

11
5 Infraestructura como código
Cometer un error es humano, propagar el error de forma automática a todos los servidores
es #devops - DevOps Borat
Muchas de las corrientes actuales tratan de automatizar todas las partes posibles del
ciclo de desarrollo del software. En este sentido están entre otros los test unitarios o los
sistemas de integración continua, sin embargo la parte de sistemas y servidores sigue siendo
un trabajo artesanal. La infraestructura incluye todas las partes de la solución que no son
desarrolladas como el software de la aplicación en sí, es decir, servidores web, sistemas
operativos, tareas programadas, etc. El concepto de infraestructura como código se reere
a intentar gestionar la infraestructura como si de un desarrollo software se tratase. Esto
se hace posible de manera sencilla gracias a la virtualización y herramientas como Puppet,
Chef o Cfengine.

5.1. Ventajas
Las principales ventajas son:

Se tiene un control de versiones de las conguraciones de forma que se pueda supervisar


quien hace los cambios, qué cambios se han hecho y tener la posibilidad de volver atrás
en un momento dado.

Los entornos dejan de estar instalados manualmente para hacerlo mediante un proceso
automático, de forma que se evitan errores y los sistemas son fácilmente reproducibles
de manera able.

Se mejora considerablemente la documentación y la auditoría, puesto que en el software


de gestión de conguraciones y el control de versiones queda reejado el proceso de
puesta en marcha y ejecución de los servidores.

Se reduce los tiempos dedicados a la administración de sistemas, puesto que las labores
de mantenimiento se hacen de forma automatizada y centralizada.

5.2. Herramientas
Gestionar una infraestructura como código se puede hacer con diversas herramientas. Un
sistema de control de versiones es indispensable, pero de eso no hablaremos ahora. Aunque
esta gestión de sistemas se puede hacer con scripts es recomendable emplear utilidades como
Puppet, Chef, Cfengine y otros.
Puppet
Puppet gestiona sistemas Linux/Unix y MS Windows de forma declarativa. El usuario
describe los recursos del sistema y sus estados utilizando un DSL (Domain Specic Lan-
guage) de Ruby en cheros de texto llamados manifests. Puppet descubre la información
del sistema con una utilidad llamada Facter y junto con los manifests crea un catálogo que
aplica a los sistemas de destino. El resultado de aplicar esta catálogo es reportado a un nodo
central.
Chef
Es una herramienta de gestión de conguraciones escrita en Ruby y Erlang. Chef describe
los recursos y estados de los sistemas en cheros llamados recetas. Los atributos de los

12
sistemas gestionados bajo Chef se reportan al servidor central que los indexa mediante Solr
y junto las recetas genera la conguración a aplicar.
Cfengine
Cfengine es una herramienta muy madura de gestión de conguraciones, se basa en la
Teoría Promesas de Mark Burgess. Esta herramienta facilita la automatización de sistemas
y el mantenimiento de sistemas de computadores de gran escala, incluyendo la gestión de
servidores, estaciones de trabajo, dispositivos de red y dispositivos móviles.

Elección de herramienta
Vamos a elegit Puppet por las siguientes razones.
Descartamos Cfengine porque posteriormente vamos a usar Vagrant para el entorno de
desarrollo y este sólo soporta Chef o Puppet, además el lenguaje de Cfengine es complicado
y cuestan bastante depurar las promesas (lenguaje de Cfengine).
El lenguaje DSL de Puppet resulta cómodo para los administradores de sistemas y el de
Chef para los programadores de Ruby. Ambos tienen una buena documentación, aunque
Puppet tiene más libros escritos.
La comunidad alrededor de Puppet y Chef es grande y crece cada día si bien es cierto
que al ser Puppet un producto más maduro tiene más comunidad y ésta es muy activa.
Otro elemento clave a la hora de elegir Puppet ha sido la inversion de 30 millones de
dolares en la herramienta por parte de VMware que es el lider en soluciones de virtualización
y pensamos que esto puede marcar una diferencia para hacer que Puppet llegue al corazón
de las empresas.
Por otro lado, el entorno servidor de Chef es algo más complicado de desplegar que el
entorno de Puppet.
De todas formas estamos totalmente seguros de que es fácil que cada uno encuentre sus
propias razones para hacer que se decante hacia una u otra herramienta sin que ello signique
una limitación de sus posibilidades a la hora de desplegar una infraestructura como código.

5.3. Conguración con Puppet


Como hemos comentado anteriormente, la conguración de una infraestructura con Pup-
pet se realiza mediante un maniesto que describe los recursos del sistema y sus estados.
A continuación podemos observar un ejemplo de un maniesto de Puppet para la con-
guración de un servidor LAMP (Linux Apache MySQL PHP)

stage{bootstrap:}
Stage[bootstrap]->Stage[main]
node default{
class {'bootstrap': stage=> bootstrap}
class {'apache': }
class {'mysql': }
class { 'mysql::server':
config_hash => { 'root_password' => 'toor' }
}
mysql::db { `myapp':
user => `dbuser',
password => 'i6vbunhkj',

13
host => 'localhost',
grant => ['all'],
}
class { 'mysql::backup':
backupuser => 'backupuser',
backuppassword => 'binyuvgmngv',
backupdir => '/tmp/backups',
}
php::module { [ 'curl', 'gd', 'mcrypt', 'mysql' ]:
notify => Class['php::fpm::service'],
}
# Add a pool definition
php::fpm::pool { 'www':}

}
Este maniesto es muy sencillo y congurar un servidor de producción requeriría una
cuantas líneas más. Nuestro ejemplo lo que hace es instalar Apache, instalar MySQL y crear
una BD así como congurar una tarea de backup para la todas las BD, instalar PHP y los
módulos requeridos.

5.4. Plataforma de producción


Un aspecto importante a la hora de montar nuestra infraestructura como código es decidir
cuál va a ser el entorno de producción donde se van a ejecutar las aplicaciones. Existen dife-
rentes opciones, desde emplear servidores físicos hasta irnos a la nube con algún proveedor
de IaaS (Infraestructura como Servicio), pasando por montar nuestra nube privada.
La elección en este caso va a ser emplear la nube de Amazon AWS porque es un proveedor
de IaaS consolidado que pueden emplear desde pequeñas startups a grandes empresas con
unos costes contenidos y mucha exibilidad para la infraestructura. Otro punto en favor
de Amazon AWS es que dispone de un API muy potente para gestionar todos aspectos
de la infraestructura y esto está totalmente alineado con el concepto de infraestructura
como código de forma que podemos manejarla desde scripts. Además Amazon AWS tiene
una comunidad grande y hay una base de conocimiento considerable relacionada con sus
servicios y diferentes arquitecturas que se pueden montar para cada situación.
El presente trabajo está orientado a aplicaciones Symfony2 por lo tanto es evidente que el
mejor entorno de ejecución para producción es un sistema LAMP. De los sistemas operativos
Linux disponibles podemos optar por dos grandes familias Ubuntu y RedHat/CentOS. Para
ambas familias existe soporte comercial y se ejecutan perfectamente en el IaaS elegido que
es Amazon AWS.
En cuanto al sistema operativo, RedHat lo descartamos porque no queremos pagar la
licencia. Entre Ubuntu y CentOS nos decantamos por Ubuntu porque dispone de gran
cantidad de software con versiones actualizadas, existe una versión de S.O. con soporte
extendido y sobre todo, porque a diferencia de CentOS, provee de AMIs (las AMIs son
las instancias de servidor de Amazon AWS) ociales con el S.O. instalado. Estas AMIs de
Ubuntu vienen con Cloud-Init incorporado y Cloud-Init está soportado por Amazon AWS.
Cloud-Init sirve para personalizar el servidor en el momento del arranque de forma que no
sea necesario tener una copia propia personalizada o tener que hacer una personalización
manual tras el arranque.

14
La versión concreta del S.O. elegido es Ubuntu 12.04 por ser la versión de soporte exten-
dido (LTS) y elegimos una arquitectura de 64bit para ejecutar la instancia en el servidor
más pequeño de Amazon y luego podemos escalar fácilmente a servidores más grandes. La
instancia de servidor más pequeña a considerar es la M1.Small puesto que las microinstan-
cias están más orientadas a desarrollo o ser ejecutadas como apoyo en ráfagas puntuales de
carga.

Instancia pequeña M1
Memoria de 1,7 GiB
1 unidad informática EC2 (1 núcleo virtual con 1 unidad informática EC2)
160 GB de almacenamiento de instancia
Plataforma de 32 o de 64 bit
Rendimiento de E/S: moderado
Instancia optimizada para EBS disponible: No
Nombre de API: m1.small

Cómo inicializar el servidor de producción


El servidor de producción se basa en una imagen Ubuntu 12.04 64 bit con almacenamiento
instance.store. Elegimos este tipo de almacenamiento porque es más barato y sencillo de
gestionar.

Figura 7: AMIs de Ubuntu Cloud en Amazon AWS

Las imagenes de Ubuntu Cloud para Amazon AWS se pueden encontrar en http://cloud-
images.ubuntu.com/locator/ec2/. Estas imágenes de Ubuntu tienen una instalación míni-
ma de software e incluyen cloud-init. Amazon AWS, desde su consola, permite especicar
conguraciones de cloud-init para inicializar el servidor. Con cloud-init personalizamos la
instancia del servidor en el momento del arranque sin tener que modicar el AMI en sí
empleamos la siguiente conguracion:

#cloud-config
package_update: true
package_upgrade: true
package_reboot_if_required: true
apt_preserve_sources_list: true
packages:
- git
- puppet

15
ssh_pwauth: False
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCjMjVJph1xs
06c2MOPYQufgdfdaS6rsJLQ71DPnkxZVGMaH
UOVSxbQ/7UBmMzASo61H7r1vJgr8rgdbtyebpc+04ig+G5QgHg8BlUl
BzKs4b+xaeka17z/807l4CP4fYV5W4TyxN
b7H/mI6zZQ/mNli75bAkvYSXWN2+7AZ8IGM+GTPo4Q
WCJKT9i//uxNcgCu++e7haGMjyXKEM+6hQLnNC8F5Z5
BInlhY8zDfxzHVghvzIwNX3IvgvHoqIvCYJmMDgfpdR2F91g09
HtQ/Pr4m5CVD0q9CO0eaOr24Z6e5p9q8tBenOcX3d/0hy+d6TNq5QoZEk/f mis-keys

disable_ec2_metadata: false
disable_root: false
locale: es_ES.UTF-8
timezone: Europe/Madrid
resize_rootfs: True
hostname: `server-01.myfirm.com'
output: {all: '| tee -a /var/log/cloud-init-output.log'}

runcmd:
- [ sh, -c ,"cat >/root/.ssh/id_rsa <<EOF
\n
-----BEGIN RSA PRIVATE KEY-----\n
MIIEpAIBAAKCrf5trddsdvdfIy8djSEGKDFf5SxPFGcykXXTuMSPCrfZdTtCN9vF\n
a2Igke43GJ5hvIIFGWuuQn1ncfxha8e+j9h+lD3yZAdgEI4AzI8Yceqb/ItcJBnR\n
Iilz2UeEDOaIbtTMXPVc5yeMVLYUFLzCHINPo8SKt2MRpr5AeIjjbAsu+0Bm0/sD\n
u1Uvu4SgaxLZE/JqmwNAhnS2D88TOYh5N0dwL1yRbNeN0CoRiYCBjBr1q4oCLzVI\n
+2cijaPM/mVTTfDM5QoBB+lBD+FZUl/lZdjU2u9FzUpVvSwffjBNg5cW12//4LkH\n
X08D3cm8T2FACXHyillC44pNALwSHEWqzaaYqQIDAQABAoIBAGU0CCGEINutQw3e\n
LDXfeTSFve+N9p08GF1AKnZvmCGTkA2zoobjEhaq+locrBPMktw3rkjcsQA37qFo\n
OZ9QukrxnEWQrahYrVp7IsZVizdn9kopmY6NuXJhkEkQlqHi1Q1agqYqLYQCnslO\n
lmlr3XbtFrC+fRfusSG8eUEuSp/PPr8aDsRVOnzzAp8woj/sXxVuIVcgoJVtyfwF\n
4MG8F6zyT54tSHx0E81XzduMgCqjxrsLNJnrtDQUq8yvHWYwYoEa4Utc8sN57Uo8\n
oIPwx439w/qMo0D6Zqf/xQ6EzuLWpsZz0PAp/+ZEsYPZMFNCs+71jBgGMFe4vJFI\n
NoBYu+gzoy0v6iM3Xi6S6NmnjcnHoJjCMD3+Ugai/2B7PbqUeZ45rHhCwyOnsA4R\n
6PtLn78yUQaNUJjqS80Bxa0CgYEAny+iqfyBlAmudrv4DLRWCloKwQiRufKLsFe6\n
3SxLGkrWFCqpasWq0UV/imnGZRm8hV6npJ1YomFReVM4/200oyIU4th6jaasFpl7\n
MWikiibnGjvgtsjqzBPyJUp6/9d1Ts90kGlt4sBzgO+aUgX60KHjKYYyXsTKmzeb\n
eehyC5ECgYAglD+xo6vU3SflOcM5CuCM7jfNumPGEj4wwb/U1Dq1k3akW7RfsWyw\n
GL+oCCaXgym9QqP5d3zpfiZ4wxHB90nRq3txhOU4tZwjho/A/kG5IMULVInAvKd0\n
9XcRdzHP3d2ChO1yJztFgH8//vJ5OZP+lkLcNkdd3sbG0IvL4qTwzg==\n
-----END RSA PRIVATE KEY-----\n
EOF"]
- [ sh, -c ,"echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA
AABAQDQx/TTz0gjLx2
NIQYoMV/lLE8UZzKRddO4xI8Kt9l1O0I328VrYiCR7jcYnmG8
ggUZa65CfWdx/GFrx76P2H6UPfJkB2AQjgDMjxhx6pv8i1wkGd
EiKXPZR4QM5ohu1Mxc9VznJ4xUt
hQUvMIcg0+jxIq3YxGmvkB4iONsCy77QGbT+wO7VS+7hKBrEtk

16
T8mqbA0CGdLYPzxM5iHk3R3AvXJFs143QKh
GJgIGMGvWrigIvNUj7Z
yKNo8z+ZVNN8MzlCgEH6UEP4VlSX+Vl2NTa70XNSlW9LB9+ME2Dlx
bXb//guQdfTwPdybxPYUAJcfKKWULjik0AvBIcRar
Nppip root@kyoki-01 > /root/.ssh/id_rsa.pub"]
- chmod 600 /root/.ssh/id_rsa
- sed 's/^ //' -i /root/.ssh/id_rsa
- rm -Rf /etc/puppet.orig
- mv /etc/puppet /etc/puppet.orig
- ssh-keyscan -H bitbucket.org > /root/.ssh/known_hosts
- git clone git@bitbucket.org:myuser/puppet-lamp.git /etc/puppet
- puppet apply -v /etc/puppet/site.pp

apt_sources:
- source: deb http://apt.puppetlabs.com precise devel
keyid: 4BD6EC30

El script hace lo siguiente:


Actualiza los paquetes del sistema operativo
Instala las fuentes de paquetes de puppetlabs
Instala los paquetes de git y puppet
Deshabilita la entrada SSH usando password
Instala una clave pública autorizada para poder entrar como root vía SSH
Establece la clave pública/privada del servidor a una concreta y conocida que está
autorizada para acceder a un repositorio de git alojado en bitbucket.com
Se conecta al servidor de bitbucket y se descarga un repositorio git que contiene
maniestos de puppet
Ejecuta los maniestos de puppet que se encargan de terminar de congurar el servidor

17
6 Entornos de producción, pruebas y desarrollo comparables
Como ya hemos comentado antes, en ciclo de vida del software hay 3 etapas claras:
desarrollo, pruebas y producción. Desarrollo y producción son inevitables. El entono de
pruebas es altamente recomendable.

6.1. Diferentes entornos en Sistemas


Dentro de lo que es la losofía de DevOps hay que acercar las prácticas de Desarrollo a los
entornos de Sistemas y por lo tanto deberían haber entornos diferenciados de producción,
pruebas y desarrollo que permitan probar las conguraciones de los servidores antes de
aplicarlos en producción.

6.2. Entorno de producción


Para el entorno de producción proponemos Amazon AWS. Podemos usar la consola web
de Amazon o si queremos algo más automatizado podemos crear un script usando, por
ejemplo, la librería boto de python. Este script podría encargarse de lanzar instancias de
los servidores con nuestra conguración, parar instancias en ejecución y listar los servidores
en ejecución
#!/usr/bin/python
__author__ = 'fernando'

from string import Template


import boto.ec2
import urllib
import yaml
import time
import argparse
import sys

class InstanceMgr:
def __init__(self):
yamlData = yaml.load(file('./settings.yaml'))
self.region = yamlData['aws']['region']
self.instance_type = yamlData['aws']['instance_type']
self.ami_id = yamlData['aws']['ami_id']
self.key_name = yamlData['aws']['key_name']
self.instance_tags = yamlData['aws']['instance_tags']
self.security_groups = yamlData['aws']['security_groups']
self.cloud_init_template_vars = yamlData['cloud-init']['template_vars']
self.cloud_init_template_url = yamlData['cloud-init']['template_url']
self.connection = boto.ec2.connect_to_region(self.region)

def get_script(self, filename = None):


if filename == None:

18
filename = self.cloud_init_template_url

template = urllib.urlopen(filename).read()
return Template(template).substitute(
self.cloud_init_template_vars
)

def launch(self):

reservation = self.connection.run_instances(
image_id = self.ami_id,
instance_type = self.instance_type,
key_name = self.key_name,
security_groups = self.security_groups,
user_data = self.get_script()
)
instance = reservation.instances[0]
self.connection.create_tags([instance.id], self.instance_tags)
self.instance = instance
return instance

def find_instances_by_tag(self, tag, value):


foundInstances = []
reservations =
self.connection.get_all_instances(filters={'instance-state-name': 'running'})
for reservation in reservations:
for instance in reservation.instances:
if tag in instance.tags and instance.tags[tag] == value:
foundInstances.append(instance)
return foundInstances

def find_all_running(self):
foundInstances = []
reservations =
self.connection.get_all_instances(filters={'instance-state-name': 'running'})
for reservation in reservations:
for instance in reservation.instances:
foundInstances.append(instance)
return foundInstances

def terminate(self, instances):


for instance in instances:
self.connection.terminate_instances(instance.id)

if __name__ == '__main__':

parser = argparse.ArgumentParser(description=

19
'Lanza una instancia de un proyecto en AWS EC2')
group = parser.add_mutually_exclusive_group()
group.add_argument(
'--launch', help=
'lanza una instancia AWS EC2', action='store_true', default=False)
group.add_argument(
'--list-instances', help='listado de instancias activas',
action='store_true', default=False)
group.add_argument(
'--delete-project',
help='termina las instancias etiquetadas con un Project=projectid')
args = parser.parse_args()
if not args.launch and not args.delete_project and not args.list_instances:
parser.print_help()

instanceMgr = InstanceMgr()

if args.launch:
print instanceMgr.launch()
while instanceMgr.instance.state == 'pending':
instanceMgr.instance.update()
print 'waiting for 30s until instance in ready state'
time.sleep(30)

print instanceMgr.instance.public_dns_name
#print instanceMgr.get_script()
sys.exit(0)

if args.delete_project:
print 'Borrando imagenes del projecto=' + args.delete_project
instances = instanceMgr.find_instances_by_tag('Project', args.delete_project)
instanceMgr.terminate(instances)
for instance in instances:
print 'Terminada -> ' + instance.id + ' ' + instance.public_dns_name
sys.exit(0)

if args.list_instances:
instances = instanceMgr.find_all_running()
for instance in instances:
print instance.id + ' ' + instance.public_dns_name
for tag in instance.tags:
print "\t" + tag + '=' + instance.tags[tag]
sys.exit(0)

El script es muy sencillo pero nos puede simplicar la gestión de nuestros servidores
en Amazon AWS. Como los datos de producción son sensibles, este script crea el script de
cloud-init basándose en una plantilla y rellenándola con los datos de un chero settings.yaml
en el que se pueden poner las passwords, claves ssh, etc

20
La instancia de EC2 lee la conguración de cloud-init que es muy sencilla y que bási-
camente le indica al servidor cómo recuperar los maniestos de Puppet de Bitbucket
para proceder a autocongurarse.
Una vez que se aplican los maniestos de Puppet (puede tardar de 5 a 10 minutos) el
servidor de producción ya está listo para recibir la aplicación

6.3. Gestión de máquinas virtuales con Vagrant


Vagrant es una herramienta que gestiona máquinas virtuales (VM) y aplica maniestos
u otros cheros de conguración de sistemas en una computadora local. Con un simple
chero de conguración (Vagrantle), Vagrant levanta y provisiona una máquina virtual
nueva en minutos a partir de una plantilla. Las plantillas de máquinas virtuales (Boxes) se
conguran mediante herramientas como Chef o Puppet. Además provee de otras utilidades
como montar carpetas de la máquina virtual a directorios locales y mapeo de puertos entre
la máquina virtual y el antrión. Las máquinas virtuales que gestiona Vagrant pueden estar
en nuestro PC de escritorio con VirtualBox o VMware o en la nube de Amazon AWS.
¾Cómo ayuda Vagrant a trabajar en Sistemas?
Concretamente en el apartado de infraestructura como código, permite desarrollar un
ujo de trabajo donde probar las conguraciones antes de desplegarlas en producción. Se
crean los entornos de desarrollo y pruebas para ser usados por los equipos de Sistemas.
¾Cómo ayuda Vagrant al DevOps?
Vagrant permite que los desarrolladores se involucren más en Sistemas de forma que
tengan un conocimiento de cómo se conguran los servidores. Además se elimina la frase de
Funciona en mi local puesto que las máquinas virtuales que levanta Vagrant son iguales
(o al menos están conguradas igual) que los servidores de producción. Y en cualquier
momento se pueden destruir las máquinas virtuales y recrearlas desde cero limpias. Las
máquinas virtuales de los diferentes entornos están conguradas igual porque se comparten
los mismos maniestos de Puppet (en nuestro caso) y la misma plantilla base de máquina
virtual para las Boxes de Vagrant que para los servidores de producción (en nuestro caso
Ubuntu Cloud 12.04)

Cómo crear la box de Vagrant


Para crear la box de Vagrant (la máquina virtual) vamos a basarnos en la misma imagen
de Ubuntu que empleamos para producción en Amazon AWS. En la página http://cloud-
images.ubuntu.com/vagrant/precise/podemos encontrar dos cheros que contienen imáge-
nes de boxes de Vagrant para 32 y 64 bits. Estas boxes tienen instalado cloud-init y Puppet.
Para que el diagrama de arranque de la máquina virtual sea lo mas parecido posible al
entorno de producción, vamos a seguir empleando cloud-init. Por ello necesitaremos que la
box de Vagrant lea los cheros de conguración de cloud-init de nuestro PC, así que necesi-
taremos tener instalado un servidor web en nuestro ordenador que permita leer los cheros
user-data y meta-data de cloud-init. Pasos a realizar:
Creamos una VM usando el disco vmdk de la box de Vagrant a usar
Arrancamos la VM, hacemos login como vagrant/vagrant y modicamos /etc/defaults/
grub para que añada en la línea de arranque ds=nocloud-net\;s=http://10.0.2.2/
10.0.2.2 es la IP correspondiente a nuestro PC en el entorno de VirtualBox. Aplica-
mos los cambios de GRUB mediante el comando update-grub
22
Actualizamos las VirtualBox Guest Additions
Eliminamos la entrada correspondiente a eth0 en el chero /etc/udev/rules.d/70-
persistent-net.rules
Se apaga la VM y se clona el disco de la VM que acabamos de arrancar para re-
emplazar el disco VMDK de la box vboxmanage clonehd UUID-del-disco-de-la-vm-
dd9e05c92789 ./box.vmdk format VMDK
Con esto obtenemos una box de Vagrant congurada para ser empleada en los equipos de
desarrollo.
Cómo usar la box de Vagrant
Una vez que tenemos la box lista procederemos de la siguiente forma:
Inicializamos un proyecto de Vagrant (vagrant init)
Conguramos el Vagrantle a nuestro gusto
Arrancamos la VM por primera vez (vagrant up). A este paso le cuesta un poco y
al terminar tendremos una VM en nuestro PC congurada igual que el servidor de
producción
Probamos los cambios a la aplicación que estamos desarrollando dentro de la VM.
Como el primer arranque de la VM tarda bastante (10 minutos) no haremos vagrant
destroy todos los días si no queremos perder ese tiempo, y nos limitaremos a apagarla
encenderla. Eso sí, al menos se debería destruir y recrear la VM una vez a la semana.
Como Vagrant permite ejecutar maniestos de Puppet desde una carpeta del proyecto
Vagrant, emplearemos esta posibilidad para hacer cambios propios de nuestro entorno
y tenerlos separados de forma que podamos ofrecérselos a la gente de Sistemas para
aplicarlos en producción.
6.4. Entorno de pruebas
Como se ha comentado anteriormente, el entorno de pruebas es deseable que sea lo más
parecido posible al entorno de producción y por ello emplearemos la misma imagen de
Ubuntu Cloud pero empaquetada como una box de Vagrant en vez de como AMI de Amazon
EC2. A esta imagen le aplicaremos los mismos maniestos de Puppet que se aplican en
producción de forma que se conguren exactamente igual.
Pasos para la creación del entorno
El entorno de pruebas se lanza con Vagrant, pero Vagrant no tiene una forma de pasar
metadatos a las instancias de la misma forma que tiene Amazon AWS EC2 para poder así
darle a la máquina virtual una conguración de cloud-init. Para suplir esto se congura la
box de Vagrant para que recoja la conguración de cloud-init ya generada de un servidor
web (que puede estar en nuestro propio ordenador). Una vez que la máquina virtual tiene
la conguración de cloud-init procede como en el entorno de producción, es decir, recoge de
BitBucket los maniestos de Puppet necesarios y se autocongura según le indican éstos.
23
Figura 10: Modelo de ramas para Git propuesto por NVIE

25
Ramas principales
Las ramas principales son master y develop. La rama master en el repositorio principal
origin siempre contiene código que está listo para ponerse en producción. La rama develop
reeja el estado actual de desarrollo entregado. Es decir con funcionalidades terminadas
aunque todavía no aprobado para pasar a producción. El código de esta rama es el que
normalmente se ejecuta en los servidores de pruebas. Cuando el código de develop esta
listo para ser integrado en producción se hace un merge de develop a master.

Figura 11: Detalle de ramas de develop y master

Otras ramas axiliares


Las ramas de feature representan una funcionalidad que está siendo desarrollada. Estas
ramas se crean a partir del código de develop. El código de estas ramas se ejecuta normal-
mente en los entornos de desarrollo. Cuando se termina la funcionalidad, se hace un merge
de esta rama a develop y se elimina la rama de feature.
Las ramas de hotx se crean cuando se detecta un bug en producción y por lo tanto
el origen de esta rama está en master. Una vez que se corrige el bug se hace un merge a
producción para corregir el error y también se hace un merge hacia develop para que el bug
no se arrastre. Una vez hechos los merges se borra la rama.
La rama de release tiene el origen en develop y hace merge en master y develop. Su nali-
dad es corregir pequeños bugs y preparar el código para producción, por ejemplo cambiando
los números de versión o escribiendo las RELEASES NOTES.

7.2. Release Candidates


¾Que es una Release Candidate? Un cambio en el código puede que sea o no una Release
en si. Si miras el cambio y te preguntas ¾debería poner en en producción este cambio? La
respuesta a esta pregunta no da sólo una pista. Es el proceso de build, despliegue y test
que aplicamos a ese cambio el que valida si el cambio debe conformar una release o no. **

26
Cada commit es una release potencial **, cada commit que un desarrolador hace sobre la
base de código se entiende que añade valor al negocio de alguna forma y mejora el sistema
en el que estamos trabajando. El trabajo de la integración continua es vericar cada release
candidate para ver si puede encajar o no producción. No hay que olvidar que una mejora
(feature) sólo está terminada cuando entrega valor al usuario, y esto sólo sucede cuando
está en producción.

7.3. Estado de commit


El estado de commit empieza con un cambio en el estado del proyecto, es decir, un commit
en el sistema de control de versiones. Termina con un informe de fallo, o si tiene éxito, con
una colección de artefactos y elementos desplegables para ser usados en los siguientes pasos
del proceso de despliegue. Idealmente, el estado de estado de commit dura menos de cinco
minutos y ciertamente menos de diez. El estado de commit representa, de más de una forma,
la entrada en el ujo de despliegue. Funciona de la siguiente manera: alguien hace un cambio
en el sistema de control de versiones, el servidor de integración continua detecta el cambio,
se descarga el código fuente y ejecuta una serie de tareas que incluyen:
Compilar, si es necesario, y empezar a ejecutar sobre el código fuente integrado.
Crear binarios (o tar.gz, rpm, deb. . . ) que puedan ser desplegables
Ejecutar algún tipo de análisis necesario para vericar la calidad y salud del código
Crear otros artefactos necesarios como migraciones de base de datos o generar datos
de test, etc
Para los desarrolladores, el estado de commit es el ciclo de feedback más importante en el
proceso de desarrollo. Los fallos en los tests que se ejecutan en este punto normalmente se
atribuyen a 3 causas: errores de sintaxis, errores semánticos y errores con la conguración

27
8 Despliegue como proceso automático
Desplegar el código en producción o pruebas, y quizás también en desarrollo, es algo
que debe hacerse pulsando un botón (ejecutando un script). Hay que evitar los procesos
manuales, estos conllevan tiempo y son propensos a errores por mucho que esos procesos se
hayan repetido.
8.1. Herramientas de despliegue
Existen diferentes herramientas que pueden ayudarnos a hacer el despliegue de manera
automática:
Ant: es una herramienta de construcción para aplicaciones Java con diferentes tipos
de tareas que pueden incluir en el script, como por ejemplo hacer FTP o crear un zip.
Phing: es el equivalente a Ant pero orientado a PHP. Es una herramienta muy com-
pleta ideal para ejecutar validación de métricas, tests unitarios y depliegues de apli-
caciones PHP.
Capifony: es una herramienta especíca de despliegue de aplicaciones Symfony. Esta
herramienta tiene diversas utilidades orientadas al despliegue y es fácilmente extendi-
ble.
Fable: La libería de python Fabric es posiblemente una de las mejores soluciones
para la creación de scripts de despliegue con carácter general. Provee un conjunto de
utilidades relacionadas con el proceso de despliegue de aplicaciones por SSH y que son
la base para la creación de nuestros scripts.
Nuestra elección es emplear Capifony porque es una utilidad especíca para el entorno
en que nos centramos qué es Symfony2. Con Capifony podemos ejecutar comandos de Sym-
fony2, hacer rollbacks sencillos de las versiones y crear un único script de despliegue que se
adapte a los diferentes servidores de despliegue. Si decidiésemos invertir recursos para te-
ner algo más personalizado o consideramos desplegar además otro tipo de software, Python
Fabric sería la solución elegida.
8.2. Alternativas a un script
Una alternativa a hacer el despliegue mediante una herramienta especíca, o un script,
es sincronizar diferentes ramas del sistema de control de versiones en los servidores. Por
ejemplo, podemos sincronizar la rama master con el directorio del servidor web corres-
pondiente. También podemos hacer esto con la rama develop para el servidor de pruebas.
Con las aplicaciones PHP es posible porque no es necesario compilar los fuentes ni crear un
paquete como en otros lenguajes.
Una ventaja de este sistema es que podemos poner una tarea programada que sincronice
los fuentes en determinado horario y así establecer un calendario de despliegue separado
para producción y desarrollo, y si hay commits nuevos en las ramas de develop o master se
aplicarán en los servidores.
El inconveniente de este sistema es que buscamos una exibilidad mas allá de aplicar
nuestros cambios en un momento determinado, además muchas veces es necesario ejecutar
tareas adicionales a copiar los fuentes, como por ejemplo hacer modicaciones en la base de
datos.
28
8.3. Capifony
Capifony es una extensión de Capistrano (herramienta de deploy de Ruby) que incorpora
recetas especícas para Symfony. Hay otra extensión de Capistrano que vamos a incorporar
y es Capistrano-ext concretamente para poder hacer un script multistage, es decir, que el
mismo script nos sirva para producción (en Amazon EC2) y en pruebas (en una box de
Vagrant)
Script de deploy de capifony
deploy.rb
set :stages, %w(production staging)
set :default_stage, "staging"
set :stage_dir, "app/config"
require 'capistrano/ext/multistage'
set :branch, "develop"

set :application, "TuitLawyer_application"


set :deploy_to, "/var/www/tuitlawyer"
set :app_path, "app"
set :user, "root"
set :scm, :git
default_run_options[:shell]= '/bin/bash'
set :deploy_via, :copy
set :copy_strategy, :export
set :model_manager, "doctrine"
set :keep_releases, 5
set :use_sudo, false
# Be more verbose by uncommenting the following line
logger.level = Logger::MAX_LEVEL

set :use_composer, true


set :shared_files, ["app/config/parameters.yml"]
set :shared_children, [app_path + "/logs", web_path + "/uploads", "vendor"]
set :writable_dirs, ["app/cache", "app/logs"]
set :webserver_user, "www-data"
set :permission_method, :acl
set :use_set_permissions, true

before "symfony:cache:warmup", "symfony:doctrine:schema:update"

after "deploy:setup", "setup:parameters_init"


namespace :setup do
desc "Copy default parameters file to remote server"
task :parameters_init, :roles => :app do
capifony_pretty_print "--> Copying parameters.yml.dist"
run "if [[ ! -d #{deploy_to}/#{shared_dir}/app/config/ ]];
then mkdir -p #{deploy_to}/#{shared_dir}/app/config/; fi"

29
top.upload "#{Dir.pwd}/app/config/parameters.yml.dist.#{stage}",
"#{deploy_to}/#{shared_dir}/app/config/parameters.yml"
end
end

stagging.rb

ssh_options[:port] = 2222
set :branch, "develop"
set :repository, "/Users/fernando/tuitlawyer"
set :update_vendors, false
set :clear_controllers, false
server 'sf.local', :app, :web, :primary => true

production.rb

ssh_options[:port] = 22
set :branch, "develop"
set :repository, "https://farconada@bitbucket.org/farconada/tuitlawyer.git"
set :update_vendors, false
set :clear_controllers, true
server 'ec2-107-20-125-86.compute-1.amazonaws.com', :app, :web, :primary => true
ssh_options[:keys] = "/home/fernando/Dropbox/ec2-keys/id-mis-keys"

30
9 Mantener la calidad del software
De nada sirve tener un sistema que permita actualizar rápidamente las versiones del
software si, a medida que crece, vamos perdiendo conanza en que haga lo que debe hacer
y sospechamos que está lleno de más errores.
Al mismo tiempo que fomentamos la agilidad para poner en producción los cambios, hay
que aumentar los procesos que revisan que nuestro software sigue siendo conable. Estos
procesos se deben ejecutar frecuentemente (por ejemplo tras cada commit en el sistema de
control de versiones) y, a ser posible, de manera automatizada.
Vamos a controlar dos aspectos fundamentales:
Las métricas y reglas de integración continua
Los tests de software automáticos
9.1. Qué es la integración continua
Una característica extraña pero común en muchos proyectos de software es que durante
largos periodos de tiempo en el proceso de desarrollo la aplicación no se encuentra en
un estado funcional. Normalmente durante el desarrollo la aplicación está rota. Esto es
especialmente cierto en proyectos que usan ramas que duran mucho tiempo o que dejan
los tests de aceptación para el nal. En cambio, hay otros proyectos que sólo durante unos
minutos la aplicación permanece rota con los últimos cambios. La diferencia entre un tipo
de proyecto y el otro es la integración continua. La integración continua requiere que cada
vez que alguien haga un commit se construya la aplicación entera y se que se ejecuten
una serie de tests automatizados. Es un cambio de paradigma. Sin integración continua el
software está roto hasta que alguien pruebe que funciona. Con la integración continua el
funcionamiento del software está comprobado en cada nuevo cambio. Para implementar la
integración continua hacen falta tres cosas:
Un sistema de control de versiones en el que se deposite todo lo relativo al proyecto.
Un sistema automatizado de build para la aplicación y ejecutar los tests.
La aceptación de los miembros del equipo, puesto que la integración continua es una
práctica y no una herramienta.
9.2. Métricas y reglas de integración contínua
En este aspecto vamos a emplear herramientas como phploc que permite obtener datos
de métricas de software como éstos:
phploc 1.7.4 by Sebastian Bergmann.
Directories: 14
Files: 54
Lines of Code (LOC): 5149
Cyclomatic Complexity / Lines of Code: 0.02
Comment Lines of Code (CLOC): 1464
Non-Comment Lines of Code (NCLOC): 3685

31
Namespaces: 15
Interfaces: 0
Traits: 0
Classes: 54
Abstract: 3 (5.56%)
Concrete: 51 (94.44%)
Average Class Length (NCLOC): 63
Methods: 252
Scope:
Non-Static: 252 (100.00%)
Static: 0 (0.00%)
Visibility:
Public: 220 (87.30%)
Non-Public: 32 (12.70%)
Average Method Length (NCLOC): 13
Cyclomatic Complexity / Number of Methods: 1.37
Anonymous Functions: 0
Functions: 0
Constants: 12
Global constants: 0
Class constants: 12

En importante jarnos en la complejidad ciclomática porque nos da una idea de lo


difícil que puede ser crear pruebas automáticas de software. La complejidad ciclomática
indica el número de caminos independientes dentro de un fragmento de código.
La información relativa a CLOC (Comment Lines of Code) y NCLOC (NonCom-
ment Lines of Code) nos da una idea de lo documentado que está el código así como el
tamaño neto de las clases y métodos que, en números reducidos, implica simplicidad para
leer y entender cada método. Otras herramientas como PHP Depend también nos calculan
métricas e incluso generan grácos como éstos
Otra herramienta recomendable para integrar es PHPMD (PHP Mess Detector) .
Esta herramienta trata de analizar el código y encontrar:
Posibles bugs
Código subóptimo (problemas de diseño, nomenclatura. . . )
Expresiones muy complicadas
Parámetros, métodos y propiedades sin usar
Además permite extender la herramienta con reglas propias.
PHP CodeSnier una herramienta que debemos integrar para mantener las calidad
del software, pero esta utilidad no genera métricas de software ni detecta posibles errores.
Esta herramienta se encarga de vericar que se cumplen los estándares de codicación de
código fuente de nuestra organización. Esto es fundamental porque el código fuente pasa
por diversas manos con el tiempo, y manteniendo un estándar hace más fácil que pase de
una manos a otra. Simplemente hay que pensar en algo tan sencillo como la nomenclatura
de las variables, si se usa nomenclatura CamelCase o no, o la disposición de las llaves {} en
las instrucciones de condición y bucle, etc.
32
9.3. Phing
Phing es una herramienta de construcción de software equivalente a la utilidad ant de
Java. Esta herramienta es muy útil para poder ejecutar todas las pruebas que verican las
métricas y tests de forma automática en un solo comando.
Junto con la ejecución de los tests, también se puede emplear phing para que ejecute
otra serie de tareas que sería recomendable efectuar en cada commit (justo antes de cada
commit), como por ejemplo:

Eliminación de cheros temporales

Minicación de cheros de CSS y JS

Generar documentación de phpdoc

Ejemplo de script build.xml de Phing para ejecutar test de PhpUnit

<?xml version="1.0"?>
<project name="BankAccount" basedir="." default="test">
<target name="test">
<phpunit haltonfailure="true" printsummary="true">
<batchtest>
<fileset dir=".">
<include name="*Test.php"/>
</fileset>
</batchtest>
</phpunit>
</target>
</Project>

34
10 Monitorización
Hay libros enteros dedicados a la monitorización y aquí no nos podemos extender en este
tema.
Simplemente comentar que, con independencia de la monitorización propia de los equipos
de Sistemas, hay que establecer otros sistemas más orientados al negocio y la funcionalidad
del software en sí para comprobar que todos los cambios que vamos haciendo tienen un
impacto positivo en los usuarios y que no se nos ha escapado nada a los tests automatizados
de software. Por esto es conveniente tener alertas de Google Analytics, vigilar que no se
estén produciendo errores HTTP 500, comprobar los tiempos de respuesta, etc.

35
11 Plan B
Todo despliegue debe tener un plan B, algo que hacer en caso de que algo salga mal.
Aun con un proceso automatizado de despliegues es posible que algo falle, por ejemplo
porque no hemos considerado los datos de producción y los datos que disponemos para
probar no son equiparables. La primera idea que viene a la cabeza como plan B es volver
a la versión anterior, esto es sencillo cuando lo único que se ha cambiado es el código
y todo lo tenemos en el sistema de control de versiones. Pero aun con esta idea de que
volver atrás un cambio que sólo afecte al código puede ser fácil, hay que tener alguna
otra alternativa como por ejemplo tener preparada una página que avise de que la web se
encuentra en mantenimiento y delimitar la ventana de trabajo que una vez superada debe
disparar el proceso de restauración de backup. Siempre hay que poder hacer rollback de los
cambios desplegados. Hacer debug de los problemas en un entorno de producción casi seguro
terminará en largas noches, errores, desafortunadas consecuencias y usuarios enfadados. En
los planes de rollback hay dos importantes obstáculos:
Si la release desplegada cambia los datos puede ser difícil volver atrás.
Si la release cambia más de un sistema entonces el proceso de rollback se complica.
Hay dos principios generales que hay que seguir cuando creamos un plan para hacer
rollback de una release desplegada:
Asegurarnos de que el entorno de producción, incluyendo las bases de datos y los
sistemas de cheros, tienen un backup antes de hacer el despliegue.
Practicar el plan de rollback, incluyendo la restauración del backup y la migración de
la base de datos.
Bajo determinadas circunstancias, y teniendo en cuenta que tenemos todo automatizado,
es posible que sea más sencillo volver a provisionar un entorno de producción nuevo. Hay
un par de buenas razones para hacer esto:
Si no tienes un proceso automatizado de rollback pero tienes un proceso automatizado
de despliegue y provisión de entornos, entonces es más sencillo puesto que es una
operación que tiene un tiempo jo y menos riesgos al ser automatizado.
Es el mismo proceso que has probado cientos de veces antes y hacer rollback es bastante
más infrecuente.

11.1. Los datos


Una de las cosas más difíciles a la hora de hacer rollback es la parte relativa a los datos
de la aplicación: las bases de datos. En las bases de datos no existe un sistema de control de
versiones como en el código. Como mucho podemos mantener el esquema de los datos pero al
irse insertando tuplas continuamente es muy difícil pasar de una versión a otra del esquema
de base da datos. Un backup frecuente es importante pero corremos el riesgo de perder los
datos generados entre los espacios de los ciclos de backup. Existen algunas soluciones que
tratan de paliar los problemas de versionar las bases de datos:
Dbdeploy
36
Liquidbase
Doctrine migrations
El funcionamiento de las tres herramientas es muy similar, las versiones de la base de
datos se numeran y cada versión tiene dos scripts asociados (que creamos nosotros), uno para
avanzar de versión y otro para retroceder. De esta forma podemos indicarle al programa a
qué versión queremos ir. Si nuestra aplicación Symfony2 emplea el ORM Doctrine2 usaremos
Doctrine migrations porque es simplemente incorporar una librería más de PHP y se integra
dentro de los comandos de Symfony2. Si queremos una solución más genérica podemos
emplear Liquidbase o dbdeploy. Con capifony podemos hacer un backup de la base de
datos y descargárnosla a nuestro ordenador justo antes de actualizar el código , únicamente
añadiendo una línea.

before 'deploy:update_code', 'deploy:web:disable', 'database:dump:remote'

11.2. Rollback con capifony


Hacer rollback (al menos del código) con capifony es un proceso automático. Capifony
crea un sistema de enlaces y carpetas que hacen muy sencillo cambiar de una versión a otra,
además tiene un comando especíco para hacer rollback, cap deploy:rollback

lrwxrwxrwx 1 root root 43 abr 3 11:24 current


-> /var/www/app/releases/20130403092221
drwxrwxr-x 4 root root 4096 abr 3 11:23 releases
drwxrwxr-x 5 root root 4096 abr 2 22:03 shared
-bash-3.2# ls -l releases/
total 8
drwxrwxr-x 6 gitandroid games 4096 abr 2 22:37 20130402203623
drwxrwxr-x 6 gitandroid games 4096 abr 3 11:23 20130403092221

Así, para capifony es tan sencillo hacer rollback como mover los enlaces simbólicos a la
carpeta de la versión anterior. Además también tiene comandos que ejecutan acciones de
Doctrine migrations que se podría ejecutar junto al rollback

11.3. Página de mantenimiento con capifony


Con capifony podemos poner y quitar de una forma automática una página de manteni-
miento. Para poner la página sólo tenemos que ejecutar cap deploy:web:disable REASON=hardware
upgrade UNTIL="12pm Central Time y capifony creará la página. Con cap deploy:web:enable
se elimina la página de mantenimiento. Para que la página de mantenimiento sea efectiva
hay que crear unas reglas de rewrite de apache de forma que detecte si existe la página de
mantenimiento y en caso de existir muestre ese contenido y un error HTTP 503.

<VirtualHost *:80>
...
RewriteEngine On

37
# Show maintenance page if it exists
ErrorDocument 503 /system/maintenance.html
RewriteCond %{REQUEST_URI} !\.(css|gif|jpg|png)$
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ - [redirect=503,last]

...
</VirtualHost>

Si queremos que la página de mantenimiento se ponga automáticamente y se quite en cada


deploy se puede hacer de forma automática simplemente incorporando un par de líneas al
script de deploy.

before 'deploy:update_code', 'deploy:web:disable'


after 'deploy:restart', 'deploy:web:enable'

38
12 Conclusiones
Para poder hacer despliegues de forma frecuente es necesario que los equipos de Desarrollo
y Sistemas comprendan que están trabajando juntos para lograr el mismo objetivo. Alredor
de la idea de que los equipos de Sistemas y Desarrollo trabajen de manera conjunta sin
enfrentamiento se gesta la losofía de DevOps, que es recomendable implantar en la empresa
para poder adaptarse a los cambios que requiere el mercado con agilidad.
El código a desplegar debe ser conable y eso se tiene que poder vericar de forma
automática.
La infraestructura debe ser tan conable como el propio código evitando dudas de sistemas
no comparables entre los entornos de desarrollo, pruebas y producción.
Hay que automatizar todo lo que sea posible, los tests de código, la vericación de calidad
el proceso de despliegue y la propia infraestructura.
Hay una serie de herramientas software de reciente aparición que permiten de una forma
sencilla automatizar procesos que hace unos años era imposible de automatizar especial-
mente en el área de sistemas y que permiten aplicar a la infraestructura los mismos modelos
de desarrollo que en el software (desarrollo, pruebas, producción, control de versiones etc)
Aún con todo, algo puede salir mal y por lo tanto siempre hay que tener un plan de
marcha atrás y monitorizar el cambio de manera continuada.

39
Bibliografía
[1] Phing. http://www.phing.info/.

[2] phploc. https://github.com/sebastianbergmann/phploc.

[3] P. Debois, Devops areas - codifying devops practices, May 2012.

[4] J. Humble and D. Farley, Continuous Delivery: Reliable Software Releases through
Build, Test, and Deployment Automation (Addison-Wesley Signature Series . Addison-

Wesley Professional, 1 ed., Aug. 2010.

[5] J. G. L. de Araujo, Que demonios es eso de devops (y porquedebería interesarme),

Feb. 2011.

[6] Scrum, Jan. 2013. Page Version ID: 63232584.

[7] A continous delivery git branching model. http://nxvl.blogspot.com.es/2012/07/a-

continous-delivery-git-branching-model.html.

[8] capistrano. https://github.com/capistrano/capistrano.

[9] M. Hüttermann, DevOps for Developers . Apress, 1 ed., Sept. 2012.

[10] Vagrant. http://www.vagrantup.com/.

[11] Using PHP_Code_Snier  techPortal. http://techportal.inviqa.com/2009/10/12/usphp_code_snier/.

[12] 2013.01.11 tech talk on git and continuous delivery | big nerd ranch.

http://learn.bignerdranch.com/videos/2013-01-11-tech-talk-on-git-and-continuous-

delivery.

[13] P. M. Duvall, S. Matyas, and A. Glover, Continuous Integration: Improving Software


Quality and Reducing Risk . Addison-Wesley Professional, 1 ed., June 2007.

[14] J. Turnbull,Pulling Strings with Puppet: Conguration Management Made Easy .

Apress, 1 ed., Feb. 2008.

[15] capifony  symfony and symfony2 deployment. http://capifony.org/.

[16] G. Kim, K. Behr, and G. Spaord, The Phoenix Project: A Novel About IT, DevOps,
and Helping Your Business Win . IT Revolution Press, Jan. 2013.

[17] Chef | opscode. http://www.opscode.com/chef/.

[18]  VMware invests $30 million in puppet labs | puppet labs.

https://puppetlabs.com/blog/vmware-invests-30-million-in-puppet-labs/.

[19] P. Sturgeon, Puppet or chef ? | blog. http://philsturgeon.co.uk/blog/2012/10/puppet-

or-chef.

[20] Software release life cycle, Mar. 2013. Page Version ID: 547341157.

40
[21] P. Swartout, Continuous delivery and DevOps: A Quickstart Guide . Packt Publishing,

Nov. 2012.

[22] Software deployment, Mar. 2013. Page Version ID: 540776027.

[23] Conguration management software | open source conguration management - CFEn-

gine - distributed conguration management. http://cfengine.com/.

[24] Continuous delivery, Jan. 2013. Page Version ID: 531155254.

[25] The buildmeister: Automating the PHP deploy-

ment process with phing, dbdeploy and FTP.

http://www.buildmeister.com/articles/automating_the_php_deployment_process_with_phing,_dbdeploy_a

[26] Vagrant. http://www.vagrantup.com/.

[27] Manual :: PHP_CodeSnier. http://pear.php.net/manual/en/package.php.php-

codesnier.php.

[28] J. Loope, Managing Infrastructure with Puppet . O'Reilly Media, Inc., June 2011.

[29] M. Pichler,  PHPmd. http://phpmd.org/, Dec. 2012.

[30] P. Swartout, Continuous Delivery and DevOps: A Quickstart guide . Packt Publishing,

Nov. 2012.

[31] Capistrano, Mar. 2013. Page Version ID: 541197302.

[32] E. Zygmuntowicz, B. Tate, and C. Begin, Deploying Rails Applications: A Step-By-Step


Guide . Pragmatic Bookshelf, 1 ed., May 2008.

[33] Fabric  fabric 1.6 documentation. http://docs.fable.org/en/1.6/.

[34] M. Zandstra, Continuous integration, in PHP Objects, Patterns, and Practice ,

pp. 427450, Apress, Jan. 2010.

[35] Puppet vs. chef - the battle wages on. https://www.scriptrock.com/articles/puppet-

vs-chef-battle-wages/.

[36] Development environment (software development process) - wikipedia, the free ency-

clopedia. http://en.wikipedia.org/wiki/Development_environment_(software_development_process).

[37] T. Copeland and A. Burns, Deploying Rails: Automate, Deploy, Scale, Maintain, and
Sleep at Night . Pragmatic Bookshelf, July 2012.

[38] J. Kutner,Deploying with JRuby: Deliver Scalable Web Apps using the JVM . Pragmatic

Bookshelf, July 2012.

[39] M. Hüttermann, Infrastructure as code, in DevOps for Developers , pp. 135156,

Apress, Jan. 2012.

[40] A successful git branching model  nvie.com. http://nvie.com/posts/a-successful-git-

branching-model/.

41
[41] Behat  BDD for PHP. http://behat.org/.

[42] The PHP quality assurance toolchain. http://phpqatools.org/.

[43] enterprise architecture - dev vs stage environment vs prod environment

- programmers. http://programmers.stackexchange.com/questions/117945/dev-vs-

stage-environment-vs-prod-environment.

[44] The problem with separating data from puppet code | puppet labs.

https://puppetlabs.com/blog/the-problem-with-separating-data-from-puppet-code/.

[45] Metodología de desarrollo de software, Jan. 2013. Page Version ID: 61865375.

[46] dvdalvarez,  DevOps. integre las operaciones para una entrega continua, Nov. 2012.

[47] Apache ant - welcome. http://ant.apache.org/.

42

Vous aimerez peut-être aussi