方式
1、纯手工scp上传
2、纯手工登录,git pull、svn update
3、纯手工xftp往上拉
4、开发给打一个压缩包,rz 上去然后解压
缺点
1、运维全程参与,占用大量时间
2、上线速度太慢
3、人为失误过多,管理混乱
4、回滚的太慢、不及时、并且难以回滚
1.2 如何设计自动代码部署系统
1、规划
2、实现
3、总结和扩展
4、在生产环境中应用
1.2.1 自动化部署环境
1、开发环境
开发者本地有自己的环境,然后运维需要配置公共的开发环境,大家可公用的服务,例如开发数据库mysql redis等
2、测试环境
功能测试环境和性能测试环境
3、预生产环境
生产环境集群中的某一个节点担任
4、生产环境
直接对用户提供的环境
1.2.2 自动化部署规划
- 有一个可以上线代码的git仓库
- 一个集群中有10个节点,实现一键部署、秒级回滚
- 所有的web服务都应该使用普通用户
- 所有的web服务都不应该监听80端口,除了负载均衡
1.2.3 自动化部署实现思路
-
代码放在那里
代码放在svn、git(优先选择)上
- 编译(可选 java环境需要)
- 获取什么版本的代码
1、svn+git:直接拉取某个分支
2、svn:指定版本号
3、git:指定tag
- 差异解决
1、各个代码直接差异,配置文件未必一样
2、代码仓库和实际的差异,代码是否放在代码仓库中(配置单独进行存放)短信接口、支付,等敏感信息不能让所有的开发知道
-项目名设计
web-demo_456_2018-09-02-15-32-14
- 如何更新
php、tomcat需要重新启动
- 测试
1、测试关键的页面、API、后台等
2、测试一个与生产环境、通过则继续部署,失败则进行回滚
- 日志记录
1、对部署进行设计
成功多少次
失败多少次
回滚多少次
- 多人同时执行脚本
防止多人同时操作,导致重复上线失败,通过lock锁文件进行控制
- 串行和并行
1、若集群中机器少,则串行看不出什么问题、若机器多则串行会非常的慢
2、分组部署、并行部署
3、测试预生产环境,成功则继续部署,失败则进行回滚
- 如何执行
1、shell执行
2、web界面进行操作
1.2.4 自动话部署实践
1、获取最新代码
2、编译(可选)
3、配置文件(软连接或者cp)
4、打包
5、scp到目标服务器
6、解压
7、放置到webroot
8、scp差异文件
9、重启(可选)
10、测试
11、加入集群
自动化部署代码的精髓在于创建软连接
1.2.5 回退实践
1.2.5.1 正常回退实践
1、列出回滚版本
2、目标服务器移除集群
3、执行回滚(删除软连接、重建软连接)
4、重启和测试
5、加入集群
1.2.5.2 紧急回退实践
1、列出回滚版本
2、执行回滚(删除软连接、重建软连接)
3、重启对应服务
1.2.5.3 更紧急回退实践
1、执行回滚
2、重启
1.3 自动化部署系统构建实践
1.3.1 环境准备
linux_node1 10.0.0.7
linux_node2 10.0.0.8
1、创建普通用户(两台同时进行)
useradd -u 1000 lzh
echo ‘123456‘|passwd --stdin lzh
2、配置密钥
[[email protected]_node1 ~]# su - lzh 切换至普通用户 [[email protected]_node1 ~]$ ssh-keygen -t dsa 生成密钥 Generating public/private dsa key pair. Enter file in which to save the key (/home/lzh/.ssh/id_dsa): 默认一路回车 Created directory ‘/home/lzh/.ssh‘. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/lzh/.ssh/id_dsa. 钥匙 Your public key has been saved in /home/lzh/.ssh/id_dsa.pub. 锁 The key fingerprint is: f9:bb:3a:7f:e3:17:56:12:d3:8a:7b:78:79:ab:e2:de [email protected]_node1 The key‘s randomart image is: +--[ DSA 1024]----+ | . | | o .| | . + | | . . o .| | S o + | | . o * .| | . + o.| | . o+ .. | | .+**oE. | +-----------------+ [[email protected]_node1 ~]$ ssh-copy-id -i ~/.ssh/id_dsa.pub [email protected] The authenticity of host ‘172.16.1.8 (172.16.1.8)‘ can‘t be established. RSA key fingerprint is c2:34:59:81:a2:a7:9c:0a:23:9b:cf:1d:bb:d4:8e:ad. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added ‘172.16.1.8‘ (RSA) to the list of known hosts. [email protected]‘s password: Now try logging into the machine, with "ssh ‘[email protected]‘", and check in: .ssh/authorized_keys to make sure we haven‘t added extra keys that you weren‘t expecting. [[email protected]_node1 ~]$ ssh 172.16.1.8 [[email protected]_node2 ~]$
3、创建相关目录
mkdir -p /deploy/code/web-demo mkdir -p /deploy/config/web-demo/base mkdir -p /deploy/config/web-demo/other mkdir -p /deploy/tar mkdir -p /deploy/tmp [[email protected]_node1 ~]# tree /deploy/ /deploy/ ├── code │?? └── web-demo ├── config │?? └── web-demo │?? ├── base │?? └── other ├── tar └── tmp 8 directories, 0 files chown -R lzh.lzh /deploy chown -R lzh.lzh /opt/webroot/ chown -R lzh.lzh /webroot/
1.3.2 自动化脚本
查看脚本
#!/bin/bash #Dir List #mkdir -p /deploy/code/web-demo #mkdir -p /deploy/config/web-demo/base #mkdir -p /deploy/config/web-demo/other #mkdir -p /deploy/tar #mkdir -p /deploy/tmp #mkdir -p /opt/webroot #chown -R lzh.lzh /deploy #chown -R lzh.lzh /opt/webroot #chown -R lzh.lzh /webroot #Node List PRE_LIST="172.16.1.7" GROUP1_LIST="172.16.1.8" ROLLBACK_LIST="172.16.1.7 172.16.1.8" #Date/Time Veriables LOG_DATE=‘date "+%Y-%m-%d"‘ LOG_TIME=‘date "+%H-%M-%S"‘ CDATE=`date "+%Y-%m-%d"` CTIME=`date "+%H-%M-%S"` #PKG_NAME TEST=pre PRODUCT=master # Shell Env SHELL_NAME="deploy.sh" SHELL_DIR="/home/lzh" SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log" # Code Env PRO_NAME="web-demo" CODE_DIR="/deploy/code/web-demo" CONFIG_DIR="/deploy/config/web-demo" TMP_DIR="/deploy/tmp" TAR_DIR="/deploy/tar" LOCK_FILE="/tmp/deploy.lock" usage(){ echo $"Usage: $0 {deploy | rollback [ list | version ]}" } writelog(){ LOG_INFO=$1 echo "${CDATE} ${CTIME}: ${SHELL_NAME} : ${LOG_INFO} " >> ${SHELL_LOG} } shell_lock(){ touch ${LOCK_FILE} } url_test(){ URL=$1 curl -s --head $URL|grep "200 OK" if [ $? -ne 0 ];then shell_unlock; writelog "test error" && exit; fi } shell_unlock(){ rm -f ${LOCK_FILE} } code_get(){ writelog " code_get"; cd $CODE_DIR && echo "git pull" cp -r ${CODE_DIR} ${TMP_DIR}/ API_VER="456" } code_build(){ echo code_build } code_config(){ writelog "code_config" /bin/cp -r ${CONFIG_DIR}/base/* ${TMP_DIR}/"${PRO_NAME}" PKG_NAME="${PRO_NAME}"_"$API_VER"_"$TEST"_"${CDATE}-${CTIME}" cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME} } code_tar(){ writelog "code_tar" cd ${TMP_DIR} && tar zcf ${PKG_NAME}.tar.gz ${PKG_NAME} writelog "${PKG_NAME}.tar.gz" } code_scp(){ writelog "code_scp" for node in $PRE_LIST;do scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot/ done for node in $GROUP1_LIST;do scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot/ done } pre_deploy(){ writelog "remove from cluster" ssh $PRE_LIST "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz" ssh $PRE_LIST "rm -f /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo" } pre_test(){ url_test "http://${PRE_LIST}/index.html" echo "add to cluster" } group1_deploy(){ writelog "remove from cluster" for node in $GROUP1_LIST;do ssh $node "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz" ssh $node "rm -f /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo" done scp ${CONFIG_DIR}/other/172.16.1.8.crontab.xml 172.16.1.8:/webroot/web-demo/crontab.xml } group1_test(){ url_test "http://172.16.1.8/index.html" echo "add to cluster" } cluster_node_in(){ echo cluster_node_in } rollback_fun(){ if [ -z $1 ];then shell_unlock echo "Pls input rollback version" && exit fi for node in $ROLLBACK_LIST;do ssh $node "rm -f /webroot/web-demo && ln -s /opt/webroot/$1 /webroot/web-demo" done } rollback_list(){ find /opt/webroot/*.tar.gz -mtime +1|tail -1 |awk -F "[/ .]" ‘{print$4}‘ } rollback(){ if [ -z $1 ];then shell_unlock echo "Pls input rollback version" && exit fi case "$1" in list) ls -l /opt/webroot/*.tar.gz ;; *) rollback_fun $1 esac } main(){ if [ -f $LOCK_FILE ];then echo "Deploy is running" && exit; fi DEPLOY_METHOD=$1 ROLLBACK_VER=$2 case "$DEPLOY_METHOD" in deploy) shell_lock; code_get; code_build; code_config; code_tar; code_scp; pre_deploy; pre_test; group1_deploy; group1_test; shell_unlock; ;; list) rollback_list; ;; rollback) shell_lock; rollback $ROLLBACK_VER; shell_unlock; ;; *) usage; esac } main $1 $2
执行部署上线
[[email protected]_node1 ~]$ ./deploy.sh deploy git pull code_build web-demo_456_pre_2018-09-02-16-06-52.tar.gz 100% 218 0.2KB/s 00:00 web-demo_456_pre_2018-09-02-16-06-52.tar.gz 100% 218 0.2KB/s 00:00 HTTP/1.1 200 OK pre add to cluster 172.16.1.8.crontab.xml 100% 0 0.0KB/s 00:00 HTTP/1.1 200 OK group1 add to cluster
查看当前版本
[[email protected]_node1 ~]$ ./deploy.sh list web-demo_456_2018-09-02-15-10-13 web-demo_456_2018-09-02-15-10-13
执行回滚操作
[[email protected]_node1 ~]$ ./deploy.sh rollback Pls input rollback version [[email protected]_node1 ~]$ ./deploy.sh 配合list使用 web-demo_456_pre_2018-08-30-00-00-06
查看日志
[[email protected]_node1 ~]$ tail deploy.sh.log 2018-09-02 16-45-23: deploy.sh : code_scp 2018-09-02 16-45-23: deploy.sh : remove from cluster 2018-09-02 16-45-23: deploy.sh : remove from cluster 2018-09-02 17-29-54: deploy.sh : code_get 2018-09-02 17-29-54: deploy.sh : code_config 2018-09-02 17-29-54: deploy.sh : code_tar 2018-09-02 17-29-54: deploy.sh : web-demo_456_pre_2018-09-02-17-29-54.tar.gz 2018-09-02 17-29-54: deploy.sh : code_scp 2018-09-02 17-29-54: deploy.sh : remove from cluster 2018-09-02 17-29-54: deploy.sh : remove from cluster