为了提高系统的可用性,避免单点故障,在分布式系统中,我们可以使用 Keepalived 来实现站点的高可用,下面就稍微介绍一下 Keepalived 的配置和使用。

因为我并没有多台主机,所以目前所选择的方案是在本机上使用 Docker 构建多台容器来实现集群,这种方式成本低,实现起来也比较简单。如果你对 Docker 不太熟悉,可以看我之前的文章使用 Docker 来构建一个 Tomcat 服务来快速了解一下 Docker。

1. 安装 Keepalived 和 Nginx 并创建为一个 Docker 镜像

我假设你已经有了一个 Ubuntu 的 Docker 镜像,如果你还没有可以通过以下命令安装

docker pull hub.c.163.com/public/ubuntu:16.04-tools

之所以选择网易的镜像是因为其在国内的访问速度比较快(很奇怪在 deepin 操作系统上只能使用 Docker 官方的镜像,163 的镜像无法使用,目前还不知道为什么)。

在这里我们的 Ubuntu 镜像的 ID 是 1196ea15dad6,我们让这个镜像以守护进程(-d)的方式运行,并且给这个运行的容器起名 keepalived

docker run -d --privileged=true --name=keepalived 1196ea15dad6

此时 Ubuntu 容器已经开始运行了,执行命令

docker ps

应该能够看到一个名为 keepalived 的容器在运行了。接下来我们使用以下命令进入 keepalived 容器的 bash

docker exec -it --privileged=true keepalived bash

成功进入 bash 之后,执行以下命令来安装 Keepalived 和 Nginx(如果安装速度慢可以考虑更换国内的镜像源)

apt-get update
apt-get install keepalived
apt-get install nginx

安装完毕后,创建文件 /etc/keepalived/keepalived.conf,并在文件中保存以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.99
}
}

文件修改完毕后执行 exit 命令退出 bash,之后执行命令

docker stop keepalived

停止此容器,此时查看 Docker 运行中的容器已经看不到 keepalived 容器了,之后执行命令

docker commit keepalived keepalived

把容器 keepalived 提交为一个名叫 keepalived 的镜像,之后执行命令

docker images

可以看到已经创建了一个名为 keepalived 的镜像,接下来我们就可以直接使用这个镜像来执行我们想要的操作了。

PS: 如果你想要跳过搭建镜像这一步,可以直接选择使用我已经构建好的镜像,使用如下命令可以获取此镜像:

docker pull hub.c.163.com/derobuka1/keepalived:latest

如果你使用我这个镜像,那么在下面使用到这个镜像的时候,要注意镜像的名称应该为 hub.c.163.com/derobuka1/keepalived:latest

2. 配置并启动 Keepalived 服务

在上面我们已经创建好了一个安装了 Nginx 和 Keepalived 的 Docker 镜像,下面我们就使用这个镜像来创建 Keepalived 服务。首先我们使用 keepalived 镜像创建一个名为 master 的容器并使其作为守护进程执行

docker run -d --privileged=true --name=master keepalived

之后通过命令

docker exec -it --privileged=true master bash

进入到 master 容器的 bash 中,然后使用以下命令来启动服务

service keepalived start
service nginx start

之后执行

ip addr

可以看到虚拟地址 172.17.0.99 已经被绑定到了此台机器上。

之后我们可以同样使用命令

docker run -d --privileged=true --name=backup keepalived

来创建一个名为 backup 的备用机器,以同样的方式进入备用机器的 bash,修改 /etc/keepalived/keepalived.conf 文件中 keepalived 的优先级低于 master 机器,例如为该改优先级为 90:

···
priority 90
···

备用机器上只需要做这一个改动即可。保存配置文件,之后启动备用机器上的 Keepalived 和 Nginx。

如果需要,我们可以再创建更多的备用机器,只需要保证这些备用机器的 priority 比 90 还要低即可。priority 的取值范围是 1 - 250,超出的数值会被当作是 100,优先级最高的机器会被当作 master 机器。

3. 模拟单点故障以测试 Keepalived 的功能

为了更直观的查看,我把 master 机器上的 Nginx 主页内容改为 master,backup 的主页改为 backup。之后在宿主机上执行 docker 命令

docker run -it 1196ea15dad6 bash

进入一台测试机器的 bash,在测试机上执行命令

curl 172.17.0.99

看到如下结果

此时请求落在了 master 机器上。执行命令

docker stop master

停止 master 容器模拟主节点失去服务的情况,此时在测试机器上再执行一次请求,得到如下结果

该结果说明我们的请求在 master 失去服务的情况下自动发往了 backup 机器,此时在备用机器上执行命令

ip addr

可以发现虚拟 IP 已经绑定到了备用机器上,这一结果符合我们预期。执行命令

docker start master

启动 master 容器,之后再启动 master 上的 Nginx 和 Keepalived 服务,随后在测试机器再执行一次请求,发现新的请求自动的切回到了 master 上,这样模拟了 master 恢复服务时的场景。

参考:

  1. 使用 keepalived 搭建主备切换环境
  2. Nginx+Keepalived 实现站点高可用
  3. 如果想要以守护进程的方式创建一个容器,那么对创建这个容器所使用到的镜像有一些要求。要求就是,这个镜像在被创建的时候,创建这个镜像所使用到的容器的 COMMAND(使用 docker ps 命令可以看到)应该为 /usr/bin/supervisord,而不是 bash