常见的代码部署方式:
1. 蓝绿部署:
两套环境
蓝绿部署指的是不停老版本代码
(不影响上一个版本访问),而是在另外一套环境部署新版本然后进行测试,测试通过后将用户流量切到新版本,
特点为业务无中断,升级风险相对较小
。
缺点:需要更多的服务器
具体过程:
1、当前版本业务正常访问(V1)
2、在另外一套环境部署新代码(V2),代码可能是增加了功能或者是修复了某些 bug
3、测试通过之后将用户请求流量切到新版本环境
4、观察一段时间,如有异常直接切换旧版本
5、下次升级,将旧版本升级到新版本(V3)
蓝绿部署适用的场景:
1、不停止老版本,额外部署一套新版本,等测试发现新版本 OK 后,删除老版本。
2、蓝绿发布是一种用于升级与更新的发布策略,部署的最小维度是容器,而发布的最小维度是应用。
3、蓝绿发布对于增量升级有比较好的支持,但是对于涉及数据表结构变更等等不可逆转的升级,并不完全合适用蓝绿发布来实现,需要结合一些业务的逻辑以及数据迁移与回滚的策略才可以完全满足需求。
2. 金丝雀发布:
金丝雀发布也叫灰度发布,是指在黑与白之间,能够平滑过渡的一种发布方式,灰度发布是增量发布的一种类型
,灰度发布是在原有版本可用的情况下,同时部署一个新版本应用作为“金丝雀”
(小白鼠),测试新版本的性能和表现,以保障整体系统稳定的情况下,尽早发现、调整问题。
一部分一部分升级
“金丝雀”的由来:17 世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;而当瓦斯含量超过一定限度时,虽然鲁钝的人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为“瓦斯检测指标”,以便在危险状况下紧急撤离
金丝雀发布、灰度发布步骤组成:
1、准备好部署各个阶段的工件,包括:构建工件,测试脚本,配置文件和部署清单文件。
2、从负载均衡列表中移除掉“金丝雀”服务器。
3、升级“金丝雀”应用(排掉原有流量并进行部署)。
4、对应用进行自动化测试。
5、将“金丝雀”服务器重新添加到负载均衡列表中(连通性和健康检查)。
6、如果“金丝雀”在线使用测试成功,升级剩余的其他服务器。(否则就回滚)
灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。
灰度发布/金丝雀部署适用的场景:
1、不停止老版本,额外搞一套新版本,不同版本应用共存。
2、灰度发布中,常常按照用户设置路由权重,例如 90%的用户维持使用老版本,10%的用户尝鲜新版本。
3、经常与 A/B 测试一起使用,用于测试选择多种方案。
3. 滚动发布
离线某些服务器升级,然后上线
滚动发布,一般是取出一个或者多个服务器停止服务
,执行更新,并重新将其投入使用。
周而复始,直到集群中所有的实例都更新成新版本。
4. A/B 测试:
A/B 测试也是同时运行两个 APP 环境,但与蓝绿部署完全是两码事,
A/B 测试是用来测试应用功能表现的方法,例如可用性、受欢迎程度、可见性
等等,
蓝绿部署的目的是安全稳定地发布新版本应用,并在必要时回滚
,
即蓝绿部署是一套
正式环境在线,
而A/B 测试是两套
正式环境在线
二. 具体实现
部署 web 服务器环境
java 环境: 各 wenb 服务器准备 tomcat
运行环境:
useradd www -u 2000
mkdir/apps
cd /apps
tar openjdk-8u181-linux-x64.tar.gz
ln -sv /apps/jdk1.8.0_181/ /apps/jdk
vim/etc/profile
export HISTTIMEFORMAT="%F %T `whoami` "
export export LANG="en_US.utf-8"
export JAVA_HOME=/apps/jdk
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
source /etc/profile
java -version
tar xvf apache-tomcat-8.5.34.tar.gz
ln -sv /apps/apache-tomcat-8.5.34 /apps/tomcat
准备 tomcat 启动脚本:
cp /root/tomcat /etc/init.d/
vim /etc/init.d/tomcat
#!/bin/bash
JDK_HOME=/usr/local/jdk
CATALINA_HOME=/usr/local/tomcat
export JDK_HOME CATALINA_HOME
source /etc/profile
#PID=`ps -ef | grep -v grep | grep java | awk '{print $2}'`
#NUM=`ps -ef | grep -v grep | grep java | awk '{print $2}' | wc -l`
#case $1 in
start() {
echo "正在判断服务状态,请稍等!"
echo "请稍等3秒钟"
echo "3";sleep 1;echo "2";sleep 1;echo "1";sleep 1
if netstat -an | grep 8080 | grep LISTEN >/dev/null
then
echo "Tomcat已经正在运行了!"
else
echo "Tomcat没有运行,1秒后启动!"
echo 1;sleep 1
$CATALINA_HOME/bin/catalina.sh start
echo "Tomcat 已经成功启动完成,5秒后判断是否启动成功"
echo "5";sleep 1;echo "4";sleep 1
echo "3";sleep 1;echo "2";sleep 1;echo "1";sleep 1
if netstat -an | grep 8080 | grep LISTEN >/dev/null
then
PID=`ps -ef | grep tomcat | grep jdk | awk '{print $2}'`
NUM=`ps -ef | grep tomcat | grep jdk | awk '{print $2}' | wc -l`
echo "Tomcat 已经成功启动${NUM} 个Tomcat进程!,PID为${PID}"
else
echo "Tomcat启动失败,请重新启动!"
echo 1
fi
fi
}
stop() {
PID=`ps -ef | grep -v grep | grep java | awk '{print $2}'`
NUM=`ps -ef | grep -v "color" | grep tomcat | awk '{print $2}' | wc -l`
echo "正在判断服务状态,请稍等3秒钟!"
echo "3";sleep 1;echo "2";sleep 1;echo "1";sleep 1
if netstat -an | grep 8080 | grep LISTEN >/dev/null
then
echo "Tomcat运行中,1秒后关闭!"
echo 1;sleep 1
echo "即将关闭Tomcat服务,请稍等!"
$CATALINA_HOME/bin/catalina.sh stop ;echo "已经执行关闭命令,正在检查关闭了多少Tomcat进程,请稍等5秒钟!"
sleep 2
echo "3";sleep 1;echo "2";sleep 1;echo "1";sleep 1
#会强制关闭tomcat
pkill java && pkill tomcat
if netstat -an | grep 8080 | grep LISTEN >/dev/null;then
PID=`ps -ef | grep -v grep | grep java | awk '{print $2}'`
NUM=`ps -ef | grep -v "color" | grep tomcat | awk '{print $2}' | wc -l`
kill -9 $PID ;echo "已成功关闭${NUM} 个tomcat进程"
else
echo "Tomcat 已经关闭完成!"
echo "3";sleep 1;echo "2";sleep 1;echo "1";sleep 1
fi
else
echo "Tomcat 没有运行"
echo 1
fi
if netstat -an | grep 8080 | grep LISTEN >/dev/null;then
PID=`ps -ef | grep -v grep | grep java | awk '{print $2}'`
#NUM=`ps -ef | grep -v "color" | grep tomcat | awk '{print $2}' | wc -l`
echo "关闭失败,即将强制删除tomcat进程!"
sleep 2
pkill tomcat ;sleep 2
if netstat -an | grep 8080 | grep LISTEN >/dev/null;then
echo "强制关闭失败,即将再次强制删除tomcat进程!"
pkill java; sleep 2
fi
fi
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
esac
chmod +x /etc/init.d/tomcat
web 部署:
部署 web 服务器并确认各 web 服务器访问正常:
多个tomcat中的用户id一致
以普通用户启动
useradd -m www -u 2021 -s /bin/bash #创建账户
useradd www -u 2021 #centos 创建账户
mkdir /data/tomcat/tomcat_appdir -p #保存 web 压缩包
mkdir /data/tomcat/tomcat_webdir #保存解压后的 web 目录
mkdir /data/tomcat/tomcat_webdir/myapp
echo 自己的ip> /data/tomcat/tomcat_webdir/myapp/index.html
chown www.www /data/tomcat/ /apps/apache-tomcat /apps/tomcat -R
配置 tomcat 配置文件:
appBase="/data/tomcat/tomcat_webdir/"
为了可以远程使用tomcat这个文件
echo 密码 | passwd --stdin www
在远程就可以
ssh www@IP "/etc/init.d/tomcat start"
启动 tomcat:
/etc/init.d/tomcat start
确认各 web 服务器访问正常
部署 keepalived+haproxy
keepalived
yum install libnfnetlink-devel libnfnetlink ipvsadm libnl libnl-devel libnl3 libnl3-devel
lm_sensors-libs net-snmp-agent-libs net-snmp-libs open server openssh-clients openssl openssldevel automake iproute
cd keepalived-2.0.7 && ./configure --prefix=/usr/local/keepalived --disable-fwmark
make && amke install
mkdir /usr/local/keepalived/etc/sysconfig –p
cp keepalived/etc/init.d/keepalived.rh.init /usr/local/keepalived/etc/sysconfig/keepalived
cp keepalived/keepalived.service /usr/lib/systemd/system/
mkdir /usr/local/keepalived/sbin
cp bin/keepalived /usr/local/keepalived/sbin/keepalived
mkdir /etc/keepalived
vim /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
# 主还是备
state MASTER
interface eth0
# id
virtual_router_id 80
# 优先级
priority 100
advert_int 1
unicast_src_ip 192.168.7.103
unicast_peer {
192.167.7.104
}
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
#VIP
192.168.7.100 dev eth0 label eth0:0
}
}
systemctl restart keepalived
部署 haproxy:
tar xvf haproxy-1.8.13.tar.gz
cd haproxy-1.8.13
make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy
make install PREFIX=/usr/local/haproxy
vim /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
#支持多配置文件读取,类似于从侧面是实现配置文件的 include 功能。
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf -p
/run/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
# mkdir /etc/haproxy
vim /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind=1
sysctl -p
测试访问:
测试 haproxy 反向代理 web 服务器:
编辑本机 hosts 文件,将 myapp.web.com
解析到对应的 IP 负载 IP:
C:\Windows\System32\drivers\etc\hosts
192.168.7.100 myapp.web.com
记录 HAProxy 访问日志:
vim/etc/rsyslog.conf:
14 # Provides UDP syslog reception
15 $ModLoad imudp #去掉注释
16 $UDPServerRun 514 #去掉注释
18 # Provides TCP syslog reception
19 $ModLoad imtcp #去掉注释
20 $InputTCPServerRun 514 #去掉注释
93 local3.* /var/log/haproxy.log
systemctl restart rsyslog
vim /etc/haproxy/haproxy.cfg
log 127.0.0.1 local3 info #global 部分
listen web_port
bind VIP:80
mode http
server 192.168.7.103 192.168.7.103:8080 check inter 3000 fall 2 rise 5
server 192.168.7.104 192.168.7.104:8080 check inter 3000 fall 2 rise 5
systemctl restart haproxy
重启 rsyslog 和 haproxy 服务,验证/var/log/haproxy.log 可以记录日志
systemctl restart syslog haproxy
验证 HAProxy 统计页面:
http://myapp.web.com:9009/haproxy-status
验证 haproxy 代理 web 服务器:
http://myapp.web.com/myapp/
配置Gatlib
配置Jenkins
gitlab面向开发
Jenkins面向运维