Слоеный трубопровод на Дженкинсе с агентами docker - PullRequest
1 голос
/ 13 января 2020

У нас есть несколько агентов Jenkins, работающих как физические машины. До сих пор я запускал конвейер Jenkins на самих агентах, теперь я пытаюсь переместить здание и выполнить тестирование в контейнеры docker с помощью плагина Jenins docker.

Ниже вы можете найти упрощенную версию нашего Jenkinsfile, который использует gradle для сборки, тестирования и упаковки Java приложения Spring Boot.

node {
    stage('Preparation') {
        cleanWs()
        checkout scm
        notifyBitbucket()
    }
}

pipeline {
    agent {
        docker {
            image "our-custom-registry.com/jenkins-build:latest"
            registryUrl 'https://our-custom-registry.com'
            registryCredentialsId '...'
            alwaysPull true
            args "-u jenkins -v /var/run/docker.sock:/var/run/docker.sock" // the pipeline itself required docker
        }
    }
    stages {
        stage('Build') {
            steps {
                sh './gradlew assemble classes testClasses'
            }
        }
        stage('Test') {
            parallel {
                stage('Unit Tests') {
                    when { expression { return build_params.ENABLE_UNITTEST } }
                    steps {
                        sh './gradlew test'
                        junit UNIT_TEST_RESULT_DIR
                    }
                }

                stage('Integration Tests') {
                    when { expression { return build_params.ENABLE_INTEGRATION } }
                    steps {
                        sh './gradlew integration'
                        junit INTEGRATION_TEST_RESULT_DIR
                    }
                }
            }
        }
        stage('Finalize') {
            stage('Docker Push') {
                when { expression { return build_params.ENABLE_DOCKER_PUSH } }
                steps {
                    sh './gradlew pushDockerImage'
                }
            }
        }
    }
    post {
        cleanup {
            cleanWs()
        }
        always {
            script {
                node {
                    currentBuild.result = currentBuild.result ?: 'SUCCESS'
                    notifyBitbucket()
                }
            }
        }
    }
}

Ниже приведен Dockerfile, который я использую для образа сборки. Как видите, я вручную создаю пользователя Jenkins и добавляю его в группы docker (к сожалению, GID равен 998 или 999 в зависимости от агента Jenkins).

FROM openjdk:8-jdk-stretch

USER root
# prerequisites:
# - a user and a group Jenkins with UID/GID=1001 exist
# - the user home is /var/jenkins
# - the user is in the docker group
# - on some agents docker has the gid 998, on some it is 999
RUN apt-get update \
    && apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common rsync tree \
    && curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - \
    && add-apt-repository \
       "deb [arch=amd64] https://download.docker.com/linux/debian \
       $(lsb_release -cs) \
       stable" \
    && apt-get update \
    && apt-get -y install docker-ce docker-ce-cli containerd.io \
    && groupadd -g 1001 jenkins \
    && groupadd -f -g 998 docker1 \
    && groupadd -f -g 999 docker2 \
    && useradd -d "/var/jenkins" -u 1001 -g 1001 -m -s /bin/bash jenkins \
    && usermod -a -G 998 jenkins \
    && usermod -a -G 999 jenkins

USER jenkins

Затем Jenkins выполняет следующую команду

docker run -t -d -u 1001:1001 -u jenkins -v /var/run/docker.sock:/var/run/docker.sock  -w /var/jenkins/workspace/JOB_NAME -v /var/jenkins/workspace/JOB_NAME:/var/jenkins/workspace/JOB_NAME:rw,z -v /var/jenkins/workspace/JOB_NAME@tmp:/var/jenkins/workspace/JOB_NAME@tmp:rw,z -e ******** ... our-custom-registry.com/base/jenkins-build:latest cat

Этот конвейер работает просто отлично ... иногда! Однако в большинстве случаев некоторые файлы загадочным образом теряются.

Например, мой build.gradle состоит из множества других файлов, которые включены. В какой-то момент во время сборки один из этих файлов, кажется, отсутствует.

+ ./gradlew pushDockerImage

FAILURE: Build failed with an exception.

* Where:
Build file '/var/****/workspace/JOB_NAME/build.gradle' line: 35

* What went wrong:
A problem occurred evaluating root project 'foo'.
> Could not read script '/var/****/workspace/JOB_NAME/build/gradle/scripts/springboot-plugin.gradle' as it does not exist.

Это всегда другой файл, который пропадает.

Я запустил tree как раз перед ./gradlew, просто чтобы убедиться, что файл на самом деле не удален.

Кто-нибудь знает, что здесь происходит?

Обновление

Забудьте все, что я сказал о docker, это чистая проблема Грэдла и Дженкинса. Когда я заменяю агент docker простым агентом Дженкинса, возникают те же проблемы. Кажется, проблема в том, что вы не можете запускать несколько задач Gradle параллельно в одном каталоге.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...