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

2019-07-31  本文已影响0人  曲谐_

后端结构:

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


脚本应用场景:

部署脚本需求的必要性:


代码实现:

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

// 具体名称已隐去
"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等这样的做法,可以使你实现一行命令完成部署的要求。

上一篇下一篇

猜你喜欢

热点阅读