Shell系列(四)——— 實例解讀后端項目自動部署的Shell腳本

后端結(jié)構(gòu):

公司后端采用了Kubernetes+OpenFaaS+Flask的架構(gòu)。openfaas提供FaaS服務(wù)。每一個flask項目具體到一個function中,一個function部署在一個docker容器中,各function之間相互獨立,保證每個后端在操作同一個工作項目時邏輯的獨立性。


腳本應(yīng)用場景:

部署腳本需求的必要性:

  • openfaas的部署需要自動生成yml文件
  • 實際部署階段需要區(qū)分生產(chǎn)環(huán)境(dev開發(fā),stage預(yù)發(fā)布,prod正式,test測試)
  • yml的生成結(jié)果需要動態(tài)化,如后端每一個項目都不一樣,一個項目相當(dāng)于一個faas function,因此function_name每個人必然是不一樣的。

代碼實現(xiàn):

里面一些比較重要的文件:

  • template.yml:OpenFaaS Function部署的模板yml,需要手動修改,這里要通過腳本自動化這個流程
  • $0:即當(dāng)前要執(zhí)行的腳本名稱,可以是"deploy.sh"
  • deploy.yml:修改模板得到的yml,用于OpenFaas的部署
  • 變量env:控制部署的環(huán)境
    具體的腳本解讀請看代碼注釋。
// 具體名稱已隱去
"deploy.sh"
#!/usr/bin/env bash

#function_basename=$(basename `pwd`)
function_basename="xx"  # function name,即openfaas function的名稱,項目名稱

env=$1   # 需要部署的環(huán)境的名稱,$1即為后面第一位輸入的參數(shù)

option=$2  # 執(zhí)行的操作,如deploy為部署
# 前幾行定義了整個腳本的操作,如 sh deploy.sh dev deploy,表明這個操作可以自動化整個項目到dev開發(fā)環(huán)境的部署

# 分配faas_gateway(openfaas的具體路由)
# 在使用變量時,如果不修改操作,調(diào)用變量需要加${env}
# 大括號的作用是隔離,如${A}B和$AB是完全不一樣的含義。
# 定義了-h/--help的含義,一個instructions,為操作全過程的介紹。
case ${env} in
    dev|test)
        faas_gateway="xx1"
        faas_gateway_="xx2"
        ;;
    prod|stage)
        faas_gateway="xx3"
        faas_gateway_="xx4"
        ;;
    *|-h|--help)
        echo "$0:usage: [ test ] | [ prod ] | [ dev ] | [ stage ] \n"

        echo "Env:"
        echo "\ttest    Testing Env"
        echo "\tprod    Prod Env"
        echo "\tdev     Dev Env"
        echo "\tstage   Stage Env\n"

        echo "Available Commands:"
        echo "\tbuild   Builds OpenFaaS function containers"
        echo "\tdeploy  Deploy OpenFaaS functions"

        echo "Examples:"
        echo "\tsh deploy.sh test    [ build | deploy ]"
        echo "\tsh deploy.sh prod    [ build | deploy ]"
        echo "\tsh deploy.sh dev     [ build | deploy ]"
        echo "\tsh deploy.sh stage   [ build | deploy ]\n"

        echo "Use \"sh $0 -h\" for more information about a command."
        exit 1
        ;;
esac

# if [ -f "..." ]; 意為檢查引號內(nèi)文件是否存在,如果存在執(zhí)行步驟,不存在執(zhí)行另一步驟
if [ -f "./template.yml" ];then
    echo "template.yml exists."
else
# 重定向內(nèi)容,cat << EOF ... EOF會將EOF開始和結(jié)束中間的內(nèi)容作為輸入
# 再通過">"將內(nèi)容重定向到template.yml
# 這里的含義就是判斷如果這個template模板不存在,創(chuàng)建一個
cat > template.yml <<EOF
provider:
  name: faas
  gateway: faas_gateway
functions:
  function_name:
    lang: xx
    handler: ./function
    image: xx.cn/xx/docker_name:version
EOF

fi

#faas template pull git@xx.cn/xx/xx.git --overwrite     
# 默認(rèn)不使用,公司后端統(tǒng)一模板,配置了orm,dockerfile,flask配置等
# faas template pull 即拉git上的模板,業(yè)務(wù)相關(guān),可忽略

# Dockerfile默認(rèn)在template業(yè)務(wù)模板中有,但每個項目都可能定制化Dockerfile
# 這里操作就是如果自定義Dockerfile,放到指定文件夾中,并覆蓋原模板的Dockerfile
# 放到指定目錄的原因就是在git中你可以看到這個目錄,提醒其他人Dockerfile是定制的
if [ -f "./function/extra/Dockerfile" ];then
    cp -rf ./function/extra/Dockerfile ./template/python3-flask/
fi

# run.sh同理,此為業(yè)務(wù)中腳本,可忽略
if [ -f "./function/extra/run.sh" ];then
    cp -rf ./function/extra/run.sh ./template/python3-flask/
fi

# commit_id為設(shè)計的Docker tag,采用當(dāng)前時間動態(tài)獲取
# 這種tag必然是不會重復(fù)的
commit_id=$(date "+%Y%m%d%H%M%S")
# new_version是當(dāng)前要部署的版本
new_version=$commit_id
echo version: $new_version-$env

# docker name即name:tag中的name,部署到私有hub上的鏡像name
docker_name=$function_basename
function_name=$function_basename

# 為openfaas的項目function起名,除了正式環(huán)境,其他都要帶上環(huán)境變量名
# 如dev-function..../stage-function...
if [ "$env" != "prod" ];then
    function_name=$env-$function_basename
fi

# 重要步驟,將template.yml模板指定內(nèi)容替換
# template.yml的固定部分:faas_gateway,funtion_name,docker_name,version
# sed不重定向不會修改原yml的內(nèi)容,用指定變量替換相應(yīng)字符串位置
sed -e "s/version/$new_version/g;s/function_name/$function_name/g;s/faas_gateway/$faas_gateway_/g;s/docker_name/$docker_name/g" template.yml > deploy.yml

# faas cli 操作 u/p登錄
faas-cli login -g $faas_gateway -u xx --password 'xx'

# option如果是build,用Dockerfile去build,但并不deploy
if [ "$option" = "build" ];then
    function_name=$env-$function_name
fi

faas-cli build -f deploy.yml --build-arg FLASK_ENV=$env

faas-cli push -f deploy.yml

echo "Version:$new_version"

if [ "$option" = "deploy" ];then
    faas-cli deploy -f deploy.yml
    echo '======deploy success======'
    echo [function]: $function_name
    echo [version ]: $new_version
    echo [image   ]: xx.cn/xx/$docker_name:$new_version
    echo '=========================='
    echo ' '

else
    echo '======build success======'
    echo [function]: $function_name
    echo [version ]: $new_version
    echo [image   ]: xx.cn/xx/$docker_name:$new_version
    echo '========================='
    echo ' '

fi

# build完后,項目代碼中刪除build目錄,本地并不需要
rm -rf ./build

以上是一些自動化部署問題的小思考~
如果架構(gòu)不同,也可以參考一下其中的動態(tài)修改,用于自己的項目中,尤其是時間代替tag等這樣的做法,可以使你實現(xiàn)一行命令完成部署的要求。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容