国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd)

這篇具有很好參考價(jià)值的文章主要介紹了實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd)

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

目錄

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

推薦文章

https://www.yuque.com/xyy-onlyone/aevhhf?# 《玩轉(zhuǎn)Typora》

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

0、流程分析

2條Jenkins pipeline

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

CI pipeline

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

CD pipeline

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

標(biāo)準(zhǔn)規(guī)范

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

項(xiàng)目規(guī)范與總體設(shè)計(jì)

公司里面要使用流水線要做持續(xù)集成CI/CD的項(xiàng)目越來越多,這對(duì)流水線的設(shè)計(jì)和開發(fā)有不同的要求。我們經(jīng)常聽到用戶的反饋:

  • 各種不同語言的技術(shù)棧, 如何使流水線適配呢? 從不同技術(shù)棧維護(hù)一套流水線模版,到我們使用共享庫進(jìn)行統(tǒng)一的管理和維護(hù)。

  • 對(duì)于不同的項(xiàng)目,大家管理代碼的方式也不同??赡苓€有一部分用戶在使用Svn等不同的版本控制系統(tǒng)。

  • 不同的項(xiàng)目,開發(fā)模式也不太一樣, 編譯構(gòu)建工具不同,發(fā)布的方式也有不同的地方…

等等,不止上面的問題。所以在做流水線的使用應(yīng)該提前把項(xiàng)目團(tuán)隊(duì)的規(guī)范定義好, 這樣后期項(xiàng)目改造后可以直接集成CI/CD流水線。更加便捷。

1.團(tuán)隊(duì)信息

信息項(xiàng) 描述
業(yè)務(wù)簡(jiǎn)稱/編號(hào) devops4
開發(fā)模式 特性分支開發(fā),版本分支發(fā)布,主干分支作為最新代碼
項(xiàng)目類型與構(gòu)建方式 前端: vue項(xiàng)目, npm打包, 制品目錄 dist
后端:springboot項(xiàng)目, maven打包, 制品目錄 target
發(fā)布主機(jī)環(huán)境(vm) LB: 192.168.1.200
Server: 192.168.1.121~192.168.1.122

2.CI/CD規(guī)范

通過上面的信息,我們采用如下規(guī)范:

工具鏈
GitLab 代碼庫 倉庫組: devops4
項(xiàng)目倉庫后端 devops4-ops-service 前端 devops4-ops-ui
Jenkins作業(yè) 文件夾: devops4
作業(yè)命名: 后端 devops4-ops-service 前端 devops4-ops-ui
CI構(gòu)建規(guī)范 前端項(xiàng)目采用npm打包后統(tǒng)一放到dist目錄下, 靜態(tài)文件以tgz打包。
后端項(xiàng)目采用maven打包后統(tǒng)一放到target目錄下,以jar包。
Sonar代碼報(bào)告 前端項(xiàng)目:devops4-ops-ui 后端項(xiàng)目:devops4-ops-service
項(xiàng)目團(tuán)隊(duì)可以使用devops4命名的自定義質(zhì)量規(guī)則和質(zhì)量閾。
Nexus制品庫目錄
devops4-ops-service/version/devops4-ops-service-version.jar
devops4-ops-ui/version/devops4-ops-ui-version.tar.gz
devops4 版本: 分割release分支獲取版本號(hào)
發(fā)布規(guī)范 用戶輸入版本,下載制品庫,使用腳本啟動(dòng)服務(wù)。

標(biāo)準(zhǔn)化

版本分支命名:RELEASE-1.1.1

分支策略

特性分支開發(fā),版本分支發(fā)布。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

環(huán)境管理

使用virtualbox創(chuàng)建2臺(tái)虛擬機(jī), 或者采用terraform操作云平臺(tái)創(chuàng)建2臺(tái)虛機(jī)。

本次,自己使用2臺(tái)本地vmwareworkstation虛機(jī)測(cè)試。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

制品管理

制品版本命名:版本號(hào)-CommitID

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

發(fā)布流水線

Jenkins pipeline * 2

  • CI pipeline

  • CD pipeline

    • 復(fù)選框參數(shù): 發(fā)布主機(jī)
    • 字符參數(shù):版本分支
    • 選項(xiàng)參數(shù):目標(biāo)環(huán)境 【dev/uat/stg/prod】

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

應(yīng)用發(fā)布與回滾策略

Deploy發(fā)布策略

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

藍(lán)綠發(fā)布

環(huán)境存在兩個(gè)版本,藍(lán)版本和綠版本同時(shí)存在,部署新版本然后進(jìn)行測(cè)試,將流量切到新版本,最終實(shí)際運(yùn)行的只有一個(gè)版本(藍(lán)/綠)。好處是無需停機(jī),并且發(fā)布風(fēng)險(xiǎn)較小。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

nginx upstream模塊實(shí)現(xiàn):

upstream webservers {
    server 192.168.1.253:8099 weight=100;
    server 192.168.1.252:8099 down;
}

server {
      listen       8017; 
      location / {
        proxy_pass http://webservers;
      }
}

nginx -s reload
灰度發(fā)布

將發(fā)行版發(fā)布到一部分用戶或服務(wù)器的一種模式。這個(gè)想法是首先將更改部署到一小部分服務(wù)器,進(jìn)行測(cè)試,然后將更改推廣到其余服務(wù)器。一旦通過所有運(yùn)行狀況檢查,當(dāng)沒有問題時(shí),所有的客戶將被路由到該應(yīng)用程序的新版本,而舊版本將被刪除。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

nginx 權(quán)重模擬:

upstream webservers {
    server 192.168.1.223:8099 weight=100;
    server 192.168.1.222:8099 weight=100;
    server 192.168.1.221:8099 weight=100;
}

server {
      listen       8017; 
      location / {
        proxy_pass http://webservers;
      }
}

nginx -s reload
版本回滾
  • 版本一直升級(jí),則無需回滾。
  • 選擇舊版本文件,進(jìn)行發(fā)布。

前端后端項(xiàng)目發(fā)布

1、前端項(xiàng)目

復(fù)制靜態(tài)文件到nginx站點(diǎn)目錄,nginx -s reload

## 進(jìn)入Web服務(wù)器的站點(diǎn)目錄下

## 下載包
[root@master html]# curl -u admin:admin123 http://192.168.1.200:8081/repository/anyops/com/anyops/anyops-devops-ui/1.1.1/anyops-devops-ui-1.1.1.tar.gz  -o anyops-devops-ui-1.1.1.tar.gz 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  196k  100  196k    0     0  24.0M      0 --:--:-- --:--:-- --:--:-- 24.0M

## 解壓包
[root@master html]# tar zxf anyops-devops-ui-1.1.1.tar.gz 
[root@master html]# ls
anyops-devops-ui-1.1.1.tar.gz  index.html  static

## 觸發(fā)nginx重載
[root@master html]# nginx -s reload

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

2、后端項(xiàng)目

  • 復(fù)制jar包到目標(biāo)目錄, 使用nohup java -jar 啟動(dòng)服務(wù)。
  • nohup java -jar app.jar >output 2>&1 &

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

1、CI

拷貝Jenkins流水線

  • 拷貝Jenkins作業(yè)devops6-maven-servicedevops6-maven-service_CI

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

保存后,點(diǎn)擊參數(shù)化構(gòu)建,會(huì)發(fā)現(xiàn)branchName的頁面參數(shù)為空,我們先直接運(yùn)行一次流水線看看效果:

運(yùn)行一次流水線后,再次運(yùn)行時(shí),就會(huì)看到branchName正常了。

接下來我們就用devops6-maven-service_CI來測(cè)試。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 我們?cè)俅芜\(yùn)行下,看下效果

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

可以看到,流水線運(yùn)行成功。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

可以看到nexus倉庫里制品被上傳成功了。

優(yōu)化pipeline代碼,去除制品庫里CI字樣

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

                    appName = "${JOB_NAME}".split('_')[0] //devops6-maven-service_CI
                    repoName = appName.split('-')[0]   //devops6
                    appVersion = "${env.branchName}".split("-")[-1] // RELEASE-1.1.1   1.1.1
                    targetDir="${appName}/${appVersion}"

再次運(yùn)行測(cè)試效果:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

符合預(yù)期。

新建Jenkins CD流水線

  • 創(chuàng)建一個(gè)devops6-maven-service_CD作業(yè),然后添加一些頁面參數(shù)

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

點(diǎn)擊參數(shù)化構(gòu)建:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

創(chuàng)建一個(gè)devops6的視圖

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

優(yōu)化pipeline代碼,nexus倉庫的版本里要帶上commitID

  • 之前倉庫是這樣的

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 先來手動(dòng)獲取下項(xiàng)目倉庫的commitID

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

[root@Devops6 ~]#cd /opt/jenkinsagent/workspace/
[root@Devops6 workspace]#ls
day2-pipeline-demo      devops6-gradle-service      devops6-maven-service     devops6-maven-service_CI@tmp  devops6-maven-test      devops6-npm-service      test-maven    
day2-pipeline-demo@tmp  devops6-gradle-service@tmp  devops6-maven-service_CI  devops6-maven-service@tmp     devops6-maven-test@tmp  devops6-npm-service@tmp  test-maven@tmp
[root@Devops6 workspace]#cd devops6-maven-service_CI
[root@Devops6 devops6-maven-service_CI]#ls
mvnw  mvnw.cmd  pom.xml  sonar-project.properties  src  target
[root@Devops6 devops6-maven-service_CI]#git rev-parse HEAD #通過這個(gè)命令之可以獲取倉庫comitID的。
b5cfb8eeee597edd752cb11f5daa9ac843fb9f97
[root@Devops6 devops6-maven-service_CI]#

然后利用片段生成器生成代碼:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

sh returnStdout: true, script: 'git rev-parse HEAD'

然后集成到piepeline代碼里。

  • 我們想讓這里的版本號(hào)也帶上commitID

這里直接寫代碼:

appVersion = "${appVersion}-${env.commitID}"

//獲取commitID
env.commitID = gitlab.GetCommitID()
println("commitID: ${env.commitID}")


package org.devops

//獲取CommitID
def GetCommitID(){
    ID = sh returnStdout: true, script:"git rev-parse HEAD"
    ID = ID -"\n"
    return ID[0..7] //取前8位id
}

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 在gitlab的devops6-maven-service里以main分支創(chuàng)建RELEASE-9.9.9分支

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 運(yùn)行devops6-maven-service_CI流水線

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

測(cè)試成功。

2、CD

下載制品

cd部分就不用再下載代碼獲取commitID了。

我們來使用gitlab api獲取分支commit。

Step1: 獲取GitLab 分支CommitID

  • 打開gitlab api官方文檔

https://docs.gitlab.com/

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/branches/main"
  • 在postman里調(diào)試

先拿取下一些參數(shù):

這里拿到Project ID

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

然后在gitlab上創(chuàng)建一個(gè)token:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

TLDgj3sz-cioyk6AfxZi

調(diào)試:

http://172.29.9.101:8076/api/v4/projects/7/repository/branches/RELEASE-9.9.9

添加get請(qǐng)求,添加PRIVARE-TOKEN,點(diǎn)擊Send。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

此時(shí),我們就通過gitalb api拿到了分支commitID了,和之前手動(dòng)執(zhí)行g(shù)it命令獲取的commitID信息一致。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 此時(shí)拿到postman給出的cURL命令

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

curl --location 'http://172.29.9.101:8076/api/v4/projects/7/repository/branches/RELEASE-9.9.9' \
--header 'PRIVATE-TOKEN: TLDgj3sz-cioyk6AfxZi'
  • 優(yōu)化pipeline代碼

創(chuàng)建Gitlab.groovy文件

package org.devops

//發(fā)起HTTP請(qǐng)求
def HttpReq(method, apiUrl){
    response = sh  returnStdout: true, 
        script: """ 
        curl --location --request ${method} \
        http:172.29.9.101:8076/api/v4/${apiUrl} \
        --header "PRIVATE-TOKEN: TLDgj3sz-cioyk6AfxZi"
    """
    response = readJSON text: response - "\n" //json數(shù)據(jù)的讀取方式
    return response
}

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

但是,這里的gitlab token是明文的,因此需要在jenkins里配置個(gè)憑據(jù)。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

然后利用片段生成器來利用次token,生成代碼:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d', variable: 'gitlabtoken')]) {
    // some block
}
  • 優(yōu)化pipeline代碼
package org.devops

//發(fā)起HTTP請(qǐng)求
def HttpReq(method, apiUrl){

    withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d', variable: 'gitlabtoken')]) {
        response = sh  returnStdout: true, 
        script: """ 
        curl --location --request ${method} \
        http:172.29.9.101:8076/api/v4/${apiUrl} \
        --header "PRIVATE-TOKEN: ${gitlabtoken}"
        """
    }
    response = readJSON text: response - "\n" //json數(shù)據(jù)的讀取方式
    return response
}

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

但是,存在一個(gè)問題,apiUrl里我們還需要知道ProjectID才行,這里繼續(xù)查找gitlab api。

  • 獲取ProjectID

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

http://172.29.9.101:8076/api/v4/projects?search=devops6-maven-service

curl --location 'http://172.29.9.101:8076/api/v4/projects?search=devops6-maven-service' \
--header 'PRIVATE-TOKEN: TLDgj3sz-cioyk6AfxZi'

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 繼續(xù)優(yōu)化pipeline代碼
package org.devops

//發(fā)起HTTP請(qǐng)求
def HttpReq(method, apiUrl){

    withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d', variable: 'gitlabtoken')]) {
        response = sh  returnStdout: true, 
        script: """ 
        curl --location --request ${method} \
        http:172.29.9.101:8076/api/v4/${apiUrl} \
        --header "PRIVATE-TOKEN: ${gitlabtoken}"
        """
    }
    response = readJSON text: response - "\n" //json數(shù)據(jù)的讀取方式
    return response
}

//獲取ProjectID
def GetProjectIDByName(projectName, groupName){
    apiUrl = "projects?search=${projectName}"
    response = HttpReq("GET", apiUrl)
    if (response != []){
        for (p in response) {
            if (p["namespace"]["name"] == groupName){
                return response[0]["id"]
            }
        }
    }
}

//獲取分支CommitID
def GetBranchCommitID(projectID, branchName){
    apiUrl = "projects/${projectID}/repository/branches/${branchName}"
    response = HttpReq("GET", apiUrl)
    return response.commit.short_id
}
  • 創(chuàng)建cd.jenkinsfile

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

@Library("devops06@main") _ 

//import  src/org/devops/Gitlab.groovy
def mygit = new org.devops.Gitlab()


//pipeline
pipeline{
    agent { label "build"}
    options {
        skipDefaultCheckout true
    }
    stages{
        stage("GetArtifact"){
            steps{
                script{
                    env.projectName = "${JOB_NAME}".split('_')[0] //devops6-maven-service
                    env.groupName = "${env.projectName}".split('-')[0]  //devops6
                    
                    projectID = mygit.GetProjectIDByName(env.projectName, env.groupName)
                    commitID = mygit.GetBranchCommitID("${projectID}", "${env.branchName}")
                    println(commitID)

                    // appVersion = "${env.branchName}".split("-")[-1]  //9.9.9
                    // println(appVersion)
                    // currentBuild.description = "Version: ${appVersion}-${commitID}"

                    currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${commitID}"
                    currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"
                
                }
            }
        }

    }
}

Gitlab.groovy代碼

package org.devops

//發(fā)起HTTP請(qǐng)求
def HttpReq(method, apiUrl){

    withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d', variable: 'gitlabtoken')]) {
        response = sh  returnStdout: true, 
        script: """ 
        curl --location --request ${method} \
        http://172.29.9.101:8076/api/v4/${apiUrl} \
        --header "PRIVATE-TOKEN: ${gitlabtoken}"
        """
    }
    response = readJSON text: response - "\n" //json數(shù)據(jù)的讀取方式
    return response
}

//獲取ProjectID
def GetProjectIDByName(projectName, groupName){
    apiUrl = "projects?search=${projectName}"
    response = HttpReq("GET", apiUrl)
    if (response != []){
        for (p in response) {
            if (p["namespace"]["name"] == groupName){
                return response[0]["id"]
            }
        }
    }
}

//獲取分支CommitID
def GetBranchCommitID(projectID, branchName){
    apiUrl = "projects/${projectID}/repository/branches/${branchName}"
    response = HttpReq("GET", apiUrl)
    return response.commit.short_id
}
  • 編輯devops6-maven-service_CD流水線使用共享庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

運(yùn)行流水線:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

測(cè)試成功。??

Step2: 下載制品

  • nexus倉庫制品地址如下
http://172.29.9.101:8081/repository/devops6/devops6-maven-service/6.1.1/devops6-maven-service-6.1.1.jar
  • 這里編寫pipeline代碼
@Library("devops06@main") _ 

//import  src/org/devops/Gitlab.groovy
def mygit = new org.devops.Gitlab()


//pipeline
pipeline{
    agent { label "build"}
    options {
        skipDefaultCheckout true
    }
    stages{
        stage("GetArtifact"){
            steps{
                script{
                    env.projectName = "${JOB_NAME}".split('_')[0] //devops6-maven-service
                    env.groupName = "${env.projectName}".split('-')[0]  //devops6
                    
                    projectID = mygit.GetProjectIDByName(env.projectName, env.groupName)
                    commitID = mygit.GetBranchCommitID("${projectID}", "${env.branchName}")
                    println(commitID)

                    appVersion = "${env.branchName}".split("-")[-1]  //9.9.9
                    println(appVersion)
                    // currentBuild.description = "Version: ${appVersion}-${commitID}"

                    currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${commitID}"
                    currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"


                    //下載制品
                    //http://172.29.9.101:8081/repository/devops6/devops6-maven-service/6.1.1-b5cfb8ee/devops6-maven-service-6.1.1-b5cfb8ee.jar
                    repoUrl = "http://172.29.9.101:8081/repository/${env.groupName}"
                    artifactName = "${env.projectName}-${appVersion}-${commitID}.jar"
                    artifactUrl = "${repoUrl}/${env.projectName}/${appVersion}-${commitID}/${artifactName}"
                    sh "wget --no-verbose ${artifactUrl} && ls -l"
                
                }
            }
        }

    }
}

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 運(yùn)行觀察效果

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

下載制品成功。

我們?cè)龠\(yùn)行一次流水線:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

會(huì)看到多了一個(gè)包,

最后我們發(fā)布完,會(huì)把它清掉的:

這里先手動(dòng)給清掉。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

Step3: 發(fā)布

準(zhǔn)備2臺(tái)linux機(jī)器
devops-deploy1-172.29.9.110
devops-deploy2-172.29.9.111
  • 給這2臺(tái)機(jī)器裝好java-11
yum install -y java-11-openjdk.x86_64
devops機(jī)器安裝ansible環(huán)境
yum install epel-release  -y
yum install ansible -y
  • 編輯下ansible的主機(jī)管理文件:
[root@Devops6 ~]#vim /etc/ansible/hosts
172.29.9.110
172.29.9.111
  • 給ansible機(jī)器到2個(gè)節(jié)點(diǎn)做個(gè)免密
ssh-keygen
ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.29.9.110
ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.29.9.111
  • 查看當(dāng)前主機(jī)是否在線:
[root@Devops6 ~]#ansible all  -m ping -u root

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

構(gòu)建一次devops6-maven-service_CD,下載制品

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

我們先來手動(dòng)發(fā)布一次,再集成到CD流水線里
  • 拷貝制品到deploy1
[root@Devops6 devops6-maven-service_CD]#ansible 172.29.9.110 -m copy -a "src=devops6-maven-service-9.9.9-b5cfb8ee.jar  dest=/opt/devops6-maven-service-9.9.9-b5cfb8ee.jar"

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 啟動(dòng)服務(wù):

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 用準(zhǔn)備好的服務(wù)啟動(dòng)腳本來啟動(dòng)/停止java服務(wù)

服務(wù)啟動(dòng)腳本:service.sh (原始腳本如下)

#!/bin/bash

# sh service.sh anyops-devops-service 1.1.1 8091 start
APPNAME=NULL
VERSION=NULL
PORT=NULL

start(){
    port_result=`netstat -anlpt | grep "${PORT}" || echo false`

    if [[ $port_result == "false" ]];then
        nohup java -jar -Dserver.port=${PORT}  ${APPNAME}-${VERSION}.jar >${APPNAME}.log.txt 2>&1 &
    else
       stop
       sleep 5
       nohup java -jar -Dserver.port=${PORT}  ${APPNAME}-${VERSION}.jar >${APPNAME}.log.txt 2>&1 &
    fi
}


stop(){
    pid=`netstat -anlpt | grep "${PORT}" | awk '{print $NF}' | awk -F '/' '{print $1}' | head -1`
    kill -15 $pid
}


check(){
    proc_result=`ps aux | grep java | grep "${APPNAME}" | grep -v grep || echo false`
    port_result=`netstat -anlpt | grep "${PORT}" || echo false`
    url_result=`curl -s http://localhost:${PORT} || echo false `

    if [[ $proc_result == "false" || $port_result == "false" || $url_result == "false" ]];then
        echo "server not running"
    else
        echo "ok"
    fi
}

case $1 in
    start)
        start
        sleep 5
        check
        ;;

    stop)
        stop
        sleep 5
        check
        ;;
    restart)
        stop
        sleep 5
        start
        sleep 5
        check
        ;;
    check)
        check
        ;;
    *)
        echo "sh service.sh {start|stop|restart|check}"
        ;;
esac

參數(shù)寫入后腳本如下

#!/bin/bash

# sh service.sh anyops-devops-service 1.1.1 8091 start
APPNAME=devops6-maven-service
VERSION=9.9.9-b5cfb8ee
PORT=8080

start(){
    port_result=`netstat -anlpt | grep "${PORT}" || echo false`

    if [[ $port_result == "false" ]];then
        nohup java -jar -Dserver.port=${PORT}  ${APPNAME}-${VERSION}.jar >${APPNAME}.log.txt 2>&1 &
    else
       stop
       sleep 5
       nohup java -jar -Dserver.port=${PORT}  ${APPNAME}-${VERSION}.jar >${APPNAME}.log.txt 2>&1 &
    fi
}


stop(){
    pid=`netstat -anlpt | grep "${PORT}" | awk '{print $NF}' | awk -F '/' '{print $1}' | head -1`
    kill -15 $pid
}


check(){
    proc_result=`ps aux | grep java | grep "${APPNAME}" | grep -v grep || echo false`
    port_result=`netstat -anlpt | grep "${PORT}" || echo false`
    url_result=`curl -s http://localhost:${PORT} || echo false `

    if [[ $proc_result == "false" || $port_result == "false" || $url_result == "false" ]];then
        echo "server not running"
    else
        echo "ok"
    fi
}

case $1 in
    start)
        start
        sleep 5
        check
        ;;

    stop)
        stop
        sleep 5
        check
        ;;
    restart)
        stop
        sleep 5
        start
        sleep 5
        check
        ;;
    check)
        check
        ;;
    *)
        echo "sh service.sh {start|stop|restart|check}"
        ;;
esac
  • service.sh腳本拷貝到測(cè)試節(jié)點(diǎn):
[root@Devops6 devops6-maven-service_CD]#ansible 172.29.9.110 -m copy -a "src=service.sh  dest=/opt/service.sh"
172.29.9.110 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "666b4746afbb9fa684f79a89102715906417c848", 
    "dest": "/opt/service.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "22868400cb2784f7c7bcf63f38a977fe", 
    "mode": "0644", 
    "owner": "root", 
    "size": 1367, 
    "src": "/root/.ansible/tmp/ansible-tmp-1688219597.85-41901-255991227715874/source", 
    "state": "file", 
    "uid": 0
}

然后啟動(dòng)程序:

給予腳本執(zhí)行權(quán)限:

[root@devops-deploy1 opt]#ll
total 17284
-rw-r--r-- 1 root root 17690913 Jul  1 20:12 devops6-maven-service-9.9.9-b5cfb8ee.jar
-rw-r--r-- 1 root root     1367 Jul  1 21:53 service.sh
[root@devops-deploy1 opt]#chmod +x service.sh 

啟動(dòng)程序:

[root@devops-deploy1 opt]#sh service.sh start
ok
[root@devops-deploy1 opt]#ps -aux|grep java
root       7626 37.4  8.7 3202716 163300 pts/0  Sl   21:55   0:04 java -jar -Dserver.port=8080 devops6-maven-service-9.9.9-b5cfb8ee.jar
root       7674  0.0  0.0 112708   972 pts/0    R+   21:55   0:00 grep --color=auto java
[root@devops-deploy1 opt]#

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

開始集成
  • 最終代碼如下

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

Deploy.groovy文件

package org.devops

//rollback
def AnsibleRollBack(){

    sh """
        # 停止服務(wù)
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh stop" -u root
        
        sleep 300
        # 清理和創(chuàng)建發(fā)布目錄
        ansible "${env.deployHosts}" -m shell -a "rm -fr ${env.targetDir}/${env.projectName}/* &&  mkdir -p ${env.targetDir}/${env.projectName} || echo file is exists" 
        
        # 將備份目錄內(nèi)容復(fù)制到發(fā)布目錄
        ansible "${env.deployHosts}" -m shell -a " mv ${env.targetDir}/${env.projectName}.bak/* ${env.targetDir}/${env.projectName}/ || echo file not exists"

        # 啟動(dòng)服務(wù)
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh  start" -u root

        # 檢查服務(wù) 
        sleep 10
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh check" -u root

        """
}


//發(fā)布制品
def AnsibleDeploy(){
    //將主機(jī)寫入清單文件
    sh "rm -fr hosts "
    for (host in "${env.deployHosts}".split(',')){
        sh " echo ${host} >> hosts"
    }


    // ansible 發(fā)布jar
    sh """
        # 主機(jī)連通性檢測(cè)
        ansible "${env.deployHosts}" -m ping -i hosts 
        
        # 創(chuàng)建備份目錄
        ansible "${env.deployHosts}" -m shell -a "mkdir -p ${env.targetDir}/${env.projectName}.bak || echo file is exists" 
        # 備份上次構(gòu)建
        ansible "${env.deployHosts}" -m shell -a " mv ${env.targetDir}/${env.projectName}/* ${env.targetDir}/${env.projectName}.bak/ || echo file not exists"

        # 清理和創(chuàng)建發(fā)布目錄
        ansible "${env.deployHosts}" -m shell -a "rm -fr ${env.targetDir}/${env.projectName}/* &&  mkdir -p ${env.targetDir}/${env.projectName} || echo file is exists" 
        # 復(fù)制app
        ansible "${env.deployHosts}" -m copy -a "src=${env.artifactName}  dest=${env.targetDir}/${env.projectName}/${env.artifactName}" 
    """
    
    // 發(fā)布腳本
    fileData = libraryResource 'scripts/service.sh'
    println(fileData)
    writeFile file: 'service.sh', text: fileData
    sh "ls -a ; cat service.sh "


    sh """
        # 修改變量
        sed -i 's#APPNAME=NULL#APPNAME=${env.projectName}#g' service.sh
        sed -i 's#VERSION=NULL#VERSION=${env.releaseVersion}#g' service.sh
        sed -i 's#PORT=NULL#PORT=${env.port}#g' service.sh

        # 復(fù)制腳本
        ansible "${env.deployHosts}" -m copy -a "src=service.sh  dest=${env.targetDir}/${env.projectName}/service.sh" 
        # 啟動(dòng)服務(wù)
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile && sh service.sh start" -u root

        # 檢查服務(wù) 
        sleep 10
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile && sh service.sh  check" -u root
    """
}

cd.jenkinsfile文件

@Library("devops06@main") _ 

//import  src/org/devops/Gitlab.groovy
def mygit = new org.devops.Gitlab()
def mydeploy = new org.devops.Deploy()


//pipeline
pipeline{
    agent { label "build"}
    options {
        skipDefaultCheckout true
    }
    stages{
        stage("GetArtifact"){
            steps{
                script{
                    env.projectName = "${JOB_NAME}".split('_')[0] //devops6-maven-service
                    env.groupName = "${env.projectName}".split('-')[0]  //devops6
                    
                    projectID = mygit.GetProjectIDByName(env.projectName, env.groupName)
                    commitID = mygit.GetBranchCommitID("${projectID}", "${env.branchName}")
                    println(commitID)

                    appVersion = "${env.branchName}".split("-")[-1]  //9.9.9
                    println(appVersion)
                    // currentBuild.description = "Version: ${appVersion}-${commitID}"

                    currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${commitID}"
                    currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"


                    //下載制品
                    //http://172.29.9.101:8081/repository/devops6/devops6-maven-service/6.1.1-b5cfb8ee/devops6-maven-service-6.1.1-b5cfb8ee.jar
                    repoUrl = "http://172.29.9.101:8081/repository/${env.groupName}"
                    env.artifactName = "${env.projectName}-${appVersion}-${commitID}.jar"
                    artifactUrl = "${repoUrl}/${env.projectName}/${appVersion}-${commitID}/${env.artifactName}"
                    sh "wget --no-verbose ${artifactUrl} && ls -l"

                    env.releaseVersion = "${appVersion}-${commitID}"
                
                }
            }
        }

        stage("Deploy"){
            steps{
                script{                    
                    mydeploy.AnsibleDeploy()
                }
            }
        }

        stage("RollBack"){
            input {
                message "是否進(jìn)行回滾?"
                ok "Yes"
                submitter ""
                parameters {
                    choice choices: ['NO','YES'], name: 'OPS'
                }
            }
            steps {
                echo "OPS  ${OPS}, doing......."

                script{
                    if ("${OPS}" == "YES"){
                        mydeploy.AnsibleRollBack()
                    }
                }
                
            }
        }        

        

    }


}
  • 測(cè)試效果

執(zhí)行CD流水線:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

運(yùn)行成功:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

再看下2個(gè)節(jié)點(diǎn)的java運(yùn)行情況:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

符合預(yù)期。

給gitlab上devops6-maven-service項(xiàng)目配置個(gè)健康檢查端口
  • 默認(rèn)這個(gè)生成的jar包啟動(dòng)后,是沒配置健康檢查端口的,我們的測(cè)試現(xiàn)象不明確

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

我們來啟動(dòng)下服務(wù):

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 因此我們來改下這個(gè)java代碼:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

BasicController.java

/*
 * Copyright 2013-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
 */
@Controller
public class BasicController {

    // http://127.0.0.1:8080/hello?name=lisi
    @RequestMapping("/hello")
    @ResponseBody
    public String hello(@RequestParam(name = "name", defaultValue = "xyy") String name) {
        return "Hello RELEASE-10.1.0 " + name;
    }
}

然后打包,運(yùn)行,觀察效果:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 最后,將devops6-maven-serviceRELEASE-9.9.9/代碼合并到main分支。

  • 打上tag

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

Step4: 回滾

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

推薦第一種。

第二種方法會(huì)存在很多邏輯問題的。

  • 回滾代碼見上述文件,這里測(cè)試下效果

1、直接發(fā)布版本方式來回滾

先運(yùn)行CI流水線

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

CI pipeline運(yùn)行成功:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

再運(yùn)行CD:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

觀察效果:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

可以看到發(fā)布老版本程序成功。

2、使用回滾代碼

注意:如果要回滾時(shí),就需要跳過發(fā)布階段,否則會(huì)有問題的,因此這里我給發(fā)布階段加了一個(gè)判斷選項(xiàng)。

發(fā)布1.1.1

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

發(fā)布9.9.9

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

回滾到1.1.1:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

符合預(yù)期。??

擴(kuò)展:參數(shù)動(dòng)態(tài)獲取實(shí)踐

  • 需要安裝active choices插件重啟Jenkins服務(wù)器后再操作。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

根據(jù)不同的環(huán)境帶出不同的機(jī)器
  • 效果

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • envName參數(shù)設(shè)置

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

return ["dev", "uat", "stag", "prod"]
  • deployHosts參數(shù)設(shè)置

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

if (envName.equals("dev")){
	return ["172.29.9.110,172.29.9.111"]
} else if (envName.equals("uat")){
	return ["172.29.9.120,172.29.9.121"]
}

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

?? 注意:記得刪除前面定義好的envName和deployHosts選項(xiàng)參數(shù)。

  • 運(yùn)行測(cè)試

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

符合預(yù)期。??

根據(jù)不同發(fā)布工具,動(dòng)態(tài)展示主機(jī)參數(shù)

這個(gè)就不做演示了,和上面這個(gè)實(shí)踐有沖突。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 定義發(fā)布工具參數(shù)

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

return ["ansible", "saltstack"]

單選類型

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 定義發(fā)布主機(jī)

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

選擇關(guān)聯(lián)的參數(shù),多個(gè)參數(shù)用逗號(hào)分割

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

3、代碼匯總

  • 本次實(shí)驗(yàn)代碼

鏈接:https://pan.baidu.com/s/1mn1EX2oX0XRGO-IjohkyLA?pwd=0820
提取碼:0820

2023.7.2-云主機(jī)模式持續(xù)部署-ci-cd-code

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 實(shí)驗(yàn)環(huán)境
gitlab-ce:15.0.3-ce.0
jenkins:2.346.3-2-lts-jdk11
sonarqube:9.9.0-community
nexus3:3.53.0

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • ci-cd流水線

這2條流水線都是測(cè)試ok的。(以后就一直用這2條流水線來測(cè)試devops了)

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • 倉庫代碼

gitlab倉庫devops6-maven-service:RELEASE-9.9.9和main分支都是一樣的代碼。

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

jenkins共享庫代碼:

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • jenkins共享庫代碼匯總

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

service.sh

#!/bin/bash

# sh service.sh anyops-devops-service 1.1.1 8091 start
APPNAME=NULL
VERSION=NULL
PORT=NULL

start(){
    port_result=`netstat -anlpt | grep "${PORT}" || echo false`

    if [[ $port_result == "false" ]];then
        nohup java -jar -Dserver.port=${PORT}  ${APPNAME}-${VERSION}.jar >${APPNAME}.log.txt 2>&1 &
    else
       stop
       sleep 5
       nohup java -jar -Dserver.port=${PORT}  ${APPNAME}-${VERSION}.jar >${APPNAME}.log.txt 2>&1 &
    fi
}


stop(){
    pid=`netstat -anlpt | grep "${PORT}" | awk '{print $NF}' | awk -F '/' '{print $1}' | head -1`
    kill -15 $pid
}


check(){
    proc_result=`ps aux | grep java | grep "${APPNAME}" | grep -v grep || echo false`
    port_result=`netstat -anlpt | grep "${PORT}" || echo false`
    url_result=`curl -s http://localhost:${PORT} || echo false `

    if [[ $proc_result == "false" || $port_result == "false" || $url_result == "false" ]];then
        echo "server not running"
    else
        echo "ok"
    fi
}

case $1 in
    start)
        start
        sleep 5
        check
        ;;

    stop)
        stop
        sleep 5
        check
        ;;
    restart)
        stop
        sleep 5
        start
        sleep 5
        check
        ;;
    check)
        check
        ;;
    *)
        echo "sh service.sh {start|stop|restart|check}"
        ;;
esac

Jenkinsfile

@Library("devops06@main") _

//import src/org/devops/xxx.groovy
def checkout = new org.devops.CheckOut()
def build = new org.devops.Build()
def sonar = new org.devops.Sonar()
def artifact = new org.devops.Artifact()
//def gitlab = new org.devops.GitLab()


//使用git 參數(shù)需要格式化
env.branchName = "${env.branchName}" - "origin/"
println(env.branchName)

pipeline {
    agent {label "build"}

    //跳過默認(rèn)的代碼檢出功能
    options {
        skipDefaultCheckout true
    }    
    

    stages{
        stage("CheckOut"){
            steps{
                script{
                    checkout.CheckOut()
                    
                    //獲取commitID
                    env.commitID = checkout.GetCommitID()
                    println("commitID: ${env.commitID}")

                    // Jenkins構(gòu)建顯示信息
                    currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${env.commitID}"
                    currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"
                    //currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
                }
            }
        }

        stage("Build"){
            steps{
                script{
                    build.Build()
                }
            }

        }        

        stage("CodeScan"){
            // 是否跳過代碼掃描?
            when {
                environment name: 'skipSonar', value: 'false'
            }
            
            steps{
                script{
                    sonar.SonarScannerByPlugin()        

                }
            }
        }

         stage("PushArtifact"){
            steps{
                script{
                    //PushArtifactByPlugin()
                    //PushArtifactByPluginPOM()

                    // init package info
                    appName = "${JOB_NAME}".split('_')[0] //devops6-maven-service_CI
                    repoName = appName.split('-')[0]   //devops6
                    appVersion = "${env.branchName}".split("-")[-1] // RELEASE-1.1.1   1.1.1
                    appVersion = "${appVersion}-${env.commitID}"
                    targetDir="${appName}/${appVersion}"
                    

                    // 通過pom文件獲取包名稱
                    POM = readMavenPom file: 'pom.xml'
                    env.artifactId = "${POM.artifactId}"
                    env.packaging = "${POM.packaging}"
                    env.groupId = "${POM.groupId}"
                    env.art_version = "${POM.version}"
                    sourcePkgName = "${env.artifactId}-${env.art_version}.${env.packaging}"
                    
                    pkgPath = "target"
                    targetPkgName = "${appName}-${appVersion}.${env.packaging}"
                    artifact.PushNexusArtifact(repoName, targetDir, pkgPath, sourcePkgName,targetPkgName)
                }
            }
    
        }       

    }
}

/*
//通過nexus api上傳制品--綜合實(shí)踐
def PushNexusArtifact(repoId, targetDir, pkgPath, sourcePkgName,targetPkgName){
    //nexus api 
    withCredentials([usernamePassword(credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad', \
                                    passwordVariable: 'PASSWD', 
                                    usernameVariable: 'USERNAME')]) {
        sh """
            curl -X 'POST' \
              "http://172.29.9.101:8081/service/rest/v1/components?repository=${repoId}" \
              -H 'accept: application/json' \
              -H 'Content-Type: multipart/form-data' \
              -F "raw.directory=${targetDir}" \
              -F "raw.asset1=@${pkgPath}/${sourcePkgName};type=application/java-archive" \
              -F "raw.asset1.filename=${targetPkgName}" \
              -u ${USERNAME}:${PASSWD}
        """
    }
}
*/

cd.jenkinsfile

@Library("devops06@main") _ 

//import  src/org/devops/Gitlab.groovy
def mygit = new org.devops.Gitlab()
def mydeploy = new org.devops.Deploy()


//pipeline
pipeline{
    agent { label "build"}
    options {
        skipDefaultCheckout true
    }
    stages{
        stage("GetArtifact"){
            steps{
                script{
                    env.projectName = "${JOB_NAME}".split('_')[0] //devops6-maven-service
                    env.groupName = "${env.projectName}".split('-')[0]  //devops6
                    
                    projectID = mygit.GetProjectIDByName(env.projectName, env.groupName)
                    commitID = mygit.GetBranchCommitID("${projectID}", "${env.branchName}")
                    println(commitID)

                    appVersion = "${env.branchName}".split("-")[-1]  //9.9.9
                    println(appVersion)
                    // currentBuild.description = "Version: ${appVersion}-${commitID}"

                    currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${commitID}"
                    currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"


                    //下載制品
                    //http://172.29.9.101:8081/repository/devops6/devops6-maven-service/6.1.1-b5cfb8ee/devops6-maven-service-6.1.1-b5cfb8ee.jar
                    repoUrl = "http://172.29.9.101:8081/repository/${env.groupName}"
                    env.artifactName = "${env.projectName}-${appVersion}-${commitID}.jar"
                    artifactUrl = "${repoUrl}/${env.projectName}/${appVersion}-${commitID}/${env.artifactName}"
                    sh "wget --no-verbose ${artifactUrl} && ls -l"

                    env.releaseVersion = "${appVersion}-${commitID}"
                
                }
            }
        }

        stage("Deploy"){

            // 是否跳過發(fā)布?
            when {
                environment name: 'skipDeploy', value: 'false'
            }
            
            steps{
                script{                    
                    mydeploy.AnsibleDeploy()
                }
            }
        }

        stage("RollBack"){
            input {
                message "是否進(jìn)行回滾?"
                ok "Yes"
                submitter ""
                parameters {
                    choice choices: ['NO','YES'], name: 'OPS'
                }
            }
            steps {
                echo "OPS  ${OPS}, doing......."

                script{
                    if ("${OPS}" == "YES"){
                        mydeploy.AnsibleRollBack()
                    }
                }
                
            }
        }        

        

    }


}

Deploy.groovy

package org.devops

//rollback
def AnsibleRollBack(){

    sh """
        # 停止服務(wù)
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh stop" -u root
        
        sleep 20
        # 清理和創(chuàng)建發(fā)布目錄
        ansible "${env.deployHosts}" -m shell -a "rm -fr ${env.targetDir}/${env.projectName}/* &&  mkdir -p ${env.targetDir}/${env.projectName} || echo file is exists" 
        
        # 將備份目錄內(nèi)容復(fù)制到發(fā)布目錄
        ansible "${env.deployHosts}" -m shell -a " mv ${env.targetDir}/${env.projectName}.bak/* ${env.targetDir}/${env.projectName}/ || echo file not exists"

        # 啟動(dòng)服務(wù)
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh  start" -u root

        # 檢查服務(wù) 
        sleep 10
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh check" -u root

        """
}


//發(fā)布制品
def AnsibleDeploy(){
    //將主機(jī)寫入清單文件
    sh "rm -fr hosts "
    for (host in "${env.deployHosts}".split(',')){
        sh " echo ${host} >> hosts"
    }


    // ansible 發(fā)布jar
    sh """
        # 主機(jī)連通性檢測(cè)
        ansible "${env.deployHosts}" -m ping -i hosts 
        
        # 創(chuàng)建備份目錄
        ansible "${env.deployHosts}" -m shell -a "mkdir -p ${env.targetDir}/${env.projectName}.bak || echo file is exists" 
        # 備份上次構(gòu)建
        ansible "${env.deployHosts}" -m shell -a " mv ${env.targetDir}/${env.projectName}/* ${env.targetDir}/${env.projectName}.bak/ || echo file not exists"

        # 清理和創(chuàng)建發(fā)布目錄
        ansible "${env.deployHosts}" -m shell -a "rm -fr ${env.targetDir}/${env.projectName}/* &&  mkdir -p ${env.targetDir}/${env.projectName} || echo file is exists" 
        # 復(fù)制app
        ansible "${env.deployHosts}" -m copy -a "src=${env.artifactName}  dest=${env.targetDir}/${env.projectName}/${env.artifactName}" 
    """
    
    // 發(fā)布腳本
    fileData = libraryResource 'scripts/service.sh'
    println(fileData)
    writeFile file: 'service.sh', text: fileData
    sh "ls -a ; cat service.sh "


    sh """
        # 修改變量
        sed -i 's#APPNAME=NULL#APPNAME=${env.projectName}#g' service.sh
        sed -i 's#VERSION=NULL#VERSION=${env.releaseVersion}#g' service.sh
        sed -i 's#PORT=NULL#PORT=${env.port}#g' service.sh

        # 復(fù)制腳本
        ansible "${env.deployHosts}" -m copy -a "src=service.sh  dest=${env.targetDir}/${env.projectName}/service.sh" 
        # 啟動(dòng)服務(wù)
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile && sh service.sh start" -u root

        # 檢查服務(wù) 
        sleep 10
        ansible "${env.deployHosts}" -m shell -a "cd ${env.targetDir}/${env.projectName} ;source /etc/profile && sh service.sh  check" -u root
    """
}


Gitlab.groovy

package org.devops

//發(fā)起HTTP請(qǐng)求
//調(diào)用gitlab api
def HttpReq(method, apiUrl){

    withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d', variable: 'gitlabtoken')]) {
        response = sh  returnStdout: true, 
        script: """ 
        curl --location --request ${method} \
        http://172.29.9.101:8076/api/v4/${apiUrl} \
        --header "PRIVATE-TOKEN: ${gitlabtoken}"
        """
    }
    response = readJSON text: response - "\n" //json數(shù)據(jù)的讀取方式
    return response
}

//獲取ProjectID
def GetProjectIDByName(projectName, groupName){
    apiUrl = "projects?search=${projectName}"
    response = HttpReq("GET", apiUrl)
    if (response != []){
        for (p in response) {
            if (p["namespace"]["name"] == groupName){
                return response[0]["id"]
            }
        }
    }
}

//獲取分支CommitID
def GetBranchCommitID(projectID, branchName){
    apiUrl = "projects/${projectID}/repository/branches/${branchName}"
    response = HttpReq("GET", apiUrl)
    return response.commit.short_id
}
  • CI頁面參數(shù)如下

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

  • CD頁面參數(shù)

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

關(guān)于我

我的博客主旨:

  • 排版美觀,語言精煉;
  • 文檔即手冊(cè),步驟明細(xì),拒絕埋坑,提供源碼;
  • 本人實(shí)戰(zhàn)文檔都是親測(cè)成功的,各位小伙伴在實(shí)際操作過程中如有什么疑問,可隨時(shí)聯(lián)系本人幫您解決問題,讓我們一起進(jìn)步!

?? 微信二維碼
x2675263825 (舍得), qq:2675263825。

?? 微信公眾號(hào)
《云原生架構(gòu)師實(shí)戰(zhàn)》

?? 語雀

https://www.yuque.com/xyy-onlyone

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

?? csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

?? 知乎
https://www.zhihu.com/people/foryouone

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫

最后

好了,關(guān)于本次就到這里了,感謝大家閱讀,最后祝大家生活快樂,每天都過的有意義哦,我們下期見!

實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd),ci/cd,數(shù)據(jù)庫
response = HttpReq(“GET”, apiUrl)
if (response != []){
for (p in response) {
if (p[“namespace”][“name”] == groupName){
return response[0][“id”]
}
}
}
}

//獲取分支CommitID
def GetBranchCommitID(projectID, branchName){
apiUrl = “projects/ p r o j e c t I D / r e p o s i t o r y / b r a n c h e s / {projectID}/repository/branches/ projectID/repository/branches/{branchName}”
response = HttpReq(“GET”, apiUrl)
return response.commit.short_id
}文章來源地址http://www.zghlxwxcb.cn/news/detail-530404.html




- CI頁面參數(shù)如下

[外鏈圖片轉(zhuǎn)存中...(img-QfPAfydf-1688300616371)]

[外鏈圖片轉(zhuǎn)存中...(img-W6JQCH3L-1688300616371)]

[外鏈圖片轉(zhuǎn)存中...(img-JyUYqNZD-1688300616372)]

[外鏈圖片轉(zhuǎn)存中...(img-cDeigiAQ-1688300616372)]

[外鏈圖片轉(zhuǎn)存中...(img-bDEQtVsW-1688300616372)]

[外鏈圖片轉(zhuǎn)存中...(img-fvknHcLW-1688300616372)]

[外鏈圖片轉(zhuǎn)存中...(img-qyBydz95-1688300616373)]

[外鏈圖片轉(zhuǎn)存中...(img-a14KH4NR-1688300616373)]



- CD頁面參數(shù)

[外鏈圖片轉(zhuǎn)存中...(img-1O4fqE3z-1688300616373)]

[外鏈圖片轉(zhuǎn)存中...(img-jjzRnpju-1688300616374)]

[外鏈圖片轉(zhuǎn)存中...(img-ZK2ULdpb-1688300616374)]

[外鏈圖片轉(zhuǎn)存中...(img-mveq9EUt-1688300616374)]

[外鏈圖片轉(zhuǎn)存中...(img-y9sgD3ZV-1688300616375)]

[外鏈圖片轉(zhuǎn)存中...(img-uwlCPq5f-1688300616375)]

[外鏈圖片轉(zhuǎn)存中...(img-Ws9rX59L-1688300616375)]

[外鏈圖片轉(zhuǎn)存中...(img-GtRKkUw5-1688300616375)]

[外鏈圖片轉(zhuǎn)存中...(img-1DUDIHmE-1688300616376)]

## 關(guān)于我

我的博客主旨:

- 排版美觀,語言精煉;
- 文檔即手冊(cè),步驟明細(xì),拒絕埋坑,提供源碼;
- 本人實(shí)戰(zhàn)文檔都是親測(cè)成功的,各位小伙伴在實(shí)際操作過程中如有什么疑問,可隨時(shí)聯(lián)系本人幫您解決問題,讓我們一起進(jìn)步!



?? 微信二維碼
x2675263825 (舍得), qq:2675263825。

[外鏈圖片轉(zhuǎn)存中...(img-p0fEeEL4-1688300616376)]



?? 微信公眾號(hào)
《云原生架構(gòu)師實(shí)戰(zhàn)》

[外鏈圖片轉(zhuǎn)存中...(img-O6MQ006k-1688300616376)]



?? 語雀

https://www.yuque.com/xyy-onlyone

[外鏈圖片轉(zhuǎn)存中...(img-5TROvRge-1688300616377)]



?? csdn
[https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421](https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421)

[外鏈圖片轉(zhuǎn)存中...(img-vUzjbf7l-1688300616379)]



?? 知乎
[https://www.zhihu.com/people/foryouone](https://www.zhihu.com/people/foryouone)

[外鏈圖片轉(zhuǎn)存中...(img-EYtkEa5o-1688300616379)]

## 最后

好了,關(guān)于本次就到這里了,感謝大家閱讀,最后祝大家生活快樂,每天都過的有意義哦,我們下期見!

[外鏈圖片轉(zhuǎn)存中...(img-MUi6bZl1-1688300616379)]

到了這里,關(guān)于實(shí)踐:devops之云主機(jī)模式持續(xù)部署(ci-cd)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • DevOps與CI/CD的最佳實(shí)踐

    DevOps與CI/CD的最佳實(shí)踐

    在當(dāng)今的軟件開發(fā)領(lǐng)域,DevOps(開發(fā)與運(yùn)維的結(jié)合)和CI/CD(持續(xù)集成/持續(xù)交付)已經(jīng)成為了不可或缺的一部分。它們不僅提高了軟件開發(fā)的效率,還幫助團(tuán)隊(duì)更快地交付高質(zhì)量的軟件。本文將深入探討DevOps文化和CI/CD的關(guān)鍵概念,以及它們?nèi)绾胃纳栖浖_發(fā)流程。 DevOps是一

    2024年02月08日
    瀏覽(29)
  • 前端自動(dòng)化部署,Devops,CI/CD

    前端自動(dòng)化部署,Devops,CI/CD

    提到 Jenkins,想到的第一個(gè)概念就是 CI/CD 在這之前應(yīng)該再了解一個(gè)概念。 DevOps? Development ?和? Operations ?的組合,是一種方法論,并不特指某種技術(shù)或者工具。DevOps 是一種重視? Dev ?開發(fā)人員和? Ops ?運(yùn)維人員之間溝通、協(xié)作的流程。通過自動(dòng)化的軟件交付,使軟件的構(gòu)建

    2024年02月10日
    瀏覽(55)
  • 【前端自動(dòng)化部署】,Devops,CI/CD

    【前端自動(dòng)化部署】,Devops,CI/CD

    提到 Jenkins ,想到的第一個(gè)概念就是 CI/CD 在這之前應(yīng)該再了解一個(gè)概念。 DevOps Development 和 Operations 的組合,是一種方法論,并不特指某種技術(shù)或者工具。 DevOps 是一種重視 Dev 開發(fā)人員和 Ops 運(yùn)維人員之間溝通、協(xié)作的流程。通過自動(dòng)化的軟件交付,使軟件的構(gòu)建,測(cè)試,發(fā)

    2024年02月10日
    瀏覽(54)
  • 【持續(xù)集成CI/持續(xù)部署CD】六、Docker Compose構(gòu)建CI全流程

    【持續(xù)集成CI/持續(xù)部署CD】六、Docker Compose構(gòu)建CI全流程

    1. 創(chuàng)建宿主機(jī)掛載目錄并賦權(quán) 2. 新建 Jenkins+Sonar 安裝腳本 jenkins-compose.yml 腳本,這里的 Jenkins 使用的是 Docker 官方推薦的鏡像 jenkinsci/blueocean,在實(shí)際使用中發(fā)現(xiàn),即使不修改插件下載地址,也可以下載插件,所以比較推薦這個(gè)鏡像。 3. 在 jenkins-compose.yml 文件所在目錄下執(zhí)行

    2024年02月10日
    瀏覽(27)
  • Eolink實(shí)踐 | 基于DevOps的持續(xù)測(cè)試策略

    Eolink實(shí)踐 | 基于DevOps的持續(xù)測(cè)試策略

    DevOps 如今在企業(yè)中顯的尤其重要。想要獲得成功我們就需要制定好的測(cè)試策略來實(shí)踐。 DevOps 的一個(gè)重要組成部分是持續(xù)集成/持續(xù)交付(CI/CD)。在CI和CD之間,應(yīng)該是持續(xù)測(cè)試。 如果不進(jìn)行持續(xù)測(cè)試,將會(huì)出現(xiàn): 缺陷的泄漏 軟件延期交付 客戶不滿意 可以提供更快的反饋 提供

    2024年02月01日
    瀏覽(17)
  • CI/CD到底是啥?持續(xù)集成/持續(xù)部署概念解釋

    大家好,我是chowley,日常工作中,我每天都在接觸CI/CD,今天就給出我心中的答案。 在現(xiàn)代軟件開發(fā)中,持續(xù)集成(Continuous Integration,CI)和持續(xù)部署(Continuous Deployment,CD)是兩個(gè)非常重要的實(shí)踐,它們通過自動(dòng)化的流程來加速軟件的開發(fā)、測(cè)試和部署,提高團(tuán)隊(duì)的效率和

    2024年02月19日
    瀏覽(25)
  • 持續(xù)集成與持續(xù)交付(CI/CD):探討在云計(jì)算中實(shí)現(xiàn)快速軟件交付的最佳實(shí)踐

    持續(xù)集成與持續(xù)交付(CI/CD):探討在云計(jì)算中實(shí)現(xiàn)快速軟件交付的最佳實(shí)踐

    ??個(gè)人主頁:程序員 小侯 ??CSDN新晉作者 ??歡迎 ??點(diǎn)贊?評(píng)論?收藏 ?收錄專欄:云計(jì)算 ?文章內(nèi)容:軟件交付 ??希望作者的文章能對(duì)你有所幫助,有不足的地方請(qǐng)?jiān)谠u(píng)論區(qū)留言指正,大家一起學(xué)習(xí)交流!?? 持續(xù)集成(Continuous Integration,CI)和持續(xù)交付(Continuous D

    2024年02月10日
    瀏覽(35)
  • 《DevOps企業(yè)級(jí)CI/CD實(shí)戰(zhàn)》:一站式掌握DevOps核心方法論,實(shí)現(xiàn)高效自動(dòng)化部署

    《DevOps企業(yè)級(jí)CI/CD實(shí)戰(zhàn)》:一站式掌握DevOps核心方法論,實(shí)現(xiàn)高效自動(dòng)化部署

    DevOps是一組實(shí)踐,由人、工具和文化理念組成。DevOps的核心是實(shí)現(xiàn)軟件開發(fā)團(tuán)隊(duì)和IT運(yùn)維團(tuán)隊(duì)之間的流程自動(dòng)化。自2018年起,筆者參與了大型企業(yè)中多個(gè)項(xiàng)目的DevOps項(xiàng)目實(shí)施和改進(jìn),從中積累了豐富的實(shí)踐經(jīng)驗(yàn)。于是將實(shí)踐思考與開發(fā)經(jīng)驗(yàn)整理成一本書分享給同路人共同學(xué)習(xí)

    2024年04月14日
    瀏覽(26)
  • 【云原生持續(xù)交付和自動(dòng)化測(cè)試】5.3 持續(xù)交付和DevOps實(shí)踐基礎(chǔ)知識(shí)

    往期回顧: 第一章:【云原生概念和技術(shù)】 第二章:【容器化應(yīng)用程序設(shè)計(jì)和開發(fā)】 第三章:【基于容器的部署、管理和擴(kuò)展】 第四章:【微服務(wù)架構(gòu)設(shè)計(jì)和實(shí)現(xiàn)】 第五章:【5.1 自動(dòng)化構(gòu)建和打包容器鏡像】 第五章:【5.2 自動(dòng)化測(cè)試和集成測(cè)試】 云原生下對(duì)持續(xù)交付(

    2024年02月09日
    瀏覽(56)
  • 【git】CI/CD持續(xù)集成與部署C++示例

    【git】CI/CD持續(xù)集成與部署C++示例

    ?? ★,° :.☆( ̄▽ ̄)/$: .°★ ?? 這篇文章主要介紹CI/CD持續(xù)集成與部署C++示例。 學(xué)其所用,用其所學(xué)?!?jiǎn)⒊?歡迎來到我的博客,一起學(xué)習(xí),共同進(jìn)步。 喜歡的朋友可以關(guān)注一下,下次更新不迷路?? CI/CD (持續(xù)集成/持續(xù)交付)是一種軟件開發(fā)實(shí)踐和方法論,旨在通過

    2024年01月19日
    瀏覽(42)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包