如何在Ubuntu14.04上设置具有Keepalived和浮动IP的高可用性HAProxy服务器

来自菜鸟教程
跳转至:导航、​搜索

介绍

高可用性是系统设计的一项功能,它允许应用程序在发生故障时自动重新启动或将工作重新路由到另一个有能力的系统。 在服务器方面,建立高可用性系统需要几种不同的技术。 必须有一个可以重定向工作的组件,并且必须有一种机制来监视故障并在检测到中断时转换系统。

keepalived 守护进程可用于监控服务或系统,并在出现问题时自动故障转移到备用服务器。 在本指南中,我们将演示如何使用 keepalived 为您的负载均衡器设置高可用性。 我们将配置一个 浮动 IP 地址 ,它可以在两个有能力的负载平衡器之间移动。 这些都将被配置为在两个后端 Web 服务器之间分配流量。 如果主负载均衡器出现故障,浮动 IP 将自动移动到第二个负载均衡器,从而恢复服务。

笔记: DigitalOcean 负载均衡器 are a fully-managed, highly available load balancing service. The Load Balancer service can fill the same role as the manual high availability setup described here. Follow our 设置负载均衡器的指南 if you wish to evaluate that option.


先决条件

为了完成本指南,您需要在您的 DigitalOcean 帐户中创建四个 Ubuntu 14.04 服务器。 所有服务器必须位于同一数据中心内,并且应启用专用网络。

在这些服务器中的每一个上,您都需要一个配置有 sudo 访问权限的非 root 用户。 您可以按照我们的 Ubuntu 14.04 初始服务器设置指南 了解如何设置这些用户。

查找服务器网络信息

在我们开始对我们的基础架构组件进行实际配置之前,最好收集有关您的每台服务器的一些信息。

要完成本指南,您需要了解有关服务器的以下信息:

  • 网络服务器:私有IP地址
  • 负载均衡器私有和锚IP地址

查找私有 IP 地址

查找 Droplet 私有 IP 地址的最简单方法是使用 curl 从 DigitalOcean 元数据服务中获取私有 IP 地址。 这个命令应该在你的 Droplets 中运行。 在每个 Droplet 上,键入:

curl 169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo

正确的 IP 地址应打印在终端窗口中:

Output10.132.20.236

查找锚点 IP 地址

“锚 IP”是浮动 IP 在连接到 DigitalOcean 服务器时将绑定到的本地私有 IP 地址。 它只是在管理程序级别实现的常规 eth0 地址的别名。

获取此值的最简单、最不容易出错的方法是直接来自 DigitalOcean 元数据服务。 使用 curl,您可以通过键入以下内容访问每台服务器上的此端点:

curl 169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address && echo

锚 IP 将打印在自己的行上:

Output10.17.1.18

安装和配置 Web 服务器

收集完上述数据后,我们可以继续配置我们的服务。

笔记

在此设置中,为 Web 服务器层选择的软件是可以互换的。 本指南将使用 Nginx,因为它是通用的并且相当容易配置。 如果您更喜欢 Apache 或(支持生产的)特定语言的 Web 服务器,请随意使用它。 HAProxy 将简单地将客户端请求传递给后端 Web 服务器,后端 Web 服务器可以处理请求,类似于处理直接客户端连接的方式。


我们将从设置后端 Web 服务器开始。 这两个服务器将提供完全相同的内容。 他们将只接受通过其私有 IP 地址进行的 Web 连接。 这将有助于确保流量通过我们稍后将配置的两个 HAProxy 服务器之一进行定向。

在负载均衡器后面设置 Web 服务器允许我们在一些相同的 Web 服务器之间分配请求负担。 随着我们的流量需求发生变化,我们可以通过在该层添加或删除 Web 服务器来轻松扩展以满足新的需求。

安装 Nginx

我们将在我们的 Web 服务机器上安装 Nginx 以提供此功能。

首先使用您的 sudo 用户登录到您希望用作 Web 服务器的两台机器。 更新每个 Web 服务器上的本地包索引并通过键入以下命令安装 Nginx:

sudo apt-get update
sudo apt-get install nginx

将 Nginx 配置为仅允许来自负载均衡器的请求

接下来,我们将配置我们的 Nginx 实例。 我们想告诉 Nginx 只监听服务器私有 IP 地址上的请求。 此外,我们只会处理来自两个负载均衡器的私有 IP 地址的请求。

要进行这些更改,请在每个 Web 服务器上打开默认的 Nginx 服务器块文件:

sudo nano /etc/nginx/sites-available/default

首先,我们将修改 listen 指令。 更改 listen 指令以在端口 80 上侦听当前 web 服务器的私有 IP 地址 。 删除多余的 listen 行。 它应该看起来像这样:

/etc/nginx/sites-available/default

server {
    listen web_server_private_IP:80;

    . . .

之后,我们将设置两个 allow 指令来允许来自我们两个负载均衡器的私有 IP 地址的流量。 我们将使用 deny all 规则来禁止所有其他流量:

/etc/nginx/sites-available/default

server {
    listen web_server_private_IP:80;

    allow load_balancer_1_private_IP;
    allow load_balancer_2_private_IP;
    deny all;

    . . .

完成后保存并关闭文件。

通过键入以下内容测试您所做的更改是否代表有效的 Nginx 语法:

sudo nginx -t

如果没有报告任何问题,请键入以下命令重新启动 Nginx 守护程序:

sudo service nginx restart

测试更改

要测试您的 Web 服务器是否受到正确限制,您可以使用 curl 从不同位置发出请求。

在您的 Web 服务器本身上,您可以通过键入以下内容尝试对本地内容的简单请求:

curl 127.0.0.1

由于我们在 Nginx 服务器块文件中设置的限制,这个请求实际上会被拒绝:

Outputcurl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused

这是意料之中的,反映了我们试图实现的行为。

现在,从任一 负载均衡器 ,我们可以请求我们任一 Web 服务器的公共 IP 地址:

curl web_server_public_IP

再一次,这应该失败。 Web 服务器没有在公共接口上监听,此外,当使用公共 IP 地址时,我们的 Web 服务器不会在来自负载均衡器的请求中看到允许的私有 IP 地址:

Outputcurl: (7) Failed to connect to web_server_public_IP port 80: Connection refused

但是,如果我们修改调用以使用 Web 服务器的 私有 IP 地址 发出请求,它应该可以正常工作:

curl web_server_private_IP

应该返回默认的 Nginx index.html 页面:

Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

. . .

从两个负载平衡器到两个 Web 服务器对此进行测试。 对私有 IP 地址的每个请求都应该成功,而对公共地址的每个请求都应该失败。

一旦证明了上述行为,我们就可以继续前进。 我们的后端 Web 服务器配置现已完成。

安装和配置 HAProxy

接下来,我们将设置 HAProxy 负载平衡器。 这些将分别位于我们的 Web 服务器前面,并在两个后端服务器之间拆分请求。 这些负载平衡器是完全冗余的。 在任何给定时间,只有一个会收到流量。

HAProxy 配置会将请求传递给两个 Web 服务器。 负载均衡器将在其锚点 IP 地址上侦听请求。 如前所述,这是浮动IP地址在附加到Droplet时将绑定到的IP地址。 这可确保仅转发源自浮动 IP 地址的流量。

安装 HAProxy

我们需要对负载均衡器采取的第一步是安装 haproxy 包。 我们可以在默认的 Ubuntu 存储库中找到它。 更新负载均衡器上的本地包索引并通过键入以下命令安装 HAProxy:

sudo apt-get update
sudo apt-get install haproxy

配置 HAProxy

我们在处理HAProxy时首先需要修改的是/etc/default/haproxy文件。 现在在您的编辑器中打开该文件:

sudo nano /etc/default/haproxy

该文件确定 HAProxy 是否会在启动时启动。 由于我们希望每次服务器开机自动启动服务,我们需要将ENABLED的值改为“1”:

/etc/default/haproxy

# Set ENABLED to 1 if you want the init script to start haproxy.
ENABLED=1
# Add extra flags here.
#EXTRAOPTS="-de -m 16"

进行上述编辑后保存并关闭文件。

接下来,我们可以打开主 HAProxy 配置文件:

sudo nano /etc/haproxy/haproxy.cfg

我们需要调整的第一项是 HAProxy 将运行的模式。 我们要配置 TCP 或第 4 层负载平衡。 为此,我们需要更改 default 部分中的 mode 行。 我们还应该立即更改处理日志的选项:

/etc/haproxy/haproxy.cfg

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

在文件的最后,我们需要定义我们的前端配置。 这将决定 HAProxy 如何侦听传入连接。 我们将 HAProxy 绑定到负载均衡器锚 IP 地址。 这将允许它侦听来自浮动 IP 地址的流量。 为简单起见,我们将前端称为“www”。 我们还将指定一个默认后端来传递流量(稍后我们将对其进行配置):

/etc/haproxy/haproxy.cfg

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

frontend www
    bind    load_balancer_anchor_IP:80
    default_backend nginx_pool

接下来,我们可以配置我们的后端部分。 这将指定 HAProxy 将传递其接收到的流量的下游位置。 在我们的例子中,这将是我们配置的两个 Nginx Web 服务器的私有 IP 地址。 我们将指定传统的循环平衡,并将模式再次设置为“tcp”:

/etc/haproxy/haproxy.cfg

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

frontend www
    bind load_balancer_anchor_IP:80
    default_backend nginx_pool

backend nginx_pool
    balance roundrobin
    mode tcp
    server web1 web_server_1_private_IP:80 check
    server web2 web_server_2_private_IP:80 check

完成上述更改后,保存并关闭文件。

通过键入以下内容检查我们所做的配置更改是否代表有效的 HAProxy 语法:

sudo haproxy -f /etc/haproxy/haproxy.cfg -c

如果没有报告错误,请键入以下内容重新启动您的服务:

sudo service haproxy restart

测试更改

我们可以通过再次使用 curl 测试来确保我们的配置是有效的。

从负载均衡器服务器,尝试请求本地主机、负载均衡器自己的公共 IP 地址或服务器自己的私有 IP 地址:

curl 127.0.0.1
curl load_balancer_public_IP
curl load_balancer_private_IP

这些都应该失败,并显示类似于此的消息:

Outputcurl: (7) Failed to connect to address port 80: Connection refused

但是,如果您向负载均衡器的 锚 IP 地址 发出请求,它应该会成功完成:

curl load_balancer_anchor_IP

您应该看到默认的 Nginx index.html 页面,从两个后端 Web 服务器之一路由:

Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

. . .

如果此行为与您的系统相匹配,那么您的负载平衡器配置正确。

构建和安装 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

创建主负载均衡器的配置

接下来,在您希望用作 服务器的负载平衡器服务器上,创建主 keepalived 配置文件。 守护程序在 /etc/keepalived 目录中查找名为 keepalived.conf 的文件:

sudo nano /etc/keepalived/keepalived.conf

在内部,我们将首先通过打开 vrrp_script 块为我们的 HAProxy 服务定义健康检查。 这将允许 keepalived 监控我们的负载均衡器是否出现故障,以便它可以发出进程已关闭的信号并开始恢复措施。

我们的检查将非常简单。 每两秒钟,我们将检查一个名为 haproxy 的进程是否仍在声明 pid

主服务器的 /etc/keepalived/keepalived.conf

vrrp_script chk_haproxy {
    script "pidof haproxy"
    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_haproxy {
    script "pidof haproxy"
    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_haproxy {
    script "pidof haproxy"
    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_haproxy 的检查来确定本地系统的运行状况。 最后,我们将设置一个 notify_master 脚本,只要该节点成为该对的“主”,就会执行该脚本。 该脚本将负责触发浮动 IP 地址重新分配。 我们将立即创建此脚本:

主服务器的 /etc/keepalived/keepalived.conf

vrrp_script chk_haproxy {
    script "pidof haproxy"
    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_haproxy
    }

    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_haproxy {
    script "pidof haproxy"
    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_haproxy
    }

    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”导航项。 从菜单中选择您的主负载均衡器进行初始分配:

将在您的帐户中创建一个新的浮动 IP 地址并分配给指定的 Droplet:

如果您在 Web 浏览器中访问浮动 IP,您应该会看到从后端 Web 服务器之一提供的默认 Nginx 页面:

向下复制浮动 IP 地址。 您将需要在下面的脚本中使用此值。

创建包装脚本

现在,我们有了创建包装脚本所需的项目,该脚本将使用正确的凭据调用我们的 /usr/local/bin/assign-ip 脚本。

现在通过键入以下内容在负载均衡器的 both 上创建文件:

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

该服务应该在每台服务器上启动并联系其对等方,使用我们配置的共享密钥进行身份验证。 每个守护进程都会监控本地 HAProxy 进程,并监听来自远程 keepalived 进程的信号。

您的主负载均衡器当前应该分配有浮动 IP 地址,它将依次将请求定向到每个后端 Nginx 服务器。 通常会应用一些简单的会话粘性,这使得您在通过 Web 浏览器发出请求时更有可能获得相同的后端。

我们可以通过简单地关闭主负载均衡器上的 HAProxy 来测试故障转移:

sudo service haproxy stop

如果我们在浏览器中访问我们的浮动 IP 地址,我们可能会暂时收到一个错误,指示找不到该页面:

http://floating_IP_addr

如果我们刷新页面几次,一会儿,我们默认的 Nginx 页面就会回来:

我们的 HAProxy 服务仍然在我们的主负载均衡器上关闭,因此这表明我们的辅助负载均衡器已接管。 使用 keepalived,辅助服务器能够确定发生了服务中断。 然后它转换到“主”状态并使用 DigitalOcean API 声明浮动 IP。

我们现在可以再次在主负载均衡器上启动 HAProxy:

sudo service haproxy start

主负载均衡器将立即重新获得对浮动 IP 地址的控制权,尽管这对用户来说应该是相当透明的。

可视化过渡

为了更好地可视化负载均衡器之间的过渡,我们可以在过渡期间监控我们的一些服务器日志。

由于有关正在使用哪个代理服务器的信息不会返回给客户端,因此查看日志的最佳位置是来自实际的后端 Web 服务器。 这些服务器中的每一个都应维护有关哪些客户端请求资产的日志。 从 Nginx 服务的角度来看,客户端是代表真实客户端发出请求的负载均衡器。

跟踪 Web 服务器上的日志

在我们的每个后端 Web 服务器上,我们可以 tail /var/log/nginx/access.log 位置。 这将显示对服务器的每个请求。 由于我们的负载均衡器使用循环轮换平均分配流量,因此每个后端 Web 服务器应该会看到大约一半的请求。

幸运的是,客户端地址是访问日志中的第一个字段。 我们可以使用简单的 awk 命令提取该值。 在 Nginx Web 服务器的 both 上运行以下命令:

sudo tail -f /var/log/nginx/access.log | awk '{print $1;}'

这些可能主要显示一个地址:

Output. . .

primary_lb_private_IP
primary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP

如果您引用您的服务器 IP 地址,您会注意到这些主要来自您的主负载均衡器。 请注意,由于 HAProxy 实现了一些简单的会话粘性,实际分布可能会有所不同。

保持 tail 命令在您的两个 Web 服务器上运行。

自动请求浮动 IP

现在,在您的本地机器上,我们将每 2 秒请求一次浮动 IP 地址的 Web 内容。 这将使我们能够轻松地看到负载均衡器发生的变化。 在您的本地终端中,键入以下内容(我们将丢弃实际响应,因为无论使用哪个负载均衡器,这都应该相同):

while true; do curl -s -o /dev/null floating_IP; sleep 2; done

在您的 Web 服务器上,您应该开始看到新的请求进入。 与通过 Web 浏览器发出的请求不同,简单的 curl 请求不会表现出相同的会话粘性。 您应该会看到对后端 Web 服务器的请求更加均匀。

中断主负载均衡器上的 HAProxy 服务

现在,我们可以再次关闭主负载均衡器上的 HAProxy 服务:

sudo service haproxy stop

几秒钟后,在您的 Web 服务器上,您应该会看到 IP 列表从主负载均衡器的私有 IP 地址转换到辅助负载均衡器的私有 IP 地址:

Output. . .

primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP

所有新请求都来自您的辅助负载均衡器。

现在,在主负载均衡器上再次启动 HAProxy 实例:

sudo service haproxy start

您将看到客户端请求在几秒钟内转换回主负载均衡器的私有 IP 地址:

Output. . .

primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP

主服务器已重新获得对浮动 IP 地址的控制权,并已恢复其作为基础架构主要负载平衡器的工作。

配置 Nginx 以记录实际客户端 IP 地址

如您所见,Nginx 访问日志显示所有客户端请求都来自当前负载均衡器的私有 IP 地址,而不是最初发出请求的客户端的实际 IP 地址(即 您的本地机器)。 记录原始客户端的 IP 地址而不是负载平衡器服务器通常很有用。 这可以通过对所有后端 Web 服务器上的 Nginx 配置进行一些更改来轻松实现。

在两个 Web 服务器上,在编辑器中打开 nginx.conf 文件:

sudo nano /etc/nginx/nginx.conf

找到“Logging Settings”部分(在 http 块内),并添加以下行:

添加到 /etc/nginx/nginx.conf

log_format haproxy_log 'ProxyIP: $remote_addr - ClientIP: $http_x_forwarded_for - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"';

保存并退出。 这指定了一种名为 haproxy_log 的新日志格式,它将 $http_x_forwarded_for 值(发出原始请求的客户端的 IP 地址)添加到默认访问日志条目中。 我们还包括 $remote_addr,它是反向代理负载均衡器的 IP 地址(即 活动负载平衡器服务器)。

接下来,要使用这种新的日志格式,我们需要在默认服务器块中添加一行。

在两台 Web 服务器上,打开 default 服务器配置:

sudo nano /etc/nginx/sites-available/default

server 块中(listen 指令正下方是一个好地方),添加以下行:

添加到 /etc/nginx/sites-available/default

        access_log /var/log/nginx/access.log haproxy_log;

保存并退出。 这告诉 Nginx 使用我们在上面创建的 haproxy_log 日志格式写入其访问日志。

在两个 Web 服务器上,重新启动 Nginx 以使更改生效:

sudo service nginx restart

现在您的 Nginx 访问日志应该包含发出请求的客户端的实际 IP 地址。 正如我们在上一节中所做的那样,通过跟踪您的应用服务器的日志来验证这一点。 日志条目应如下所示:

New Nginx access logs:. . .
ProxyIP: load_balancer_private_IP - ClientIP: local_machine_IP - - [05/Nov/2015:15:05:53 -0500] "GET / HTTP/1.1" 200 43 "-" "curl/7.43.0"
. . .

如果您的日志看起来不错,则一切就绪!

结论

在本指南中,我们介绍了设置高可用性、负载平衡的基础架构的完整过程。 此配置运行良好,因为活动 HAProxy 服务器可以将负载分配到后端的 Web 服务器池。 随着需求的增长或缩减,您可以轻松扩展此池。

浮动 IP 和 keepalived 配置消除了负载均衡层的单点故障,即使主负载均衡器完全失败,您的服务也能继续运行。 此配置相当灵活,可以通过在 HAProxy 服务器后面设置您喜欢的 Web 堆栈来适应您自己的应用程序环境。