Jenkins+Gitlab搭建CICD流程进阶——制品管理和自动部署

一、制品的管理

1.1 从Pipeline中下载制品

在如上的pipeline流程中,我们是无法从Jenkins的流水线详情中下载制品的:

pipeline中不能下载制品

但Jenkins本身就支持该种模式,只需要将Jenkinsfile中的流水线定义改为:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                bat 'mvn -B -DskipTests clean package'
            }
        }

        stage('Archive') {
            steps {
                archiveArtifacts artifacts: 'target/*.jar',allowEmptyArchive: true,fingerprint: true,onlyIfSuccessful: true
            }
        }
    }
}

再次运行流水线,就可以查看和下载制品了:

pipeline中可以下载制品

该种方式比较原始,需要手动下载和管理制品,不太推荐。

1.2 将制品上传到私仓

大多数公司都是有自己的制品私仓的,比如使用Nexus搭建的Maven仓库,这种方式比较适合研发中间件项目,直接上传到私仓供别的依赖项目使用了。

方式一:通过maven

首先项目的pom文件中需要增加如下配置:


    
        
            org.apache.maven.plugins
            maven-deploy-plugin
            2.8.2
        
    



    
        nexus-snapshot
        my nexus snapshot
        http://10.x.x.x:8081/repository/maven-snapshots
    
    
        nexus-release
        my nexus release
        http://10.x.x.x:8081/repository/maven-releases
    

然后在需要使用的maven settings.xml中增加nexus私仓的账密信息:

  
    
        nexus-snapshot
        admin
        password
    
    
        nexus-release
        admin
        password
    
  

我们再修改pipeline的流程如下:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                bat 'mvn -B -DskipTests clean package'
            }
        }

        stage('Archive') {
            steps {
                bat 'mvn deploy'
            }
        }
    }
}

提交代码,运行流水线,Deploy插件会根据Maven项目中定义的version值决定是使用nexus-snapshot仓库还是nexus-release仓库。当version值是以-SNAPSHOT后缀结尾时,则发布到nexus-snapshot仓库。

如下是流水线输入日志的最后部分:

Uploaded to nexus-snapshot: http://10.x.x.x:8081/repository/maven-snapshots/com/example/java-cicd-test/0.0.2-SNAPSHOT/java-cicd-test-0.0.2-20221012.055840-1.jar (18 MB at 14 MB/s)
Uploading to nexus-snapshot: http://10.x.x.x:8081/repository/maven-snapshots/com/example/java-cicd-test/0.0.2-SNAPSHOT/java-cicd-test-0.0.2-20221012.055840-1.pom
Progress (1): 2.2 kB
                    
Uploaded to nexus-snapshot: http://10.x.x.x:8081/repository/maven-snapshots/com/example/java-cicd-test/0.0.2-SNAPSHOT/java-cicd-test-0.0.2-20221012.055840-1.pom (2.2 kB at 66 kB/s)
Downloading from nexus-snapshot: http://10.x.x.x:8081/repository/maven-snapshots/com/example/java-cicd-test/maven-metadata.xml
Uploading to nexus-snapshot: http://10.3.17.71:8081/repository/maven-snapshots/com/example/java-cicd-test/0.0.2-SNAPSHOT/maven-metadata.xml
Progress (1): 775 B
                   
Uploaded to nexus-snapshot: http://10.x.x.x:8081/repository/maven-snapshots/com/example/java-cicd-test/0.0.2-SNAPSHOT/maven-metadata.xml (775 B at 5.8 kB/s)
Uploading to nexus-snapshot: http://10.x.x.x:8081/repository/maven-snapshots/com/example/java-cicd-test/maven-metadata.xml
Progress (1): 285 B
                   
Uploaded to nexus-snapshot: http://10.x.x.x:8081/repository/maven-snapshots/com/example/java-cicd-test/maven-metadata.xml (285 B at 9.2 kB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  14.466 s
[INFO] Finished at: 2022-10-12T13:58:41+08:00
[INFO] ------------------------------------------------------------------------
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

然后搜索nexus上我们的项目名称,就能搜索到了:

nexus上搜索结果

方式二:通过Jenkins插件

首先需要在jenkins的插件市场上安装Nexus Platform,然后在Jenkins的系统设置中添加nexus服务的信息:

!jenkins配置nexus服务](https://upload-images.jianshu.io/upload_images/5673257-e14728f08afd0ab4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

然后需要我们编写流水线Archive阶段的脚本,这个有点复杂,我们借助Jenkins Pipeline流水线语法工具生成:

使用pipeline语法生成器1

使用pipeline语法生成器2

使用pipeline语法生成器3
  • 示例步骤:选择nexus publisher;
  • nexus instance:选择上一步配置好的nexus服务;
  • nexus repository:根据自己需要选择release库或者snapshots库;
  • tag:随意;
  • packages Group:填写你项目的GroupId;
  • packages Artifact:填写你项目的ArtifactId;
  • packages Version:填写你项目的Version;
  • packages packaging:选择打包方式,我们是jar;
  • packages Artifacts File Path:选择需要上传的制品内容;

其余保持默认不动。然后点击下面的“生成流水线脚本”按钮,即可得到该步骤的流水线脚本了,将其放到流水线文件中:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                bat 'mvn -B -DskipTests clean package'
            }
        }

        stage('Archive') {
            steps {
                nexusPublisher nexusInstanceId: 'my-nexus', nexusRepositoryId: 'maven-snapshots', packages: [[$class: 'MavenPackage', mavenAssetList: [[classifier: '', extension: '', filePath: './target/*.jar']], mavenCoordinate: [artifactId: 'java-cicd-test', groupId: 'com.example', packaging: 'jar', version: '0.0.3-SNAPSHOT']]]
            }
        }
    }
}

然后提交代码,触发流水线运行,就能看到执行成功,同样查看下日志,并在nexus上搜索下我们的制品,这里同上,就不再赘述了。

总结下,这两种方式,第二种的好处就是和nexus的配置,包括密码都保存在Jenkins的配置中了,Jenkins本身就有权限控制,比较安全;缺点就是pipeline的配置略显麻烦,不如maven的方式简单好用,个人比较推荐使用maven。

1.3 将制品上传到镜像仓库

首先我们自己新建一个镜像私仓,这个可以参考:Docker Registry的搭建与使用 - (jianshu.com)

然后,我们需要在项目根目录下新增一个Dockerfile:

FROM openjdk:8
EXPOSE 8080
ADD target/java-cicd-test-0.0.3-SNAPSHOT.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

方式一:在Pipeline中使用docker命令

我们修改pipeline的描述:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                bat 'mvn -B -DskipTests clean package'
            }
        }

        stage('Archive') {
            steps {
                bat 'docker build -t java-cicd-test:0.0.3-SNAPSHOT .'
                bat 'docker tag java-cicd-test:0.0.3-SNAPSHOT localhost:5000/java-cicd-test:0.0.3-SNAPSHOT'
                bat 'docker push localhost:5000/java-cicd-test:0.0.3-SNAPSHOT'
            }
        }
    }
}

提交代码运行流水线,就能将当前项目打成镜像并提交到私仓镜像仓库了。

C:\Users\zhangxun\.jenkins\workspace\java-cicd-test>docker push localhost:5000/java-cicd-test:0.0.3-SNAPSHOT 
The push refers to repository [localhost:5000/java-cicd-test]
cc71e4dd775f: Preparing
bff9fe6e429c: Preparing
7c245b2fe4f1: Preparing
f9e18e59a565: Preparing
26a504e63be4: Preparing
8bf42db0de72: Preparing
31892cc314cb: Preparing
11936051f93b: Preparing
8bf42db0de72: Waiting
31892cc314cb: Waiting
11936051f93b: Waiting
7c245b2fe4f1: Pushed
f9e18e59a565: Pushed
cc71e4dd775f: Pushed
8bf42db0de72: Pushed
31892cc314cb: Pushed
11936051f93b: Pushed
bff9fe6e429c: Pushed
26a504e63be4: Pushed
0.0.3-SNAPSHOT: digest: sha256:06fb42031d422fbfdac62918ccdf375537e145f607a01409198eaf9c7fba4c13 size: 2007
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

真实生产中,我们搭建的镜像仓库或者使用的公有云进行仓库,比如阿里云、腾讯云镜像仓库肯定是需要登录验证的,只需要加一行命令docker login --username=xxx --password=xxx即可,而且公有云镜像仓库还配有webhook,可用于让Jenkins监控到镜像推送是否成功,从而决定是否继续下一个部署操作,这块内容和上面讲解sonarqube比较类似,而且需要开通公有云服务,此处就不展开了。

方式二:使用maven的docker插件

由于我们项目使用的是Spring Boot2.7.3,自身就包含了对镜像制作的支持,因此无需下载和引入其它插件,而且也不需要项目根目录下的Dockefile。

首先,我们需要设置本地的Docker Engine,使之对外暴露端口,否则SpringBoot无法和Docker Engine进行交互:

本地DockerEngine暴露访问端口

然后,我们pom中增加如下配置:

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                    
                        
                        localhost:5000/${project.name}:${project.version}
                        
                        true
                    
                    
                        
                        http://localhost:2375
                        
                        false
                        
                        
                            
                            admin
                            
                            admin
                            
                            http://localhost:5000
                        
                    
                
            
        
    

然后执行构建命令mvn spring-boot:build-image或者双击IDEA中Maven面板中的SpringBoot:build-image,就可以尝试镜像的制作了。此处需要下载一些内容,时间较长,对github的访问也要畅通。如果能顺利完成的话,我们修改Pipeline中内容:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                bat 'mvn -B -DskipTests clean package'
            }
        }

        stage('Archive') {
            steps {
                bat 'mvn spring-boot:build-image'
            }
        }
    }
}

如此就可以通过简单的配置晚上将项目打包镜像推送到私仓中了。

总结下,这两种方式,个人比较偏向第一种,Dockerfile比较灵活,可以定制自己需要的内容,而且docker命令比较直观简单,方便修改。第二种方式试了几次,因为不能从github很流畅地下载内容,并没有真的实验成功,估计在真实环境中也会存在这个问题。

二、自动部署

自动部署则是在Jenkinsfile中增加一个stage,通过远程命令或者接口调用的方式将制品从私仓中拉取到目标服务器上进行部署。这块内容如果涉及远程服务器或者公有云,甚至是k8s集群会比较复杂,此处为简单演示起见,就在本机上演示下如何将上一步的镜像拉取下来进行部署。

修改Jenkinsfile如下:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                bat 'mvn -B -DskipTests clean package'
            }
        }

        stage('Archive') {
            steps {
                bat 'docker build -t java-cicd-test:0.0.4-SNAPSHOT .'
                bat 'docker tag java-cicd-test:0.0.4-SNAPSHOT localhost:5000/java-cicd-test:0.0.4-SNAPSHOT'
                bat 'docker push localhost:5000/java-cicd-test:0.0.4-SNAPSHOT'
            }
        }

        stage('Deploy') {
            steps {
                bat 'docker pull localhost:5000/java-cicd-test:0.0.4-SNAPSHOT'
                bat 'docker run -d -p 8080:8080 --name java-cicd-test localhost:5000/java-cicd-test:0.0.4-SNAPSHOT'
            }
        }
    }
}

然后提交代码运行流水线,流水线能正常运行成功,且发现新的0.0.4-SNAPSHOT镜像已经成功上传私仓镜像仓库。然后我们看下本地的Docker Desktop,发现镜像也从私仓中拉取下来并成功运行了。

私仓镜像上传成功
将制品镜像pull到目标服务器
使用制品镜像在目标服务器上运行

DevOps和CICD是一个永恒的话题,其中的思想、组件、工具都有很多种选择,没有说一定要如何如何,各家公司也需要按照自己实际情况制定合适的流水线模式。

你可能感兴趣的:(Jenkins+Gitlab搭建CICD流程进阶——制品管理和自动部署)