一「腳」到位-淋漓盡致的自動化部署

本文來自網易雲社區linux


文/洪曉歡
git

1 利用自動部署平臺遇到的困境

自從使用了自動部署平臺,環境部署變得簡單不少,在嚐到甜頭的同時也有問題隨之產生。開發修改了代碼或修復了bug後告知QA須要部署環境,經常使用部署方式是:
選擇環境-定義部署版本-一鍵部署-等待環境和實例部署完成。
因爲項目較特殊,須要自定義一鍵部署會覆蓋的config文件內容,所以適用於項目的部署方式:
選擇環境-定義構建版本-構建版本-等待構建完成-部署實例-等待實例部署完成-到服務器上執行腳原本替換與環境相關的一些配置文件。
能夠想象,一次兩次的手工觸發平臺還能忍受,若是一天屢次或還須要切換部署分支又或者代碼編譯不經過,QA的效率會受到較大影響。
github

因而想到調用自動部署平臺現有的API,但手工調用API後仍是須要人工干預:如校驗是否構建和部署成功、須要更新token。因此進行了如下實踐來完全解放人力進行真正的自動化部署。
web

幾種利用自動部署平臺進行部署的對比:
shell

表1 幾種利用自動部署平臺進行部署的對比



自動部署平臺使用方式 是否須要認爲檢查 能完美結合Jenkins
瀏覽器點擊 不能
手工調用API 不能
下文實踐的方式

2 解決問題的思路和工具的選型

2.1 選擇收發http請求的方式

調用自動部署平臺的API,須要知道如何在服務器內發送請求並獲取到返回值,這樣才能完成你預期的操做。比較通用的有兩種方法: 1)經過編程語言實現 好比Java程序:各自有http請求的相關方法,編寫完成後編譯執行達到目的,這種方式雖然較爲熟悉但過於重量級,執行一個源文件還須要引入依賴包等,最致命的是太笨拙,分支等參數寫死在代碼中,牽一髮而動全身,即便變化的參數寫在一個配置文件中,在須要修改如分支的值還要編輯文件,放棄之。 好比Python、Perl:對熟悉編程的人來講Python、Perl這類標準的編程語言可能更快,但shell腳本的學習成本更低,代碼也更簡約。考慮到僅在linux裏實現,遵循「KEEP IT SIMPLE,STUPID」的原則,未採用Python或Perl。 2)使用命令行工具 嘗試了兩種工具:curl和wget。curl基於libcurl庫,這個庫是一個穩定的跨平臺的類庫,任何人能夠無償使用其API進行開發,wget僅支持命令行方式運行,沒有類庫,不提供API,二者都支持http協議,都能抓取網頁信息,具體的使用方法請--help。 curl命令調用接口:
編程

圖1 curl發送http請求


wget調用接口後的文件: json

圖2 wget發送http請求

 

圖3 wget返回存入文件


前者直接返回結果:一個json object。後者會生成一個文件,文件內容爲請求返回的結果。不選擇wget的兩個緣由:其一,太多的文件生成,每次執行wget就生成一個文件,假設一次完整部署須要調用N個接口,一天須要部署M次,當前文件夾下會產生N*M個文件,固然你能夠每次調用前或後刪除文件,這又多了一次操做;其二,須要讀取文件內容,僅一個json對象不必花費如此大的精力。
api

不一樣收發請求方式的對比:
數組


表2 不一樣收發請求方式的對比



服務器收發請求方式 是否有依賴包 返回結果的解析成本 學習成本 傳參是否靈活
Java程序 較高
curl工具
wget工具 較高

2.2 選擇解析json文本的方式

既然已經獲取到接口返回,下一步就是對返回值進行提取來做爲具體操做的判斷,使用Java的json包解析json是很是熟悉和簡單的,但拋棄Java的狀況會怎樣,使用sed、awk解析和拼接?若是隻是鍵和值的簡單列表,又有較強的操縱能力,能夠嘗試,但從開放的API返回值來看,部分具備數組和複雜的對象,硬上的話花費的時間還不如選擇編程語言了,json這類具備特定格式的文本不會被linux忽視,jq工具解決了解析的問題。
瀏覽器

jq是一個輕量級和靈活的命令行json處理器,由C語言編寫而且運行時無依賴,適用於幾乎全部平臺,你能夠把它想象成專門處理json數據的sed命令,用它來切割和篩選、映射和轉換結構化數據。更多的jq介紹可訪問官網:http://stedolan.github.io/jq/,不只提供了各類平臺能直接運行的二進制文件:



圖4 jq工具的多平臺支持


還有完整的使用手冊:

圖5 jq使用手冊


除了經常使用的文本輸出格式化、json查詢,更有運算、內置函數、條件比較、變量聲明、自定義函數等高級功能。

json解析方式的對比:



表3 json解析方式的對比



服務器上解析json方式 學習成本 功能是否強大 複雜度
awk、sed工具 較高
jq工具


注意:debian系統須要下載並安裝deb文件,若是沒有必定的權限是沒法安裝的,須要提交任務請SA安裝。  

3 項目實踐

3.1 腳本編寫思路

發送請求和解析返回值的方式都已肯定,接下來就開始編寫shell腳本。整個腳本的設計思路簡單清晰:每發送一次請求後獲取指定返回值,對比指望值來判斷是否符合預期。項目中涉及到幾個接口的調用和判斷:


獲取token—>判斷返回碼—>指定部署分支—>判斷返回碼—>構建版本—>判斷構建狀態—>部署實例—>判斷實例狀態。


其中構建版本和部署實例須要循環調用,循環體內判斷構建和部署狀態,一旦成功跳出循環,超過循環次數還未成功視爲失敗則退出程序。正常狀況下構建和部署在必定時間內能成功,不須要循環等待和判斷狀態,但若是出現偶爾獲取源碼失敗或部署平臺自己偶發問題而引發的響應滯後,仍是容許多等待幾回的。一開始在循環體內判斷有異常跳出循環,幾回執行後發現異常值沒法窮舉的,改爲了判斷成功狀態。用戶執行腳本需定義一個參數:分支名。


if [ $estatus = "build_succ" ];then
        DEPLOY_URL1=http://omad.hz.netease.com/api/cli/deploy?token=
        DEPLOY_URL2="&moduleId=真實ID&envId=真實ID&instanceId=真實ID"
        DEPLOY_URL="$DEPLOY_URL1$token$DEPLOY_URL2"        
        DEPLOY_CMD=`curl $DEPLOY_URL`
        deploy_code=`echo $DEPLOY_CMD | jq .code`        #判斷接口返回值
        if [ $deploy_code -eq 200 ];    then
        sleep 3
        istatus_count=0
        #循環並判斷環境狀態和實例狀態
                while [ $istatus_count -ne 10 ]                do
                    ISTATUS_URL1=http://omad.hz.netease.com/api/cli/istatus?token=
          ISTATUS_URL2="&envId=真實ID&instanceId=真實ID"
          ISTATUS_URL="$ISTATUS_URL1$token$ISTATUS_URL2"
                    ISTATUS_CMD=`curl $ISTATUS_URL`
                    istatus=`echo $ISTATUS_CMD | jq .status | sed 's/^"//g' | sed 's/\"//g'`
                    ideployStatus=`echo $ISTATUS_CMD | jq .deployStatus | sed 's/^"//g' | sed 's/\"//g'`                    if [ $istatus != "running" -o $ideployStatus != "success" ];                    then
                            let istatus_count++
                            sleep 5        
                    else
                            break
                    fi
                done    
        else
                echo "deploy error:$deploy_code"                                
                exit 1
        fi        else
        echo "estatus error:$estatus"                                
        exit 1                    fi

腳本調試中遇到的問題可能是語法和格式錯誤,好比使用變量時缺乏變量符、if判斷的格式書寫錯誤、拼接url出錯等。

3.2 結合Jenkins完成代碼自動檢測和部署


至此,符合現有環境的自動部署腳本完成,接下來就是利用Jenkins進行自動觸發。推薦使用參數化構建過程來肯定分支名,在一個環境須要切換多個分支時比較靈活和下降輸入錯誤:

圖6 Jenkins上配置branch_name參數

 

圖7 Jenkins上配置部署和重啓腳本


構建後發現job構建成功,服務器上確實部署成功但沒有應用進程啓動,腳本單獨在服務器上執行並無問題,詢問了大牛和搜索一些資料後知道了還須要設置一個jenkins的環境變量,部署後重啓的是後臺進程,jenkins每次構建結束會默認kill這類進程。避免進程被殺掉的簡單方法就是修改jenkins的環境變量BUILD_ID的值,從而讓Jenkins認爲此進程不是由Job的構建過程衍生的。官方說明:https://wiki.jenkins-ci.org/display/JENKINS/ProcessTreeKiller。 

 

圖8 設置Jenkins環境變量


符合項目的自動部署操做已集成在Jenkins中,若是能定義部署的觸發條件就讓「自動」變得更有意義,配置源碼管理和構建觸發器讓Jenkins定時查詢分支是否有更新,若是有更新就觸發構建的shell進行環境部署:



圖9 Jenkins上配置源碼管理


一個job完成了根據定義的分支進行代碼檢測+觸發自動部署+自定義腳本。

4 總結

此次實踐必定程度上提高了QA的工做效率,部署一次環境不再用在瀏覽器、服務器上花費至少3分鐘的時間,也節省了開發和QA的溝通成本,開發不用通知QA代碼是否更新,在項目頻繁有代碼提交的時候效果更爲突出。

對於自動部署腳本自己還存在一些值得改進的地方,好比適用於多個應用、環境和實例構建部署的狀況,這須要編寫更復雜的腳本將三種值都做爲參數傳入。

自動部署只是項目持續集成中的一個環節,自動部署後須要根據不一樣狀況觸發冒煙和迴歸測試,再進行靜態代碼檢查及測試覆蓋率統計,這些工做後續都須要完善。


原文:一「腳」到位-淋漓盡致的自動化部署

網易雲新用戶大禮包:https://www.163yun.com/gift

本文來自網易實踐者社區,經做者洪曉歡受權發佈。

相關文章
相關標籤/搜索