用hoststated保证负载均衡正确
当你通过round-robin重定向运行了一段时间的负载均衡后, 你也许会注意到这个重定向不能自动适应外部条件的变化。一个例子就是在一台或多台列在名单内的重定向主机无法访问时,除非采取特殊的措施, 否则不管通讯能否抵达目的主机或者目标主机是否已经无力处理服务请求,PF仍会将通讯重定向到名单内提供的IP地址上。很显然, 需要一个可监控的解决方案, 而幸运的是, OpenBSD的基本系统提供了一个主机状态进程hoststated。 hoststated和PF配置相互作用, 提供了一个将失效主机从池中剔除的功能。
要在你的规则集中引入hoststated, 不管怎样,需要对规则集进行一下小调整。 hoststated工作在services范畴内,并且期望能在PF的表格内添加或删除主机的IP地址。
hoststated进程通过一个特定的重定向锚hoststated与你的规则集相互作用。我们来看一下怎样让我们的规则集工作得更佳出色一些, 我们先复习一下负载均衡规则集。
在你的pf.conf文件的最前面, 在NAT部分前面加入下行:
代码: 全选
rdr-anchor "hoststated/*"
在那个负载均衡规则集里, 我们已经对webserver池进行了定义
代码: 全选
webpool = "{ 192.0.2.214, 192.0.2.215, 192.0.2.216, 192.0.2.217 }"
而这个重定向
代码: 全选
rdr on $ext_if from any to $webserver port $webports -> $webpool \
round-robin sticky-address
可以使配置与hoststated共同工作, 我们需要将webpool表格格式的定义改成像这样
代码: 全选
table <webpool> persist { 192.0.2.214, 192.0.2.215, 192.0.2.216, 192.0.2.217 }
然后改变重定向以便使用新的 <webpool> 表格:
代码: 全选
rdr on $ext_if from any to $webserver port $webports -> <webpool> \
round-robin sticky-address
一旦处理好了pf.conf的相关内容, 我们现在该处理hoststated自己的配置文件hoststated.conf 了。这个配置文件的语法和pf.conf的语法极其相似,所以它很容易阅读和理解。首先, 我们添加后面要用到的宏定义:
代码: 全选
table webpool {
check http "/status.html" code 200
timeout 300
real port 80
host $web1
host $web2
host $web3
host $web4
}
所有这些全对应于我们在pf.conf文件中的定义, 除了最后一个。 (大家一会儿就会知道其作用了。) hoststated的默认检查间隔是10秒, 这意味着一台主机在被记录为离线前至多就宕机了10秒钟。
谨慎起见, 为了最小化可察觉的宕机时间,我们用下面这行将检查时间间隔设置为5秒:
代码: 全选
interval 5 # check hosts every 5 seconds
现在我们设置一个名为webpool表格,它使用这些宏来匹配我们刚在PF的配置文件中设置的表格:
代码: 全选
table webpool {
check http "/status.html" code 200
timeout 300
real port 80
host $web1
host $web2
host $web3
host $web4
}
除了定义成员主机, 我们的表格还指定了hoststated应该通过向一台主机请求/status.html文件以检查其是否可用, 它使用的是HTTP协议, 并且期望主机返回一个值200。这是一台正在运行的web服务器应该返回的结果。
现在不奇怪了吧? hoststated将把不工作的主机从表格内剔除。但是如果webpool表格内所有的主机全宕机了会怎样呢? 幸运的是开发者们也考虑了这种情况,且引入了备份服务表格的概念。这是www服务定义的最后部分, 用表格sorry作为backup表格:
代码: 全选
table sorry {
check icmp
real port 80
host $sorry_server
}
service www {
virtual ip $webserver port 80
table webpool
backup table sorry
}
在sorry表格内的主机是webpool表格为空时被接管的。这意味着你需要设置一个服务,当web池内的所有主机失效时它可以提供一条信息“Sorry, we’re down”。
如果你想在启动时启用hoststated, 将这行
代码: 全选
hoststated_flags="" # for normal use: ""
加入到rc.conf.local文件。然而, 多数情况下你是通过hoststatectl管理程序来操控hoststated。除了可以监视状态, hoststatectl还可以让你重新导入hoststated的配置以及选择禁用或启用主机, 表格, 和服务, 并且它甚至可以让你交互式地查看服务状态,像这样:
代码: 全选
$ sudo hoststatectl show summary
Type Id Name Avlblty Status
service 0 www active
table 0 webpool active (2 hosts up)
host 3 192.0.2.217 0.00% down
host 2 192.0.2.216 100.00% up
host 1 192.0.2.215 0.00% down
host 0 192.0.2.214 100.00% up
table 1 sorry active (1 hosts up)
host 4 192.0.2.200 100.00% up
这里的web池严重退化, 4台主机里仅有两台还在工作。幸好backup表格还在工作。只要有一台主机还在工作这里的表格就全在。对于那些没有任何内容的表格, 状态列显示为空。
要让hoststatectl以host-centered的格式显示主机信息 :
代码: 全选
$ sudo hoststatectl show hosts
Type Id Name Avlblty Status
service 0 www active
table 0 webpool active (2 hosts up)
host 3 192.0.2.217 0.00% down
total: 0/6 checks
host 2 192.0.2.216 100.00% up
total: 0/6 checks
host 1 192.0.2.215 0.00% down
total: 0/6 checks
host 0 192.0.2.214 100.00% up
total: 6/6 checks
table 1 sorry active (1 hosts up)
host 4 192.0.2.200 100.00% up
total: 6/6 checks
如果你想将一台主机从池中取出以便进行维护或需要对其进行时间比较长的操作, 你可以用下面的命令禁用它:
代码: 全选
$ sudo hoststatectl host disable 192.168.103.1
多数情况下, 上面的命令会得到操作完全成功的显示。一旦你完成对机器的维护,你就需要让其重新上线, 你可以用下列命令重新激活它,使它成为hoststated池的一个成员:
代码: 全选
$ sudo hoststatectl host enable 192.168.103.1
再说一遍, 你应该确认看到了命令成功的信息,它表明操作完全成功。
除了我们在这里演示的基本负载均衡, 在最近的一些OpenBSD版本中hoststated得到了进一步的扩展,它还提供了一些适合应付复杂设定的其它功能。现在它能为HTTP和HTTPS处理7层代理或中继。 这包括了处理hearder扩展和rewrite的协议, 而且甚至可以处理session和cookie。
要处理此类协议,你需要为应用程序进行定制。下面是一个简单的HTTPS中继,它为从客户端到web服务器的加密web通讯提供负载均衡。
代码: 全选
protocol httpssl {
protocol http
header append "$REMOTE_ADDR" to "X-Forwarded-For"
header append "$SERVER_ADDR:$SERVER_PORT" to "X-Forwarded-By"
header change "Keep-Alive" to "$TIMEOUT"
url hash "sessid"
cookie hash "sessid"
path filter "*command=*" from "/cgi-bin/index.cgi"
ssl { sslv2, ciphers "MEDIUM:HIGH" }
tcp { nodelay, sack, socket buffer 65536, backlog 128 }
}
这个协议处理程序定义向我们展示了在HTTP headers上的简单操作以及处理优化连接的SSL和特定TCP参数。 这里的header选项作用于协议headers, 要插入变量值可以通过附加到已存在的headers (append)中, 或者将其更换为新值 (change)。 这里的url hash和cookie hash用于负载平衡,目的是选择将请求发送给目标池中的具体哪一台主机。path filter指定了任何获得的请求中如果包含了以第一对引号内的“字符串”作为第二个引号内的"字符串"的子串,则此请求将被丢弃。 而ssl选项指定只接受第二号版本的SSL,而且key的长度在中-高的范围内, 或者, 换句话说, 128位或更多。
详说明2 最后, 这里的tcp选项指定ToS标签应该设置为nodelay(不延迟), 指定了用于确认选择的方法 (RFC 2018) 和设定的socket buffer大小以及负载平衡程序最大允许的连接数。
relay定义使用的协议处理程序使用的模式应该符合我们前面的www服务的service定义:
代码: 全选
relay wwwssl {
# Run as a SSL accelerator
listen on $webserver port 443 ssl
protocol httpssl
table webhosts loadbalance
}
不过, 启用SSL的web应用程序可能受益于稍微不同的参数设定。
最后, 对于网络中运行hoststate的基于CARP故障转移的主机(请参阅 “冗余和故障转移: CARP and pfsync” page 97)可以通过设置CARP demotion counter来指定关闭或启动时的接口组或组,这样就可以将hoststated设置为与CARP相互配合使用。像所有OpenBSD系统的组件一样, hoststated的相关内容及其风格,你可在其用户手册上查阅。对于那些我们这里没有涉及的选项和思考角度来说 (不太多了), 我推荐您仔细阅读hoststated的用户手册, hoststated.conf文件, 还有hoststatectl以及通过自己动手尝试找出适合你自己的配置。
说明2
请参阅OpenSSL的用户手册以获取更多的相关cipher选项的解释。