第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




