Недавно я обнаружил, что вы можете динамически сопоставить серверную часть на основе заголовка хоста запроса, например:
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
Добавление и удаление записей DNS позволяет вам на лету маршрутизировать поддомены на различные серверные ВМ, но вам все равно необходимо определить эти серверные ВМ, чтобы перезапустить службу. Таким образом, я не совсем уверен в полезности этой конфигурации.
В любом случае вот как вы это сделаете.
Мы знаем, что можем найти содержимое host
заголовок, используя req.hdr (req.hdr(host)
), но это дает нам полное доменное имя запроса, а не субдомен.
К счастью, есть regsub конвертер мы должен иметь возможность обращаться в req.hdr
образец, чтобы вырезать базовый домен и TLD.
regsub (<regex>, <subst> [, <flags>])
Применяет к входной строке подстановку на основе регулярного выражения. Он делает то же самое
операция как хорошо известная утилита "sed" с "s / <regex> / <subst> /". По
по умолчанию он заменит во входной строке первое вхождение
наибольшая часть, соответствующая регулярному выражению <regex> с заменой
строка <подстрока>. Вместо этого можно заменить все вхождения, добавив
флаг «g» в третьем аргументе <flags>. Также возможно сделать
regex нечувствителен к регистру, добавив флаг "i" в <flags>. Поскольку <flags> - это
строка, она состоит из конкатенации всех желаемых флагов. Таким образом, если
желательны и «i», и «g», использование «gi» или «ig» будет иметь тот же эффект.
Важно отметить, что из-за текущих ограничений
парсер конфигурации, некоторые символы, такие как закрывающая скобка или запятая
нельзя использовать в аргументах. Первое использование этого конвертера
для замены определенных символов или последовательности символов на другие.
Акцент в этой цитате мой и нацелен на то, чтобы показать, что в этом случае, когда вам понадобится регулярное выражение, ^(.*)(?:\..*){2}$
, это не сработает из-за скобок.
Таким образом, вам нужно будет использовать поле конвертер.
поле (<индекс>, <разделители>)
Извлекает подстроку по заданному индексу с учетом заданных разделителей из
входная строка. Индексы начинаются с 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
...
Вы можете стать еще интереснее, если захотите, имея разные «динамические» бэкенды для каждого субдомена, для каждого базового домена; вам просто нужно использовать приведенные выше части, чтобы решить эту проблему.
Насколько мне известно, HAProxy не поддерживает регулярные выражения для извлечения определенной части поддомена из заголовка Host и последующего присвоения этого значения переменной, которая позже используется для формирования полного имени серверной части.
Однако один из способов решить вашу проблему - использовать отображение:
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
бэкэнд.