我最近发现,您可以根据请求主机头动态匹配后端,如下所示:
use_backend %[req.hdr(host),lower]
然而,有谁知道我可以使用请求主机头的子域来匹配后端吗?
例如以下这样的内容:
backend one
backend two
use_backend %[<SUBDOMAIN OF HOSTHEADER>,lower]
匹配如下:
one.example.com -> backend one
two.example.com -> backend two
答案1
添加和删除 DNS 条目允许您动态地将子域路由到各种后端,但您仍然需要定义这些后端,因此仍然需要重新启动服务。因此,我并不完全确定此配置的用处。
无论如何,您可以这样做。
我们知道我们可以host
通过使用请求文件(req.hdr(host)
),但是这给了我们请求的 FQDN,而不是子域。
值得庆幸的是,有一个注册子程序转换器我们应该能够应用于req.hdr
样本以剪掉基础域和 TLD。
regsub(<regex>,<subst>[,<flags>])
对输入字符串应用基于正则表达式的替换。它
与著名的“sed”实用程序“s/<regex>/<subst>/”执行相同的操作。
默认情况下,它将在输入字符串中用
替换字符串
<subst> 替换与正则表达式 <regex> 匹配的最大部分的第一次出现。通过在第三个参数 <flags> 中添加标志“g”,可以替换所有出现的情况
。还可以
通过在 <flags> 中添加标志“i”使正则表达式不区分大小写。由于 <flags> 是一个
字符串,它由所有所需标志的连接组成。因此,如果
同时需要“i”和“g”,则使用“gi”或“ig”将具有相同的效果。
值得注意的是,由于
配置解析器当前的限制,某些字符(例如右括号或逗号)
无法在参数中使用。该转换器的第一个用途是
用其他字符或字符序列替换某些字符或字符序列。
该引文中的重点是我的,目的是表明在这种情况下,您需要的正则表达式是^(.*)(?:\..*){2}$
,由于括号的存在,它将无法工作。
因此,您需要使用场地转换器。
field(<index>,<delimiters>)
考虑到输入字符串中给定的分隔符,提取给定索引处的子字符串
。索引从 1 开始,分隔符是字符串格式的
字符列表。
field(1,'.')
如果我们将整个示例管道放在一起,该use_backend
行看起来如下:
use_backend BE:subs-%[req.hdr(host),lower,field(1,'.')]
现在,这揭示了将进入相同后端的事实one.*.*
,并可能导致一些非常奇怪的情况。
检查基本域和 TLD 以确保它们符合您的预期可能会有所帮助。假设您只有两个(example.com
和foo.com
),您可以使用req.hdr_end(host)
来检查它们,使 ACL 看起来像:
acl is_valid_base_domain req.hdr_end(host) -i example.com foo.com
如果我们把它们放在一起,整个配置看起来会像这样:
frontend FE:subs
...
acl is_valid_base_domain req.hdr_end(host) -i example.com foo.com
use_backend BE:subs-%[req.hdr(host),lower,field(1,'.')] if is_valid_base_domain
default_backend BE:subs:default
backend BE:subs-one
#matches one.example.com, one.foo.com
...
backend BE:subs-two
#matches two.example.com, two.foo.com
...
backend BE:subs-three
#matches three.example.com, three.foo.com
...
backend BE:subs:default
#matches *.example.com, *.foo.com
...
如果您愿意,可以为每个子域、每个基本域设置不同的“动态”后端,从而获得更加精美的效果;您只需要使用上面的部分即可解决这个问题。
答案2
据我所知,HAProxy 不支持正则表达式从主机头中提取子域的特定部分,然后将该值分配给变量,该变量稍后用于形成完整的后端名称。
但是,解决问题的一种方法是使用映射:
frontend frontend_main
...
use_backend %[req.hdr(host),lower,map(/etc/haproxy/subdomains.map,backend_main)]
的内容/etc/haproxy/subdomains.map
看起来会像这样:
#domainname backendname
one.example.com backend_one
two.example.com backend_two
etc.domain1.com backend_etc
与该文件中的任何子域不匹配的所有请求都将转到backend_main
后端。