Usando la misma imagen del docker en múltiples agentes durante la construcción paralela

Estoy tratando de reducir el tiempo de construcción al ejecutar algunas de mis etapas en parallel. Actualmente mi Jenkinsfile Parece que esto:

String NODE_DOCKER_IMAGE = 'company-docker.com:11452/digital-help/node-12-react:latest'

pipeline {
    agent {
        node {
            label 'centos'
        }
    }

    triggers { cron('H 1 * * *') }
    
    stages {
        stage('Prepare') {
            ...
        }

        stage('Install') {
            when {
                beforeAgent true
                not { triggeredBy 'TimerTrigger' }
                not { expression { isSkipCi } }
                not { expression { isReleaseDeployment } }
            }

            agent {
                docker {
                    reuseNode true
                    image NODE_DOCKER_IMAGE
                    args '-u root'
                }
            }

            steps {
                sh 'git clean -dxff'
                sh 'npm ci  --unsafe-perm'
            }
        }

        stage('Unit') {
            when {
                beforeAgent true
                not { triggeredBy 'TimerTrigger' }
                not { expression { isSkipCi } }
                not { expression { isReleaseDeployment } }
            }

            agent {
                docker {
                    reuseNode true
                    image NODE_DOCKER_IMAGE
                    args '-u root'
                }
            }

            steps {
                sh 'npm run test:unit'
            }

            post {
                success {
                    step([$class: 'CoberturaPublisher', coberturaReportFile: 'coverage/jest/cobertura-coverage.xml'])
                }
            }
        }

        stage('Integration') {
            when {
                beforeAgent true
                not { triggeredBy 'TimerTrigger' }
                not { expression { isSkipCi } }
                not { expression { isReleaseDeployment } }
            }

            agent {
                docker {
                    reuseNode true
                    image NODE_DOCKER_IMAGE
                    args '-u root'
                }
            }

            steps {
                sh 'npm run test:integration'
            }
        }

        stage('Artifact') {
            when {
                beforeAgent true
                not { triggeredBy 'TimerTrigger'}
                not { expression { isSkipCi } }
            }

            agent {
                docker {
                    reuseNode true
                    image NODE_DOCKER_IMAGE
                    args '-u root'
                }
            }

            steps {
                script {
                    ...
                }
            }
        }
    }
}

He editado el archivo y las etapas paralelas así:

String NODE_DOCKER_IMAGE = 'company-docker.com:11452/digital-help/node-12-react:latest'

pipeline {
    agent {
        node {
            label 'centos'
        }
    }

    triggers { cron('H 1 * * *') }
    
    stages {
        stage('Prepare') {
            ...
        }

        stage('Install') {
            when {
                beforeAgent true
                not { triggeredBy 'TimerTrigger' }
                not { expression { isSkipCi } }
                not { expression { isReleaseDeployment } }
            }

            agent {
                docker {
                    reuseNode true
                    image NODE_DOCKER_IMAGE
                    args '-u root'
                }
            }

            steps {
                sh 'git clean -dxff'
                sh 'npm ci  --unsafe-perm'
            }
        }

        stage('Tests & Artifacts') {
            when {
                beforeAgent true
                not { triggeredBy 'TimerTrigger' }
                not { expression { isSkipCi } }
            }
            stage('Unit') {
                when { not { expression { isReleaseDeployment } } }
                agent {
                    docker {
                        reuseNode true
                        image NODE_DOCKER_IMAGE
                        args '-u root'
                    }
                }

                steps {
                    sh 'npm run test:unit'
                }

                post {
                    success {
                        step([$class: 'CoberturaPublisher', coberturaReportFile: 'coverage/jest/cobertura-coverage.xml'])
                    }
                }
            }

            stage('Integration') {
                when { not { expression { isReleaseDeployment } } }
                agent {
                    docker {
                        reuseNode true
                        image NODE_DOCKER_IMAGE
                        args '-u root'
                    }
                }

                steps {
                    sh 'npm run test:integration'
                }
            }

            stage('Artifact') {
                agent {
                    docker {
                        reuseNode true
                        image NODE_DOCKER_IMAGE
                        args '-u root'
                    }
                }

                steps {
                    script {
                        ...
                    }
                }
            }        
        }
    }
}

Todas las etapas utilizan la misma imagen del docker que Install etapa añadió todo lo que necesita durante npm ci . Las etapas paralelas tardan mucho tiempo ya que todas están ejecutando la misma imagen del docker usando el mismo agente, sin hacer que valga la pena.

¿Alguna idea sobre cómo puedo mejorar mis tiempos de ejecución paralelos?

Pregunta hecha hace 3 años, 4 meses, 28 días - Por techtactician


2 Respuestas:

  • Para mejorar los tiempos de ejecución paralelos en tu Jenkinsfile, una opción es utilizar diferentes agentes con la misma imagen de Docker. De esta manera, cada etapa paralela se ejecutará en un agente diferente, lo que puede reducir el tiempo total de construcción al distribuir las tareas entre varios agentes.

    Aquí te muestro cómo podrías modificar tu Jenkinsfile para lograr esto:

    • Define diferentes etiquetas para los agentes que quieres utilizar. Por ejemplo, podrías tener etiquetas como 'node1', 'node2', 'node3', etc.
    • Modifica las etapas paralelas para que cada una utilice un agente diferente con la misma imagen de Docker. Puedes hacer esto asignando una etiqueta específica a cada agente en las secciones 'agent' de las etapas.

    Aquí te dejo un ejemplo de cómo podrías modificar tu Jenkinsfile:

    groovy
    String NODE_DOCKER_IMAGE = 'company-docker.com:11452/digital-help/node-12-react:latest'
    
    pipeline {
        agent {
            node {
                label 'centos'
            }
        }
    
        triggers { cron('H 1   *') }
    
        stages {
            stage('Prepare') {
                ...
            }
    
            stage('Install') {
                when {
                    beforeAgent true
                    not { triggeredBy 'TimerTrigger' }
                    not { expression { isSkipCi } }
                    not { expression { isReleaseDeployment } }
                }
    
                agent {
                    docker {
                        reuseNode true
                        image NODE_DOCKER_IMAGE
                        args '-u root'
                    }
                }
    
                steps {
                    sh 'git clean -dxff'
                    sh 'npm ci  --unsafe-perm'
                }
            }
    
            stage('Tests & Artifacts') {
                when {
                    beforeAgent true
                    not { triggeredBy 'TimerTrigger' }
                    not { expression { isSkipCi } }
                }
                parallel {
                    stage('Unit') {
                        when { not { expression { isReleaseDeployment } } }
                        agent {
                            label 'node1'
                            docker {
                                reuseNode true
                                image NODE_DOCKER_IMAGE
                                args '-u root'
                            }
                        }
    
                        steps {
                            sh 'npm run test:unit'
                        }
    
                        post {
                            success {
                                step([$class: 'CoberturaPublisher', coberturaReportFile: 'coverage/jest/cobertura-coverage.xml'])
                            }
                        }
                    }
    
                    stage('Integration') {
                        when { not { expression { isReleaseDeployment } } }
                        agent {
                            label 'node2'
                            docker {
                                reuseNode true
                                image NODE_DOCKER_IMAGE
                                args '-u root'
                            }
                        }
    
                        steps {
                            sh 'npm run test:integration'
                        }
                    }
    
                    stage('Artifact') {
                        agent {
                            label 'node3'
                            docker {
                                reuseNode true
                                image NODE_DOCKER_IMAGE
                                args '-u root'
                            }
                        }
    
                        steps {
                            script {
                                ...
                            }
                        }
                    }
                }
            }
        }
    }
    

    Con esta modificación, cada etapa paralela se ejecutará en un agente diferente, lo que potencialmente puede reducir el tiempo de construcción al distribuir las tareas entre varios agentes. Asegúrate de ajustar el número de agentes y etiquetas según tus necesidades y la capacidad de tu infraestructura.

    Espero que esta sugerencia te ayude a mejorar tus tiempos de ejecución paralelos en Jenkins. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 18, 2020 a las 23:19 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Utiliza agentes dedicados para cada etapa paralela

    En lugar de utilizar el mismo agente para todas las etapas paralelas, considera utilizar agentes dedicados para cada etapa. Esto asegurará que cada etapa tenga sus propios recursos y no compita con otras etapas por CPU, memoria u otros recursos.

    Ejemplo modificado de Jenkinsfile:

    
    pipeline {
        agent {
            node {
                label 'centos'
            }
        }
    
        triggers { cron('H 1   ') }
    
        stages {
            stage('Prepare') {
                ...
            }
    
            stage('Install') {
                when {
                    beforeAgent true
                    not { triggeredBy 'TimerTrigger' }
                    not { expression { isSkipCi } }
                    not { expression { isReleaseDeployment } }
                }
    
                agent {
                    docker {
                        reuseNode true
                        image NODE_DOCKER_IMAGE
                        args '-u root'
                    }
                }
    
                steps {
                    sh 'git clean -dxff'
                    sh 'npm ci  --unsafe-perm'
                }
            }
    
            stage('Tests & Artifacts') {
                when {
                    beforeAgent true
                    not { triggeredBy 'TimerTrigger' }
                    not { expression { isSkipCi } }
                }
                parallel {
                    stage('Unit') {
                        when { not { expression { isReleaseDeployment } } }
                        agent {
                            docker {
                                reuseNode true
                                image NODE_DOCKER_IMAGE
                                args '-u root'
                            }
                        }
    
                        steps {
                            sh 'npm run test:unit'
                        }
    
                        post {
                            success {
                                step([$class: 'CoberturaPublisher', coberturaReportFile: 'coverage/jest/cobertura-coverage.xml'])
                            }
                        }
                    }
    
                    stage('Integration') {
                        when { not { expression { isReleaseDeployment } } }
                        agent {
                            docker {
                                reuseNode true
                                image NODE_DOCKER_IMAGE
                                args '-u root'
                            }
                        }
    
                        steps {
                            sh 'npm run test:integration'
                        }
                    }
    
                    stage('Artifact') {
                        agent {
                            docker {
                                reuseNode true
                                image NODE_DOCKER_IMAGE
                                args '-u root'
                            }
                        }
    
                        steps {
                            script {
                                ...
                            }
                        }
                    }
                }        
            }
        }
    }
    

    Beneficios:

    Cada etapa paralela se ejecuta en su propio agente, eliminando la contención de recursos. Las etapas se pueden ejecutar simultáneamente, reduciendo el tiempo total de construcción. La configuración es relativamente sencilla, solo requiere que definas agentes adicionales para cada etapa paralela.

    Nota:

    Asegúrate de tener suficientes agentes disponibles para ejecutar todas las etapas paralelas simultáneamente.

    Respondida el Dec 18, 2020 a las 23:28 - por Gemini

    Votos positivos: 0 | Votos negativos: 0