jenkins 自動化部署實戰


  jenkins 作為一個自動化的集成工具,已經是必不可少的了。它里面提供各種插件,以及完備的基礎流程設施,為大家的自動化集成之路提供了很多的方便。所以,我們有必要完整的實踐一回。以切身體會到它的好處!

一、 操作步驟說明陳列

  1. 下載jenkins包,並安裝;(兩種方案,基於物理機和基於docker,視情況而定建議使用docker)

  2. 安裝后,初始化jenkins,基本都是下一步下一步搞定,保持默認是比較穩妥的選擇;

  3. 訂立目標,需要完成什么的場景下的打包功能? git ?  subversion? 或者其他 ?

  4. 選擇此場景需要的必要插件安裝,並進行簡單調試;

  5. 新建一個任務,嘗試使用工具完成一次簡單的打包操作;

  6. 完善一個任務,使其可以支持一些簡單的參數定制,如分支的選擇;

  7. 打包完成后,編寫部署腳本,使其可以一鍵部署;

  8. 設置權限管理,使不同環境的包由不同級別的同學進行操作;

  9. 進行反復功能驗證,及權限驗證;

  10. 備注所有的操作流程,以便在進行下次重新安裝時,能夠隨時搞定;

 

 二、具體實踐操作

  簡單的安裝和初始化,咱們就不多說了,網上一大堆的信息,隨便找一個就能搞定,不找也能搞定,請參考官網: https://wiki.jenkins.io/display/JENKINS/Use+Jenkins

打包場景一: 如何打包 maven 管理的java項目 ?

  其實要打包這種項目比較簡單,只要安裝一個 maven integeration 的插件即可!如下:

  安裝好后,新建一個 maven 任務即可!

  其實maven任務和其他任務不太一樣的地方是,它會出現一個 pom.xml 的字樣,其實就是自己去加載這個配置文件,然后自行調用 maven 進行打包。而如果想要更靈活,也是可以的,只需要使用 系統的命令進行自由構建即可!

 

  goal 里可寫: clean install | package

   經過上面的操作后,你可能會發現,其實並不會打包成功,為什么呢?因為我們還沒有安裝 maven 的工具到系統上,或者說沒有向 jenkins 解釋 maven 在哪里,所以需要到全局工具配置一下!

  另外,如果你是需要打包 git 類的代碼的話,一般只需要進行簡單授權就可以了!

  到此,一個 簡單的 maven java 項目打包就成功了!

 

但是,其實,打包到這個程度,其實對我們的環境部署一點更多的意義都沒有,所以我們需要更深的定制化!咱們稍后再說!

 

先來說說,另一種項目的打包方式, h5 代碼的打包。 更具體的講,就是 基於 nodejs 的打包實現!

 

  首先,我們當然需要安裝 node js 的插件了!

  同樣,該插件安裝好后,還要安裝  nodejs 的軟件!可以直接選擇自動 安裝 ! 注意要求的版本!

  安裝好后,新建一個自由風格的任務!

  進入,把 node 的環境支持勾選上!然后定稿node 的打包命令!

  同樣,git 相關的操作一樣!

  至此,簡單的 node 版本的代碼打包功能也做好了。 

  同樣,只是進行打包,無法定制化的東西,對我們毫無意義,所以,我們需要更高級的定制 jenkins !

  例外:如果有依賴一些私有的包,那么,你可以選擇安裝私服,或者用如下方式解決:

# for local repository dependency...
ln -sf /var/lib/jenkins/pkg-bak/testmodule/ $WORKSPACE/node_modules/testmodule
npm install
npm run prod

 

 

三、 定制你的 jenkins 功能!

場景一: 我需要為一個git 倉庫的多個分支打包?

  這個,簡單, jenkins 中一添加定制化參數的功能,只需要添加一個文本參數就可以 了!

  在 git 分支一欄,寫入 $branch 替換即可!

 

   如此,一個簡單的支持 git 多分支打包的功能就做好了!

但是:每次都讓我自己輸入分支,好煩啊! 而且,我自己也不一定知道有什么樣的分支,這可怎么辦?

  借助 groovy 腳本,可以動態拉取 分支列表,進行顯示了!

  簡單來說就是,執行一些shell腳本 , 從 git 遠端列舉出分支,給到列表選項! groovy 腳本如下:

def git_url = "https://github.com/yougewe/elastic-job-lite"
def git_cmd = "/usr/local/git/bin/git ls-remote -h $git_url  | grep -oP '(?<=refs/heads/).*' "
branch = ['bash', '-c', git_cmd].execute().text.readLines()

  好了,分支的選擇,看起來我們已經解決得差不多了!

  但是,前端有個點,就是這分支的觸發問題,其實我們可以更動態方式實現!

場景二: 我需要支持多個倉庫進行切換打包,當然這里的倉庫將必然影響到上面分支列表的選擇!

  可以使用 Active Choice 這個插件,可以讓我們在需要的時候觸發一次分支的選擇,比如支持 分支快速過濾!達到數據聯動的效果;

  然后,也可以使分支依賴於動態的倉庫進行變更分支列表等等!總之, Active Choice 插件真是很方便發揮!

 

  最終的效果就是,我們可以選擇,多倉庫,動態列表多分支,進行打包!

      總之,通過這個聯動支持,以及簡單groovy知識,你可以有很大的發揮空間;

 

場景三: 我需要將打好的包部署到指定服務器上?

      這是個關鍵的問題,就是我們打包來的包,應該處理的問題!

      這里有兩個核心問題: 1. 我如何找到打包后的東西? 2. 如何將找到的東西部署到線上?

  如果不能很好的處理這些包,我們將很無奈!所以  shell 就出場了!

  jenkins 支持在打包后進行一些自定義的操作! 比如 上傳包到另外的服務器,或者部署到另外的地方等等!總之,就是任你發揮!

      一般地說,查找打包后的東西,要依賴於你的代碼實現,所以具體問題具體分析;當然了,你可以通過mvn等命令直接訂制打包的各種配置,從而活動查找的麻煩;

      另外,對於部署到服務器,至少有兩個解決方案:1. 直接通過scp等服務器拷貝技術,將包放到目標服務器即可; 2. 將包打包成可執行的安裝包,上傳yum源服務器,在使用端直接拉取鏡像即可;

  比如如下的腳本 ,我們可以將它部署到我們指定服務器的 docker 容器中!

  參考腳本如下:

echo "hello, build over ??? would you scp or deploy apps ??? work dir: $WORKSPACE , repository: $spec_repository;"
# specify dev environment or product environment
deploy_env_server="root@172.10.11.16"
deploy_path_prefix="/opt/docker/webapps/test"
docker_app_startup_script="/etc/init.d/startup restart";
case "$spec_repository" in
    richCash)
        docker_container_name="test_container";
        docker_app_startup_script="/etc/init.d/startup restart";
        deploy_path_prefix="/opt/docker/webapps/";
        deploy_sub_path="$deploy_environment"
        case "$deploy_environment" in
            "test-p8081")
                docker_container_name="test_p8081_container"
                ;;
                docker_container_name="test_p8083_container"
                ;;
            *)
                # default container
                ;;
        esac
        deploy_path_prefix="/opt/docker/webapps/$deploy_sub_path";
        ;;
    test2-01)
        deploy_path_prefix="/opt/docker/webapps/test2-01";
        docker_container_name="test2_01_container";
        docker_app_startup_script="/etc/init.d/startup restart";
        ;;
    *)
        echo "not find special configures in $spec_repository, do the default thing";
    ;;
esac
# deploy script
deploy_script_path="ssh $deploy_env_server \"docker exec $docker_container_name bash -c '$docker_app_startup_script'\"";

pom_file="$WORKSPACE/pom.xml";
pom_file_tmp="$pom_file\.tmp";
cd $WORKSPACE;
cat $pom_file | awk '{if($0 ~ /<parent>/){parent_begin++; print "no dump parent"} else if(parent_begin > 0){ if($0 ~ /<\/parent>/){parent_begin = 0; print "match the parent end.";} else {print "hit parent dump"; }} else { print $0;}}' > $pom_file_tmp
package_artifactId=`grep "<artifactId>" $pom_file_tmp | head -n 1 | sed -e 's/\(\s*<artifactId>\|<\/artifactId>\s*\)//g'`;
package_version=`grep "<version>" $pom_file_tmp | head -n 1 | sed -e 's/\(\s*<version>\|<\/version>\s*\)//g'`;
package_full_name="$package_artifactId-$package_version.jar"    # 定義為jar包寫死
package_full_path="$WORKSPACE/target/$package_full_name";
echo "packaged file is: $package_full_name";
scp $package_full_path $deploy_env_server:"$deploy_path_prefix/$package_full_name";
# restart the server...
eval $deploy_script_path;

  如上,是對 jar 包的部署方式,我們再來看下 h5 包的部署方式:

echo "hello, build over ??? work dir: $WORKSPACE , repository: $spec_repository; branch: $branch ;"
# specify dev environment or product environment
deploy_env_server="root@172.11.1.12"
docker_container_name="web_container";
deploy_path_prefix="/opt/docker/webapps/";
deploy_sub_path="$deploy_environment"
deploy_path_prefix="$deploy_path_prefix""$deploy_sub_path"
deploy_package_bak_path="/opt/docker/webapps/bak/"
docker_app_startup_script="ls "
case "$deploy_environment" in
    "web-p81")
        docker_container_name="web_81_container"
    ;;
    *)
        # default container
    ;;
esac
datetime=`date '+%Y%m%d%H%M'`;
package_full_name="$spec_repository-$branch-$datetime.tar.gz"
package_full_origin_path_prefix="/var/lib/jenkins/tmppackages/h5"
package_full_origin_path="$package_full_origin_path_prefix/$package_full_name";
deploy_package_bak_path="$deploy_package_bak_path""$package_full_name"
# deploy script
deploy_script_path="ssh $deploy_env_server \"rm -rf $deploy_path_prefix/*; if [ ! -d $deploy_path_prefix ]; then mkdir -p $deploy_path_prefix; fi; tar -xzf $deploy_package_bak_path -C $deploy_path_prefix\"";

package_dist_origin_path="$WORKSPACE/dist";
cd $package_dist_origin_path;
tar -czf $package_full_origin_path -C $package_dist_origin_path .;
echo "packaged file is: $package_full_origin_path";
scp $package_full_origin_path $deploy_env_server:"$deploy_package_bak_path";
# restart the server...
eval $deploy_script_path;

  如上,h5 的打包方式,區別在於需要手動打包一為 gz 包,然后到目標機器進行解壓縮即是安裝!

  
  如上,就可以進行一鍵部署測試環境了!
  剩下的,就是自己自由發揮了!
  同理於 h5 的部署方式!

四、重難點提示

       其實,准確來說,上面的操作都比較常規,因為都是最終的結果步驟展示!但是其實這其中有很多的坑,期望提示對你有幫助!

       1. 使用groovy 進行分支獲取時, 需要對 git 命令進行免密授權操作,否則將永遠拉不到分支;

       2. 使用scp, scp 這些命令調用遠程,需要免密登錄,否則授權失敗;

       3. 使用 ssh xx@1.2.2.4 "ls ." 運行遠程命令如同本地命令;

       4. 真正的部署腳本可以遠程服務器上,也可以寫在部署機器上;

       5. 出於安全考慮,默認情況下運行jenkins的用戶都不是root,所以一般不要以為在terminal操作正常的命令,在jenkins上也能正常;

 五、jenkins帶來的切實好處

       為什么一定要用jenkins?難道就因為其名聲大燥嗎?其實是是因為它真的能帶來這些好處:

       1. 部署速度指數級提升,以前按照個人的操作速度,要10分鍾左右的操作且要記憶多種復雜關聯命令,現在可能只要2分鍾一鍵搞定,爽不爽?

       2. 部署信息有跡可查,如果按照之前的部署,誰部署出了問題,完全不知道,但是jenkins上有操作記錄,更易發現問題;

       3. 解決了系統兼容性問題引發的不適,之前各自部署來源不一致,可能導致各種難查問題,而用jenkins則保證完全一致;

       4. 拒絕不可靠錯誤代碼的上線,借助於jenkins的單元測試功能,可以發現在一些簡單代碼的問題,避免之前的誤操作上線;

       5. 因為收口部署方式,對於后續新的部署方案,有了更加有利的支持,比如想加入sonar代碼掃描,只需修改下部署部署腳本即可;

 

附:

  Q: jenkins 使用插件進行部署,調用運行shell腳本不成功?
    nohup 運行 java 程序,被關掉后無法重啟。可能原因是 該進程尚未被掛到當前會話,就被kill或者退出。解決辦法是加上適當延遲。

# 該進程可能啟動緩慢
nohup java -jar a.jar &

#sleep 延遲可以處理異步問題
sleep 3
echo " start over, new pid: $! !!!"

  Q: 有哪些方便的插件推薦?
  Publish On SSH & SSH Slaves, 方便進行遠程部署。
  Rebuilder, 方便進行相同參數的部署重新執行, rebuild 即可,避免反復選擇參數信息。
  Active Choice, 下拉框,可以觸發腳本執行,方便進行動態響應,而不是全靜態的參數。
  Timestamper, 可以獲取時間參數,以便進行日志類記錄;
  user build vars plugin, 獲取各種系統變量;
  Workspace Cleanup Plugin, 空間清理插件,避免jenkins占用太多空間;

 

一句話總結:有時知道問題比解決問題更重要!


免責聲明!

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



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