Cómo recopilar proyectos en Jenkins si necesitas muchos entornos diferentes

Cómo recopilar proyectos en Jenkins si necesitas muchos entornos diferentes

Hay muchos artículos en Habré sobre Jenkins, pero pocos describen ejemplos de cómo funcionan Jenkins y los agentes acoplables. Todas las herramientas populares de creación de proyectos como Drone.io, Canalización de Bitbucket, GitLab, Acciones de GitHub y otros, pueden recoger todo en contenedores. ¿Pero qué pasa con Jenkins?

Hoy hay una solución al problema: Jenkins 2 es excelente para trabajar con Agentes acoplables. En este artículo quiero compartir mi experiencia y mostrarte cómo puedes hacerlo tú mismo.

¿Por qué comencé a resolver este problema?

ya que estamos en compañia citronio Debido a que utilizamos muchas tecnologías diferentes, debemos mantener diferentes versiones de Node.JS, Gradle, Ruby, JDK y otros en la máquina de ensamblaje. Pero a menudo no se pueden evitar los conflictos de versiones. Sí, tendrás razón si dices que existen varios administradores de versiones como nvm, rvm, pero no todo es tan sencillo con ellos y estas soluciones tienen problemas:

  • una gran cantidad de tiempo de ejecución que los desarrolladores olvidan limpiar;
  • hay conflictos entre diferentes versiones de los mismos tiempos de ejecución;
  • Cada desarrollador necesita un conjunto diferente de componentes.

Hay otros problemas, pero déjame contarte la solución.

Jenkins en Docker

Dado que Docker ahora está bien establecido en el mundo del desarrollo, casi cualquier cosa se puede ejecutar con Docker. Mi solución es tener Jenkins en Docker y poder ejecutar otros contenedores Docker. Esta pregunta empezó a plantearse allá por 2013 en el artículo “Docker ahora puede ejecutarse dentro de Docker«.

En resumen, solo necesita instalar Docker en un contenedor que funcione y montar el archivo. /var/run/docker.sock.

Aquí hay un Dockerfile de ejemplo que resultó para Jenkins.

FROM jenkins/jenkins:lts

USER root

RUN apt-get update && 

apt-get -y install apt-transport-https 
     ca-certificates 
     curl 
     gnupg2 
     git 
     software-properties-common && 
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && 
add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") 
   $(lsb_release -cs) 
   stable" && 
apt-get update && 
apt-get -y install docker-ce && 
usermod -aG docker jenkins

RUN curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose 

RUN apt-get clean autoclean && apt-get autoremove —yes && rm -rf /var/lib/{apt,dpkg,cache,log}/

USER jenkins

Por lo tanto, obtuvimos un contenedor Docker que puede ejecutar comandos Docker en la máquina host.

Configuración de compilación

No hace mucho, Jenkins tuvo la oportunidad de describir sus reglas usando Tubería sintaxis, lo que hace que sea bastante fácil cambiar el script de compilación y almacenarlo en el repositorio.

Entonces, coloquemos un Dockerfile especial en el repositorio, que contendrá todas las bibliotecas necesarias para la compilación. De esta manera, el propio desarrollador puede preparar un entorno repetible y no tendrá que pedirle a OPS que instale una versión específica de Node.JS en el host.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Esta imagen de compilación es adecuada para la mayoría de las aplicaciones Node.JS. ¿Qué pasa si, por ejemplo, necesitas una imagen para un proyecto JVM con un escáner Sonar incluido en su interior? Eres libre de elegir los componentes que necesitas para el montaje.

FROM adoptopenjdk/openjdk12:latest

RUN apt update 
    && apt install -y 
        bash unzip wget

RUN mkdir -p /usr/local/sonarscanner 
    && cd /usr/local/sonarscanner 
    && wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.3.0.1492-linux.zip 
    && unzip sonar-scanner-cli-3.3.0.1492-linux.zip 
    && mv sonar-scanner-3.3.0.1492-linux/* ./ 
    && rm sonar-scanner-cli-3.3.0.1492-linux.zip 
    && rm -rf sonar-scanner-3.3.0.1492-linux 
    && ln -s /usr/local/sonarscanner/bin/sonar-scanner /usr/local/bin/sonar-scanner

ENV PATH $PATH:/usr/local/sonarscanner/bin/
ENV SONAR_RUNNER_HOME /usr/local/sonarscanner/bin/

Describimos el entorno de ensamblaje, pero ¿qué tiene que ver Jenkins con él? Y los agentes de Jenkins pueden trabajar con dichas imágenes de Docker y crearlas internamente.

stage("Build project") {
    agent {
        docker {
            image "project-build:${DOCKER_IMAGE_BRANCH}"
            args "-v ${PWD}:/usr/src/app -w /usr/src/app"
            reuseNode true
            label "build-image"
        }
    }
    steps {
        sh "yarn"
        sh "yarn build"
    }
}

Directiva agent usa propiedad dockerdonde puedes especificar:

  • el nombre del contenedor de ensamblaje según su política de nombres;
  • argumentos necesarios para ejecutar el contenedor de compilación, donde en nuestro caso montamos el directorio actual como un directorio dentro del contenedor.

Y ya en los pasos de compilación indicamos qué comandos ejecutar dentro del agente de compilación de Docker. Esto puede ser cualquier cosa, por lo que también inicio la implementación de aplicaciones usando ansible.

A continuación quiero mostrar un archivo Jenkins genérico que puede crear una aplicación Node.JS simple.

def DOCKER_IMAGE_BRANCH = ""
def GIT_COMMIT_HASH = ""

pipeline { 
    options {
        buildDiscarder(
            logRotator(
                artifactDaysToKeepStr: "",
                artifactNumToKeepStr: "",
                daysToKeepStr: "",
                numToKeepStr: "10"
            )
        )
        disableConcurrentBuilds()
    }

    agent any

    stages {

        stage("Prepare build image") {
            steps {
                sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
            }
        }

        stage("Build project") {
            agent {
                docker {
                    image "project-build:${DOCKER_IMAGE_BRANCH}"
                    args "-v ${PWD}:/usr/src/app -w /usr/src/app"
                    reuseNode true
                    label "build-image"
                }
            }
            steps {
                sh "yarn"
                sh "yarn build"
            }
        }

    post {
        always {
            step([$class: "WsCleanup"])
            cleanWs()
        }
    }

}

¿Qué pasó?

Gracias a este método solucionamos los siguientes problemas:

  • el tiempo de configuración del ensamblaje del entorno se reduce a 10 - 15 minutos por proyecto;
  • un entorno de creación de aplicaciones completamente repetible, ya que puede crearlo de esta manera en su computadora local;
  • no hay problemas de conflictos entre diferentes versiones de herramientas de montaje;
  • Siempre un espacio de trabajo limpio y que no se obstruya.

La solución en sí es simple y obvia y le permite obtener algunas ventajas. Sí, el umbral de entrada ha aumentado un poco en comparación con los comandos simples para ensamblajes, pero ahora existe la garantía de que siempre se construirá y el propio desarrollador puede elegir todo lo que sea necesario para su proceso de construcción.

También puedes usar la imagen que recopilé. Jenkins + Docker. Todas las fuentes están abiertas y ubicadas en rmuhamedgaliev/jenkins_docker.

Mientras escribía este artículo, surgió una discusión sobre el uso de agentes en servidores remotos para no cargar el nodo maestro usando un complemento. complemento-acoplador. Pero hablaré de esto en el futuro.

Fuente: habr.com

Añadir un comentario