美文网首页
Shell系列(四)——— 实例解读后端项目自动部署的Shel

Shell系列(四)——— 实例解读后端项目自动部署的Shel

作者: 曲谐_ | 来源:发表于2019-07-31 16:15 被阅读0次

    后端结构:

    公司后端采用了Kubernetes+OpenFaaS+Flask的架构。openfaas提供FaaS服务。每一个flask项目具体到一个function中,一个function部署在一个docker容器中,各function之间相互独立,保证每个后端在操作同一个工作项目时逻辑的独立性。


    脚本应用场景:

    部署脚本需求的必要性:

    • openfaas的部署需要自动生成yml文件
    • 实际部署阶段需要区分生产环境(dev开发,stage预发布,prod正式,test测试)
    • yml的生成结果需要动态化,如后端每一个项目都不一样,一个项目相当于一个faas function,因此function_name每个人必然是不一样的。

    代码实现:

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

    • template.yml:OpenFaaS Function部署的模板yml,需要手动修改,这里要通过脚本自动化这个流程
    • $0:即当前要执行的脚本名称,可以是"deploy.sh"
    • deploy.yml:修改模板得到的yml,用于OpenFaas的部署
    • 变量env:控制部署的环境
      具体的脚本解读请看代码注释。
    // 具体名称已隐去
    "deploy.sh"
    #!/usr/bin/env bash
    
    #function_basename=$(basename `pwd`)
    function_basename="xx"  # function name,即openfaas function的名称,项目名称
    
    env=$1   # 需要部署的环境的名称,$1即为后面第一位输入的参数
    
    option=$2  # 执行的操作,如deploy为部署
    # 前几行定义了整个脚本的操作,如 sh deploy.sh dev deploy,表明这个操作可以自动化整个项目到dev开发环境的部署
    
    # 分配faas_gateway(openfaas的具体路由)
    # 在使用变量时,如果不修改操作,调用变量需要加${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 "..." ]; 意为检查引号内文件是否存在,如果存在执行步骤,不存在执行另一步骤
    if [ -f "./template.yml" ];then
        echo "template.yml exists."
    else
    # 重定向内容,cat << EOF ... EOF会将EOF开始和结束中间的内容作为输入
    # 再通过">"将内容重定向到template.yml
    # 这里的含义就是判断如果这个template模板不存在,创建一个
    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     
    # 默认不使用,公司后端统一模板,配置了orm,dockerfile,flask配置等
    # faas template pull 即拉git上的模板,业务相关,可忽略
    
    # Dockerfile默认在template业务模板中有,但每个项目都可能定制化Dockerfile
    # 这里操作就是如果自定义Dockerfile,放到指定文件夹中,并覆盖原模板的Dockerfile
    # 放到指定目录的原因就是在git中你可以看到这个目录,提醒其他人Dockerfile是定制的
    if [ -f "./function/extra/Dockerfile" ];then
        cp -rf ./function/extra/Dockerfile ./template/python3-flask/
    fi
    
    # run.sh同理,此为业务中脚本,可忽略
    if [ -f "./function/extra/run.sh" ];then
        cp -rf ./function/extra/run.sh ./template/python3-flask/
    fi
    
    # commit_id为设计的Docker tag,采用当前时间动态获取
    # 这种tag必然是不会重复的
    commit_id=$(date "+%Y%m%d%H%M%S")
    # new_version是当前要部署的版本
    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起名,除了正式环境,其他都要带上环境变量名
    # 如dev-function..../stage-function...
    if [ "$env" != "prod" ];then
        function_name=$env-$function_basename
    fi
    
    # 重要步骤,将template.yml模板指定内容替换
    # template.yml的固定部分:faas_gateway,funtion_name,docker_name,version
    # sed不重定向不会修改原yml的内容,用指定变量替换相应字符串位置
    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
    
    

    以上是一些自动化部署问题的小思考~
    如果架构不同,也可以参考一下其中的动态修改,用于自己的项目中,尤其是时间代替tag等这样的做法,可以使你实现一行命令完成部署的要求。

    相关文章

      网友评论

          本文标题:Shell系列(四)——— 实例解读后端项目自动部署的Shel

          本文链接:https://www.haomeiwen.com/subject/uwktdctx.html