ylab color categoryorder python linux deployment pylons

color - Un simple problema de implementación de Python-todo un mundo de dolor



plotly layout (8)

Eche un vistazo a buildout para implementaciones reproducibles.

Tenemos varias aplicaciones Python 2.6 que se ejecutan en Linux. Algunas de ellas son aplicaciones web de Pylons, otras son simplemente procesos de larga ejecución que ejecutamos desde la línea de comandos usando nohup . También estamos usando virtualenv , tanto en desarrollo como en producción. ¿Cuál es la mejor manera de implementar estas aplicaciones en un servidor de producción?

En el desarrollo, simplemente obtenemos el árbol de origen en cualquier directorio, configuramos un virtualenv y lo ejecutamos, lo suficientemente fácil. Podríamos hacer lo mismo en producción y tal vez esa sea realmente la solución más práctica, pero se siente un poco mal al ejecutar svn update en producción. También probamos fab , pero nunca funciona la primera vez. Para cada aplicación algo más sale mal. Me parece que todo el proceso es demasiado difícil , dado que lo que estamos tratando de lograr es fundamentalmente muy simple. Esto es lo que queremos de un proceso de implementación.

  1. Deberíamos poder ejecutar un comando simple para implementar una versión actualizada de una aplicación. (Si la implementación inicial implica un poco de complejidad adicional, está bien).
  2. Cuando ejecutamos este comando, debería copiar ciertos archivos, ya sea de un repositorio de Subversion o de una copia de trabajo local, a un "entorno" específico en el servidor, lo que probablemente significa un virtualenv diferente. Tenemos tanto la versión de prueba como la de producción de las aplicaciones en el mismo servidor, por lo que debemos mantenerlas separadas de alguna manera. Si se instala en paquetes de sitio, también está bien, siempre y cuando funcione.
  3. Tenemos algunos archivos de configuración en el servidor que deben conservarse (es decir, no se deben sobrescribir ni eliminar por el proceso de implementación).
  4. Algunas de estas aplicaciones importan módulos de otras aplicaciones , por lo que deben poder hacer referencia entre sí como paquetes de alguna manera. ¡Esta es la parte con la que más problemas hemos tenido! No me importa si funciona mediante importaciones relativas, paquetes de sitios o lo que sea, siempre y cuando funcione de manera confiable tanto en el desarrollo como en la producción.
  5. Idealmente, el proceso de implementación debería instalar automáticamente paquetes externos de los que dependen nuestras aplicaciones (por ejemplo, psycopg2).

¡Eso es realmente! ¿Qué tan difícil puede ser?


El desarrollo y la implementación del código Python se hacen mucho más fáciles con las setuptools de setuptools en combinación con virtualenv y pip .

Ideas centrales

He encontrado que la parte más complicada es ejecutar un entorno de desarrollo que refleje la configuración implementada lo más cerca posible, al mismo tiempo que respeta las herramientas y los lenguajes de Pythonic. Pero resulta que esto es muy fácil de lograr con pip y setuptools, que en conjunto le permiten "instalar" un árbol de desarrollo en un entorno Python sin mover los archivos. (En realidad, setuptools lo hace todo por sí mismo, pero pip actúa mejor como dependencias de control de front-end.)

Otro problema clave es preparar un entorno limpio con un conjunto de paquetes conocidos en ambos entornos. Python''s virtualenv es un envío de Dios a este respecto, lo que le permite configurar un entorno Python completamente personalizado con su propia elección de paquetes, sin requerir acceso de root, o paquetes de sistema operativo (rpm o dpkg), y sin estar limitado por ningún paquete y versión. De los que se instalan en tu distro.

Finalmente, un bug-bear molesto es la dificultad de crear scripts de línea de comandos que funcionen bien con PYTHON_PATH. Esto también es tratado con bastante elegancia por setuptools.

Estableciendo

(Para mantener las cosas simples, esto es bastante prescriptivo. Siéntase libre de divergir según corresponda).

  1. Prepare un directorio de trabajo que sus cosas de Python puedan llamar hogar.
  2. Toma el último virtualenv de la parte inferior de virtualenv y descomprímelo (no importa dónde).
  3. Desde el directorio de trabajo, configure un nuevo entorno virtual de Python:

    $ python <untarred_directory>/virtualenv.py venv

  4. Querrás hacer la mayor parte de tu trabajo desde este entorno virtual. Use este comando para hacerlo ( . Es un acceso directo para la source ):

    $ . venv/bin/activate

  5. Instalar pip:

    $ easy_install pip

  6. Cree directorios para cada paquete instalable que desee crear.

  7. En cada directorio, necesitará un setup.py que define el contenido y la estructura del paquete. La setuptools setuptools es un recurso muy bueno para comenzar con esto. Vale la pena tomarse el tiempo para absorber grandes porciones de ella.

Desarrollo

Una vez que la estructura de su árbol esté lista, estará casi listo para comenzar a codificar. Pero ahora, los paquetes que dependen unos de otros no se pueden ver como lo harán en el entorno implementado. Este problema se resuelve con un pequeño truco que setuptools ofrece, y que pip utiliza. Para cada paquete que esté desarrollando, ejecute el siguiente comando (asegúrese de estar en el entorno virtual para su proyecto, como se indica en el paso 3, arriba):

$ pip install -e pkg1

Este comando instalará pkg1 en su entorno virtual, y lo hace sin copiar ninguno de sus archivos. Simplemente agrega un enlace al directorio de site-packages apunta a la raíz de desarrollo del paquete y crea un directorio de información de huevo en esa raíz. También puedes hacer esto sin pip, de la siguiente manera:

$ cd pkg1 $ python setup.py develop

Y generalmente funcionará, pero si tiene dependencias de terceros (que deberían estar enumeradas en setup.py, como se explica here en la documentación de setuptools), pip es más inteligente en cuanto a encontrarlas.

Una advertencia a tener en cuenta es que ni setuptools ni pip tienen ninguna inteligencia sobre cómo encontrar dependencias entre sus propios paquetes. Si PkgB en el directorio B, depende de PkgA en el directorio A, entonces pip install -e B fallará, porque pip no tiene forma de saber que PkgA se puede encontrar en el directorio A; en su lugar, intentará, y fallará, descargar PkgA desde sus fuentes de repositorio en línea. La solución es simplemente instalar cada paquete después de sus dependencias.

En este punto, puede iniciar Python, cargar uno de sus módulos y comenzar a jugar con él. Puede editar el código y estará disponible de inmediato la próxima vez que lo importe.

Finalmente, si desea crear herramientas de línea de comandos con sus paquetes. No los escribas a mano. Terminarás con un horrible desorden de hacks PYTHON_PATH que nunca funcionan bien. Simplemente lea sobre la creación automática de scripts en la documentación de setuptools. Esto te ahorrará mucho dolor.

Despliegue

Cuando sus paquetes están listos para la acción, puede usar setup.py para crear paquetes de implementación. Hay demasiadas opciones para entrar aquí, pero las siguientes deben comenzar:

$ cd pkg1 $ python setup.py --help $ python setup.py --help-commands

Cabos sueltos

Debido a la naturaleza amplia de la pregunta, esta respuesta es necesariamente incompleta. No he manejado servidores de larga duración, marcos web o el proceso de implementación real en sí (en particular, uso de pip install --index-url para administrar un repositorio privado de paquetes internos y de terceros y -e vcs+... , que sacará paquetes de svn, git, hg o bzr). Pero espero haberte dado la cuerda suficiente para atarlo todo (simplemente no te cuelgues con él :-).


Esto realmente no es difícil. Necesitas jugar principalmente con buildout y supervisord IMO.

Si bien el aprendizaje de buildout puede tomar un poco de tiempo, pero vale la pena, dada la cantidad de dolor que se reduce en configuraciones repetidas.

Acerca de nohup: el enfoque nohup no se adapta a implementaciones serias. Tengo muy buena experiencia con supervisor. Es una excelente solución para ejecutar aplicaciones de producción de python. Es muy fácil de configurar.

Algunas respuestas específicas a continuación.

  1. comando único para desplegar: Buildout es la respuesta. Lo estamos usando desde hace un par de años sin muchos problemas.
  2. Por lo general, es como usted comprueba la fuente. A continuación, ejecute buildout. Además, puede que no sea una buena idea dejar que la configuración se copie en los paquetes del sitio. Mejor mantener ambientes separados.
  3. No se sobrescribirían las configuraciones.
  4. Puede / debería considerar la posibilidad de construir huevos para los paquetes comunes. Al igual que usted puede construir el huevo para un paquete (por ejemplo, commonlib) y cargarlo en su repositorio de código. Luego puede especificar esto como una dependencia en su buildout.cfg
  5. Buildout es capaz de construir la mayoría de los paquetes esenciales completamente separados de la instalación central / superior. Sin embargo, en mi experiencia, los paquetes de Python con extensión c, si se instalan como paquetes de SO, son mucho más fáciles.

He estado trabajando en la implementación de esto para nuestros proyectos de trabajo. Son algunas partes diferentes involucradas.

Primero, personalizamos virtualenv.py usando sus habilidades de arranque para agregar sus propias funciones y marcas personalizadas posteriores a la creación. Estos nos permiten definir tipos comunes de proyectos y también nos da un solo comando para crear un nuevo virtualenv, retirar un proyecto del repositorio de git e instalar cualquier requisito en el virtualenv utilizando los archivos pip y Requirements.txt.

para que nuestros comandos se vean como: python venv.py --no-site-packages -g $ git_proj -t $ tag_num $ venv_dir

virtualenv http://pip.openplans.org/

Ahora que nos lleva a la salida inicial de un proyecto existente. A medida que trabajamos y actualizamos el proyecto, usamos comandos de estructura dentro de cada proyecto para crear versiones y luego implementarlas:

http://docs.fabfile.org/0.9.0/

Tengo un comando fab: make_tag que comprueba si hay confirmaciones no utilizadas, abre archivos que necesitan cadenas de versión actualizadas, crea y carga documentos de sphinx, y luego confirma la etiqueta final en el repositorio.

La otra cara es un comando fab deploy que, a través de ssh, realizará un git co de la etiqueta especificada, ejecutará una actualización de pip en cualquier nuevo requisito, ejecutará las migraciones de base de datos necesarias y luego restablecerá el servidor web si se trata de una aplicación web. .

Aquí hay un ejemplo de la función de etiquetado: http://www.google.com/codesearch/p?hl=en#9tLIXCbI4vU/fabfile.py&q=fabfile.py%20git%20tag_new_version&sa=N&cd=1&ct=rc&l=143

Hay un montón de archivos de buena tela que puede navegar utilizando la búsqueda de códigos de Google. Sé que engañé a algunos para mi propio uso.

Definitivamente es complicado y tiene varias partes para que todo funcione sin problemas. Sin embargo, una vez que lo pones en marcha, la flexibilidad y la velocidad de las cosas son increíbles.


Otro voto para la tela (no he probado Buildout todavía). Lo hemos estado utilizando con éxito durante un par de meses.

Si tienes problemas con la tela, otra opción es Capistrano . Funciona muy bien (incluso para aplicaciones no ferroviarias). Solo dejó de usarlo porque se siente raro usar Ruby para implementar aplicaciones de Python;)


Parece que lo que quieres es un script de compilación. Así que escribe uno, usando shell, python, ant o tu herramienta de construcción favorita. Si no te gusta escribir en XML, pant te permite escribir scripts ant en python. Varias personas han mencionado buildout pero no tengo ninguna experiencia con eso.

Primero define tus pasos. Suena como si quisieras:

  1. Exportación SVN desde su etiqueta de producción (no desea tener una copia de trabajo en prod)
  2. establecer virtualenv
  3. Easy_install o pip instala los paquetes requeridos (o probablemente use versiones pre-descargadas y probadas)
  4. copie los archivos de configuración de producción a su destino (no es una buena idea mantener esta información en el repositorio de origen, aunque podría tener su versión por separado)
  5. reinicia tu servidor y haz cualquier otra tarea de configuración
  6. Ejecutar pruebas de humo y revertir en caso de fallo.

Si está realizando un balanceo de carga o dependiendo de la producción de otros servicios, es posible que desee encontrar una manera de implementar un alcance limitado para que todos sus clientes no se vean afectados de inmediato. Si tiene un entorno de producción similar a la producción que también podría satisfacer esa necesidad.


Si eres una persona de buildout, entonces deberías conocer la capacidad de minitage.recipe.scripts para generar un archivo para configurar tu entorno de Python. Fuente a su servidor web y su buildout es completamente portátil.


Usaría rsync para sincronizar desde el servidor "principal" de producción a los demás, y desde su plataforma de "prueba beta" a su servidor "primario" de producción.

rsync tiene la ventaja de copiar solo los archivos que cambiaron, y copiar solo partes de archivos que se modificaron parcialmente, y verificar la integridad y el contenido idéntico al final en todas las máquinas. Una actualización que se complete parcialmente y se interrumpa se puede continuar fácilmente más adelante, lo que hace que su implementación sea más robusta.

Subversión o Mercurial tampoco sería una mala idea en este caso. Mercurial tiene la ventaja de permitirle "tirar" o "empujar" en lugar de solo actualizar desde una fuente central. Puede encontrar casos interesantes donde un modelo descentralizado (mercurial) funcione mejor.