jenkins集成gitlab (jenkins分布式部署)

前言

Jenkins在实际的项目使用中,遇到多个 pipeline流水线有比较多重复代码的情况下,每次新增pipeline job时候都需要重新粘贴这些代码,流水线维护变得非常麻烦,可以通过jenkins的共享库来将这些重复的代码整合封装,然后在多个pipeline中进行调用,让流水线代码易于维护和版本化。

安装jenkins

  • 首先需要准备一个jenkins,这里使用compose方式运行;
$ mkdir jenkins && cd jenkins/
$ sudo mkdir -p data
$ sudo chown 1000.1000 -R data
$ vim docker-compose.yml

version: '3.9'
services:
  jenkins-master:
    image: docker.io/jenkins/jenkins:2.377-jdk17
    container_name: jenkins
    hostname: jenkins
    restart: always
    privileged: true
    network_mode: 'host'
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./data:/var/jenkins_home
    environment:
      - JAVA_OPTS='-Djava.util.logging.config.file=/var/jenkins_home/log.properties
      - TZ=Asia/Shanghai

  • 启动成功后,安装如下插件;
Pipeline: Groovy Libraries # 共享库插件
List Git Branches Parameter # Git扩展插件

创建共享库

  • 准备一个共享库,推送到Git上,目录结构如下;
.
├── resources # 存放构建流程需要用到的文件
│   └── build
│       └── mvn
│           ├── Dockerfile
│           └── settings.xml
├── src # 封装一些常用构建方法
│   └── org
│       └── devops
│           ├── GlobalVars.groovy
│           └── tools.groovy 
└── vars # 存放具体执行的pipeline脚本
    └── pipeline01 

  • 定义常用的构建方法;
$ vim tools.groovy

// 导入当前包
package org.devops


// 拉取项目方法
def gitCheckout(URL, credentialsId) {
   steps.checkout(
       [
           $class: 'GitSCM', 
           branches: [[name: '\$BRANCH']], 
           extensions: [], 
           userRemoteConfigs: [[credentialsId: "${credentialsId}", 
           url: "${URL}"]]
           ]
    )
}


// 获取git提交
def gitMsg() {
    sh '''
        git show --stat --format=提交日期:%ci,%n提交人:%cn,%n提交备注:%s,%n提交Hash:%H,%n提交分支:%d,%n%b%n提交修改的文件:
    '''
}


// 清理workspace
def cleanWS() {
    cleanWs deleteDirs: true, notFailBuild: true
}


// 创建文件
def creatFile(filename, content) {
    steps.writeFile encoding: 'UTF-8', file: "$filename", text: "$content"
}


// 获取提交id
def commitId() {
    String commit = steps.sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
    return commit
}


// 构建项目
def build(action, commitid, repourl, tag){
    sh """
       # build
       DOCKER_BUILDKIT=1 docker build --progress=auto \
                 --target=${action} \
                 --build-arg version=${commitid} \
                 -t ${repourl}:${tag} .
       # push
       docker push ${repourl}:${tag} && docker rmi ${repourl}:${tag}
    """
}


// 推送镜像
def loginRepo(username, password, repourl){
   sh """
      docker login -u $username -p $password $repourl
   """
}

$ vim tools.groovy

package org.devops

// 全局变量参数定义
class GlobalVars {

    // 项目仓库地址
    static String giturl = 'https://example.com/example/test.git'
    static String certid = 'e6655bac-85cc-4a61-9ae3-3eeb02ff2e4c'
    
    // 镜像仓库
    static String imageRepo = 'harbor.example.cn/public'
    static String pushRepo = 'harbor.example.cn/public/test'
    static String userRepo = 'root'
    static String passRepo = 'root1234'

}

  • 定义pipeline;
$ vim pipeline01

// 说明:jenkinslibrary是后面在jenkins中定义的共享库名称
// 引用共享库,注意后面的"_"不要漏掉
@Library('jenkinslibrary@master') _

// 导入构建库
def GlobalVars = new org.devops.GlobalVars()
def tools = new org.devops.tools()

// 引用文件
def buildfile = libraryResource "build/mvn/Dockerfile"
def mvnconf = libraryResource "build/mvn/settings.xml"

// 流水线
pipeline {

    agent any

    // 运行参数定义
    options {
        buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '5', numToKeepStr: '5') // 保留历史构建数和记录
        disableConcurrentBuilds() // 设置job不能够同时运行
        disableResume() // 如果控制器重启,不允许管道恢复
        skipDefaultCheckout() // 跳过默认的代码检出
        timestamps() // 为控制台输出增加时间戳
    }

    // 步骤定义
    stages {
        stage("拉取代码") {
            steps {
                // 在script中执行
                script {
                    tools.gitCheckout(GlobalVars.giturl, GlobalVars.certid)
                    tools.gitMsg()
                }
            }
        }
        stage("构建镜像"){
            steps {

                script {

                    // 获取提交id
                    def commitID = tools.commitId()

                    // 获取构建id
                    def imagetag = currentBuild.id

                    // 创建文件
                    tools.creatFile("settings.xml", mvnconf)
                    tools.creatFile("Dockerfile", buildfile)

                    // 执行构建
                    tools.loginRepo(GlobalVars.userRepo, GlobalVars.passRepo, GlobalVars.imageRepo)
                    tools.build("release", commitID, GlobalVars.pushRepo, imagetag)

                }
            }
        }
    }
    post {
        always {
            script {
                // 清理构建文件
                tools.cleanWS()
            }
        }
    }
}

  • 定义构建文件
$ vim Dockerfile

FROM docker.io/library/maven:3.8-openjdk-8-slim AS build
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
    echo $TZ > /etc/timezone
WORKDIR /build
COPY settings.xml /root/.m2/
COPY . /build
RUN mvn -Dmaven.test.skip=true package

FROM docker.io/library/eclipse-temurin:8u332-b09-jre-focal AS release
ENV TZ=Asia/Shanghai
ARG version
EXPOSE 8080
WORKDIR /app
COPY --from=build /build/target/test-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT java -server \
           ${JAVA_OPTS} \
           -jar /app/app.jar \
           --user.timezone=GMT+08 \
           --java.security.egd=file:/dev/./urandom ${JAVA_CLI}

$ vim settings.xml

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
    <mirrors>
        <mirror>
              <id>aliyun</id>
              <mirrorOf>*</mirrorOf>
              <name>aliyun-public</name>
              <url>https://maven.aliyun.com/repository/public</url>
          </mirror>
          <mirror>
              <id>aliyun-center</id>
              <mirrorOf>central</mirrorOf>
              <name>aliyun-central</name>
              <url>https://maven.aliyun.com/repository/central</url>
          </mirror>
          <mirror>
              <id>aliyun-spring</id>
              <mirrorOf>spring</mirrorOf>
              <name>aliyun-spring</name>
              <url>https://maven.aliyun.com/repository/spring</url>
          </mirror>
    </mirrors>
</settings>

添加共享库

  • 在jenkins中添加共享库,找到 "系统设置" -> " Global Pipeline Libraries" ;

Jenkins共享库应用

Jenkins共享库应用

配置流水线

  • 创建一个pipeline job,配置Git分支拉取;

Jenkins共享库应用

  • 配置构建流水线地址;

Jenkins共享库应用

  • 构建测试job;

Jenkins共享库应用

Jenkins共享库应用

end ~