¿Cómo estructurar el código y las configuraciones relacionadas con DevOps en un repositorio de código?

10

Hemos estado creciendo como compañía, nuestros productos se están expandiendo y nuestras actividades y esfuerzos relacionados con DevOps también están creciendo: hemos cambiado de Bamboo a una Jenkins más flexible y configurable, utilizando tuberías de implementación y otros complementos; cambió a Ansible y comenzó a usar Docker aquí y allá internamente.

Todas estas cosas requieren un cierto nivel de codificación o configuración: scripts y configuraciones Ansible, scripts geniales de Jenkins, Dockerfiles y configuraciones YAML.

Por ahora, hemos creado una por separado "operaciones" repositorio con los directorios de alto nivel para jenkins, ansible, dockery other(lo que es un nombre terrible, pero por ahora todas las cosas "otros" DevOps de automatización están allí).

Nuestro enfoque no se siente bien y podría no escalar, pero ¿cuáles son las mejores prácticas y recomendaciones para mantener el código relacionado con DevOps en un repositorio o repositorios de código?

alecxe
fuente
66
Voy con el método "cada parte es una aplicación, un repositorio por aplicación", en chef significa 1 repositorio por libro de cocina.
Tensibai
@Tensibai bien, tenía miedo de que un solo repositorio de "operaciones" se volviera poco práctico rápidamente. Gracias.
alecxe
1
Esa ha sido la forma heredada de administración de libros de cocina en chef, 1 repositorio con todos los libros de cocina y demostró ser una pistola en la mayoría de los casos, de ahí el cambio, pero estoy menos cómodo con ansible para decir que encajaría también, las tuberías de Jenkins (si v2) y los archivos acoplables deberían vivir con el proyecto que manejan en la OMI, y no tengo idea de lo que pones debajo de otro, así que realmente no puedo darte ningún consejo aquí
Tensibai
¡@Tensibai lo consiguió! Otro consiste principalmente en utilidades de bash y python o scripts ejecutados periódicamente para múltiples herramientas internas ... realmente no caben en ningún lugar y no podríamos pensar en un lugar mejor que "otro" ... Veré si puedo publicar el contenido de los directorios en la pregunta también. Gracias.
alecxe
1
Los dividiría en múltiples repositorios por 'afinidad' de trabajo, los scripts que trabajan juntos en la aplicación X, es posible que se use un script en dos aplicaciones, pero si la aplicación A cambia de alguna manera, el script debe manejar con qué aplicación se comunica , es mejor tener dos versiones separadas, por lo que ATEOTD las almacenaría con la aplicación con la que se relacionan o si abarcan múltiples aplicaciones en un repositorio específico por tarea, por lo que siempre tiene una versión en línea con las aplicaciones implementadas y usted no No es necesario etiquetar un script no relacionado al mismo tiempo.
Tensibai

Respuestas:

3

La organización actual del código y la configuración que describe está estructurada por las soluciones técnicas involucradas. Este es un mal diseño que agregará muchos gastos generales en nuestras actividades de mantenimiento y también agregará muchas trampas en nuestro camino. En cambio, esa organización debería estructurarse en torno a los artefactos que estamos implementando.

La razón de esto es que queremos considerar los artefactos ( por ejemplo, una imagen acoplable o un paquete de software) como los objetos de los siguientes verbos:

  • construir
  • prueba
  • desplegar

considerar un conjunto mínimo de tareas automatizadas que queremos realizar. Si queremos cambiar algo sobre cómo se implementa el verbo de prueba, es fácil visitar la carpeta correspondiente a ese artefacto en el repositorio apropiado y luego descubrir los elementos de automatización específicos de jenkins que deben actualizarse. En cambio, si las recetas de automatización están estructuradas en torno a soluciones técnicas, entonces necesitamos averiguar de la nada que Jenkins está involucrado en los procedimientos de prueba y encontrar allí los elementos de automatización relacionados con el artefacto. En situaciones complejas, la organización en torno a las soluciones técnicas hace que las actualizaciones sean muy difíciles, porque tenemos que conocer a priori todas las soluciones técnicas involucradas en algún servicio para actualizarlas en consecuencia.

Por ejemplo, un repositorio que contiene el código de un sitio web y un microservicio "a" podría tener los siguientes subdirectorios dedicados a las operaciones:

./ops/website
./ops/micro-service-a

cada uno con tres guiones llamados build, testy deploy. Ahora que la organización de los elementos de automatización se ha aclarado de alguna manera, volvamos nuestra atención a la configuración.

El deployverbo establece las principales condiciones y requisitos sobre la organización de la configuración cuando se aplica a un artefacto similar a un servicio. El deployverbo debe tener los siguientes parámetros:

  • la versión del artefacto para desplegar,
  • el objetivo de implementación del artefacto, que describe el entorno concreto donde se ejecutará el artefacto desplegado ( por ejemplo, un clúster y puntos finales con los que debería hablar)
  • las credenciales que debe usar para conectarse a otros puntos finales ( por ejemplo, bases de datos)
  • la configuración de tiempo de ejecución de (como cuánto tiempo deben permanecer las entradas de caché, etc.)

Desde la perspectiva operativa, este desglose de la parametrización coincide con los grados naturales de libertad del problema de implementación, aparte de las credenciales que podrían agruparse con la configuración de tiempo de ejecución, pero es mejor separarlas para evitar distribuirlas descuidadamente.

Michael Le Barbier Grünewald
fuente
5

Puedo responder sobre Docker, una de las mejores prácticas para usar Docker es mantener el archivo Docker y los archivos de composición en el mismo repositorio del proyecto, por lo que donde sea que clones el proyecto puedes construir la imagen del Docker, y es bueno mantenga múltiples versiones de los archivos de composición de Docker, por ejemplo (prod, staging, dev) para que pueda construir la imagen y ejecutar el contenedor con una opción específica para cada entorno, por ejemplo, para la máquina de desarrollo, puede usar una red específica y ejecutar más contenedores de dependencias o lo que sea.

Wissam Roujoulah
fuente
4

El código de cada herramienta entra en su propio repositorio. por ej.

  1. Plantilla de Jenkins Groovy en un repositorio de Jenkins
  2. Playbooks de YAML en su propio repositorio (con los roles, tareas, subdirectorios de inventario)
  3. Plantillas Cloudformation / Terrform en su propio repositorio
  4. Docker archiva en sus propios 5 .. Y así sucesivamente

Esto lo ayudaría a escalar mejor en términos de orquestación de procesos y mantener varias ramas para cada entorno

Esto le daría un control más granular y descargaría todos sus gastos generales de control de versiones a los sistemas de control de versiones. También cree ramas separadas para cada entorno y etiquete el código para cada versión de producción (como lo hacemos para la base del código de la aplicación). Piense en Infra y procese en términos de código. (Cualquier cambio en el proceso debe ser codificado y enviado a QA, SIT, UAT y luego a PROD) similar a la aplicación.

Por ejemplo, puede tener V2.1 de Ansible ejecutándose en Producción (rama maestra) pero V2.0 de contenedores acoplables ejecutándose en Prod (rama maestra)

Del mismo modo, mantenga sus scripts de DB / scripts de bash en sus propios repositorios y tal vez pueda tener un archivo de comprobación de estado (JSON / YAML) configurado para mostrar las versiones de todas las herramientas / partes en cada URL implementada para fines de seguimiento y automatización. (Para que sus webhooks lean la URL y automaticen las implementaciones)

Ameen Ibrahim Raffic - 'AIRE'
fuente
2
El escollo de este enfoque es que v2.1 está en qa y no está validado y debe parchear la producción con urgencia, no puede modificar la v2.0 y si crea una v2.2 para este parche, existe un alto riesgo de que sea se pierde o se sobrescribe cuando v2.1 sale a producción, multiplíquelo por la cantidad de código separado en un repositorio y pronto tendrá una pesadilla de backports (funciona, pero tuve que agregar este descargo de responsabilidad :))
Tensibai
3
El uso de ramas para realizar un seguimiento de la información específica del entorno / implementación me parece un patrón de hormigas: si tenemos 20 entornos, esto significa que tenemos 20 ramas para mantener sincronizadas ... una fuente probable de errores y confusión. ¿Podría explicar por qué no utiliza archivos de configuración para realizar un seguimiento de la información específica del entorno / implementación y cuál es su flujo de trabajo trabajando con estas ramas? ¡Estos no son problemas triviales!
Michael Le Barbier Grünewald
3

Hacer una distinción entre Ops, Dev y DevOps promueve el aislamiento y aplica una mentalidad de "tirarlo por la pared". Para aumentar la cooperación entre los equipos, uno debe poner todo en un repositorio que se requiere para construir y desplegar el proyecto.

Dicho esto, la respuesta a la pregunta:

¿Cómo estructurar el código y las configuraciones relacionadas con DevOps en un repositorio de código?

es que si se requiere config para ejecutar el proyecto, entonces uno debe ponerlo en el mismo directorio.

030
fuente