jjzjj

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

文景大大 2024-01-10 原文

一、制品的管理

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文件中需要增加如下配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>2.8.2</version>
        </plugin>
    </plugins>
</build>

<distributionManagement>
    <snapshotRepository>
        <id>nexus-snapshot</id>
        <name>my nexus snapshot</name>
        <url>http://10.x.x.x:8081/repository/maven-snapshots</url>
    </snapshotRepository>
    <repository>
        <id>nexus-release</id>
        <name>my nexus release</name>
        <url>http://10.x.x.x:8081/repository/maven-releases</url>
    </repository>
</distributionManagement>

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

  <servers>
    <server>
        <id>nexus-snapshot</id>
        <username>admin</username>
        <password>password</password>
    </server>
    <server>
        <id>nexus-release</id>
        <username>admin</username>
        <password>password</password>
    </server>
  </servers>

我们再修改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中增加如下配置:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                    <image>
                        <!--镜像名称-->
                        <name>localhost:5000/${project.name}:${project.version}</name>
                        <!--生成镜像后是否推送到镜像仓库-->
                        <publish>true</publish>
                    </image>
                    <docker>
                        <!--docker daemon地址,此处是本机的Docker Desktop暴露的地址-->
                        <host>http://localhost:2375</host>
                        <!--不使用TLS访问-->
                        <tlsVerify>false</tlsVerify>
                        <!--Docker推送镜像仓库配置-->
                        <publishRegistry>
                            <!--推送镜像仓库用户名-->
                            <username>admin</username>
                            <!--推送镜像仓库密码-->
                            <password>admin</password>
                            <!--推送镜像仓库地址-->
                            <url>http://localhost:5000</url>
                        </publishRegistry>
                    </docker>
                </configuration>
            </plugin>
        </plugins>
    </build>

然后执行构建命令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流程进阶——制品管理和自动部署的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  5. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  6. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  7. ruby-on-rails - Ruby on Rails 可以部署在 Azure 网站上吗? - 2

    我可以在Azure网站上部署RubyonRails吗? 最佳答案 还没有。目前仅支持.NET和PHP。 关于ruby-on-rails-RubyonRails可以部署在Azure网站上吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/12964010/

  8. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  9. ruby-on-rails - rbenv:从 RVM 移动到 rbenv 后,在 Jenkins 执行 shell 中找不到命令 - 2

    我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions

  10. jenkins部署1--jenkins+gitee持续集成 - 2

    前置步骤我们都操作完了,这篇开始介绍jenkins的集成。话不多说,看操作1、登录进入jenkins后会让你选择安装插件,选择第一个默认的就行。安装完成后设置账号密码,重新登录。2、配置JDK和Git都需要执行路径,所以需要先把执行路径找到,先进入服务器的docker容器,2.1JDK的路径root@69eef9ee86cf:/usr/bin#echo$JAVA_HOME/usr/local/openjdk-82.2Git的路径root@69eef9ee86cf:/#whichgit/usr/bin/git3、先配置JDK和Git。点击:ManageJenkins>>GlobalToolCon

随机推荐