目录
一、系统高可用
二、Nginx 的高可用
1、概念
1.1、KeepAlived
1.2、VRRP协议
1.3、Nginx Master-Slave多进程模型
1.4、双机备热、多点集群
Nginx+keepalived 双机主从模式:
Nginx+keepalived 双机主主模式:
Nginx+keepalived 多点模式:
1.5、总结:
2、实战
1、实践思路
1.1、自定义镜像
1.2、使用docker-compose打造镜像
2、环境准备
2.1、docker编排(docker-compose)
2.2、docker编排镜像
2.3、dockerfile
2.4、容器启动后执行脚本
2.5、高可用配置keepalived-X
2.6、可视化验证文件
3、运行并验证
3.1、运行docker编排
3.2、查看docker容器
3.3、验证
3、总结
高可用性英文简称HA(High Availability),指的是系统具备较高的无故障运行的能力。是咱们系统设计的一个重要的目标。系统的高可用基本上可以从开发和运维的交底进行考虑。两个方面关注的重点也是不一样的,今天就不做过多的阐述,咱们今天重点从运维的视角看看Nginx的高可用方案。
之所以提出Nginx的高可用,从下图就可以看出,咱们后端服务器是集群部署。在生产环境下,Nginx作为流量的入口,如果Nginx不能正常工作或服务器宕机,将导致整个微服务架构的不可用。所以负责负载均衡、反向代理的服务(Nginx)为了提高处理性能,高可用,也需要集群部署。本期咋们采用 keepalived 和 Nginx实现高可用。
KeepAlived是Linux下的基于VRRP备份路由的高可靠性中间件。如果一台服务器宕机,KeepAlived会检测到并将发生故障的机器从集群中摘除,同时使用其他的服务器代替该故障机器的工作。当服务器重新正常工作后KeepAlived就会自动将该服务器加入到工作集群中。以上的工作都是KeepAlived自动完成无需人工介入。
VRRP协议英文全称:Virtual Router Redundancy Protocol,即”虚拟路由冗余协议“。将多台提供相同功能的路由器组成路由器组,包含一个master和多个backup。提供虚拟IP,占有这个虚拟IP的master负责ARP的响应和转发IP数据包。master负责发布组广播消息,若master发送的广播长时间没有被backup接收到就会触发选举backup当新master。
Nginx进程基于 Master-Slave(worker)多进程模型,在Master进程分配模式下,Master进程只负责进行任务分发不做业务处理,从而达到Master进程的高可靠性。Slave(worker)进程的所有业务信号都由主节点进程发出,只负责业务处理。同时Slave(worker)进程业务执行超时会被Master终止。属于非阻塞式任务模型。
双机热备方案是目前使用最为普遍的一种高可用方案,双机热备就是指一台服务器整在提供服务,另外一台作为备用状态,当一台服务器挂掉之后另外一台就会代替他继续提供服务。主要有以下来两种模式。
使用两台Nginx服务器,一台主服务器和一台热备服务器,正常情况下,主服务器绑定一个公网虚拟IP,提供负载均衡服务,热备服务器处于空闲状态;当主服务器发生故障时,热备服务器接管主服务器的公网虚拟IP,提供负载均衡服务;但是热备服务器在主机器不出现故障的时候,永远处于浪费状态,对于服务器不多的网站,该方案不经济实惠。
使用两台Nginx服务器,互为主备,且都处于活动状态,同时各自绑定一个公网虚拟IP,提供负载均衡服务;当其中一台发生故障时,另一台接管发生故障服务器的公网虚拟IP(这时由非故障机器一台负担所有的请求)。该方案解决了双击主从的资源浪费问题,但是有个性能瓶颈的问题在这种模式会出现。就是单台机器上的负载会瞬时过大。那如何解决这个问题呢,就出现了多点集群模式。
以上两种方式都有各自的有缺点,多点集群模式应运而生。多点集群可以理解为双机热备在技术上的提升。多机服务器可以组成一个集群。根据应用的实际情况,可以灵活地在这些服务器上进行部署,同时可以灵活地设置接管策略。比如,可以由一台服务器作为其他所有服务器的备机,也可以设置多重的接管关系,等等。这样,就可以充分地利用服务器的资源,同时保证系统的高可用性。
基于以上的技术组合就可以搭建一套比较稳定的软件高可用方案。
进行高可用的实践最好是有多台服务器,然后不同的机器上部署相关的Nginx,咱们用Keepalived监听不同服务的存活保证在部分服务宕机的情况下依然可以对外提供服务。但是实际情况及时本人只有一台电脑,并且没有买云服务器。现实情况很多人跟我的情况差不多,那就另辟蹊径着手解决。最后在各种尝试下采用docker编排(docker-compose)的方式搭建好了环境进行验证。还是那句话“纸上得来终觉浅,绝知此事要躬行”。
我的思路就是使用docker builder自己的服务器镜像,基于centos操作系统,在原始的操作系统上安装nginx、keepalived重新打包镜像,在基于自己打包的镜像run两个容器来模拟两个服务器。奈何本人目前的水平有限,并且网上一大堆粘贴过来的文章根本没有自己时间操作。导致这个思路么有走通,但是这条路肯定是没问题的,我在进行尝试的过程中也遇到了很多奇怪的问题,我没有一一记录,要是有小伙伴搞定过可以给我分享一下,我在尝试尝试。否则只能等我后面梳理完毕docker的教程了在尝试一次。
第二种就是说基于,docker的编排打造自定义镜像,采用docker编排的好处就是不用你自己手动启动centos镜像进入容器中在逐个安装Nginx、keepalived、网络等等依赖的各种包。你只需要配置一些模版文件就可以帮助你打好你想要的镜像。非常方便。
前面提到我自己只有一台mac机器,所以使用docker模拟多台服务器。因为要进行docke容器上的虚拟IP映射到本地机器,又要进行配置,这里我采用HaProxy进行代理达到这个映射的结果(HaProxy和Nginx一样都是可以进行代理的服务器感兴趣的同学可以自行查资料学习)。
要进行docker编排需要遵循一下配置,下图中已经截全,咱们挨个进行详述。总的概念就是:docker-compose进行编排,dockerfile负责打目标镜像,entrypoint.sh负责容器启动后执行启动脚本,keepalived-X进行高可用观察。
docker-compose.yml:docker编排配置文件,主要指定服务,指定打包当前服务部署所使用的镜像的文件(dockerfile),指定网络。
Dockerfile:就是docker-compose文件中制定的需要打包镜像的镜像文件。
entrypoint.sh:容器中要执行的启动脚本。
favicon.ico:可有可无的配置,nginx挂载里执行的浏览器上的图标。
index-X.html:这个是Nginx里的挂载的默认打开地址,这里只是为了可观测性配置。
keepalived-X:keepalived对应的配置。
编辑docker-compose.yml文件进行容器编排。
version: "3"
services: # 指定服务
# 主服务
nginx_master:
build:
context: ./
# 指定打镜像的镜像文件
dockerfile: ./Dockerfile
# 镜像挂载
volumes:
- ./index-master.html:/usr/share/nginx/html/index.html
- ./favicon.ico:/usr/share/nginx/html/favicon.ico
- ./keepalived-master.conf:/etc/keepalived/keepalived.conf
# 容器网络
networks:
static-network:
ipv4_address: 172.20.128.2
cap_add:
- NET_ADMIN
# 辅服务(以下配置参考主服务)
nginx_slave:
build:
context: ./
dockerfile: ./Dockerfile
volumes:
- ./index-slave.html:/usr/share/nginx/html/index.html
- ./favicon.ico:/usr/share/nginx/html/favicon.ico
- ./keepalived-slave.conf:/etc/keepalived/keepalived.conf
networks:
static-network:
ipv4_address: 172.20.128.3
cap_add:
- NET_ADMIN
# 代理,为了解决容器IP映射到本机
proxy:
image: haproxy:1.7-alpine
# 代理,监听的端口,外界端口是8000。映射到haproxy的6301端口上
ports:
- 8000:6301
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
networks:
- static-network
# 指定网络
networks:
static-network:
ipam:
config:
- subnet: 172.20.0.0/16
编辑上文codker编排提到的镜像文件,这个镜像文件是我们的重中之重,他定义了咱们自定义的镜像都包含了哪些能力,我们是基于nginx + keepalived达到高可用。这里特别注意我注视掉的一段脚本,是因为采用alpinelinux这种轻量级稳定快捷版本更容易下载和节省打包时间。
# 镜像文件先拉取Nginx当作基础镜像
FROM nginx:1.13.5-alpine
# RUN apk update && apk upgrade
# RUN apk add --no-cache bash curl ipvsadm iproute2 openrc keepalived && \
# rm -f /var/cache/apk/* /tmp/*
# 在基础镜像上添加需要的能力,包括添加keepalived镜像
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \
&& apk -U upgrade \
&& apk add --no-cache bash curl ipvsadm iproute2 openrc keepalived && \
rm -f /var/cache/apk/* /tmp/*
# 将咱们容器启动后要操作的执行脚本copy到目标位置
COPY entrypoint.sh /entrypoint.sh
# 给执行脚本增加可执行权限
RUN chmod +x /entrypoint.sh
# 在目标镜像里指定启动脚本,其实就是启动咱们Nginx和Keepalived
CMD ["/entrypoint.sh"]
容器启动之后的执行脚本:entrypoint.sh,其实就是启动咱们Nginx和Keepalived。这里需要说明的是“nginx -g "daemon off;"”这个命令,CMD在执行的shell脚本["sh", "replace_api_url.sh"],实际上是启动shell进程来执行,脚本执行完,进程就会退出(此时nginx还是一摊死的物理文件),所以我们要在脚本内再添加。nginx -g "daemon off;" 将整个shell进程转为前台能持续运行的进程。
#!/bin/sh
/usr/sbin/keepalived -n -l -D -f /etc/keepalived/keepalived.conf --dont-fork --log-console &
nginx -g "daemon off;"
keepalived配置,这里需要强调的是两部分,第一个是vrrp_instance实例中的state字段,该字段控制是主节点还是从节点,只有主节点“宕机”的情况下从节点才会进行重新选举接收请求。否则一直都是主节点接收请求并处理。大家看我注释中描述的两个“很重要”字样标注的字段即可理解。
keepalived-master:
# 指定多久检测一次nginx的健康状态
vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
# master负责接收用户的请求,当master宕掉后才会有slave接收
state MASTER
# 容器内部的网卡名称
interface eth0
# 虚拟路由ID
virtual_router_id 33
# 优先级,很重要
priority 200
advert_int 1
unicast_src_ip 172.20.128.2
unicast_peer {
172.20.128.3
}
authentication {
auth_type PASS
auth_pass letmein
}
# 虚拟IP地址,很重要
virtual_ipaddress {
172.20.128.4/24 dev eth0
}
track_script {
chk_nginx
}
}
keepalived-slave:
vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 33
priority 100
advert_int 1
unicast_src_ip 172.20.128.3
unicast_peer {
172.20.128.2
}
authentication {
auth_type PASS
auth_pass letmein
}
virtual_ipaddress {
172.20.128.4/24 dev eth0
}
track_script {
chk_nginx
}
}
这两个文件就不用过多描述了,只是Nginx里的默认打开页面。
index-master.html:
Master
index-slave.html:
Slave
经过上面的准备工作,我们已经知道并且能够编排、打包目标镜像,接下来及时将我们的镜像打包生成并运行。废话补多说开搞。
使用命令“docker-compose up”即可执行docker编排,下图中我用红框标记了几个模块,感兴趣的同学可以在执行的时候看看相关执行日志,就知道自定义镜像是怎么进行构造出来的。
docker-compose up -d
使用“docker ps”可以查看容器的启动情况,可以看到启动了三个容器。第二个图是我的dockerDesktop上的截图也是一个意思,我红框标记的是咱们要验证的服务端口,也是咱们设置的Haproxy代理监听的端口。
第一步:首选验证没有异常的情况。浏览器输入“http://localhost:8000/”。
第二步:首选验证master节点down机。浏览器输入“http://localhost:8000/”。
docker pause 容器Id
第三步:首选验证master节点重启机。浏览器输入“http://localhost:8000/”。
docker unpause 容器Id
咱们本次基于docker编排自定了镜像验证Nginx的高可用。学习了KeepAlived基于VRRP协议来达到高可用的监控。但是咱们本次只是实践了Nginx+keepalived 双机主从模式,还有主主模式,集群模式都没有尝试感兴趣的同学可以抽空做一个尝试,但是我们也要知道对应的模式都是怎样的原理这样才能在技术选型的时候做一个最优的衡量。最后就是由于本人的原因完全基于centos系统自定义镜像没有搞定,希望我学习完docker的知识可以搞定这个难题,最后还是希望这个系列可以可以帮助到大家少走弯路。