一键实现自动化部署(灰度发布)实践

标签: github svn git centos | 发表时间:2019-08-27 10:55 | 作者:民工哥技术之路
出处:https://segmentfault.com/blogs

在过去几年的DevOps的浪潮中,自动化、持续集成这两个概念早已深入人心(互联网技术人)。比尔盖茨先生曾经都说过:“任何技术在一个业务中使用的第一条规则就是,将自动化应用到一个高效的操作上将会放大高效。第二条就是自动化应用到一个低效操作上,则放大了低效率。”

自动化部署也逐渐成为各中小型企业追求的方向,那么,今天民工哥就自动化部署的概述、自动化部署的工具、自动化部署的流程、自动化部署实践等4个方面,与大家一同来讨论、交流一下关于中小企业自动部署的问题。

1、自动化部署概述

1.1 什么是自动化部署

一句简单的话概括:部署的过程中所有的操作全部自动化,无需人工手工干预。

1.2 自动部署的好处

传统的部署方式如下:

运维人员手工使用Scp、Xftp等方式来传输数据

手工登录服务器执行git pull 、svn update等命令进行更新代码的操作

开发人员手工编译打包,然后通过内网传输给运维人员

运维人员通过rz上传的方式上传到目标服务器,然后,执行重命名原包、拷贝新包到目标目录,再执行服务应用重启命令完成整个部署过程

看似非常简单,也不是很麻烦,但是一旦项目多,部署频繁,这种情况下就会大大降低工作效率。民工哥之前工作中就有这类体验,公司的活动类项目高达100+,很多都是需要快速上线及下线、或者更新的,手工部署真的累。

传统的部署方式有以下的缺点:

整个过程都需要人员参与,占用大量的时间,效率低下

上线、更新、回滚速度慢

存在一定的管理混乱,人为误操作的机率增大

所以,自动化部署的优势就通过这种对比显现出来了!!

2、自动化部署的工具

有自动动部署的概念,就需要自动化部署的工具,今天来介绍下一些这方面的工具给大家,怎么用?如何用?大家根据实际需求来定,一切不以需求来定的工具、流程、方法等都是耍流氓。

2.1 Jenkins

Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。Jenkins应该说是目前最好用的持续集成工具之一,它的插件非常多,安装也很方便,功能相当的强大、灵活,最大的缺点就是学习成本较高。

2.2 ElectricFlow
ElectricFlow 是一个发布自动化工具,提供免费的社区版本,你可以在VirtualBox上运行。ElecticFlow支持大量插件和基于Groovy的 DSL,CLI,APIs。

2.3 Microsoft Visual Studio
微软DevOps产品的基础之一是 Visual Studio。 Visual Studio允许用户定义版本定义,自动化运行,跟踪版本等等。

2.4 Octopus Deploy
Octopus Deploy创建目的是为了.NET应用的自动化部署。你可以在一台服务器安装或在Azure里做成实例。

2.5 IBM UrbanCode
2013年被IBM公司收购,UrbanCode 自动化部署到本地或云环境。

2.6 AWS CodeDeploy
Amazon的自动化部署工具CodeDeploy,有着令人印象深刻的客户名单、平台与语言无关。

2.7 DeployBot
DeployBot 可以链接任何Git存储库,并且允许手动或自动部署到多种环境。DeployBot提供大量集成,包括通过Slack部署的能力。

2.8 Shippable
Shippable 规定了它们自己的“DevOps支柱”和它们自己的CI平台,运行依靠称为minions的基于Docker的容器。

2.9 TeamCity
TeamCity 是一个来自Jet Brains的CI服务器。TeamCity 有智能的配置功能和拥有官方Docker镜像服务器和代理。

2.10 Bamboo
Bamboo Server 是CI,由来自在Atlassian的人们提供,他们是Jira和Confluence的制造者。Bamboo公布“integrations that matter”并提供一个“small teams”包,捐赠给 Room to Read慈善事业。

2.11 Codar
Codar 是一个HP的持续部署解决方案。部署使用Jenkins触发。

2.12 CircleCI
CircleCI 是一个CI解决方案,强调灵活性、可靠性和速度。CircleCI提供从资源到创建到部署的解决方案,并且支持大量的语言和应用。

2.13 Gradle
Gradle 是一个被一些业内最有名的例如LinkedIn, Netflix, 和Adobe所使用的创建工具。Gradle使用Groovy创建脚本,按惯例构建框架,并认为构建工具同时作为Apache的Ant的通用工具。

2.14 Automic
Automic 试图应用DevOps原理给一些后端应用,允许他们从已经在过去几年里许多前端、基于web的应用相同的实践上受益。

2.15 Distelli
Distelli 专门在任何地方部署Kubernetes集群,除了可以在任何云或物理服务器上使用。根据TechCrunch这篇文章,Distelli 在2015年12月获得了280万美元的资金,是由前AWS员工Rahul Singh创立的。

2.16 XL Deploy
XL Deploy 是一个来自XebiaLabs的应用发布自动化工具,支持大量插件和环境,使用无代理架构。

2.17 Codeship
Codeship是服务器托管CI解决方案,通过原生Docker支持定制。

2.18 GoCD
一个CD服务器,强调可视化工作流,GoCD 是一个开源项目,由ThoughtWorks公司赞助开发。

2.19 Capistrano
Capistrano 是一个开源部署工具,使用Ruby开发。Capistrano 文档具有脚本语言和“理智的,富有表现力的API。”

2.20 Travis CI
Travis CI 可以同步到你的GitHub账户,允许自动化测试和部署。Travis CI是一个免费的开源项目。

2.21 BuildBot
BuildBot 是一个开源的基于Python的持续集框架,自称为“内含有电池的框架”。BuildBot是面向罐装的解决方案用例,目前还不够灵活。

3、自动化部署的流程

大概的流程步骤如下:

  • 获取代码
  • 编译打包
  • 移除目标服务器
  • 解压文件到目标目录
  • 拷贝差异化文件
  • 重启服务
  • 测试
  • 重新加入集群
  • 继续下一个节点或一组节点

clipboard.png

如果在测试时出现问题,则需要回滚到上一次稳定版本。

一般可以将需要回滚的版本先列出来,然后将现有的软链接文件删除,重新将上一个版本的源文件生成一个软链接至目标目录,然后重新启动服务,进行自动化测试,最终加入集群。

4、自动化部署实践

说完了一堆的理论东东,接下来就是需要实践操作了,我之前也写过一个自动化的脚本,如下图:

clipboard.png

这里列举两个实例,这两个实例是由网友西门飞冰投稿提供,具体的实例如下:

4.1 使用shell脚本实现java灰度发布
脚本使用环境:

1、操作系统:centos 6.5 64位

2、代码使用gitlab进行管理

3、代码每次上线通过tag控制

4、前端使用haproxy实现负载均衡,使用haproxy socat实现RS的平滑上下线

5、WEB container使用tomcat实现

6、项目构建使用maven

使用脚本注意事项:
1、 发布机器需要能够解析web服务器主机名,并且配置ssh通信
2、 变量中的目录以及用户等信息需要自己创建,脚本没有做判断自己创建。我这里web服务器是使用ansible进行部署的,相关目录和用户都会自动创建。
3、代码的部署使用tag,但是代码的更新使用软连接来控制,回滚则切换到上一个软连接
4、由于java是编译型语言,我们使用maven来进行编译,所以需要安装maven环境。
5、关于环境配置文件:配置文件为自己手动维护,每次都是删除git仓库拉取下来的配置文件,把对应环境的代码文件复制进编译目录进行编译。

脚本代码大概的步骤如下:

  #!/bin/bash

# 设置时间变量
CTIME=$(date "+%Y-%m-%d-%H-%M")
# 项目名称,建议和gitlab仓库名称一致
project=
# 本地代码目录(gitlab拉取代码后存放目录)
CODE_DIR=/data/gitlab/"$project"
# 临时代码目录,用来修改配置文件和编译打包代码
TMP_DIR=/data/tmp/"$project"
# 用来存放war包
WAR_DIR=/data/war/"$project"
# 对应环境配置文件
deploy_conf=/data/conf/pro/"$project"/*
# 代码中的配置文件路径
local_conf=$TMP_DIR/src/main/resources/config
# 远程主机名称
REMOTE_HOST="tomcat-01 tomcat-02"
# 远程主机代码目录
REMOTE_CODE_DIR=/data/webapps/"$project"
# 远程主机用户
REMOTE_USER=root
# 远程主机war包存放目录
REMOTE_WAR_DIR=/data/war/
# 代码临时目录
CODE_TMP=/data/code_tmp/
# 上线日志
DEPKOY_LOG=/data/log/pro_log.log

# 脚本使用帮助
usage(){
echo $"Usage: $0 [deploy tag | rollback_list | rollback_pro ver]"
}

# 拉取代码
git_pro(){
if [ $# -lt 1 ];then
echo "请传入tag"
exit 1
fi
tag=$1
cd $CODE_DIR && git checkout master && git pull && git checkout $1
if [ $? != 0 ];then
echo "拉取代码失败"
exit 10
fi
cd $CODE_DIR && git pull 2>/dev/null >/dev/null
# 推送代码到临时目录
rsync -avz --delete $CODE_DIR/ $TMP_DIR/ 2>/dev/null >/dev/null
}

# 设置代码的配置文件
config_pro(){
echo "设置代码配置文件"
rm -f $local_conf/config.properties
.........
}

# 打包代码
tar_pro(){
echo "本地打包代码"
cd $TMP_DIR && /usr/local/maven/bin/mvn clean compile war:war && cp target/"$project".war "$WAR_DIR"/"$project"_"$tag"_"$CTIME".war
}

# 推送war包到远端服务器
rsync_pro(){
echo "推送war包到远端服务器"
for host in $REMOTE_HOST;do
scp "$WAR_DIR"/"$project"_"$tag"_"$CTIME".war $REMOTE_USER@$host:$REMOTE_WAR_DIR
done
}

# 解压代码包
solution_pro(){
echo "解压代码包"
for host in $REMOTE_HOST;do
ssh $REMOTE_USER@$host "unzip "$REMOTE_WAR_DIR""$project"_"$tag"_"$CTIME".war -d "$CODE_TMP""$project"_"$tag"_"$CTIME"" 2>/dev/null >/dev/null
done
}

# api测试
test_pro(){
# 运行api测试脚本,如果api测试有问题,则退出部署
if [ $? != 0 ];then
echo "API测试存在问题,退出部署"
exit 10
fi
}


# 部署代码
deploy_pro(){
echo "部署代码"
...................
sleep 3
# 执行api测试
test_pro
ssh haproxy "echo "enable server $project/$host" | /usr/bin/socat /var/lib/haproxy/stats stdio"
done
}
# 列出可以回滚的版本
rollback_list(){
echo "------------可回滚版本-------------"
ssh $REMOTE_USER@$REMOTE_HOST "ls -r "$CODE_TMP" | grep -o $project.*"
}

# 回滚代码
rollback_pro(){
   echo "回滚中"
   for host in $REMOTE_HOST;do
   .............................
   sleep 3
   ssh haproxy "echo "enable server $project/$host" | /usr/bin/socat /var/lib/haproxy/stats stdio"
   done
}

# 记录日志
record_log(){
   echo "$CTIME 主机:$REMOTE_HOST 项目:$project tag:$1" >> $DEPKOY_LOG
}

# 代码执行选项设置
main(){
   case $1 in
    deploy)
    git_pro $2;
    config_pro;
    tar_pro;
    rsync_pro;
    solution_pro;
    deploy_pro;
    record_log $2;
    ;;
    rollback_list)
    rollback_list;
    ;;
    rollback_pro)
    rollback_pro $2;
    record_log;
    ;;
    *)
    usage;
    esac
}
main $1 $2

4.2 使用shell实现php代码自动发布

脚本适应环境:

1、操作系统:centos 6.5 64位

2、代码使用gitlab进行管理

3、代码每次上线和回滚通过tag控制

补充:如果需要在你的企业使用我的这种部署方式,还需要有相应环境规范以及git分支管理规范。

使用脚本注意事项:
1、 发布机器需要能够解析web服务器主机名,并且配置ssh通信
2、 变量中的目录以及用户等信息需要自己创建,脚本没有做判断自己创建。我这里web服务器是使用ansible进行部署的,相关目录和用户都会自动创建。
3、代码的部署使用tag,回滚原则为回滚到上个tag版本,所以部署脚本本身没有备份代码。
4、如果需要过滤一些临时目录或者日志目录,可以在rsync推送代码的时候使用–exclude选项进行过滤,示例脚本中过滤了.git目录和config.php文件是不会部署的。

  #!/bin/bash

# 设置时间相关变量
CTIME=$(date "+%Y-%m-%d-%H-%M")
# 项目名称,建议和gitlab仓库名称一致
project=test
# 本地代码目录(gitlab拉取代码后存放目录)
CODE_DIR=/data/gitlab/pro/$project/
# 远程主机
REMOTE_HOST="LNMP-01.fblinux.com LNMP-02.fblinux.com"
# 远程主机代码目录
REMOTE_DIR=/data/www/fblinux/
# 远程主机用户
REMOTE_USER=root
# 远程主机代码执行用户
CODE_USER=php
# 上线日志
DEPKOY_LOG=/data/log/pro_log.log

#脚本使用帮助
usage(){
echo $"Usage: $0 [deploy tag]"
}

#拉取代码
git_pro(){
if [ $# -lt 1 ];then
echo "请传入tag"
exit 1
fi
echo "拉取代码"
cd $CODE_DIR && git checkout master && git pull && git checkout $1
if [ $? != 0 ];then
echo "拉取代码失败"
exit 10
fi
cd $CODE_DIR && git pull
}

#推送代码服务器
rsync_pro(){
for host in $REMOTE_HOST;do
echo "推送代码到服务器$host"
rsync -rPv -P --delete --exclude="config.php" --exclude=".git" $CODE_DIR -e 'ssh -p 22' $REMOTE_USER@$host:$REMOTE_DIR
if [ $? != 0 ];then
echo "推送代码失败"
exit 10
fi
echo "代码授权"
ssh $REMOTE_USER@$host "chown -R $CODE_USER $REMOTE_DIR"
if [ $? != 0 ];then
echo "代码授权失败"
exit 10
fi
done
}

#记录日志
record_log(){
echo "$CTIME 主机:$REMOTE_HOST 项目:$project tag:$1" >> $DEPKOY_LOG
}

main(){
case $1 in
deploy)
git_pro $2;
rsync_pro;
record_log $2;
;;
*)
usage;
esac
}
main $1 $2

以上就是两个实际的生产部署实例的配置环境、注意事项及代码等讲解。

读者如果需要上述两个实例的完整代码请在 民工哥技术之路 公众号后台回复 “自动化部署”来获取脚本完整代码的下载地址。

参考资料如下:
https://dzone.com/articles/21...
http://www.fblinux.com/?p=489
http://www.fblinux.com/?p=476

在 民工哥技术之路 微信公众号对话框回复关键字:1024 可以获取一份最新整理的技术干货。

clipboard.png

相关 [自动化 灰度 实践] 推荐:

一键实现自动化部署(灰度发布)实践

- - SegmentFault 最新的文章
在过去几年的DevOps的浪潮中,自动化、持续集成这两个概念早已深入人心(互联网技术人). 比尔盖茨先生曾经都说过:“任何技术在一个业务中使用的第一条规则就是,将自动化应用到一个高效的操作上将会放大高效. 第二条就是自动化应用到一个低效操作上,则放大了低效率. 自动化部署也逐渐成为各中小型企业追求的方向,那么,今天民工哥就自动化部署的概述、自动化部署的工具、自动化部署的流程、自动化部署实践等4个方面,与大家一同来讨论、交流一下关于中小企业自动部署的问题.

微店 MySQL 自动化运维实践

- - IT瘾-tuicool
互联网时代,数据库如何满足敏捷开发,敏捷交付的要求. 传统靠DBA人肉执行的方式,在面对大量业务需求时,DBA手速再快,记忆力再好估计也不能提供好的数据库服务. 在介绍自动化运维之前,我们来了解下是怎么使用数据库的. 数据库的使用方式主要有两种:. 应用混合部署(实例):有新数据库需求时,很多人都会选择找个实例,建个数据库和帐号提供给业务.

Puppeteer前端自动化测试实践

- - SegmentFault 最新的文章
本篇内容将记录并介绍使用Puppeteer进行自动化网页测试,并依靠约定来避免反复修改测试用例的方案. 主要解决页面众多时,修改代码导致的牵连错误无法被发现的运行时问题. 目前我们在持续开发着一个几十个页面,十万+行代码的项目,随着产品的更迭,总会出现这样的问题. 在对某些业务逻辑或者功能进行添加或者修改的时候(尤其是通用逻辑),这些通用的逻辑或者组件往往会牵扯到一些其他地方的问题.

SpringCloud灰度发布实践(附源码) - 微服务实践 - SegmentFault 思否

- -
在平时的业务开发过程中,后端服务与服务之间的调用往往通过. resttemplate两种方式. 但是我们在调用服务的时候往往只需要写服务名就可以做到路由到具体的服务,这其中的原理相比大家都知道是. ribbon组件帮我们做了负载均衡的功能. 灰度的核心就是路由,如果我们能够重写ribbon默认的负载均衡算法是不是就意味着我们能够控制服务的转发呢.

Python项目自动化部署最佳实践@搜狐

- - the5fire的技术博客
今天主要介绍下我们组刚刚开源出来的一个自动化部署的工具 essay ,功能在readme上已经介绍的很详细了,这篇文章只是介绍下外围的情况,产生的环境,一些决策的考虑. 事情还得从头开始说起,从那些自动化的fabric文件开始,也从我刚入职搜狐负责手机搜狐开发开始说起. 我参与开发的时候项目的部署已经是自动化了,不过并没有抽象出一个工具来.

发布及其检查的自动化实践

- - 淘宝网综合业务平台团队博客
这里记录的是Dubbo注册中心的发布过程中的自动化改进点. 实践是通用的,希望可以能给你一些借鉴和启发. Dubbo注册中心记录整个网站服务信息,服务消费者(Consumer)通过注册中心获得服务提供者(Provider)列表,才能完成服务调用. 注册中心是网站服务的一个关键组件. # 现在一个站点的注册中心上的服务Consumer和Provider就有35K+.

自动化接口测试实践经验

- -
作者:faithchen,腾讯 PCG 测试开发工程师. 自动化测试对于我们提升研发效能、CI/CD(持续集成/持续交付)是不可或缺的部分. 在后台自动化测试中,接口测试尤为重要,它能够保证被测后台服务的质量,以及接口逻辑的正确性等,帮助我们快速测试功能、提高测试覆盖率、把控质量风险等. 接口测试是功能测试的一种,是测试系统组件间接口的一种测试,重点在于检验对于服务接口的数据交换的正确性,一般全部依赖真实链路,测试时需要启动被测服务.

收钱吧高效自动化测试实践

- - IT瘾-dev
收钱吧业务服务千万级商家,业务庞大,产品背后有复杂的应用支撑. 我们采用了微服务架构,有成百上千个不同类型的后端服务,使用了包括Node.js、Java、Go、Python等后端语言,还有Mysql、MongoDB等数据库以及Elasticsearch、Kafka、Redis、Apollo、RabbitMQ等中间件.

前端开发中的流程自动化与提效实践

- - Joe’s Blog
随着前端的发展,越来越多的工具库、方法被用在日常研发流程中,这大大提升了业务开发的效率,而随着各类自动化流程的建设,开发同学也不再需要关注到每一个细节. 前段时间项目阶段性交付,在推进的过程中也做了不少尝试,虽然从长期看,这类工作最后可能都该收敛到基础设施部门或者标准的自动化流程中去,但并不妨碍我通过实践来落实一些对项目开发的思考和想法.

大规模微服务场景下灰度发布与流量染色实践

- - DockOne.io
最近微服务很热,与微服务相关的架构、流程、DevOps都很热. 很多公司,包括传统企业,到互联网公司做交流的时候,会问道,你们互联网公司号称能够加速业务创新、快速迭代,那我们是否也可以引入类似这样的机制. 我们做微服务,主要分为两个方面,一个是业务方面,另一个是技术方面. 最下面是运维部,不过现在我们的运维部已经拓展成云计算,DBA里的数据管理部门,已经发展成大数据,于是就有了技术中台和数据中台,另外还有共享用户中心的业务中台,总体构成了下层的中台部门,在上层业务一定要做微服务化.