Jenkins+Gitlab持续集成和部署

501 阅读7分钟

安装Jenkins

1.安装Jenkins

#1.安装jdk环境,卸载 openjdk
rpm -qa | grep java
#带openjdk的都要卸载
yum -y remove java-1.7.0-openjdk-1.7.0.141-2.6.10.5.el7.x86_64 等
#在 /usr/local/ 下创建 java ⽂件夹并进⼊,把jdk压缩包放在该目录下
tar -zxvf /root/jdk-8u161-linux-x64.tar.gz -C ./
#编辑 /etc/profile ⽂件,在⽂件尾部加⼊如下 JDK 环境配置即可
vim /etc/profile
JAVA_HOME=/usr/local/java/jdk1.8.0_261
CLASSPATH=$JAVA_HOME/lib/
PATH=$PATH:$JAVA_HOME/bin
export PATH JAVA_HOME CLASSPATH
#然后执⾏如下命令让环境变量⽣效
source /etc/profile
#javac 验证是否安装成功

#下载Jenkins rpm安装包 https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat-stable/
#把安装包上传到服务器
rpm -ivh 安装包
#修改Jenkins配置
vim /etc/sysconfig/jenkins
#修改内容
JENKINS_USER="root"
JENKINS_PORT="8088"
#启动jenkins
systemctl start jenkins
#若启动报错,则添加我们的javahome路径/usr/local/java/jdk1.8.0_261
1> 查看当前Java的环境变量   echo $JAVA_HOME
2> 复制Java的环境变量地址, 编辑/etc/init.d/jenkins文件, 指定位置添加该地址, 后缀附上/bin/java,注意一定要加上/bin/java   vim /etc/init.d/jenkins
3> 重新加载配置文件 systemctl daemon-reload
#把端口添加到防火墙
firewall-cmd --zone=public --add-port=8088/tcp --permanent
firewall-cmd --reload
#虽然,初始化的时候,如果机器的CPU和内存配置都比较低的话,就多等一会儿;但是操作时发现很久都加载不出来。
#解决:
[root@zj secrets]# cd /var/lib/jenkins/updates/
[root@zj updates]# ls
default.json
[root@zj updates]# vim default.json 
#重启
systemctl restart jenkins
#访问测试
http://192.168.3.51:8088

2.配置

  1. 配置管理员用户密码 root root123456

  2. 修改jenkins插件下载地址

    然后在进入 updates目录

  3. 修改配置文件

    sed -i 's/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json && sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json
    
  4. 修改jenkins的plugin-Manager的Advanced的 update-site地址

    https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
    
  5. 重启jenkins

    http://192.168.3.51:8088/restart
    
  6. 安装汉化插件 搜索 chinese,安装完启动

3.用户权限管理

  1. 安装Role-based Author 插件

  2. 进入 Configure Global Security选项

    授权策略 选择 Role-Based Strategy

  3. 进入 Manage and Assign Roles 管理角色

  4. 新增用户,并赋值对应的角色权限

4.安装凭证管理

记录我们的密码信息,便于登录之类

  1. 安装Credentials Binding插件

5.拉取代码通过http的形式

  1. jenkins安装git插件

  2. centos安装git环境

    #安装包上传解压
    #提前安装好依赖
    yum install curl-devel expat-devel gettext-devel openssl-devel zlibdevel gcc-c++ perl-ExtUtils-MakeMaker
    #cd到git目录,编译
    make configure
    ./configure --prefix=/usr/local/git
    make profix=/usr/local/git
    make install
    #将git加入环境变量
    vim /etc/profile
    
    export GIT_HOME=/usr/local/git
    export PATH=$PATH:$GIT_HOME/bin
    #执行生效
    source /etc/profile
    git --version
    

    jenkin配置新安装的git

  3. 创建凭证,新建item,buildNow,查看服务器 /var/lib/jenkins/workspace/ 看代码是否拉取下来

6.通过ssh私钥拉取代码

  1. 使用root用户生成公钥和私钥

    ssh-keygen -t rsa
    cd /root/.ssh  #pub是公钥 另一个是私钥
    
  2. gitlab配置sshkey公钥

  3. jenkins凭证管理,添加私钥

  4. 配置完重启下jenkins或者gitlab,否则拉取的时候会报没有权限。

7.配置maven环境

#复制安装包到 /opt/maven目录下
#解压
#配置仓库路径
mkdir /root/repo
#xml文件修改为 /root/repo
#配置阿里云镜像
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
#配置环境变量
vim /opt/maven/apache-maven-3.6.2/conf/settings.xml
vim /etc/profile 
export MAVEN_HOME=/opt/maven/apache-maven-3.6.2
export PATH=$MAVEN_HOME/bin:$PATH

#生效
source /etc/profile 
mvn –v
  1. jenkins配置maven环境

  2. jenkins配置jdk

  3. 添加jenkins全局变量,在configure system

  4. 重新构建项目测试

    新增 构建步骤 shell 脚本,mvn clean package

    在 var/lib/jenkins/workspace/项目名/xxx.war

8.配置tomcat

  1. 配置jdk环境

  2. 传输解压

  3. 在bin目录下启动

    ./startup.sh
    firewall-cmd --zone=public --add-port=8080/tcp --permanent
    firewall-cmd --reload
    如果启动不了 修改conf下的setting.xml的端口号 
    重启tomcat ./shutdown.sh ./startup.sh
    #http://192.168.3.51:8083/
    #配置tomcat权限
    cd /tomcat/conf
    vim tomcat-users.xml
    
    <role rolename="tomcat"/>
      <role rolename="role1"/>
      <role rolename="manager-script"/>
      <role rolename="manager-gui"/>
      <role rolename="manager-status"/>
      <role rolename="admin-gui"/>
      <role rolename="admin-script"/>
      <user username="tomcat" password="tomcat" roles="manager-gui,manager-script,tomcat,admin-gui,admin-script"/>
      
      
     #重启tomcat
     #还需要修改一下配置
     vim tomcat/webapps/manager/META-INF/context.xml 看下图
     #然后访问以下网址
     http://192.168.3.51:8083/manager/html
     #登录密码就是我们上面users.xml的 用户名和密码 都是tomcat
    

  4. 配置我们的编译步骤,新增构建步骤,比如 mvn clean package

  5. 增加远程部署功能,如果下载插件失败则修改插件的镜像地址,修改jenkins的plugin-Manager的Advanced的 update-site地址;

    1、修改 jenkins 数据目录中(var/lib/jenkins)的hudson.model.UpdateCenter.xml值为: mirrors.tuna.tsinghua.edu.cn/jenkins/upd… 2、修改updates文件夹中的 default.json文件

    替换文件中所有 updates.jenkins-ci.org/downloadmirrors.tuna.tsinghua.edu.cn/jenkins www.google.com 修改为 www.baidu.com

    3、在浏览器中,http:localhost:8080/reload,这样可以重新载入配置。 或者使用http:localhost:8080/restart,重启一下Jenkins ,选择安装推荐插件, 秒速安装成功,简直超速!!

  6. springboot配置成war包打包的形式并修改我们打包后生成的war包名称

  7. 查看部署结果

9.构建pieline项目

  1. 安装pipeline插件

  2. 生成语法

  3. 拉取代码的片段生成

  4. 复制生成后的脚本并替换

  5. 编译构建脚本生成

  6. 部署

  7. 通过文件来读取流水线脚本,(常用)

10.配置Git Hook

  1. 安装gitlab hook 和gitlab两个插件

  2. 修改之前的流水线配置

    在 Manage Jenkins -》Configure System ->gitlab

  3. 修改gitlab的配置,开启web hooks

11.使用参数构建项目

比如我们构建的时候传个参数,类似分支名字,这个需要我们手动构建

12.配置邮件通知

  1. 安装email extension template 插件

  2. 配置相关参数

  3. 准备邮件内容,html

  4. 生成脚本

    流水线脚本

    pipeline {
        agent any
    
        stages {
            stage('pull code') {
                steps {
                    checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'bfa846d4-a0b9-4d06-b2cd-58d43421b1bb', url: 'git@192.168.3.44:sb-group/sp-demo.git']]])
                }
            }
            stage('build project') {
                steps {
                    sh 'mvn clean package'
                }
            }
            stage('deploy project') {
                steps {
                    deploy adapters: [tomcat8(credentialsId: '6d944268-8e28-4964-944a-370646f7a2f2', path: '', url: 'http://192.168.3.49:8083')], contextPath: null, war: 'target/*.war'
                }
            }
        }
        post {
          always {
            emailext(
                body: '${FILE,path="email.html"}',
                subject: '本邮件由系统自动发出,无需回复!',
                to: '610398531@qq.com'
            )
          }
        }
    }
    
    

    email.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
    </head>
    
    <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
          offset="0">
    <table class="table" width="1000" border="1" cellspacing="0" cellpadding="5">
        <caption align="center"><h3>项目构建信息</h3></caption>
        <thead>
        <tr>
            <th>构建项目-<b>${PROJECT_NAME}</b></th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td><font color="#CC0000"><b>构建结果 - ${BUILD_STATUS}</b></font></td>
        </tr>
        <tr>
            <td>测试数量-${TEST_COUNTS, var="total"}</td>
        </tr>
        </tbody>
        <tr>
            本邮件由系统自动发出,无需回复!<br/>
            各位同事,大家好,以下为${PROJECT_NAME}项目构建信息</br>
        </tr>
    
        <tr>
            <td><br/>
                <b><font color="#0B610B">构建报告</font></b>
                <hr size="2" width="100%" align="center"/>
                <ul>
                    <li>构建报告:<a href="${BUILD_URL}allure/">${PROJECT_URL}allure/</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td><br/>
                <b><font color="#0B610B">构建信息</font></b>
                <hr size="2" width="100%" align="center"/>
                <ul>
                    <li>项目名称: ${PROJECT_NAME}</li>
                    <li>构建编号: 第${BUILD_NUMBER}次构建</li>
                    <li>触发原因:${CAUSE}</li>
                    <li>构建状态:${BUILD_STATUS}</li>
                    <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
                    <li>构建 Url: <a href="${BUILD_URL}">${BUILD_URL}</a></li>
                    <li>工作目录: <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
                    <li>项目 Url: <a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <b><font color="#0B610B">构建详细信息</font></b>
                <hr size="2" width="100%" align="center"/>
                <ul>
                    <li>BRANCH_NAME: ${BRANCH_NAME}</li>
                    <li>CHANGE_ID: ${CHANGE_ID}</li>
                    <li>CHANGE_URL: ${CHANGE_URL}</li>
                    <li>CHANGE_TITLE: ${CHANGE_TITLE}</li>
                    <li>CHANGE_AUTHOR: ${CHANGE_AUTHOR}</li>
                    <li>CHANGE_AUTHOR_DISPLAY_NAME: ${CHANGE_AUTHOR_DISPLAY_NAME}</li>
                    <li>CHANGE_AUTHOR_EMAIL: ${CHANGE_AUTHOR_EMAIL}</li>
                    <li>CHANGE_TARGET: ${CHANGE_TARGET}</li>
                    <li>BUILD_NUMBER: ${BUILD_NUMBER}</li>
                    <li>BUILD_DISPLAY_NAME: ${BUILD_DISPLAY_NAME}</li>
                    <li>BUILD_ID: ${BUILD_ID}</li>
                    <li>JOB_NAME: ${JOB_NAME}</li>
                    <li>JOB_BASE_NAME: ${JOB_BASE_NAME}</li>
                    <li>BUILD_TAG: ${BUILD_TAG}</li>
                    <li>EXECUTOR_NUMBER: ${EXECUTOR_NUMBER}</li>
                    <li>NODE_NAME: ${NODE_NAME}</li>
                    <li>NODE_LABELS: ${NODE_LABELS}</li>
                    <li>WORKSPACE: ${WORKSPACE}</li>
                    <li>JENKINS_HOME: ${JENKINS_HOME}</li>
                    <li>JENKINS_URL: ${JENKINS_URL}</li>
                    <li>BUILD_URL: ${BUILD_URL}</li>
                    <li>JOB_URL: ${JOB_URL}</li>
                    <li>GIT_COMMIT: ${GIT_COMMIT}</li>
                    <li>GIT_PREVIOUS_COMMIT: ${GIT_PREVIOUS_COMMIT}</li>
                    <li>GIT_PREVIOUS_SUCCESSFUL_COMMIT: ${GIT_PREVIOUS_SUCCESSFUL_COMMIT}</li>
                    <li>GIT_BRANCH: ${GIT_BRANCH}</li>
                    <li>GIT_LOCAL_BRANCH: ${GIT_LOCAL_BRANCH}</li>
                    <li>GIT_URL: ${GIT_URL}</li>
                    <li>GIT_COMMITTER_NAME: ${GIT_COMMITTER_NAME}</li>
                    <li>GIT_AUTHOR_NAME: ${GIT_AUTHOR_NAME}</li>
                    <li>GIT_COMMITTER_EMAIL: ${GIT_COMMITTER_EMAIL}</li>
                    <li>GIT_AUTHOR_EMAIL: ${GIT_AUTHOR_EMAIL}</li>
                    <li>MERCURIAL_REVISION: ${MERCURIAL_REVISION}</li>
                    <li>MERCURIAL_REVISION_SHORT: ${MERCURIAL_REVISION_SHORT}</li>
                    <li>MERCURIAL_REVISION_NUMBER: ${MERCURIAL_REVISION_NUMBER}</li>
                    <li>MERCURIAL_REVISION_BRANCH: ${MERCURIAL_REVISION_BRANCH}</li>
                    <li>MERCURIAL_REPOSITORY_URL: ${MERCURIAL_REPOSITORY_URL}</li>
                    <li>SVN_REVISION: ${SVN_REVISION}</li>
                    <li>SVN_URL: ${SVN_URL}</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <h4><font color="#0B610B">失败用例</font></h4>
                ${FAILED_TESTS}<br/>
            </td>
        </tr>
    
        <tr>
            <td>
                <h4><font color="#0B610B">最近提交(#$GIT_REVISION)</font></h4>
                <!--
                <ul>
                    ${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="
                    <li>%d [%a] %m</li>
                    "}
                </ul>
                <-->
            </td>
        </tr>
        <tr>
            <td>
                <b><font color="#0B610B">变更信息:</font></b>
                <hr size="2" width="100%" align="center"/>
            </td>
        </tr>
        <tr>
            <td>
                <ul>
                    <li>
                        上次构建成功后变化 : ${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"}
                    </li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <ul>
                    <li>上次构建不稳定后变化 : ${CHANGES_SINCE_LAST_UNSTABLE, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"}
                    </li>
                </ul>
            </td>
        <tr>
            <td>
                <ul>
                    <li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <ul>
                    <li>变更集:${JELLY_SCRIPT,template="html"}</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td><b><font color="#0B610B">构建日志 (最后 200行):</font></b>
                <hr size="2" width="100%" align="center"/>
            </td>
        </tr>
        <tr>
            <td><textarea cols="120" rows="30" readonly="readonly"
                          style="font-family: Courier New">${BUILD_LOG, maxLines=200}</textarea>
            </td>
        </tr>
    </table>
    </body>
    </html>
    

13.配置代码审查

  1. 配置SonarQube(7.8版本及以下,否则更新的版本不支持mysql)

  2. 安装mysql

  3. 安装解压

    #因为是.zip文件,所以解压需要安装unzip
    yum install unzip
    #不能使用root用户,需要新建sonarqube用户
    useradd sonar
    #更改权限
    chown -R sonar. /usr/local/sonarqube
    #修改目录下的conf的sonar.peoperties的数据库连接地址
    sonar.jdbc.username=root
    sonar.jdbc.password=123456
    sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
    #如果发现端口被占用 也可以在这个文件里面修改端口号 sonar.web.port 默认是9000
    #启动,以sonar用户启动
    su sonar /usr/local/sonarqube/sonarqube-7.8/bin/linux-x86-64/sonar.sh start
    #查看启动日志
    tail -f /usr/local/sonarqube/sonarqube-7.8/logs/es.log
    #访问
    
    #如果查看es的启动日志报错,而且报的是关于内存方面的问题
    max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
    elasticsearch启动时遇到的错误
    #问题翻译过来就是:elasticsearch用户拥有的内存权限太小,至少需要262144;
    #解决(1):
    vim  /etc/security/limits.conf
    * soft nofile 65536
    * hard nofile 65536
    #解决(2):
    #切换到root用户
    #执行命令:
    sysctl -w vm.max_map_count=262144
    #查看结果:
    sysctl -a|grep vm.max_map_count
    #显示:
    vm.max_map_count = 262144
    #上述方法修改之后,如果重启虚拟机将失效,所以:
    #解决办法:
    #在 /etc/sysctl.conf文件最后添加一行
    vm.max_map_count=262144
    #即可永久修改
    

  4. 安装完成后登陆 admin admin,并新建我们的token,以便在jenkins集成的时候使用

  5. jenkin集成sonarqube

    安装sonarqube scanner插件

    修改Global Tool Configuration配置里面的SonarQube Scanner

    修改Configure system配置里面的SonarQube servers,因为需要我们用到token值,所以需要新建个凭证,类型是 Secret Text

  6. 在配置带sonarqube的流水线项目

  7. 先写好 sonar-project.properties文件,注意文件名不能改

    # must be unique in a given SonarQube instance
    sonar.projectKey=sp-demo-pieline
    # this is the name displayed in the SonarQube UI
    sonar.projectName=sp-demo-pieline
    sonar.projectVersion=1.0
    
    # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
    # Since SonarQube 4.2, this property is optional if sonar.modules is set.
    # If not set, SonarQube starts looking for source code from the directory containing
    # the sonar-project.properties file.
    #sonar.sources=admin-core/src/main/java,admin-console/src/main/java
    sonar.sources=.
    sonar.exclusions=**/target/**,**/test/**
    sonar.java.source=1.8
    sonar.java.target=1.8
    #加上这个是为了防止报错
    sonar.java.binaries=target/classes 
    
    
    # Encoding of the source code. Default is default system encoding
    sonar.sourceEncoding=UTF-8
    

    然后在我们的JenkinsFile里面新增步骤

            stage('check code') {
                steps {
                    script {
                        //引入sonarQubeScnner工具 下面tool后面这个参数就是我们在Global Tool Configuration.SonarQube Scanner的name
                        scnnerHome = tool 'sonar-scanner'
                    }
                        //引入SonarQube的服务器环境
                        //下面这个参数是configureSystem的SonarQube servers的name
                    withSonarQubeEnv('sonarQube'){
                        sh "${scnnerHome}/bin/sonar-scanner"
                    }
                }
            }
    

    如果报一下错误

    ERROR: Error during SonarScanner execution
    org.sonar.java.AnalysisException: Please provide compiled classes of your project with sonar.java.binaries property
    

    在sonar-project.properties文件中增加

    sonar.java.binaries=target/classes