運維與自動化系列④自動化部署基礎與githtml
自動化部署基礎與git前端
一:上一篇的代碼是保存在本地,可是在生產環境當中是由版本控制進行代碼管理,以便於發佈代碼和回滾,通常是使用gitlib比較多,另外還有用svn的公司,趨勢是git爲主,所以本文以git爲使用對象node
1.1:在git服務器新建一個web組和項目web-demo:git
準備web頁面並提交至git服務器(此處我用一個簡單的html項目,你們若是沒有現成的項目能夠本身建一個簡單的index.html頁面便可):
#準備提交代碼目錄web
# mkdir /source/web/web-demo -p
# 準備一個項目而後提交至git服務器
將項目上傳到/source/web/web-demo目錄shell
[www@master web-demo]$ pwd /source/web/web-demo [www@master web-demo]$ ll total 20 drwxr-xr-x 6 www www 4096 Jun 6 13:46 assets -rw-r--r-- 1 www www 1150 Jun 6 17:59 favicon.ico drwxr-xr-x 2 www www 4096 Jun 6 15:32 images -rw-r--r-- 1 www www 4323 Jun 6 16:19 index.html # chown -R www.www /source # su - www cd /source/web git config --global user.name "reblue520" git config --global user.email "reblue520@163.com" git config --global color.ui true cd /source/web/web-demo git init git add * git commit -m 'web-demo all' git remote add origin git@192.168.3.198:web/web-demo.git git push -u origin master # 確認代碼提交成功
1.2:使用ssh key受權www用戶能夠更新和提交代碼:vim
#在admin area–web-demo-profile settings-ssh keys將www用戶的公鑰放在gitlab的web界面: [www@master ~]$ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArALvWj9fYnDtZxOue7OXvznI02QAyQgeR1SkjnlE3YwZIfjOJU1x2n7jPUxRuPR+wQPRZ9/AQUD5mNzYGLGxXY0Tpjw7zRQ8HFEmZSm4NgMNfYedyHpWbbJLrYTR4vg5pNFtJm7vmZdaV6JP6WLtyDkC83pKK8oOOha8PhNwXKcMMUMjS9NGhbaR0I8cDsgOOo0wAZl8oNGD/6FWc4XsDAfvWLac4a9BUtisn14YZcTqjEwkEv0DxnXZ2yVtGwPNmiPEhdfvyDM6kPtBL0BptWEVWvqD0bBS31Ro8FH3BPWunrgDQA/XAkjhHChF+A0mU+lVYncqjtSG9HsKvMUU1Q== www@master
1.3在部署機準備目錄環境:bash
mkdir -p /deploy/code/web-demo -p mkdir -p /deploy/config/web-demo/base mkdir -p /deploy/config/web-demo/other mkdir -p /deploy/tar mkdir -p /deploy/tmp mkdir -p /opt/webroot mkdir /webroot chown -R www:www /deploy chown -R www:www /opt/webroot chown -R www:www /webroot
# su - www # 切換到www用戶 $ rm -rf /deploy/code/web-demo # 刪除原目錄,改用git倉庫管理代碼 $ cd /deploy/code/ $ git clone git@192.168.3.198:web/web-demo.git # 克隆後會生成deb-demo目錄,裏面的代碼即咱們在1.1中準備的代碼
1.4:編輯部署腳本並準備相關目錄:
1.4.1:或git提交的代碼版本號,用戶記錄提交的版本,作部署或代碼回滾使用:服務器
[www@master web-demo]$ pwd /source/web/web-demo $ git show #獲取最近更新的版本信息 [www@master web-demo]$ git show |grep commit | cut -d ' ' -f2 # 只獲取版本號 91d09cc28f48803d8795f62d925de70f192daeda [www@master web-demo]$ VERSION_L=$(git show |grep commit | cut -d ' ' -f2) [www@master web-demo]$ echo ${VERSION_L:0:8} # 切片取固定長度 91d09cc2
1.4.3:在各web服務器準備如下目錄:
#web服務器操做網絡
# mkdir /opt/webroot #保存代碼的目錄 # chown www.www /opt/webroot/ -R # mkdir /webroot #生成配置文件的web主目錄,下面是項目的工做目錄,好比/webroot/web-demo # chown www.www /webroot/ -R $ touch /webroot/web-demo
1.4.4:腳本改造以下,主要實現從git拉取代碼再部署至服務器:
#!/bin/bash #Dir List 部署節點(即部署節點須要作的操做) # mkdir -p /deploy/code/web-demo # mkdir -p /deploy/config/web-demo/base # mkdir -p /deploy/config/web-demo/other # mkdir /deploy/tmp # mkdir /deploy/tar # chown -R www.www /deploy # chown -R www.www /webroot # chown -R www.www /opt/webroot/ # chown -R www.www /webroot # 須要在客戶端節點作的操做 # mkdir /opt/webroot # mkdir /webroot # chown -R www.www /webroot # chown -R www.www /opt/webroot/ # chown -R www.www /webroot # [www@ ~]$ touch /webroot/web-dem # Node List 服務器節點 PRE_LIST="192.168.3.12" # 預生產節點 GROUP1_LIST="192.168.3.12 192.168.3.13" GROUP2_LIST="192.168.3.13" ROLLBACK_LIST="192.168.3.12 192.168.3.13" # 日誌日期和時間變量 LOG_DATE='date "+%Y-%m-%d"' # 若是執行的話後面執行的時間,此時間是不固定的,這是記錄日誌使用的時間 LOG_TIME='date "+%H-%M-%S"' # 代碼打包時間變量 CDATE=$(date "+%Y-%m-%d") # 腳本一旦執行就會取一個固定時間賦值給變量,此時間是固定的 CTIME=$(date +"%H-%M-%S") # shell env 腳本位置等變量 SHELL_NAME="deploy.sh" # 腳本名稱 SHELL_DIR="/home/www/" # 腳本路徑 SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log" # 腳本執行日誌文件路徑 # code env 代碼變量 PRO_NAME="web-demo" # 項目名稱的函數 CODE_DIR="/deploy/code/web-demo" # 從版本管理系統更新的代碼目錄 CONFIG_DIR="/deploy/config/web-demo" # 保存不一樣項目的配置文件,一個目錄裏面就是一個項目的一個配置文件或多個配置文件 TMP_DIR="/deploy/tmp" # 臨時目錄 TAR_DIR="/deploy/tar" # 打包目錄 LOCK_FILE="/tmp/deploy.lock" # 鎖文件路徑 usage(){ # 使用幫助函數 echo $"Usage: $0 [ deploy | rollback [ list | version ]" } writelog(){ # 寫入日誌的函數 LOGINFO=$1 # 將參數做爲日誌輸入 echo "${CDATE} ${CTIME} : ${SEHLL_NAME} : ${LOGINFO}" >> ${SHELL_LOG} } # 鎖函數 shell_lock(){ touch ${LOCK_FILE} } # 解鎖函數 shell_unlock(){ rm -f ${LOCK_FILE} } # 獲取代碼的函數 code_get(){ echo "code_get" writelog code_get cd $CODE_DIR && git pull # 進入到代碼目錄更新代碼,此處必須免密碼更新,此目錄僅用於代碼更新不能放其餘任何文件 cp -rf ${CODE_DIR} ${TMP_DIR}/ # 臨時保存代碼並重命名,包名爲時間+版本號,準備複製到web服務器 API_VERL=$(git show | grep commit | cut -d ' ' -f2) API_VER=$(echo ${API_VERL:0:8}) # 版本號 } code_build(){ # 代碼編譯函數 echo code_build } code_config(){ # 配置文件函數 writelog "code_config" /bin/cp -rf ${CONFIG_DIR}/base/* ${TMP_DIR}/"${PRO_NAME}" # 將配置文件放在本機保存配置文件的臨時目錄,用於暫時保存代碼項目 PKG_NAME="${PRO_NAME}"_"$API_VER"_"${CDATE}-${CTIME}" # 定義代碼目錄名稱 cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME} # 重命名代碼文件爲web-demo_123-20170629-11-19-10格式 } code_tar(){ # 對代碼打包函數 writelog code_tar cd ${TMP_DIR} && tar czf ${PKG_NAME}.tar.gz ${PKG_NAME} --exclude=".git" # 將目錄打包成壓縮文件,便於網絡傳輸 writelog "${PKG_NAME}.tar.gz packaged success" # 記錄打包成功的日誌 } code_scp(){ # 代碼壓縮包scp到客戶端的函數 writelog "code_scp" for node in $PRE_LIST;do # 循環服務器節點列表 scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot/ # 將壓縮後的代碼包複製到web服務器的/opt/webroot done for node in $GROUP1_LIST;do # 循環服務器節點列表 scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot/ # 將壓縮後的代碼包複製到web服務器的/opt/webroot done } cluster_node_add(){ #將web服務器添加至前端負載 echo cluster_node_add } cluster_node_remove(){ # 將web服務器從集羣移除函數(正在部署的時候應該不處理業務) writelog "cluster_node_remove" } url_test(){ URL=$1 curl -s --head $URL |grep '200 OK' if [ $? -ne 0 ];then shell_unlock; writelog "test error" && exit; fi } pre_deploy(){ # 代碼解壓部署函數,預生產節點 writelog "pre_deploy" for node in ${PRE_LIST};do # 循環預生產服務器節點列表 cluster_node_remove ${node} # 部署以前將節點從前端負載刪除 echo "pre_deploy, cluster_node_remove ${node}" ssh ${node} "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz" #分別到web服務器執行壓縮包解壓命令 ssh ${node} "rm -f /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo" # 整個自動化的核心,建立軟鏈接 done } pre_test(){ # 預生產主機測試函數 for node in ${PRE_LIST};do # 循環預生產主機列表 curl -s --head http://${node}:9999/index.html | grep "200 OK" # 測試web界面訪問 if [ $? -eq 0 ];then # 若是訪問成功 writelog " ${node} Web Test OK!" # 記錄日誌 echo " ${node} Web Test OK!" cluster_node_add ${node} # 測試成功以後調用添加函數把服務器添加至節點, writelog "pre,${node} add to cluster OK!" # 記錄添加服務器到集羣的日誌 else # 若是訪問失敗 writelog "${node} test no OK" # 記錄日誌 echo "${node} test not OK" shell_unlock # 調用刪除鎖文件函數 break # 結束部署 fi done } group1_deploy(){ # 代碼解壓部署函數 writelog "group1_code_deploy" for node in ${GROUP1_LIST};do # 循環生產服務器節點列表 cluster_node_remove $node echo "group1, cluster_node_remove $node" ssh ${node} "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz" # 分別到各web服務器節點執行壓縮包解壓命令 ssh ${node} "rm -f /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo" # 整個自動化的核心,建立軟鏈接 done scp ${CONFIG_DIR}/other/192.168.3.13.server.xml 192.168.3.13:/webroot/web-demo/server.xml # 將差別項目的配置文件scp到此web服務器並以項目結尾 } group1_test(){ # 生產主機測試函數 for node in ${PRE_LIST};do # 循環生產主機列表 curl -s --head http://${node}:9999/index.html | grep "200 OK" #測試web界面訪問 if [ $? -eq 0 ];then #若是訪問成功 writelog " ${node} Web Test OK!" #記錄日誌 echo "group1_test,${node} Web Test OK!" cluster_node_add writelog " ${node} add to cluster OK!" #記錄將服務器 添加至集羣的日誌 else #若是訪問失敗 writelog "${node} test no OK" #記錄日誌 echo "${node} test no OK" shell_unlock # 調用刪除鎖文件函數 break # 結束部署 fi done } rollback_fun(){ for node in $ROLLBACK_LIST;do # 循環服務器節點列表 # 注意必定要加"號,不然沒法在遠程執行命令 ssh $node "rm -f /webroot/web-demo && ln -s /opt/webroot/$1 /webroot/web-demo" # 當即回滾到指定的版本,$1即指定的版本參數 echo "${node} rollback success!" done } rollback(){ # 代碼回滾主函數 if [ -z $1 ];then shell_unlock # 刪除鎖文件 echo "Please input rollback version" && exit 3; fi case $1 in # 把第二個參數作當本身的第一個參數 list) ls -l /opt/webroot/*.tar.gz ;; *) rollback_fun $1 esac } main(){ if [ -f $LOCK_FILE ] ;then # 先判斷鎖文件在不在,若是有鎖文件直接退出 echo "Deploy is running" && exit 10 fi DEPLOY_METHOD=$1 # 避免出錯誤將腳本的第一個參數做爲變量 ROLLBACK_VER=$2 case $DEPLOY_METHOD in deploy) # 若是第一個參數是deploy就執行如下操做 shell_lock; # 執行部署以前建立鎖。若是同時有其餘人執行則提示鎖文件存在 code_get; # 獲取代碼 code_build; # 若是要編譯執行編譯函數 code_config; # cp配置文件 code_tar; # 打包 code_scp; # scp到服務器 pre_deploy; # 預生產環境部署 pre_test; # 預生產環境測試 group1_deploy; # 生產環境部署 group1_test; # 生產環境測試 shell_unlock; # 執行完成後刪除鎖文件 ;; rollback) # 若是第一個參數是rollback就執行如下操做 shell_lock; # 回滾以前也是先建立鎖文件 rollback $ROLLBACK_VER; shell_unlock; # 執行完成刪除鎖文件 ;; *) usage; esac } main $1 $2
1.5 運行部署腳本:
[www@master ~]$ ./deploy.sh deploy code_get Already up-to-date. code_build web-demo_75463f1b_2017-06-30-15-05-57.tar.gz 100% 1207KB 1.2MB/s 00:00 web-demo_75463f1b_2017-06-30-15-05-57.tar.gz 100% 1207KB 1.2MB/s 00:00 web-demo_75463f1b_2017-06-30-15-05-57.tar.gz 100% 1207KB 1.2MB/s 00:00 pre_deploy, cluster_node_remove 192.168.3.12 HTTP/1.1 200 OK 192.168.3.12 Web Test OK! cluster_node_add group1, cluster_node_remove 192.168.3.12 group1, cluster_node_remove 192.168.3.13 /deploy/config/web-demo/other/192.168.3.13.server.xml: No such file or directory HTTP/1.1 200 OK group1_test,192.168.3.12 Web Test OK! cluster_node_add
1.5.2測試修改代碼後可否正常獲取最新代碼,並部署成功
# 在本身的項目裏面修改代碼而後提交至git服務器
[www@master web-demo]$ pwd /source/web/web-demo [www@master web-demo]$ vim index.html [www@master web-demo]$ git add "index.html" [www@master web-demo]$ git commit -m "edit index.html add www.chinasoft.com" [master 7886914] edit index.html add www.chinasoft.com 1 file changed, 2 insertions(+), 2 deletions(-) [www@master web-demo]$ git push origin master Counting objects: 5, done. Delta compression using up to 2 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 324 bytes | 0 bytes/s, done. Total 3 (delta 2), reused 0 (delta 0) To git@192.168.3.198:web/web-demo.git 75463f1..7886914 master -> master
# 再次部署
[www@master ~]$ ./deploy.sh deploy
能夠看到客戶端已經更新了
http://192.168.3.13:9999/