第1章 环境的规划
1.开发环境-开发者本地有自己的环境,然后运维需要设置的开发环境,大家公用的服务。
例如:开发数据库Mysql,其它:Redis、Mermcached
2.测试环境:功能测试环境和性能测试环境。
3.预生产环境:生产环境集群中的某一个节点担任。
4.生产环境:直接对用户提供服务的环境。
预生产环境产生的原因:
■数据库不一致:测试环境和生产环境数据库可定是不一样的。
■使用生产环境的联调接口。例如:支付接口。
使用这些环境就是解决某些问题。
预生产环境—–生产环境—–灰度发布
1.1 自动化部署系统
我们有一个上线的代码在代码仓库。我们如何设计一套生产自动化部署系统。
1.规划
2.实现
3.总结和扩展。 PDCA
4.在 生产环境应用
1.1.1 规划
1、一个集群10个节点。实现,一键部署10个节点。
2、一键回滚到任意版本。
部署 回滚
部署
1.部署在哪里:SVN git
2.获取什么版代码?
SVN + git直接拉取某个分支master
SVN 指定版本号
git 指定tag标签
1.1.2 差异解决:
1各个节点直接差异、配置文件未必一样、定时任务代码(只能在一个跑如java crotab.xml)
、预生产节点。
2.代码仓库和实际的差异。配置文件对否放在代码仓库中。配置文件只在部署上有。单独的项目。config.sample
4.如何更新。java tomcat 需要重启。
5.测试
6.串行和并行 (需要根据业务需要)分组部署
7.执行 1界面./shell 执行 2.web界面
- 配置文件放进去 (什么配置文件放进去)
- 打包 (tar.gz)
- scp 不需要密码验证
- nginx注释
- 怎么放进去(重点)
自动化部署注意问题
1.用户 所有的Web服务,都应该使用普通用户。所有的Web服务都不应该监听80端口,除了负载均衡8080
useradd www
2秘钥认证
[root@www ~]# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: f5:54:b3:bb:02:32:79:95:0b:22:2d:31:82:6e:e1:70 root@www.xuebao.com The key's randomart image is: +--[ RSA 2048]----+ | .. o o | |. E . + o o | | = . o o o + . | | + o + = . . | | . S o o . | | + . . | | . . | | . | | | +-----------------+
查看
[root@www ~]# ls .ssh/
id_rsa id_rsa.pub known_hosts
1.1 自动化脚本部署
问题:
1、这个脚本记录日志
2、可不可以多个人执行
[www@node1 deploy]$ tree
.
├── code
│ └── web-demo ##项目
│ └── index.html #git下来
├── config
│ └── web-demo #配置文件
│ └── config.ini
├── tar
└── tmp
1.2 版本回滚
回滚主机是遇到BUG
紧急流程
一般流程
更紧急回滚
介绍一下一个比较完善的发布脚本,该脚本可实现从gitlab服务器获取代码,打包,部署到WEB服务器,回滚到任意版本,一键回滚到上一版本。
1.1 1、环境准备
首先,脚本发布一定是用普通用户www来发布。脚本放在www的用户家目录,每个WEB都创建www用户并且UID相同,web目录和权限一致,其次需要创建一些必须的文件目录。
[root@jenkins shell]# cat /etc/redhat-release 系统:CentOS release 6.7 (Final) [root@jenkins shell]# rpm -qa|grep gitlab-ce gitlab版本:gitlab-ce-8.17.5-ce.0.el6.x86_64 web主机IP: 172.16.1.79 代码上线主机IP:172.16.1.56 gitlab主机IP:172.16.1.55 1.5 脚本详解 [www@node1 shell]$ cat deploy.sh #!/bin/bash #mkdir list 需要执行脚本前创建的目录、可以根据自己修改。 #mkdir -p /deploy/code/web-demp -p #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 #mkdir /webroot #chown -R www.www /deploy #chown -R www.www /opt//webroot #chown -R www.www /webroot ##定义scp 服务器,如果主机名 #Node List #推送web服务IP地址 NODE_LIST="172.16.1.79" #回滚列表 ROLLBACK_LIST="172.16.1.79" #Date/Time Variables #日期和时间变量(时间不固定,时间是变量) LOG_DATE='date "+%Y-%m-%d"' LOG_TIME='date "+%H-%M-%S"' #代码打包时间变量(时间固定) CDATE=$(date "+%Y-%m-%d") CTIME=$(date "+%H-%M-%S") #变量 #shell Env #脚本名称 SHELL_NAME="deploy.sh" #脚本路径 SHELL_DIR="/home/www" #脚本执行日志文件路径 SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log" #代码变量 #Code Env ###项目名称,此名称是从gitlab服务器clone 下来的代码目录 PRO_NAME="web-demo" #从gitlab服务器更新的目录 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(){ LOGINFO=$1 echo "${CDATE} ${CTIME}: ${SHELL_NAME} : ${LOGINFO}" >> ${SHELL_LOG} } ####创建log文件 shell_lock(){ touch ${LOCK_FILE} } #测试网页 url_test(){ URL=$1 curl -s --head $URL |grep '200 OK' if [ $? -ne 0 ];then shell_unlock; echo "test error" && exit; fi } #删除log文件 shell_unlock(){ rm -f ${LOCK_FILE} } #拉代码、更新 code_get(){ writelog "code_get"; cd $CODE_DIR && git pull #拷过去要改名,现在叫web-demo,时间加版本号 cp -r ${CODE_DIR} ${TMP_DIR}/ #定义一个版本 API_VERL=$(git show|grep commit|cut -d ' ' -f2) API_VER=${API_VERL:0:6} } #编译JAVA 构建工具 code_build(){ echo coode_guild } #配置文件地方 code_config(){ writelog " code_dconfig" #拷贝完重命名、拷贝打包,base放一样的,other 放不一样的。 /bin/cp -r ${CONFIG_DIR}/base/* ${TMP_DIR}/"${PRO_NAME}" #先弄个包名变量。 PKG_NAME="${PRO_NAME}"_"$API_VER"_"${CDATE}-${CTIME}" #重命名 cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME} } #打包,svn 加时间加版本号 code_tar(){ writelog "code_tar" cd ${TMP_DIR} && tar zcvf ${PKG_NAME}.tar.gz ${PKG_NAME} writelog "${PKG_NAME}.tar.gz" } #如果公司项目少、建议用手写不要for 循环。 code_scp(){ writelog code_scp for node in $NODE_LIST;do scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot done } cluster_node_remove(){ writelog "cluster_node_remove" } #回滚模块 rollback_fun(){ for node in $ROLLBACK_LIST;do ssh $node "rm -f /webroot/web-demo && ln -s /opt/webroot/$1 /webroot/web-demo" echo "rollback version $1 ok! " done } #解压for循环解压 code_deploy(){ echo code_deploy for node in $NODE_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/buyiyang.crontab.xml 172.16.1.79:/webroot/web-demo/crontab.xml } code_test(){ url_test "http://$NODE_LIST/index.html" echo "d to cluster" } cluster_node_in(){ echo code_cluster_node } rollback(){ if [ -z $1 ];then shell_unlock; echo "Usage: $0 [ deploy | rollback [ list | version ] ]" && exit; fi case $1 in list) ssh $ROLLBACK_LIST " ls -l /opt/webroot/*.tar.gz" ;; *) rollback_fun $1 esac } #main函数中替换。 main(){ #锁文件,存在退出,不存在往下走。 if [ -f $LOCK_FILE ];then echo "Deploy is running" && exit; fi #定义参数 $1 $2 DEPLOY_METHOD=$1 ROLLBACK_VER=$2 case $DEPLOY_METHOD in deploy) ##部署前锁住 shell_lock; code_get; code_build; code_config; code_tar; code_scp; cluster_node_remove; code_deploy; code_test; cluster_node_in; ##部署后解锁 shell_unlock; ;; ##rollback 必须有参数 $2 rollback) shell_lock; #输入版本号,回滚 rollback $ROLLBACK_VER; shell_lock; ;; *) usage; esac } ###脚本的第一个参数,部署$1 回滚$2 main $1 $2