介绍
本教程将向您展示如何在Ubuntu 14.04上创建高可用性HAProxy负载均衡器设置,并支持浮动IP和Corosync / Pacemaker集群堆栈。HAProxy负载平衡器将分别配置为在两个后端应用程序服务器之间分割流量。如果主负载均衡器发生故障,则浮动IP将自动移至第二个负载均衡器,从而允许恢复服务。
准备
为了完成本教程,您需要在Ubuntu 14.04上完成用Corosync,Pacemaker和浮动IP创建高可用性设置。这将为您留下两个Droplet,我们将其称为主要和次要,具有可在它们之间转换的浮动IP。总的来说,我们将这些服务器称为负载平衡器。这些是我们将安装负载均衡器HAProxy的Droplet。
您还需要能够在启用了专用网络的同一数据中心中创建另外两个Ubuntu 14.04 Droplet,以证明HA负载均衡器设置有效。这些是由HAProxy负载平衡的服务器。我们将引用这些应用程序服务器,我们将在其上安装Nginx,作为app-1和app-2。如果您已经有要加载平衡的应用程序服务器,请随意使用它们。
在每个服务器上,您将需要一个配置了sudo
访问权限的非root用户,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。
创建应用程序Droplet
第一步是在与负载均衡器相同的数据中心中创建两个启用了专用网络的Ubuntu Droplet,它们将充当上述app-1和app-2服务器。我们将在两个Droplet上安装Nginx,并用唯一标识它们的信息替换它们的索引页面。这将允许我们以一种简单的方式来演示HA负载均衡器设置是否正常工作。如果您已经拥有要进行负载平衡的应用程序服务器,请随意调整本教程的相应部分以使教程继续(并跳过与您的设置无关的任何部分)。
如果您想按照示例设置,创建两个Ubuntu 14.04 Droplet,app-1和app-2,并使用此bash脚本作为用户数据:
示例用户数据
代码语言:javascript复制#!/bin/bash
apt-get -y update
apt-get -y install nginx
export HOSTNAME=$(curl -s http://169.254.169.254/metadata/v1/hostname)
export PUBLIC_IPV4=$(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)
echo Droplet: $HOSTNAME, IP Address: $PUBLIC_IPV4 > /usr/share/nginx/html/index.html
此用户数据将安装Nginx并使用droplet的主机名和公共IP地址(通过引用元数据服务)替换index.html的内容。访问Droplet将显示带有Droplet主机名和公共IP地址的基本网页,这对于测试负载均衡器将流量引导到哪个应用服务器非常有用。
收集服务器网络信息
在我们开始实际配置基础架构组件之前,最好收集有关每个服务器的一些信息。
要完成本教程,您需要获得有关服务器的以下信息:
- 应用服务器:私有IP地址
- 负载均衡器专用和锚定IP地址
查找专用IP地址
查找Droplet私有IP地址的最简单方法是使用curl
从服务器元数据服务中获取私有IP地址。应该从Droplet中运行此命令。在每个Droplet上输入:
curl 169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo
应在终端窗口中打印正确的IP地址:
代码语言:javascript复制Private IP address:10.132.20.236
在所有四个Droplet上执行此步骤,并将私有IP地址复制到您可以轻松引用的位置。
查找Anchor IP地址
该锚IP是浮动IP将绑定时,连接服务器到本地的私有IP地址。它只是eth0
在虚拟机管理程序级别实现的常规地址的别名。
获取此值最简单,最不易出错的方法是直接来自服务器元数据服务。使用curl
,您可以通过输入以下内容以在每台服务器上联系此端点:
curl 169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address && echo
锚IP将打印在自己的行上:
代码语言:javascript复制Output10.17.1.18
在两个负载均衡器Droplet上执行此步骤,并将锚IP地址复制到您可以轻松引用的位置。
配置App Server
收集上述数据后,我们可以继续配置我们的服务。
注意 ,在此设置中,为Web服务器层选择的软件是可以互换的。本教程将使用Nginx,因为它是通用的,而且很容易配置。如果您对Apache或(支持生产的)特定于语言的Web服务器更熟悉,您可以随意更换。HAProxy将简单地将客户端请求传递给后端Web服务器,后端Web服务器可以处理请求,类似于处理直接客户端连接的方式。
我们将从设置后端应用服务器开始。这两个服务器都只提供其名称和公共IP地址; 在实际设置中,这些服务器将提供相同的内容。他们只接受私人IP地址的网络连接。这将有助于确保流量仅通过我们稍后将配置的两个HAProxy服务器之一进行定向。
在负载均衡器后面设置应用服务器允许我们在一些数量相同的应用服务器之间分配请求负担。随着我们的流量需求发生变化,我们可以通过在此层添加或删除应用服务器来轻松扩展以满足新需求。
将Nginx配置为仅允许来自负载均衡器的请求
如果您正在关注该示教程,并且在创建应用服务器时使用了提供的用户数据,则您的服务器已经安装了Nginx。下一步是进行一些配置更改。
我们希望将Nginx配置为仅侦听服务器私有IP地址上的请求。此外,我们只会处理来自两个负载均衡器的私有IP地址的请求。这将强制用户通过负载均衡器访问您的应用服务器(我们将配置为只能通过浮动IP地址访问)。
要进行这些更改,请在每个应用服务器上打开默认的Nginx服务器阻止文件:
代码语言:javascript复制sudo vi /etc/nginx/sites-available/default
首先,我们将修改listen
指令。更改listen
指令以侦听端口80上当前应用服务器的专用IP地址。删除额外的listen
行。它看起来像这样:
server {
listen app_server_private_IP:80;
. . .
在listen
指令的正下方,我们将设置两个allow
指令,以允许来自我们两个负载平衡器的私有IP地址的流量。我们将遵循此deny all
规则禁止所有其他流量:
allow load_balancer_1_private_IP;
allow load_balancer_2_private_IP;
deny all;
完成后保存并关闭文件。
通过输入以下内容来测试您所做的更改是否代表有效的Nginx语法:
代码语言:javascript复制sudo nginx -t
如果没有报告任何问题,请输入以下命令重新启动Nginx守护程序:
代码语言:javascript复制sudo service nginx restart
请记住在两台应用服务器上执行所有这些步骤(使用适当的应用服务器专用IP地址)。
测试更改
要测试您的应用服务器是否受到正确限制,您可以使用curl
来自不同位置的请求。
在您的应用服务器本身,您可以通过输入以下内容来尝试对本地内容的简单请求:
代码语言:javascript复制curl 127.0.0.1
由于我们在Nginx服务器块文件中设置的限制,实际上将拒绝此请求:
代码语言:javascript复制Outputcurl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused
这是预期的,反映了我们试图实施的行为。
现在,从任一负载均衡器,我们可以请求我们的任一应用服务器的公共IP地址:
代码语言:javascript复制curl web_server_public_IP
再次,这应该失败。应用服务器没有在公共接口上侦听,而且,当使用公共IP地址时,我们的应用服务器将无法在负载均衡器的请求中看到允许的私有IP地址:
代码语言:javascript复制Outputcurl: (7) Failed to connect to app_server_public_IP port 80: Connection refused
但是,如果我们使用应用服务器的私有IP地址修改调用以发出请求,它应该正常工作:
代码语言:javascript复制curl app_server_private_IP
Nginx的index.html
页面应该返回。如果您使用了此教程用户数据,则该页面应包含要访问的应用服务器的名称和公共IP地址:
app server index.htmlDroplet: app-1, IP Address: 159.203.130.34
从负载均衡器到两个应用服务器进行测试。每个对公共地址的请求都应该失败,对私有IP地址的每个请求都应该成功。
一旦证明了上述行为,我们就可以继续前进。我们的后端应用服务器配置现已完成。
从负载均衡器中删除Nginx
通过使用Corosync,Pacemaker和Floating IPs教程遵循准备步骤的HA设置,您的负载均衡器服务器将安装Nginx。因为我们将使用HAProxy作为反向代理负载均衡器,所以我们应该删除Nginx和任何相关的集群资源。
删除Nginx群集资源
如果在遵循准备步骤的同时添加了Nginx集群资源,请在其中一个负载平衡器上使用这些命令停止并删除Nginx
资源:
sudo crm resource stop Nginx
sudo crm configure delete Nginx
这还应删除依赖于Nginx
资源的任何集群设置。例如,如果您创建了一个引用该Nginx
资源的clone
或colocation
资源,那么它们也将被删除。
删除Nginx包
现在我们准备在两个负载均衡器服务器上卸载Nginx 。
首先,停止Nginx服务:
代码语言:javascript复制sudo service nginx stop
然后使用以下命令清除包:
代码语言:javascript复制sudo apt-get purge nginx
您可能还想删除Nginx配置文件:
代码语言:javascript复制sudo rm -r /etc/nginx
现在我们已准备好安装和配置HAProxy。
安装和配置HAProxy
接下来,我们将设置HAProxy负载平衡器。这些将分别位于我们的Web服务器前面,并在两个后端应用服务器之间分割请求。在主动 - 被动配置中,这些负载平衡器将是完全冗余的; 只有一台服务器会在任何给定时间接收流量。
HAProxy配置会将请求传递给两个Web服务器。负载平衡器将监听其锚定IP地址上的请求。如前所述,这是浮动IP地址连接到Droplet时将绑定的IP地址。这可确保仅转发源自浮动IP地址的流量。
安装HAProxy
此部分需要在两个负载平衡器服务器上执行。
我们将安装HAProxy 1.6,它不在默认的Ubuntu存储库中。但是,如果我们使用PPA,我们仍然可以使用包管理器安装HAProxy 1.6,使用此命令:
代码语言:javascript复制sudo add-apt-repository ppa:vbernat/haproxy-1.6
更新负载均衡器上的本地软件包索引并输入以下内容安装HAProxy:
代码语言:javascript复制sudo apt-get update
sudo apt-get install haproxy
现在安装了HAProxy,但我们现在需要对其进行配置。
配置HAProxy
打开主HAProxy配置文件:
代码语言:javascript复制sudo vi /etc/haproxy/haproxy.cfg
找到该defaults
部分,并在其下添加以下两行:
option forwardfor
option http-server-close
该forwardfor选项设置HAProxy的添加X-Forwarded-For
标题到每个请求,其中,如果你希望你的应用服务器知道哪些IP地址最初发送的请求,并且是有用的HTTP服务器关闭选项可减少HAProxy的和用户之间的延时通过关闭连接,但保持活力。
接下来,在文件的末尾,我们需要定义我们的前端配置。这将决定HAProxy如何侦听传入连接。我们将HAProxy绑定到负载均衡器锚点IP地址。这将允许它侦听源自浮动IP地址的流量。为简单起见,我们将前端称为“http”。我们还将指定一个默认后端app_pool
,以便将流量传递给(我们将在稍后配置):
frontend http
bind load_balancer_anchor_IP:80
default_backend app_pool
注意:锚IP是HAProxy配置中唯一应该在负载均衡器服务器之间有所不同的部分。也就是说,请务必指定您当前正在处理的负载均衡器服务器的锚点IP。
接下来,我们可以定义后端配置。这将指定HAProxy将传递其接收的流量的下游位置。在我们的教程中,这将是我们配置的两个Nginx应用服务器的私有IP地址:
代码语言:javascript复制backend app_pool
server app-1 app_server_1_private_IP:80 check
server app-2 app_server_2_private_IP:80 check
完成上述更改后,保存并退出文件。
通过输入以下内容,检查我们所做的配置更改是否代表有效的HAProxy语法:
代码语言:javascript复制sudo haproxy -f /etc/haproxy/haproxy.cfg -c
如果未报告任何错误,请输入以下命令重新启动服务:
代码语言:javascript复制sudo service haproxy restart
同样,请确保在两个负载均衡器服务器上执行本节中的所有步骤。
测试更改
我们可以通过curl
再次测试来确保我们的配置有效。
从负载均衡器服务器,尝试请求本地主机,负载均衡器自己的公共IP地址或服务器自己的专用IP地址:
代码语言:javascript复制curl 127.0.0.1
curl load_balancer_public_IP
curl load_balancer_private_IP
这些都应该失败,输出看起来类似于这样:
代码语言:javascript复制Outputcurl: (7) Failed to connect to IP_address port 80: Connection refused
但是,如果您向负载均衡器的锚IP地址发出请求,它应该成功完成:
代码语言:javascript复制curl load_balancer_anchor_IP
您应该看到其中一个应用服务器的Nginx的index.html
页面:
app server index.htmlDroplet: app-1, IP Address: app1_IP_address
再次执行相同的curl请求:
代码语言:javascript复制curl load_balancer_anchor_IP
您应该看到其他应用服务器的index.html
页面,因为默认情况下HAProxy使用循环负载平衡:
app server index.htmlDroplet: app-2, IP Address: app2_IP_address
如果此行为与您的系统的行为相匹配,那么您的负载均衡器配置正确; 您已成功测试了负载均衡器服务器正在平衡两个后端应用服务器之间的流量。此外,您的浮动IP应该已经分配给其中一个负载平衡器服务器,因为它是在先前的HA设置中使用Corosync,Pacemaker和浮动IP 设置的。
下载HAProxy OCF资源代理
此时,您已实施基本的主机级故障转移,但我们可以通过将HAProxy添加为集群资源来改进设置。这样做将允许您的群集确保HAProxy正在您的浮动IP分配给的服务器上运行。如果Pacemaker检测到HAProxy未运行,它可以重新启动服务或将浮动IP分配给另一个节点(应该运行HAProxy)。
Pacemaker允许通过将OCF资源代理放置在特定目录中来添加它们。
在两个负载平衡器服务器上,使用以下命令下载HAProxy OCF资源代理:
代码语言:javascript复制cd /usr/lib/ocf/resource.d/heartbeat
sudo curl -O https://raw.githubusercontent.com/thisismitch/cluster-agents/master/haproxy
在两个负载均衡器服务器上,使其可执行:
代码语言:javascript复制sudo chmod x haproxy
在继续之前,请随意查看资源的内容。它是一个shell脚本,可用于管理HAProxy服务。
现在我们可以使用HAProxy OCF资源代理来定义我们的haproxy
集群资源。
添加haproxy资源
通过安装我们的HAProxy OCF资源代理,我们现在可以配置一个haproxy
允许集群管理HAProxy的资源。
在任一负载均衡器服务器上,使用以下命令创建haproxy
原始资源:
sudo crm configure primitive haproxy ocf:heartbeat:haproxy op monitor interval=15s
指定的资源告诉集群每15秒监视一次HAProxy,如果它变得不可用则重新启动它。
使用sudo crm_mon
或sudo crm status
检查群集资源的状态:
crm_mon:...
Online: [ primary secondary ]
FloatIP (ocf::digitalocean:floatip): Started primary
Nginx (ocf::heartbeat:nginx): Started secondary
不幸的是,Pacemaker可能决定在单独的节点上启动haproxy
和FloatIP
资源,因为我们没有定义任何资源限制。这是一个问题,因为当HAProxy服务在另一个Droplet上运行时,浮动IP可能指向一个Droplet。访问浮动IP将指向未运行应具有高可用性的服务的服务器。
要解决此问题,我们将创建一个克隆资源,该资源指定应在多个节点上启动现有原始资源。
使用以下命令创建克隆名为“haproxy-clone” 的haproxy
资源:
sudo crm configure clone haproxy-clone haproxy
现在,集群状态应如下所示:
代码语言:javascript复制crm_mon:Online: [ primary secondary ]
FloatIP (ocf::digitalocean:floatip): Started primary
Clone Set: haproxy-clone [Nginx]
Started: [ primary secondary ]
如您所见,克隆资源haproxy-clone
现在在我们的两个节点上启动。
最后一步是配置共置约束,以指定FloatIP
资源应在具有活动haproxy-clone
资源的节点上运行。要创建名为“FloatIP-haproxy”的共置约束,请使用以下命令:
sudo crm configure colocation FloatIP-haproxy inf: FloatIP haproxy-clone
您将看不到crm status输出中的任何差异,但您可以看到使用此命令创建了共置资源:
代码语言:javascript复制sudo crm configure show
现在,两个服务器都应该运行HAProxy,而其中只有一个运行FloatIP资源。
尝试在任一负载均衡器服务器上停止HAProxy服务:
代码语言:javascript复制sudo service haproxy stop
您会注意到它会在接下来的15秒内再次启动。
接下来,我们将通过重新启动您的活动负载平衡器服务器(FloatIP
资源当前“已启动”的服务器)来测试您的HA设置。
测试负载均衡器的高可用性
使用新的高可用性HAProxy设置,您将需要测试一切是否按预期工作。
为了更好地可视化负载平衡器之间的转换,我们可以在转换期间监控应用服务器Nginx日志。
由于有关正在使用的代理服务器的信息未返回给客户端,因此查看日志的最佳位置来自实际的后端Web服务器。每个服务器都应该维护有关哪些客户端请求资产的日志。从Nginx服务的角度来看,客户端是代表真实客户端发出请求的负载均衡器。
监视集群状态
在执行即将进行的测试时,您可能希望查看集群节点和资源的实时状态。您可以在任一负载均衡器服务器上使用此命令执行此操作(只要它正在运行):
代码语言:javascript复制sudo crm_mon
输出应该如下所示:
代码语言:javascript复制crm_mon output:Last updated: Thu Nov 5 13:51:41 2015
Last change: Thu Nov 5 13:51:27 2015 via cibadmin on primary
Stack: corosync
Current DC: secondary (2) - partition with quorum
Version: 1.1.10-42f2063
2 Nodes configured
3 Resources configured
Online: [ primary secondary ]
FloatIP (ocf::digitalocean:floatip): Started primary
Clone Set: haproxy-clone [haproxy]
Started: [ primary secondary ]
这将显示哪些负载均衡器节点在线,以及哪些节点启动了FloatIP
和haproxy
资源。
请注意,FloatIP
资源所在的节点是Started
的(上例中为primary) ,是当前为其分配浮动IP的负载平衡器服务器。我们将此服务器称为活动负载平衡器服务器。
自动请求浮动IP
在本地计算机上,我们将每2秒在浮动IP地址请求Web内容。这样我们就可以轻松查看主动负载均衡器如何处理传入流量。也就是说,我们将看到它向哪个后端应用服务器发送流量。在本地终端中,输入以下命令:
代码语言:javascript复制while true; do curl floating_IP_address; sleep 2; done
每两秒钟,您应该会看到其中一个后端应用服务器的响应。它可能会在app-1和app-2之间交替,因为我们未指定的HAProxy默认平衡算法设置为循环法。所以,你的终端应该显示如下:
代码语言:javascript复制[secondary_label curl loop output:
Droplet: app-1, IP Address: app_1_IP_address
Droplet: app-2, IP Address: app_2_IP_address
...
保持此终端窗口打开,以便不断将请求发送到您的服务器。它们将有助于我们的下一个测试步骤。
关闭Web服务器上的日志
在我们的每个后端应用服务器上,我们都可以tail
该/var/log/nginx/access.log
位置。这将显示对服务器的每个请求。由于我们的负载均衡器使用循环轮换均匀地分配流量,因此每个后端应用服务器应该看到大约一半的请求。
客户端地址是访问日志中的第一个字段,因此很容易找到。在两个 Nginx应用服务器上运行以下命令(在单独的终端窗口中):
代码语言:javascript复制sudo tail -f /var/log/nginx/access.log
第一个字段应该显示您的活动负载均衡器服务器的私有IP地址,每四秒钟一次(我们假设它是主要负载均衡器,但在您的情况下可能是次要负载均衡器):
代码语言:javascript复制Output. . .
primary_loadbalancer_IP - - [05/Nov/2015:14:26:37 -0500] "GET / HTTP/1.1" 200 43 "-" "curl/7.43.0"
primary_loadbalancer_IP - - [05/Nov/2015:14:26:37 -0500] "GET / HTTP/1.1" 200 43 "-" "curl/7.43.0"
. . .
保持tail
命令在两个应用服务器上运行。
中断主负载均衡器上的HAProxy服务
现在,让我们重新启动主负载均衡器,以确保浮动IP故障转移工作:
代码语言:javascript复制sudo reboot
现在请注意两个应用服务器上的Nginx访问日志。您应该注意到,在发生浮动IP故障转移后,访问日志显示正在使用与以前不同的IP地址访问应用服务器。日志应指示辅助负载平衡器服务器正在发送请求:
代码语言:javascript复制Output. . .
secondary_loadbalancer_IP - - [05/Nov/2015:14:27:37 -0500] "GET / HTTP/1.1" 200 43 "-" "curl/7.43.0"
secondary_loadbalancer_IP - - [05/Nov/2015:14:27:37 -0500] "GET / HTTP/1.1" 200 43 "-" "curl/7.43.0"
. . .
这表明检测到主负载均衡器故障,并且浮动IP已成功重新分配给辅助负载均衡器。
您可能还需要检查本地终端的输出(每两秒访问一次浮动IP)以验证辅助负载均衡器是否向两个后端应用服务器发送请求:
代码语言:javascript复制[secondary_label curl loop output:
Droplet: app-1, IP Address: app_1_IP_address
Droplet: app-2, IP Address: app_2_IP_address
...
一旦另一个负载均衡器再次联机,您也可以尝试另一个方向的故障转移。
配置Nginx以记录实际客户端IP地址
如您所见,Nginx访问日志显示所有客户端请求都来自当前负载均衡器的私有IP地址,而不是最初发出请求的客户端的实际IP地址(即本地计算机)。记录原始请求者的IP地址而不是负载均衡器服务器通常很有用。通过对所有后端应用服务器上的Nginx配置进行一些更改,可以轻松实现这一点。
在两个应用服务器上,在编辑器中打开nginx.conf
文件:
sudo vi /etc/nginx/nginx.conf
找到“日志设置”部分(在http
块中),并添加以下行:
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
,该格式将创建原始请求的客户端的IP值$http_x_forwarded_for
添加到默认访问日志条目。我们还包括$remote_addr
,它是反向代理负载平衡器(即主动负载平衡器服务器)的IP地址。
接下来,要使用这种新的日志格式,我们需要在默认服务器块中添加一行。
在两个应用服务器上,打开default
服务器配置:
sudo vi /etc/nginx/sites-available/default
在server
块内(listen
指令右下方是个好地方),添加以下行:
access_log /var/log/nginx/access.log haproxy_log;
保存并退出。这告诉Nginx使用我们最近创建的日志格式haproxy_log
来编写其访问日志。
在两个应用服务器上,重新启动Nginx以使更改生效:
代码语言:javascript复制sudo service nginx restart
现在,您的Nginx访问日志应包含发出请求的客户端的实际IP地址。通过拖动应用服务器的日志来验证这一点,就像我们在上一节中所做的那样。日志条目应如下所示:
代码语言:javascript复制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服务器可以将负载分配到后端的app服务器池。随着需求的增长或缩减,您可以轻松扩展此池。
浮动IP和Corosync / Pacemaker配置消除了负载平衡层的单点故障,即使主负载平衡器完全失效,您的服务也可以继续运行。此配置非常灵活,可以通过在HAProxy服务器后面设置首选应用程序堆栈来适应您自己的应用程序环境。
想要了解更多Linux开源信息教程,请前往腾讯云 社区学习更多知识。
参考文献:《How To Create a High Availability HAProxy Setup with Corosync, Pacemaker, and Floating IPs on Ubuntu 14.04》