kangyuetao
for me

nginx主机宕机解决方案

2019-02-21 技术点
Word count: 1.3k | Reading time: 5min

使用Docker-compose搭建nginx-keepalived双机热备来实现高可用nginx集群

最近一直在想一个问题,如果使用nginx反向代理tornado,部署了多台机器,如果主机也就是部署了nginx那台机器并发过大导致宕机了怎么办?

想必大家也都明白 ,不考虑带宽峰值的话,比较新的 CPU 跑 nginx 单核每秒能接近 2 万请求,而且nginx如果纯做 HTTP 转发的话,Nginx 的性能高到恐怖,会挂掉很不科学。。。。

那如果插头被踢掉了怎么办,机房断电之类的原因,因为没电导致服务器宕机。但话又说回来,服务器用的阿里云的话,难道阿里云机房也会断电。。。你特么在逗我吧。。。

其实负责转发的主机宕机概率很小,但是绝对不是没有,任何事都不是绝对,所谓的高可用架构就是体现在容灾机制上,如果主机宕机就必须要做预案,万无一失才叫高可用架构,所以我自己通过研究学习,私下实践了一下这套方案。。。

这里我们使用docker-compose来部署nginx-keepalived双机热备机制,vip主机可以进行漂移,这样主机挂掉了,还有备用机可以顶上

​ Keepalived是Linux下面实现VRRP备份路由的高可靠性运行件。基于Keepalived设计的服务模式能够真正做到主服务器和备份服务器故障时IP瞬间无缝交接。二者结合,可以构架出比较稳定的软件LB方案。

​ 简单点说,就是keepalived可以将下面这种简单的负载均衡模式

改造成下面这种高可用的架构

​ 当有主机挂掉的时候,服务能瞬间切换到备用机

​ 首先,安装docker和docker-compose按下不表,可以参考这篇文章,在centos7.6上利用docker-compose统一管理容器和服务

​ 建立nginx_keepalived文件夹

​ 建立Dockerfile文件,这里我们使用alpine作为基础镜像,原因很简单,因为它体积小啊

1
2
3
4
5
6
7
8
9
10
11
12
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/*

COPY entrypoint.sh /entrypoint.sh

RUN chmod +x /entrypoint.sh

CMD ["/entrypoint.sh"]

​ 然后建立docker-compose.yml文件,这里我们仿照线上环境,部署一台主机和一台从机,分别安装nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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
proxy:
image: haproxy:1.7-alpine
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

​ 随后,撰写nginx配置文件,keepalived-master.conf 这里由于我们没有后端tornado服务,所以使用虚拟代理服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}

vrrp_instance VI_1 {
state MASTER
interface eth0
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
}

virtual_ipaddress {
172.20.128.4/24 dev eth0
}

track_script {
chk_nginx
}
}

​ 同理再复制一份从机的nginx配置keepalived-slave.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
}
}

​ 随后为后端服务做两个网页,一个主机index-master.html一个从机index-slave.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>主机</title>
<style>

#box{
margin: 0px auto;
font-family: 'Times New Roman', Times, serif;
font-size: 30px;
font-style: initial;
color: aliceblue;
}

body{
background-color: black
}

</style>
</head>
<body>

<div id="box">

主机

</div>

</body>
</html>

​ 从机的复制一份,将主机改成从机即可

​ 因为我们要模拟后台服务,所以需要haproxy.cfg配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
global
log 127.0.0.1 local0
maxconn 4096
daemon
nbproc 4

defaults
log 127.0.0.1 local3
mode http
option dontlognull
option redispatch
retries 2
maxconn 2000
balance roundrobin
timeout connect 5000ms
timeout client 5000ms
timeout server 5000ms

frontend main
bind *:6301
default_backend webserver

backend webserver
server ngxin_master 172.20.128.4:80 check inter 2000 rise 2 fall 5

​ 最后,撰写服务的shell脚本entrypoint.sh

1
2
3
4
5
#!/bin/sh

/usr/sbin/keepalived -n -l -D -f /etc/keepalived/keepalived.conf --dont-fork --log-console &

nginx -g "daemon off;"

​ 整个项目结构如下:

​ 现在我们来启动容器集群,输入命令:docker-compose up

​ 发现容器已经启动

​ 另外一个命令行,输入:docker ps

​ 可以看到,后台分别三个容器正在启动,两台nginx反向代理8000端口的后台服务,访问 localhost:8000

​ 现在我们来模仿一下nginx主机宕机的情况

1
docker pause nginx_keepalive_nginx_master_1

再次访问 localhost:8000

​ 发现已经自动无缝切换到备用机,整个过程非常流畅

​ 高可用架构的特性就体现在这里

Author: kangyuetao

Link: https://kangyuetao.github.io/7569/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
JSON Web Token
NextPost >
在centos7.6上利用docker-compose统一管理容器和服务
CATALOG
  1. 1. 使用Docker-compose搭建nginx-keepalived双机热备来实现高可用nginx集群