如何在Ubuntu14.04上设置具有Keepalived和浮动IP的高可用性Web服务器
介绍
高可用性是系统设计的一项功能,它允许应用程序在发生故障时自动重新启动或将工作重新路由到另一个有能力的系统。 在服务器方面,建立高可用性系统需要几种不同的技术。 必须有一个可以重定向工作的组件,并且必须有一种机制来监视故障并在检测到中断时转换系统。
keepalived
守护进程可用于监控服务或系统,并在出现问题时自动故障转移到备用服务器。 在本指南中,我们将演示如何使用 keepalived
设置高可用的 Web 服务。 我们将配置一个 浮动 IP 地址 ,它可以在两个有能力的 Web 服务器之间移动。 如果主服务器宕机,浮动IP会自动移动到第二台服务器,让服务恢复。
先决条件
为了完成本指南,您需要在您的 DigitalOcean 帐户上创建两个 Ubuntu 14.04 服务器。 两台服务器必须位于同一数据中心内,并且应启用专用网络。
在这些服务器中的每一个上,您都需要一个配置有 sudo
访问权限的非 root 用户。 您可以按照我们的 Ubuntu 14.04 初始服务器设置指南 了解如何设置这些用户。
当您准备好开始时,使用您的非 root 用户登录到您的两台服务器。
安装和配置 Nginx
虽然 keepalived
通常用于监控和故障转移负载均衡器,但为了降低我们的操作复杂性,我们将在本指南中使用 Nginx 作为简单的 Web 服务器。
首先更新每台服务器上的本地包索引。 然后我们可以安装 Nginx:
sudo apt-get update sudo apt-get install nginx
在大多数情况下,对于高可用性设置,您会希望两台服务器提供完全相同的内容。 但是,为了清楚起见,在本指南中,我们将使用 Nginx 来指示两个服务器中的哪一个在任何给定时间为我们的请求提供服务。 为此,我们将更改每个主机上的默认 index.html
页面。 现在打开文件:
sudo nano /usr/share/nginx/html/index.html
在您的第一台服务器上,将文件的内容替换为:
主服务器的 /usr/share/nginx/html/index.html
<h1>Primary</h1>
在您的第二台服务器上,将文件的内容替换为:
辅助服务器的 /usr/share/nginx/html/index.html
<h1>Secondary</h1>
完成后保存并关闭文件。
构建和安装 Keepalived
接下来,我们将在我们的服务器上安装 keepalived
守护程序。 在 Ubuntu 的默认存储库中有一个 keepalived
版本,但它已经过时并且存在一些阻止我们的配置工作的错误。 相反,我们将从源代码安装最新版本的 keepalived
。
在开始之前,我们应该获取构建软件所需的依赖项。 build-essential
元包将提供我们需要的编译工具,而 libssl-dev
包包含 keepalived
需要构建的 SSL 库:
sudo apt-get install build-essential libssl-dev
一旦依赖关系到位,我们就可以下载 keepalived
的压缩包。 访问本页,查找最新版本的软件。 右键单击最新版本并复制链接地址。 回到您的服务器,移动到您的主目录并使用 wget
获取您复制的链接:
cd ~ wget http://www.keepalived.org/software/keepalived-1.2.19.tar.gz
使用 tar
命令展开存档,然后移动到生成的目录:
tar xzvf keepalived* cd keepalived*
通过键入以下内容构建和安装守护程序:
./configure make sudo make install
守护程序现在应该安装在系统上。
创建一个 Keepalived Upstart 脚本
keepalived
安装将所有二进制文件和支持文件移动到我们系统上的适当位置。 但是,没有包含的一个是我们的 Ubuntu 14.04 系统的 Upstart 脚本。
我们可以创建一个非常简单的 Upstart 脚本来处理我们的 keepalived
服务。 在 /etc/init
目录中打开一个名为 keepalived.conf
的文件以开始使用:
sudo nano /etc/init/keepalived.conf
在里面,我们可以从 keepalived
提供的功能的简单描述开始。 我们将使用包含的 man
页面中的描述。 接下来,我们将指定应该启动和停止服务的运行级别。 我们希望此服务在所有正常条件下(运行级别 2-5)都处于活动状态,并在所有其他运行级别(例如,当重新启动、断电或单用户模式启动时)停止:
/etc/init/keepalived.conf
description "load-balancing and high-availability service" start on runlevel [2345] stop on runlevel [!2345]
由于此服务对于确保我们的 Web 服务保持可用是不可或缺的,因此我们希望在发生故障时重新启动此服务。 然后我们可以指定将启动服务的实际 exec
行。 我们需要添加 --dont-fork
选项,以便 Upstart 可以正确跟踪 pid
:
/etc/init/keepalived.conf
description "load-balancing and high-availability service" start on runlevel [2345] stop on runlevel [!2345] respawn exec /usr/local/sbin/keepalived --dont-fork
完成后保存并关闭文件。
创建 Keepalived 配置文件
有了我们的 Upstart 文件,我们现在可以继续配置 keepalived
。
该服务在 /etc/keepalived
目录中查找其配置文件。 现在在您的两台服务器上创建该目录:
sudo mkdir -p /etc/keepalived
收集服务器的私有 IP 地址
在我们创建配置文件之前,我们需要找到我们两台服务器的私有 IP 地址。 在 DigitalOcean 服务器上,您可以通过输入以下内容通过元数据服务获取我们的私有 IP 地址:
curl http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo
Output10.132.7.107
这也可以通过输入 iproute2
工具找到:
ip -4 addr show dev eth1
您正在寻找的价值将在这里找到:
Output3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 10.132.7.107/16 brd 10.132.255.255 scope global eth1 valid_lft forever preferred_lft forever
从您的两个系统中复制此值。 我们需要在下面的配置文件中引用这些地址。
创建主服务器的配置
接下来,在您的主服务器上,创建主 keepalived
配置文件。 守护程序在 /etc/keepalived
目录中查找名为 keepalived.conf
的文件:
sudo nano /etc/keepalived/keepalived.conf
在内部,我们将首先通过打开 vrrp_script
块来为 Nginx 服务定义健康检查。 这将允许 keepalived
监控我们的 Web 服务器的故障,以便它可以发出进程已关闭的信号并开始恢复措施。
我们的检查将非常简单。 每两秒钟,我们将检查一个名为 nginx
的进程是否仍在声明 pid
:
主服务器的 /etc/keepalived/keepalived.conf
vrrp_script chk_nginx { script "pidof nginx" interval 2 }
接下来,我们将打开一个名为 vrrp_instance
的块。 这是定义 keepalived
实现高可用性的方式的主要配置部分。
我们将首先告诉 keepalived
通过我们的私有接口 eth1
与其对等方通信。 由于我们正在配置我们的主服务器,我们将 state
配置设置为“MASTER”。 这是 keepalived
将使用的初始值,直到守护进程可以联系其对等方并举行选举。
在选举过程中,priority
选项用于决定选举哪个成员。 该决定仅基于哪个服务器具有此设置的最高编号。 我们将使用“200”作为我们的主服务器:
主服务器的 /etc/keepalived/keepalived.conf
vrrp_script chk_nginx { script "pidof nginx" interval 2 } vrrp_instance VI_1 { interface eth1 state MASTER priority 200 }
接下来,我们将为这个集群组分配一个由两个节点共享的 ID。 我们将在此示例中使用“33”。 我们需要将 unicast_src_ip
设置为我们之前检索到的 primary 服务器的私有 IP 地址。 我们将 unicast_peer
设置为我们的 secondary 服务器的私有 IP 地址:
主服务器的 /etc/keepalived/keepalived.conf
vrrp_script chk_nginx { script "pidof nginx" interval 2 } vrrp_instance VI_1 { interface eth1 state MASTER priority 200 virtual_router_id 33 unicast_src_ip primary_private_IP unicast_peer { secondary_private_IP } }
接下来,我们可以为我们的 keepalived
守护进程设置一些简单的身份验证以相互通信。 这只是确保相关服务器合法的基本措施。 创建一个 authentication
子块。 在里面,通过设置auth_type
来指定密码认证。 对于 auth_pass
参数,设置两个节点都将使用的共享密钥。 不幸的是,只有前八个字符是重要的:
主服务器的 /etc/keepalived/keepalived.conf
vrrp_script chk_nginx { script "pidof nginx" interval 2 } vrrp_instance VI_1 { interface eth1 state MASTER priority 200 virtual_router_id 33 unicast_src_ip primary_private_IP unicast_peer { secondary_private_IP } authentication { auth_type PASS auth_pass password } }
接下来,我们将告诉 keepalived
使用我们在文件顶部创建的例程,标记为 chk_nginx
,以确定本地系统的运行状况。 最后,我们将设置一个 notify_master
脚本,只要该节点成为该对的“主”,就会执行该脚本。 该脚本将负责触发浮动 IP 地址重新分配。 我们将立即创建此脚本:
主服务器的 /etc/keepalived/keepalived.conf
vrrp_script chk_nginx { script "pidof nginx" interval 2 } vrrp_instance VI_1 { interface eth1 state MASTER priority 200 virtual_router_id 33 unicast_src_ip primary_private_IP unicast_peer { secondary_private_IP } authentication { auth_type PASS auth_pass password } track_script { chk_nginx } notify_master /etc/keepalived/master.sh }
设置完上述信息后,保存并关闭文件。
创建辅助服务器的配置
接下来,我们将在辅助服务器上创建伴随脚本。 在辅助服务器上的 /etc/keepalived/keepalived.conf
处打开一个文件:
sudo nano /etc/keepalived/keepalived.conf
在内部,我们将使用的脚本将在很大程度上等同于主服务器的脚本。 我们需要更改的项目是:
state
:这应该在辅助服务器上更改为“BACKUP”,以便节点在选举发生之前初始化为备份状态。priority
:应设置为低于主服务器的值。 我们将在本指南中使用值“100”。unicast_src_ip
:这应该是 辅助 服务器的私有 IP 地址。unicast_peer
:这应该包含 primary 服务器的私有 IP 地址。
当您更改这些值时,辅助服务器的脚本应如下所示:
辅助服务器的 /etc/keepalived/keepalived.conf
vrrp_script chk_nginx { script "pidof nginx" interval 2 } vrrp_instance VI_1 { interface eth1 state BACKUP priority 100 virtual_router_id 33 unicast_src_ip secondary_private_IP unicast_peer { primary_private_IP } authentication { auth_type PASS auth_pass password } track_script { chk_nginx } notify_master /etc/keepalived/master.sh }
输入脚本并更改适当的值后,保存并关闭文件。
创建浮动 IP 转换脚本
接下来,我们需要创建一对脚本,当本地 keepalived
实例成为主服务器时,我们可以使用它们将浮动 IP 地址重新分配给当前 Droplet。
下载浮动 IP 分配脚本
首先,我们将下载一个通用 Python 脚本(由 DigitalOcean 社区管理员 编写),该脚本可用于使用 DigitalOcean API 将浮动 IP 地址重新分配给 Droplet。 我们应该将此文件下载到 /usr/local/bin
目录:
cd /usr/local/bin sudo curl -LO http://do.co/assign-ip
此脚本允许您通过运行重新分配现有的浮动 IP:
python /usr/local/bin/assign-ip floating_ip droplet_ID
这仅在您将名为 DO_TOKEN
的环境变量设置为您帐户的有效 DigitalOcean API 令牌时才有效。
创建 DigitalOcean API 令牌
为了使用上面的脚本,我们需要在我们的帐户中创建一个 DigitalOcean API 令牌。
在控制面板中,单击顶部的“API”链接。 在 API 页面的右侧,单击“生成新令牌”:
在下一页上,为您的令牌选择一个名称,然后单击“生成令牌”按钮:
在 API 页面上,将显示您的新令牌:
复制令牌 now。 出于安全目的,以后无法再次显示此令牌。 如果你丢失了这个令牌,你将不得不销毁它并创建另一个。
为您的基础架构配置浮动 IP
接下来,我们将创建并分配一个浮动 IP 地址以用于我们的服务器。
在 DigitalOcean 控制面板中,单击“Networking”选项卡并选择“Floating IPs”导航项。 从您指定为“主要”服务器的列表中选择 Droplet:
将在您的帐户中创建一个新的浮动 IP 地址并分配给指定的 Droplet:
如果您在网络浏览器中访问浮动 IP,您应该会看到“主”服务器 index.html
页面:
向下复制浮动 IP 地址。 您将需要在下面的脚本中使用此值。
创建包装脚本
现在,我们有了创建包装脚本所需的项目,该脚本将使用正确的凭据调用我们的 /usr/local/bin/assign-ip
脚本。
现在通过键入以下内容在 两个 服务器上创建文件:
sudo nano /etc/keepalived/master.sh
在内部,首先分配和导出一个名为 DO_TOKEN
的变量,该变量包含您刚刚创建的 API 令牌。 在此之下,我们可以分配一个名为 IP
的变量来保存您的浮动 IP 地址:
/etc/keepalived/master.sh
export DO_TOKEN='digitalocean_api_token' IP='floating_ip_addr'
接下来,我们将使用 curl
向元数据服务询问我们当前所在服务器的 Droplet ID。 这将分配给一个名为 ID
的变量。 我们还会询问这个 Droplet 当前是否有分配给它的浮动 IP 地址。 我们将该请求的结果存储在一个名为 HAS_FLOATING_IP
的变量中:
/etc/keepalived/master.sh
export DO_TOKEN='digitalocean_api_token' IP='floating_ip_addr' ID=$(curl -s http://169.254.169.254/metadata/v1/id) HAS_FLOATING_IP=$(curl -s http://169.254.169.254/metadata/v1/floating_ip/ipv4/active)
现在,我们可以使用上面的变量来调用 assign-ip
脚本。 如果浮动 IP 尚未与我们的 Droplet 关联,我们只会调用该脚本。 这将有助于最大限度地减少 API 调用,并有助于防止在您的服务器之间快速切换主状态的情况下对 API 的请求发生冲突。
为了处理浮动 IP 已经有事件正在进行的情况,我们将重试 assign-ip
脚本几次。 下面,我们尝试运行脚本 10 次,每次调用之间的间隔为 3 秒。 如果浮动 IP 移动成功,循环将立即结束:
/etc/keepalived/master.sh
export DO_TOKEN='digitalocean_api_token' IP='floating_ip_addr' ID=$(curl -s http://169.254.169.254/metadata/v1/id) HAS_FLOATING_IP=$(curl -s http://169.254.169.254/metadata/v1/floating_ip/ipv4/active) if [ $HAS_FLOATING_IP = "false" ]; then n=0 while [ $n -lt 10 ] do python /usr/local/bin/assign-ip $IP $ID && break n=$((n+1)) sleep 3 done fi
完成后保存并关闭文件。
现在,我们只需要使脚本可执行,以便 keepalived
可以调用它:
sudo chmod +x /etc/keepalived/master.sh
启动 Keepalived 服务并测试故障转移
现在应该完全配置 keepalived
守护程序及其所有伴随脚本。 我们可以通过键入以下内容在两台机器上启动服务:
sudo start keepalived
该服务应该在每台服务器上启动并联系其对等方,使用我们配置的共享密钥进行身份验证。 每个守护进程都会监控本地 Nginx 进程,并会监听来自远程 keepalived
进程的信号。
当两台服务器都正常时,如果您在 Web 浏览器中访问您的浮动 IP,您应该会被带到主服务器的 Nginx 页面:
现在,我们已准备好测试配置的故障转移功能。
当出现以下任一情况时,应发生故障转移:
- 当主服务器上的Nginx健康检查表明Nginx不再运行时。这种情况下,主服务器的
keepalived
守护进程将进入“故障”状态。 它将通知辅助服务器它应该转换到主状态并声明浮动 IP。 - 当辅助服务器失去与主服务器的keepalived连接时。 如果从服务器由于任何原因无法访问主服务器,它将转换到“主”状态并尝试申请浮动 IP。
如果主服务器稍后恢复,它将转换回 master 状态并回收浮动 IP,因为它将发起新的选举(它仍然具有最高优先级)。
测试 Nginx 失败
我们可以通过停止主服务器上的 Nginx 服务来测试第一个条件:
sudo service nginx stop
如果您刷新 Web 浏览器,您最初可能会收到指示该页面不可用的响应:
然而,仅仅几秒钟后,如果你刷新页面几次,你会看到从服务器已经认领了浮动IP地址:
我们可以通过重启主服务器上的 Nginx 守护进程来从故障中恢复:
sudo service nginx start
几秒后,如果刷新页面,会发现主服务器又收回了浮动IP的所有权:
测试服务器故障
我们应该测试的另一个场景是,如果辅助服务器无法连接到主服务器,它是否正确转换到主服务器状态。 我们可以重启主服务器来测试:
sudo reboot
同样,我们首先应该看到浮动 IP 地址处的服务中断:
几秒钟后,辅助服务器将接收请求:
片刻之后,当主服务器完成重启后,它将回收 IP 地址:
这验证了我们的第二个失败场景。
结论
在本指南中,我们使用 keepalived
、DigitalOcean API 和浮动 IP 地址配置了一个高可用性 Web 服务器环境。 实际的基础架构相当简单,但这些概念可以应用于服务可用性和正常运行时间很重要的任何类型的基础架构。