基於Jenkins+Maven+Gitea+Nexus從0到1搭建CICD環境


在傳統的單體軟件架構中,軟件開發、測試、運維都是以單個進程為單位。

當拆分成微服務之后,單個應用可以被拆分成多個微服務,比如用戶系統,可以拆分成基本信息管理、積分管理、訂單管理、用戶信息管理、合同管理等多個微服務模塊。

這個時候對每個模塊分別打包、發布運行、開發、測試、運維的,對於測試、運維的工作量會極大增加。

在這個過程中,如果缺乏自動化測試、自動化集成/部署、自動運維等能力,帶來的影響是

  1. 軟件交付周期增加
  2. 多環境部署的情況下,各個環境差異帶來的問題。
  3. 人工運維容易給環境帶來一些不可重現的影響,而且一旦發生運維錯誤又比較難立刻恢復,造成故障處理時間較長。並且對於運維人員的能力要求較高

所有的這些問題,會導致軟件交付時間變長、風險增加、以及運維成本增加等問題。因此,我們需要一套自動化部署體系,來構建一個CICD的模型。

image-20211204145303729

普通Jar包的運行方式

  1. 使用maven package
  2. nohup java -jar ${APP_NAME} > goods-service.log 2>&1 &
  • nohup用途:不掛斷地運行命令

  • &用途,在后台運行

  • 2>&1: 在bash中:

    • 0 代表STDIN_FILENO 標准輸入(一般是鍵盤),
    • 1 代表STDOUT_FILENO 標准輸出(一般是顯示屏,准確的說是用戶終端控制台),
    • 2 三代表STDERR_FILENO (標准錯誤(出錯信息輸出)。

    2>&1就是用來將標准錯誤2重定向到標准輸出1中的。此處1前面的&就是為了讓bash將1解釋成標准輸出而不是文件1。至於最后一個&,則是讓bash在后台執行。

  • > 直接把內容生成到指定文件

搭建Nexus私服環境

Nexus是一個強大的Maven倉庫管理器,它極大地簡化了本地內部倉庫的維護和外部倉庫的訪問。Nexus是一套“開箱即用”的系統不需要數據庫,它使用文件系統加Lucene來組織數據。

Maven私服環境需要用sonatype nexus,下面我們從安裝和配置進行詳細分析

部署服務器: 192.168.8.138

下載和安裝

  1. 訪問:https://sonatype-download.global.ssl.fastly.net/repository/downloads-prod-group/3/nexus-3.37.0-01-unix.tar.gz地址,下載Sonatype Nexus。
  2. 解壓縮到/data/program目錄下
[root@localhost program]# tar -zxvf nexus-3.37.0-01-unix.tar.gz 
  1. 進入到${NEXUS_HOME}\bin目錄,執行下面命令啟動Nexus
./nexus start 

安裝Maven

  1. 下載Maven: https://dlcdn.apache.org/maven/maven-3/3.8.4/binaries/apache-maven-3.8.4-bin.tar.gz
  2. 配置Maven 和JDK 環境變量。
export JAVA_HOME=/data/program/jdk1.8.0_241
export MAVEN_HOME=/data/program/apache-maven-3.8.4
export PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
  1. 進入到${NEXUS_HOME}\bin目錄,執行下面命令啟動Nexus

    用./nexus start啟動,后台啟動,啟動成功后可以訪問

    用./nexus run啟動,前台啟動,顯示日志,啟動后可以訪問

./nexus start 

啟動時,會有如下提示,這個是建議我們使用非root賬戶來訪問。

WARNING: ************************************************************
WARNING: Detected execution as "root" user.  This is NOT recommended!
WARNING: ************************************************************
  1. 訪問:http://localhost:8081訪問Nexus倉庫

如果想配置 nexus 的應用在本地啟動的 JVM參數,可以在 nexus.vmoptions

如果想改變 nexus 的 端口號,可以在 nexus-default.properties

登錄控制台

  1. 默認登錄的帳號是admin,密碼在會提示你在:/data/program/sonatype-work/nexus3/admin.password文件中。

  1. 內容如下,直接復制該內容登錄即可。
090849ac-cea7-4353-b2c8-59b2bceadb50

Nexus控制台說明

進入Nexus控制台的Browse菜單,可以看到四種倉庫類型:

1)maven-central: maven中央庫,默認從https://repo1.maven.org/maven2/拉取jar

2)maven-releases: 私庫發行版jar

3)maven-snapshots:私庫快照(調試版本)jar

4)maven-public: 倉庫分組,把上面三個倉庫組合在一起對外提供服務,在本地maven基礎配置settings.xml中使用。

image-20211205153818994

Nexus默認的倉庫類型有以下四種:(上面的名字可以隨便取,關鍵是它對應的是什么倉庫類型)

1)group(倉庫組類型):又叫組倉庫,用於方便開發人員自己設定的倉庫;

2)hosted(宿主類型):內部項目的發布倉庫(內部開發人員,發布上去存放的倉庫);

3)proxy(代理類型): 從遠程中央倉庫中尋找數據的倉庫(可以點擊對應的倉庫的Configuration頁簽下Remote Storage Location屬性的值即被代理的遠程倉庫的路徑);

4)virtual(虛擬類型): 虛擬倉庫(這個基本用不到,重點關注上面三個倉庫的使用);

Nuget是用於微軟.NET開發平台的軟件包管理器,和Maven類似。

目錄說明

nexus-3.34.0-01 目錄

  1. bin 包含nexus的啟動腳本和相關配置
  2. etc jetty、karaf等配置文件
  3. jre jre環境
  4. lib java架包庫
  5. public 關於nexus應用在本地跑起來所需要的資源
  6. system 應用所有的插件和組件
  7. LICENSE.txt 和 NOTICE.txt 版權聲明和法律細則

sonatype-work\nexus3 目錄

  1. blobs/ 創建blob的默認路徑,當然也可以重新指定
  2. cache/ 當前緩存的karaf包的信息
  3. db/ OrientDB數據庫的數據,用於存儲nexus的元數據的數據庫
  4. elasticsearch/ 當前配置的Elasticsearch狀態
  5. etc/ 大概是運行時配置狀態和關於資源庫的自定義的相關的東西
  6. health-check/ 看目錄,健康檢查的相關報告的存儲目錄吧
  7. keystores/ 自動生成的關於資源庫的ID主鍵
  8. log/ 運行實例生成的日志文件,也有日志文件的壓縮包,貌似是每天都會生成日志文件,你可以定期刪除老的日志文件
  9. tmp/ 用於存儲臨時文件的目錄

Nexus設置成系統服務

按照以下步驟執行

  1. 修改${NEXUS_HOME}\bin\nexus這個腳本,增加下面的配置
INSTALL4J_JAVA_HOME_OVERRIDE=/data/program/jdk1.8.0_241
  1. 設置軟鏈接
[root@localhost bin]# ln -s /data/program/nexus-3.37.0-01/bin/nexus /etc/init.d/nexus
  1. 通過chkconfig方式配置系統服務
cd /etc/init.d
sudo chkconfig --add nexus #添加nexus服務
sudo chkconfig --levels 345 nexus on #設置開啟自啟動
  1. 啟動和停止服務

    sudo service nexus start #開啟服務
    service nexus status #查看服務狀態

搭建Gitea環境

參考文檔: https://docs.gitea.io/zh-cn/install-from-binary/

  1. 安裝git環境: yum -y install git
  2. 通過下面的命令下載linux中的安裝包到/data/program/gitea目錄下。
wget -O gitea https://dl.gitea.io/gitea/1.15.7/gitea-1.15.7-linux-amd64
  1. 執行chmod +x gitea命令,授予執行權限
  2. 執行下面這個命令運行gitea
./gitea web

安裝成系統服務(重要)

  1. 創建Git用戶
sudo useradd \
   --system \
   --shell /bin/bash \
   --comment 'Git Version Control' \
   --create-home \
   --home /home/git \
   git
  1. 下載二進制文件
wget -O gitea https://dl.gitea.io/gitea/1.15.7/gitea-1.15.7-linux-amd64
  1. 根據gitea官方推薦,按照以下方式配置gitea的安裝目錄

    • 把下載的文件移動到/usr/local/bin目錄

      sudo mv /data/program/gitea /usr/local/bin
      
    • 使二進制文件可執行:

      chmod +x /usr/local/bin/gitea
      
    • 按照一下命令創建必要目錄並設置權限

      sudo mkdir -p /var/lib/gitea/{custom,data,indexers,public,log}
      sudo mkdir -p /var/lib/gitea/{custom,data,indexers,public,log}
      sudo chown git: /var/lib/gitea/{data,indexers,custom,public,log}
      sudo chmod 750 /var/lib/gitea/{data,indexers,log}
      sudo mkdir /etc/gitea
      sudo chown root:git /etc/gitea
      sudo chmod 770 /etc/gitea
      
    • 根據Gitea官方提供的Systemd Unit文件,配置系統服務。

      sudo wget https://raw.githubusercontent.com/go-gitea/gitea/master/contrib/systemd/gitea.service -P /etc/systemd/system/
      

      注意,gitea.service, 不能通過wget下載,需要去github上復制

    • 完成上述過程后,通過下面命令開啟自動啟動

      systemctl enable gitea
      systemctl start gitea
      
  2. 安裝啟動完成后,訪問:http://192.168.8.136:3000,配置數據庫相關屬性即可。

搭建Jenkins環境

Jenkins是一個用JAVA編寫的開源的持續集成工具,運行在servlet容器中,支持軟件配置管理(SCM)工具,可以執行基於APACHE ANT和APACHE MAVEN的項目,以及任意Shell腳本和Windows批處理命令

Jenkins提供了自動構建和部署的功能,具體安裝方式如下:

wget -O /etc/yum.repos.d/jenkins.repo \
    https://pkg.jenkins.io/redhat-stable/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum upgrade
yum install epel-release java-11-openjdk-devel
yum install jenkins
systemctl daemon-reload

通過下面的命令啟動或停止jenkins

systemctl start jenkins
systemctl stop jenkins

訪問: http://192.168.8.136:8080 訪問jenkins

按照控制台提示的步驟一步步執行即可。

image-20211206175235556

注意: Jenkins安裝默認采用JENKINS用戶,所以如果是使用root權限,則需要修改帳號

[root@localhost bin]# vim /etc/sysconfig/jenkins

JENKINS_USER="root"

項目改造

項目配置本地的私服

  1. 修改setting.xml文件,增加mirror配置

    <mirrors>
        <mirror>
            <id>nexus</id>
            <mirrorOf>maven-public</mirrorOf>
            <url>http://192.168.8.136:8081/repository/maven-public/</url>
        </mirror>
    </mirrors>
    

    mirror相當於一個攔截器,它會攔截maven對remote repository的相關請求,走該鏡像進行jar包的獲取。

  2. 在項目中增加如下配置,也就是指定snapshots和releases 不同發行版本jar包的發布倉庫

    <distributionManagement>
        <snapshotRepository>
            <id>snapshots</id>
            <name>Nexus Snapshot Repository</name>
            <url>http://192.168.8.136:8081/repository/maven-snapshots/</url>
        </snapshotRepository>
        <repository>
            <id>releases</id>
            <name>Nexus Release Repository</name>
            <url>http://192.168.8.136:8081/repository/huhy-nexus/</url>
        </repository>
    </distributionManagement>
    

修改發布服務器的settings.xml文件

修改發布服務器的settings.xml文件的目的,是因為Jenkins服務器在進行持續集成時,需要通過maven實現依賴jar包的下載,而這個下載需要從我們本地的私服中獲取。

<mirrors>
    <mirror>
        <id>nexus</id>
        <mirrorOf>maven-public</mirrorOf>
        <url>http://192.168.8.136:8081/repository/maven-public/</url>
    </mirror>
</mirrors>
<profiles>
     <profile>
      <id>nexusRep</id>
      <repositories>
        <repository>
          <id>nexus</id>
          <url>http://192.168.8.136:8181/repository/maven-public/</url>
          <layout>default</layout>
          <releases>
              <enabled>true</enabled>
              <updatePolicy>always</updatePolicy>
          </releases>
        </repository>
      </repositories>
      <pluginRepositories>  
        <pluginRepository>  
          <!--插件地址--> 
            <id>nexus</id>  
            <url>http://192.168.8.136:8181/repository/maven-public/</url>  
            <snapshots>     
              <enabled>true</enabled>    
            </snapshots>    
            <releases>      
                <enabled>true</enabled>    
            </releases> 
        </pluginRepository>
       </pluginRepositories>
    </profile>
  </profiles>

  <activeProfiles>
    <activeProfile>nexusRep</activeProfile>
  </activeProfiles>

配置自動集成與發布

配置Jenkins的環境變量

進入到如下頁面,紅色標注的配置。

image-20211206195831934

配置Maven的環境,指定發布服務器上安裝的Maven目錄。

image-20211206200050850

安裝Jenkins插件

  • Gitea , 集成Gitea,安裝好之后,在Jenkins全局配置中,添加Gitea Server信息。

    image-20211206202555784

  • Git Parameter , 配置Git發布屬性

  • Publish Over SSH ,在遠程機器上執行腳本,這一步需要先配置能ssh遠程機器

  • Maven Integration, 支持Maven項目的集成

配置發布目標服務器信息

我們把下面兩台服務器當成是web節點

  1. 192.168.8.134
  2. 192.168.8.135

在Jenkins 全局配置中,配置這兩台服務器的信息,用來后續實現jar包遠程傳輸。其中Remote Directory目標服務器的工作目錄,jar包會被遠程傳輸到該目錄下

image-20211206203254587

添加項目發布機制

創建一個Maven項目的任務。

image-20211206204153959

配置源碼來源,這里使用Gitea中項目的源碼地址,並配置登錄帳號密碼信息。

image-20211206204554726

配置Maven的執行命令,其中root POM,如果是在多模塊項目中,需要指定當前要構建的模塊的pom.xml。

image-20211206205541294

增加構建成功之后的執行邏輯,就是把jar包發布到遠程目標服務器,然后執行相關shell腳本啟動服務

image-20211206231510128

編寫發布腳本

編寫shell腳本,當jar包發送到目標服務器之后,執行下面腳本。

  1. 做歷史jar備份和清理
  2. 執行shell腳本啟動服務
#! bin/sh -e
export JAVA_HOME=/data/program/jdk1.8.0_241
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=${PATH}:$JAVA_HOME/bin
source /etc/profile 

# define property
JAR_PATH='/app/service/goods-service'
TEMP_PATH='/app/service/temp'
BACKUP_PATH='/app/service/backup'
JAR_NAME=goods-service.jar
FILE_NAME=goods-service

# stop target service
cd ${JAR_PATH}
sh run-goods-service.sh stop
sleep 2
rm -rf $FILE_NAME.log

# backup old jar
BACKUP_DATE=$(date +%Y%m%d_%H%M)

if [ ! -d $JAR_PATH/backup/$FILE_NAME ];then
    mkdir -p $JAR_PATH/backup/$FILE_NAME
fi

cd ${JAR_PATH}
pwd
if [ -f $JAR_NAME ];then
   mv -f ./$JAR_NAME ./backup/$FILE_NAME/$JAR_NAME$BACKUP_DATE
   sleep 1
fi

# start jar
BUILD_ID=dontKillMe
cd ${TEMP_PATH}
mv -f $JAR_NAME  $JAR_PATH
cd ${JAR_PATH}
sh run-goods-service.sh restart

# clear old backup
cd ${JAR_PATH}/backup/$FILE_NAME
ls -lt|awk 'NR>5{print $NF}' |xargs rm -rf

ps -ef|grep java
echo "=============deploy success========"

編寫運行腳本run-goods-service.sh

# 表示當前腳本采用/bin路徑的bash程序來解釋執行
#!/bin/bash

# 執行的jar包
APP_NAME=goods-service.jar

usage() {
  echo "執行操作命令 [start|stop|restart|status]"
  exit 1
}

if_exist() {
  pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}'`
  if [ -z "${pid}" ]; then
    return 1
  else
    return 0
  fi
}

start() {
  if_exist
  if [ $? -eq 0 ]; then
    echo "${APP_NAME} already running . pid=${pid}"
  else
    nohup java -jar ${APP_NAME} > goods-service.log 2>&1 &
    npid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}'`
    echo "start ${APP_NAME} success, pid=${npid}"
  fi
}

stop() {
  if_exist
  if [ $? -eq 0 ]; then
    kill -9 $pid
    echo "stop $pid success".
  else
    echo "${APP_NAME} is not running"
  fi
}

status() {
  if_exist
  if [ $? -eq 0 ]; then
    echo "${APP_NAME} is running. pid is ${pid}"
  else
    echo "${APP_NAME} is not running "
  fi
}

restart() {
  stop
  sleep 5
  start
}

case "$1" in
   "start")
      start
       ;;
    "stop")
      stop
       ;;
    "status")
      status
       ;;
    "restart")
      restart
       ;;
    *)
    usage
     ;;
esac

配置代碼提交后動態構建

如果我們希望代碼提交合並到某個分支后,自動構建進行發布,怎么實現呢?

安裝Webhook插件

  1. 在Jenkins中安裝Generic Webhook Trigger 插件,安裝成功后,會在構建的配置頁面多了下面所示的一個選項。

    image-20211207000120205

  2. 配置Generiac Webhook Trigger,增加一個token作為驗證。

    image-20211207000421036

    注意這個地址: http://JENKINS_URL/generic-webhook-trigger/invoke , 在webhook中需要配置這個作為觸發調用。

gitea添加webhook鈎子

  1. 在gitea的項目中,找到Web鈎子,添加Web鈎子. 選擇gitea

    image-20211207000530187

  2. 添加webhook

    image-20211207000722202

驗證自動觸發的行為

  1. 修改gpmall-pc這個項目的任何一個代碼,然后提交到gitea上。

  2. 觀察Jenkin的項目構建目錄,會增加一個自動構建的任務,如下圖所示。

    image-20211207000953071

  3. 並且在gitea的webhook中,可以看到最近的推送記錄

    image-20211207001046181

源碼地址

文章演示使用的源碼: https://github.com/2227324689/spring-cloud-netflix-example.git

版權聲明:本博客所有文章除特別聲明外,均采用 CC BY-NC-SA 4.0 許可協議。轉載請注明來自 Mic帶你學架構
如果本篇文章對您有幫助,還請幫忙點個關注和贊,您的堅持是我不斷創作的動力。歡迎關注「跟着Mic學架構」公眾號公眾號獲取更多技術干貨!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM