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 將制品上傳到私倉

大多數(shù)公司都是有自己的制品私倉的,比如使用Nexus搭建的Maven倉庫,這種方式比較適合研發(fā)中間件項目,直接上傳到私倉供別的依賴項目使用了。

方式一:通過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插件會根據(jù)Maven項目中定義的version值決定是使用nexus-snapshot倉庫還是nexus-release倉庫。當version值是以-SNAPSHOT后綴結(jié)尾時,則發(fā)布到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上搜索結(jié)果

方式二:通過Jenkins插件

首先需要在jenkins的插件市場上安裝Nexus Platform,然后在Jenkins的系統(tǒng)設(shè)置中添加nexus服務(wù)的信息:

!jenkins配置nexus服務(wù)](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服務(wù);
  • nexus repository:根據(jù)自己需要選擇release庫或者snapshots庫;
  • tag:隨意;
  • packages Group:填寫你項目的GroupId;
  • packages Artifact:填寫你項目的ArtifactId;
  • packages Version:填寫你項目的Version;
  • packages packaging:選擇打包方式,我們是jar;
  • packages Artifacts File Path:選擇需要上傳的制品內(nèi)容;

其余保持默認不動。然后點擊下面的“生成流水線腳本”按鈕,即可得到該步驟的流水線腳本了,將其放到流水線文件中:

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']]]
            }
        }
    }
}

然后提交代碼,觸發(fā)流水線運行,就能看到執(zhí)行成功,同樣查看下日志,并在nexus上搜索下我們的制品,這里同上,就不再贅述了。

總結(jié)下,這兩種方式,第二種的好處就是和nexus的配置,包括密碼都保存在Jenkins的配置中了,Jenkins本身就有權(quán)限控制,比較安全;缺點就是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

真實生產(chǎn)中,我們搭建的鏡像倉庫或者使用的公有云進行倉庫,比如阿里云、騰訊云鏡像倉庫肯定是需要登錄驗證的,只需要加一行命令docker login --username=xxx --password=xxx即可,而且公有云鏡像倉庫還配有webhook,可用于讓Jenkins監(jiān)控到鏡像推送是否成功,從而決定是否繼續(xù)下一個部署操作,這塊內(nèi)容和上面講解sonarqube比較類似,而且需要開通公有云服務(wù),此處就不展開了。

方式二:使用maven的docker插件

由于我們項目使用的是Spring Boot2.7.3,自身就包含了對鏡像制作的支持,因此無需下載和引入其它插件,而且也不需要項目根目錄下的Dockefile。

首先,我們需要設(shè)置本地的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>

然后執(zhí)行構(gòu)建命令mvn spring-boot:build-image或者雙擊IDEA中Maven面板中的SpringBoot:build-image,就可以嘗試鏡像的制作了。此處需要下載一些內(nèi)容,時間較長,對github的訪問也要暢通。如果能順利完成的話,我們修改Pipeline中內(nèi)容:

pipeline {
    agent any

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

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

如此就可以通過簡單的配置晚上將項目打包鏡像推送到私倉中了。

總結(jié)下,這兩種方式,個人比較偏向第一種,Dockerfile比較靈活,可以定制自己需要的內(nèi)容,而且docker命令比較直觀簡單,方便修改。第二種方式試了幾次,因為不能從github很流暢地下載內(nèi)容,并沒有真的實驗成功,估計在真實環(huán)境中也會存在這個問題。

二、自動部署

自動部署則是在Jenkinsfile中增加一個stage,通過遠程命令或者接口調(diào)用的方式將制品從私倉中拉取到目標服務(wù)器上進行部署。這塊內(nèi)容如果涉及遠程服務(wù)器或者公有云,甚至是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'
            }
        }
    }
}

然后提交代碼運行流水線,流水線能正常運行成功,且發(fā)現(xiàn)新的0.0.4-SNAPSHOT鏡像已經(jīng)成功上傳私倉鏡像倉庫。然后我們看下本地的Docker Desktop,發(fā)現(xiàn)鏡像也從私倉中拉取下來并成功運行了。

私倉鏡像上傳成功
將制品鏡像pull到目標服務(wù)器
使用制品鏡像在目標服務(wù)器上運行

DevOps和CICD是一個永恒的話題,其中的思想、組件、工具都有很多種選擇,沒有說一定要如何如何,各家公司也需要按照自己實際情況制定合適的流水線模式。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容