Это многостраничная версия текущего раздела для печати. .
Документация HAProxy 3.4.4
- 1: Основы балансировки нагрузки
- 2: Что такое HAProxy и как он работает
- 3: Базовые возможности
- 4: Стандартные возможности
- 5: Расширенные возможности
- 6: Расчёт ресурсов и производительность
- 7: Выпуски, пакеты и обновления
- 8: Сопутствующие продукты и альтернативы
- 9: Документация и сообщество
- 10: 1. Краткое напоминание об HTTP
- 11: 2. Настройка HAProxy
- 12: 5. Параметры bind и server
- 13: 6. Кеш
- 14: 9. Поддерживаемые фильтры
- 15: 10. Приложения FastCGI
- 16: 11. Таблицы привязок и одноранговые узлы
- 17: 12. Другие секции
- 18: 1. Предварительные требования
- 19: 2. Архитектура HAProxy
- 20: 3. Запуск HAProxy
- 21: 4. Остановка и перезапуск HAProxy
- 22: 5. Ограничения файловых дескрипторов
- 23: 6. Управление памятью
- 24: 7. Использование CPU
- 25: 8. Ведение журнала
- 26: 10. Упрощение управления конфигурацией
- 27: 11. Известные подводные камни, которых следует избегать
- 28: 12. Отладка и проблемы производительности
- 29: 13. Соображения безопасности
HAProxy — свободный, быстрый и надёжный обратный прокси для обеспечения высокой доступности, балансировки нагрузки TCP и HTTP и управления трафиком приложений. Английское издание содержит полный текст трёх основных руководств HAProxy 3.4, организованных в единую плоскую последовательность страниц Markdown для чтения в OINK. Русское издание публикует готовые переводы; ссылки на ещё не переведённые страницы открывают английскую версию.
Выберите руководство
- Руководство для начинающих — 9 тем о принципах балансировки нагрузки, архитектуре HAProxy, возможностях, выборе ресурсов, выпусках и экосистеме.
- Руководство по конфигурации — 12 глав о прокси, ACL, образцах, ведении журнала, фильтрах и всех семействах параметров.
- Руководство по управлению — 13 глав о запуске, перезагрузке конфигурации, ресурсах, ведении журнала, статистике, CLI времени выполнения, отладке и безопасности.
Охват издания
| Руководство | Исходный материал проекта | Локальная организация |
|---|---|---|
| Руководство для начинающих | 1,695 строк | 9 страниц тем без вложенности |
| Руководство по конфигурации | 33,148 строк | 12 страниц глав без вложенности |
| Руководство по управлению | 5,285 строк | 13 страниц глав без вложенности |
В полном английском издании все 34 страницы для чтения находятся непосредственно в корне компонента HAProxy. Три разделителя без ссылок отделяют руководства в боковой панели, не добавляя уровней каталогов или остановок в последовательной навигации.
Полные исходные материалы зафиксированной версии и контрольные суммы SHA-256 сохранены в sources/haproxy/.
Лицензионное уведомление проекта
и текст GPLv2
опубликованы вместе с руководствами. Для каждой страницы также доступно проверенное издание на упрощённом
китайском языке.
1 - Основы балансировки нагрузки
Этот документ знакомит с HAProxy тех, кто ещё не знает продукт, а также тех, кто знаком с его старыми версиями и хочет открыть его заново. Главная цель — предоставить все сведения, необходимые для решения, подходит ли HAProxy пользователю. Опытные пользователи могут найти здесь решения ранее возникших задач, о которых они не знали из-за незнакомства с новой функцией. Также приведены сведения для расчёта ресурсов, описан жизненный цикл продукта и даны сравнения с продуктами, чьи возможности частично пересекаются с HAProxy.
Этот документ не содержит помощи или советов по настройке, но объясняет, где искать соответствующую документацию. Руководство представлено плоской последовательностью тематических страниц в боковой панели HAProxy.
Балансировка нагрузки объединяет несколько компонентов, чтобы получить общую производительность выше производительности каждого из них, без вмешательства конечного пользователя и с возможностью масштабирования. В результате за время, необходимое одному компоненту для выполнения одной операции, одновременно выполняется больше операций. Однако отдельная операция по-прежнему выполняется только на одном компоненте и не ускоряется по сравнению с работой без балансировки. Чтобы задействовать все компоненты и полностью использовать преимущества балансировки, всегда нужно как минимум столько же операций, сколько компонентов, а также эффективный механизм распределения нагрузки. Наглядный пример — число полос на автомагистрали: оно позволяет пропустить больше автомобилей за одно и то же время без увеличения скорости каждого автомобиля.
Примеры балансировки нагрузки:
- Планирование процессов в многопроцессорных системах.
- Балансировка нагрузки каналов связи (например, EtherChannel, Bonding).
- Балансировка по IP-адресам (например, ECMP, циклический выбор DNS).
- Балансировка нагрузки серверов (с помощью балансировщиков нагрузки).
Механизм или компонент, выполняющий распределение нагрузки, называется балансировщиком нагрузки. В веб-средах такие компоненты называют «сетевыми балансировщиками нагрузки», а чаще просто «балансировщиками нагрузки», поскольку это наиболее известная область их применения.
Балансировщик нагрузки может действовать:
На уровне канала: балансировка нагрузки каналов связи выбирает сетевой канал, по которому отправить пакет.
На уровне сети: сетевая балансировка нагрузки выбирает маршрут для последовательности пакетов.
На уровне сервера: балансировка нагрузки серверов определяет сервер, который обработает соединение или запрос.
Существуют две разные технологии, решающие разные, хотя частично пересекающиеся задачи. В обоих случаях важно помнить: балансировка отклоняет трафик от его естественного пути, поэтому всегда требуется некоторая осторожность, чтобы сохранять необходимую согласованность всех решений о маршрутизации.
Первая технология работает на уровне пакетов и обрабатывает их более или менее независимо. Между входными и выходными пакетами существует соответствие 1-к-1, поэтому трафик по обе стороны балансировщика можно отслеживать обычным анализатором сетевого трафика. Эта технология может быть очень дешёвой и чрезвычайно быстрой. Обычно она реализуется аппаратно, на ASIC, и позволяет достичь скорости линии — например, в коммутаторах с ECMP. Чаще всего она не хранит состояние, но может учитывать сеанс, к которому относится пакет; такой вариант называют layer4-LB или L4. Если пакеты не изменяются, возможна поддержка DSR — прямого ответа сервера без повторного прохождения через балансировщик. Однако содержимое практически не анализируется. Эта технология отлично подходит для балансировки на уровне сети, хотя иногда применяется и для простейшей высокоскоростной балансировки нагрузки серверов.
Вторая технология работает с содержимым сеансов. Для этого входной поток необходимо собрать и обработать целиком. Содержимое можно изменить, а выходной поток разбивается на новые пакеты. Поэтому такую обработку обычно выполняют прокси, часто называемые балансировщиками нагрузки уровня 7 или L7. Это подразумевает два отдельных соединения по обе стороны балансировщика и отсутствие связи между размерами и числом входных и выходных пакетов. Клиенты и серверы не обязаны использовать один и тот же протокол: например, возможны IPv4 и IPv6 или незашифрованный трафик и SSL. Операции всегда сохраняют состояние, а обратный трафик обязательно проходит через балансировщик. Дополнительная обработка требует ресурсов, поэтому достичь скорости линии удаётся не всегда, особенно на маленьких пакетах. Зато технология даёт широкие возможности и обычно реализуется целиком программно, даже во встроенных аппаратных устройствах. Она отлично подходит для балансировки нагрузки серверов.
Балансировщики, работающие с пакетами, обычно развёртываются в режиме сквозной пересылки: их устанавливают на обычном пути трафика, который они перенаправляют согласно конфигурации. Обратный трафик не обязательно проходит через балансировщик. Для направления трафика нужному адресату может изменяться сетевой адрес назначения. В таком случае обратный трафик обязательно должен проходить через балансировщик. Если маршруты этого не позволяют, балансировщик может также заменить исходный адрес пакетов своим, принудительно направляя обратный трафик через себя.
Балансировщики на основе прокси развёртываются как серверы с собственными IP-адресами и портами, без изменения архитектуры. Иногда приходится адаптировать приложения, чтобы клиенты направлялись на IP-адрес балансировщика, а не прямо к серверу. Некоторым балансировщикам для этого нужно изменять ответы серверов — например, поле заголовка HTTP Location, используемое при перенаправлениях. Некоторые балансировщики на основе прокси умеют перехватывать трафик для чужого адреса и подставлять адрес клиента при соединении с сервером. Это позволяет развёртывать их как обычный маршрутизатор или межсетевой экран, в режиме сквозной пересылки, очень похожем на режим пакетных балансировщиков. Это особенно ценится в продуктах, сочетающих режим обработки пакетов и режим прокси. Очевидно, что DSR в таком случае по-прежнему невозможен, а обратный трафик необходимо направлять через балансировщик.
Хорошо масштабируемая многоуровневая схема может начинаться с пограничного маршрутизатора, принимающего трафик из нескольких сбалансированных каналов и распределяющего его с помощью ECMP на первый уровень из нескольких пакетных балансировщиков с состоянием (L4). Эти балансировщики L4 передают трафик ещё большему числу балансировщиков на основе прокси (L7), которые разбирают содержимое и выбирают конечный сервер-получатель.
Увеличение числа компонентов и возможных путей трафика повышает риск отказа. В очень больших средах нормально, когда несколько неисправных компонентов постоянно находятся на ремонте или замене. Балансировка без учёта работоспособности всего стека значительно снижает доступность. Поэтому любой разумно устроенный балансировщик проверяет, что компоненты, которым он собирается отправлять трафик, работают и доступны, и прекращает направлять трафик неисправным. Для этого применяют разные методы.
Самый распространённый метод — периодические пробы, подтверждающие работоспособность компонента. Их называют «проверками работоспособности». Они должны соответствовать типам отказов, которые требуется выявить. Например, проверка ping не обнаружит, что веб-сервер аварийно завершился и больше не прослушивает порт. Соединение с портом выявит такую проблему, а более сложный запрос может также подтвердить работоспособность сервера и доступность используемой им базы данных. Проверки часто повторяют несколько раз, чтобы исключить случайные ошибки измерения. Интервал между ними должен быть достаточно мал, чтобы неисправный компонент не использовался слишком долго после возникновения ошибки.
Другие методы анализируют выборку рабочего трафика, отправляемого адресату, проверяют правильность его обработки и исключают компоненты с некорректными ответами. Однако при этом приходится жертвовать частью рабочего трафика, что не всегда допустимо. Сочетание обоих механизмов объединяет их преимущества: для выявления отказа применяются оба, а для определения восстановления — только проверки работоспособности. Ещё один метод основан на централизованных сообщениях: центральный агент мониторинга периодически сообщает всем балансировщикам состояние всех компонентов. Это даёт каждому компоненту общее представление об инфраструктуре, хотя иногда с меньшей точностью или оперативностью. Такой подход лучше всего подходит для сред с большим числом балансировщиков и серверов.
Балансировщики уровня 7 сталкиваются и с другой задачей — привязкой сеансов, также называемой сохранением привязки. Обычно несколько последовательных запросов или соединений от одного источника, например конечного пользователя, нужно направлять одному адресату. Самый известный пример — корзина интернет-магазина. Если каждый щелчок создаёт новое соединение, пользователя всегда необходимо отправлять на сервер, где хранится его корзина. Анализ содержимого позволяет легче выделить в запросе элементы для определения нужного сервера, но этого не всегда достаточно. Например, если ключом выбора сервера служит исходный адрес, можно применить алгоритм хеширования: один IP-адрес всегда направляется на один сервер на основе деления адреса на число доступных серверов. Но при отказе сервера результат изменится, и все пользователи внезапно попадут на другие серверы, потеряв свои корзины. Решение — запоминать выбранного адресата и при каждом появлении того же посетителя направлять его на тот же сервер независимо от числа доступных серверов. Сведения можно хранить в памяти балансировщика; если он не единственный, их может потребоваться реплицировать другим балансировщикам. Либо их можно разными способами хранить у клиента, если он способен передавать их с каждым запросом: посредством вставки cookie, перенаправления на поддомен и т. п. Дополнительное преимущество такого механизма — отсутствие зависимости от нестабильных или неравномерно распределённых сведений, например исходного IP-адреса. Именно это является главным доводом в пользу балансировщика уровня 7 вместо уровня 4.
Чтобы извлечь cookie, поле заголовка host, URL или другие сведения, балансировщику может потребоваться расшифровать трафик SSL/TLS и, возможно, снова зашифровать его перед передачей серверу. Высокая стоимость этой операции объясняет, почему в некоторых инфраструктурах с большим объёмом трафика бывает много балансировщиков.
Поскольку балансировщик уровня 7 выполняет множество сложных операций с трафиком — расшифровывает, разбирает, изменяет, сопоставляет cookie, выбирает сервер и т. п., — он действительно может вызывать проблемы. Но очень часто его обвиняют и в тех проблемах, которые он лишь выявил. Нередко обнаруживается нестабильность серверов, которые периодически отключаются и возвращаются в работу; жёстко заданные ссылки на веб-страницах, заставляющие клиентов обращаться прямо к определённому серверу в обход балансировщика; либо очень медленные ответы под высокой нагрузкой, вызывающие тайм-ауты. Поэтому ведение журнала — исключительно важная часть балансировки уровня 7. После сообщения о проблеме необходимо выяснить, принял ли балансировщик неверное решение и, если да, почему, чтобы исключить повторение.
2 - Что такое HAProxy и как он работает
Название «HAProxy» обозначает продукт, а «haproxy» — исполняемую программу, программный пакет или процесс. Однако оба варианта часто используются в обоих значениях и произносятся как H-A-Proxy. На раннем этапе «haproxy» расшифровывалось как «прокси высокой доступности», а название писалось в два отдельных слова, хотя сейчас оно означает только «HAProxy».
3.1. Чем является и чем не является HAProxy
HAProxy — это:
TCP-прокси: он может принять TCP-соединение на прослушивающем сокете, подключиться к серверу и связать эти сокеты, обеспечивая передачу трафика в обоих направлениях; с обеих сторон поддерживаются IPv4, IPv6 и даже сокеты UNIX, что даёт простой способ преобразовывать адреса между разными семействами.
обратный HTTP-прокси (в терминологии HTTP — «шлюз»): он выступает в качестве сервера, получает HTTP-запросы по соединениям, принятым на прослушивающем TCP-сокете, и передаёт запросы из этих соединений серверам по другим соединениям. Он может использовать любую комбинацию HTTP/1.x и HTTP/2 с любой стороны и даже автоматически определяет протокол каждой стороны при использовании ALPN поверх TLS.
средство завершения, инициирования и разгрузки SSL: SSL/TLS можно использовать на соединении от клиента, на соединении к серверу или даже на обоих соединениях. Многие параметры можно задавать для отдельных имён (SNI) и обновлять во время выполнения без перезапуска. Такие конфигурации прекрасно масштабируются: сообщалось о развёртываниях, использующих от десятков до сотен тысяч сертификатов.
нормализатор TCP: поскольку соединения локально завершаются операционной системой, их стороны не связаны между собой, поэтому аномальный трафик, например некорректные пакеты, сочетания флагов, объявления окон, номера последовательности, незавершённые соединения (SYN-флуд) и тому подобное, не передаётся на другую сторону. Это защищает уязвимые стеки TCP от атак на протокол, а также позволяет оптимизировать параметры соединения с клиентом без изменения настроек стеков TCP на серверах.
нормализатор HTTP: при настройке обработки HTTP-трафика передаются только корректные полные запросы. Это защищает от множества атак на протокол. Кроме того, отклонения от протокола, допустимые по спецификации, исправляются, чтобы не вызывать проблем на серверах (например, многострочные заголовки).
инструмент исправления HTTP: он может изменять, исправлять, добавлять, удалять и переписывать URL или любой заголовок запроса либо ответа. Это помогает устранять проблемы совместимости в сложных средах.
коммутатор на основе содержимого: он может учитывать любой элемент запроса, решая, какому серверу передать запрос или соединение. Поэтому через один порт можно обслуживать несколько протоколов (например, HTTP, HTTPS, SSH).
балансировщик серверной нагрузки: он может распределять TCP-соединения и HTTP-запросы. В режиме TCP решение о балансировке принимается для всего соединения. В режиме HTTP решение принимается для каждого запроса.
регулятор трафика: он может ограничивать интенсивность в различных точках, защищать серверы от перегрузки, менять приоритеты трафика в зависимости от содержимого и даже передавать эту информацию нижним уровням и внешним сетевым компонентам с помощью маркировки пакетов.
средство защиты от DDoS и злоупотребления сервисом: он может вести обширную статистику по IP-адресам, URL, файлам cookie и другим признакам, выявлять злоупотребления и принимать меры (замедлять нарушителей, блокировать их, перенаправлять к устаревшему содержимому и т. д.).
точка наблюдения для устранения сетевых неполадок: благодаря точности информации, записываемой в журналы, он часто используется для сужения круга причин сетевых проблем.
средство разгрузки HTTP-сжатия: он может сжимать ответы, которые сервер не сжал, сокращая время загрузки страниц для клиентов с плохим подключением или использующих мобильные сети с высокой задержкой.
кэширующий прокси: он может кэшировать ответы в оперативной памяти, чтобы последующие запросы того же объекта не требовали повторной передачи по сети с сервера, пока объект остаётся в кэше и сохраняет актуальность. При этом объекты не сохраняются в постоянном хранилище. Учтите, что эта функция кэширования не требует обслуживания и направлена исключительно на экономию ценных ресурсов haproxy, а не ресурсов сервера. Кэши, предназначенные для оптимизации серверов, требуют гораздо более тонкой настройки и гибкости. Если нужен такой расширенный кэш, используйте Varnish Cache, который прекрасно интегрируется с haproxy, особенно когда SSL/TLS требуется с любой из сторон.
шлюз FastCGI: FastCGI можно рассматривать как другое представление HTTP, и поэтому HAProxy может непосредственно распределять нагрузку по группе серверов приложений FastCGI в любых сочетаниях, без дополнительного уровня шлюза между ними. Это экономит ресурсы и снижает затраты на обслуживание.
HAProxy не является:
явным HTTP-прокси, то есть прокси, через который браузеры выходят в Интернет. Для этой задачи есть отличное специализированное ПО с открытым исходным кодом, например Squid. Однако HAProxy можно установить перед таким прокси для балансировки нагрузки и обеспечения высокой доступности.
средством очистки данных: он не изменяет тела запросов или ответов.
статическим веб-сервером: при запуске он изолирует себя в окружении chroot и сбрасывает привилегии, поэтому после запуска вообще не обращается к файловой системе. По этой причине его невозможно превратить в статический веб-сервер (однако динамические серверы поддерживаются через FastCGI). Для этого есть отличное ПО с открытым исходным кодом, например Apache и Nginx, а HAProxy можно легко установить перед ними для балансировки нагрузки, обеспечения высокой доступности и ускорения.
балансировщиком нагрузки на уровне пакетов: он не видит IP-пакеты или UDP-дейтаграммы, не выполняет NAT и тем более DSR. Эти задачи относятся к нижним уровням. Некоторые компоненты на уровне ядра, например IPVS (Linux Virtual Server), уже прекрасно с ними справляются и отлично дополняют HAProxy.
3.2. Как работает HAProxy
HAProxy — это неблокирующий движок с событийной архитектурой, сочетающий очень быстрый уровень ввода-вывода с многопоточным планировщиком на основе приоритетов. Поскольку он изначально предназначен для пересылки данных, его архитектура оптимизирована для максимально быстрой передачи данных с минимальным числом операций. Особое внимание уделяется эффективному использованию кэша CPU: соединения закрепляются за одним CPU как можно дольше. Для этого реализована многоуровневая модель с механизмами обхода на каждом уровне, которые гарантируют, что данные не попадут на более высокие уровни без необходимости. Основная обработка происходит в ядре, а HAProxy старается помочь ядру выполнить работу как можно быстрее, передавая подсказки или избегая определённых операций, если предполагает, что их можно будет сгруппировать позже. В результате типичное распределение времени обработки составляет 15% в HAProxy и 85% в ядре в режиме TCP или HTTP close и около 30% в HAProxy и 70% в ядре в режиме HTTP keep-alive.
Один процесс может запускать множество экземпляров прокси; сообщалось об успешной работе конфигураций с 300000 отдельными прокси в одном процессе. Системы с одним процессором и одним ядром более чем достаточно для более чем 99% пользователей, поэтому пользователям контейнеров и виртуальных машин рекомендуется выбирать самые маленькие доступные образы, чтобы снизить эксплуатационные затраты и упростить устранение неполадок. Однако машина, на которой работает HAProxy, ни при каких обстоятельствах не должна использовать подкачку, а её CPU нельзя искусственно ограничивать (выделяя долю CPU в гипервизоре) или делить с ресурсоёмкими вычислительными процессами, которые создавали бы очень большую задержку переключения контекста.
Многопоточность позволяет задействовать всю доступную вычислительную мощность, используя один поток на ядро CPU. Это особенно полезно для SSL или когда требуется скорость пересылки данных выше 40 Гбит/с. В таких случаях критически важно избегать взаимодействия между несколькими физическими CPU: оно может создавать серьёзные узкие места в сетевом стеке и в самом HAProxy. Хотя некоторым это кажется нелогичным, при возникновении проблем с производительностью первым действием часто должно быть уменьшение числа CPU, на которых работает HAProxy.
Для работы HAProxy нужны только исполняемый файл haproxy и файл конфигурации. Для ведения журнала настоятельно рекомендуется настроить демон syslog и ротацию журналов. Журналы также можно отправлять в stdout/stderr, что бывает полезно внутри контейнеров. Файлы конфигурации разбираются до запуска, затем HAProxy пытается привязать все прослушивающие сокеты и отказывается запускаться, если что-либо не удалось. После этого сбои уже невозможны. Это означает, что ошибок во время выполнения не возникает и, если запуск прошёл успешно, программа будет работать до остановки.
После запуска HAProxy выполняет ровно 3 действия:
обрабатывает входящие соединения;
периодически проверяет состояние серверов (проверки работоспособности);
обменивается информацией с другими узлами haproxy.
Обработка входящих соединений — безусловно, самая сложная задача, поскольку зависит от множества вариантов конфигурации, однако её можно свести к следующим 9 шагам:
принять входящие соединения с прослушивающих сокетов, принадлежащих сущности конфигурации «frontend», которая ссылается на один или несколько прослушиваемых адресов;
применить к этим соединениям правила обработки фронтенда, которые могут привести к их блокировке, изменению некоторых заголовков или перехвату для выполнения внутренних апплетов, таких как страница статистики или CLI;
передать эти входящие соединения другой сущности конфигурации, представляющей группу серверов «backend», которая содержит список серверов и стратегию балансировки нагрузки для этой группы серверов;
применить к этим соединениям правила обработки бэкенда;
выбрать сервер для передачи соединения в соответствии со стратегией балансировки нагрузки;
применить к данным ответа правила обработки бэкенда;
применить к данным ответа правила обработки фронтенда;
создать запись в журнале с подробным описанием произошедшего;
в случае HTTP вернуться ко второму шагу и ждать нового запроса, иначе закрыть соединение.
Фронтенды и бэкенды иногда считают половинами прокси, поскольку каждый из них работает только с одной стороной сквозного соединения: фронтенд — только с клиентами, а бэкенд — только с серверами. HAProxy также поддерживает полные прокси, которые представляют собой точное объединение фронтенда и бэкенда. Когда нужна обработка HTTP, конфигурацию обычно разделяют на фронтенды и бэкенды: это открывает много возможностей, поскольку любой фронтенд может передать соединение любому бэкенду. Для прокси, работающих только с TCP, разделение на фронтенды и бэкенды редко даёт преимущество, а конфигурация с полными прокси может быть удобнее для чтения.
3 - Базовые возможности
В этом разделе перечислены возможности HAProxy: одни обычно ожидаются от любого современного балансировщика нагрузки, другие непосредственно вытекают из архитектуры HAProxy. Более сложные возможности подробно рассматриваются в следующем разделе.
3.3.1. Базовые возможности: проксирование
Проксирование — передача данных между клиентом и сервером по двум независимым соединениям. HAProxy поддерживает следующие базовые возможности проксирования и управления соединениями:
Предоставление серверу корректного соединения для защиты от любых ошибок или атак со стороны клиента.
Прослушивание нескольких IP-адресов и/или портов, в том числе диапазонов портов.
Прозрачный приём: перехват трафика к произвольному IP-адресу, даже не принадлежащему локальной системе.
Порт сервера не обязан быть связан с прослушиваемым портом и может даже преобразовываться с фиксированным смещением, что удобно для диапазонов.
Прозрачное подключение: при необходимости подстановка IP-адреса клиента или любого другого адреса при соединении с сервером.
Предоставление серверам надёжного IP-адреса для обратного трафика при балансировке между несколькими площадками.
Снижение нагрузки на сервер за счёт буферов и, при необходимости, короткоживущих соединений, уменьшающих число одновременных соединений и потребление памяти.
Оптимизация стеков TCP, например SACK, управления перегрузкой и уменьшение влияния RTT.
Поддержка разных семейств протоколов по обе стороны, например IPv4/IPv6/Unix.
Соблюдение тайм-аутов: HAProxy поддерживает несколько уровней тайм-аутов в зависимости от этапа соединения, чтобы неработающий клиент, сервер или злоумышленник не удерживал ресурсы слишком долго.
Проверка протокола: анализ HTTP, SSL или полезной нагрузки с отклонением некорректных элементов протокола, если явно не предписано их принимать.
Применение политик: пересылается только разрешённый трафик.
Ограничение входящих и исходящих соединений определёнными сетевыми пространствами имён (только Linux), упрощающее создание балансировщика между контейнерами для нескольких арендаторов.
Протокол PROXY передаёт серверу IP-адрес клиента даже для трафика, отличного от HTTP. Это расширение HAProxy уже принято рядом сторонних продуктов; на момент написания как минимум следующими:
- клиент: haproxy, stud, stunnel, exaproxy, ELB, squid;
- сервер: haproxy, stud, postfix, exim, nginx, squid, node.js, varnish.
3.3.2. Базовые возможности: SSL
Инженеры Google считают стек SSL HAProxy одним из самых функциональных (http://istlsfastyet.com/ ). Наиболее часто используемые возможности, обеспечивающие его полноту:
Обслуживание нескольких сайтов на основе SNI без ограничения их числа и с упором на производительность. Известно как минимум одно развёртывание с 50000 доменов и отдельными сертификатами для них.
Поддержка сертификатов с подстановочными знаками, уменьшающая необходимое число сертификатов.
Аутентификация клиентов по сертификатам с настраиваемыми действиями при отсутствии действительного сертификата. Например, можно направить клиента на другую серверную ферму для повторного выпуска его сертификата.
Аутентификация сервера бэкенда, подтверждающая, что это настоящий сервер, а не посредник.
Аутентификация перед сервером бэкенда, позволяющая ему убедиться, что подключается именно ожидаемый узел haproxy.
Расширения TLS NPN и ALPN, позволяющие надёжно завершать зашифрованные соединения SPDY/HTTP2 и передавать их серверам бэкенда в открытом виде.
OCSP stapling, дополнительно сокращающий время загрузки первой страницы за счёт передачи ответа OCSP вместе с остальными данными, когда клиент запрашивает Certificate Status Request.
Динамический размер записей, обеспечивающий одновременно высокую производительность и низкую задержку и заметно сокращающий время загрузки страницы: браузер может начинать получать новые объекты, пока предыдущие пакеты ещё находятся в пути.
Постоянный доступ ко всем существенным сведениям уровня SSL/TLS для журналирования, контроля доступа, отчётности и т. п. Эти сведения можно включать в заголовки HTTP или даже в расширение протокола PROXY, чтобы сервер получил всю информацию, доступную ему при самостоятельном завершении SSL.
Обнаружение, запись в журнал и блокировка известных атак даже при уязвимых библиотеках SSL, например атаки Heartbleed на некоторые версии OpenSSL.
Поддержка возобновления сеансов без хранения состояния (расширение TLS Ticket из RFC 5077). Билеты TLS можно обновлять через CLI, что позволяет реализовать совершенную прямую секретность, часто меняя билеты.
3.3.3. Базовые возможности: мониторинг
HAProxy уделяет большое внимание доступности, поэтому следит за состоянием серверов и сообщает собственное состояние другим сетевым компонентам:
Состояние серверов постоянно контролируется с параметрами, заданными для каждого сервера. Это подтверждает работоспособность пути к серверу для обычного трафика.
Проверки работоспособности поддерживают два порога гистерезиса для переходов в рабочее и нерабочее состояния, защищая от частого переключения состояний.
Проверки можно отправлять на другой адрес, порт или по другому протоколу. Это позволяет проверять одну службу как показатель работоспособности нескольких, например порт HTTPS у сервера HTTP+HTTPS.
Серверы могут отслеживать другие серверы и одновременно переходить в нерабочее состояние. Так сервер, предоставляющий несколько служб, исключается целиком, и никто не направляется на частично отказавший сервер.
На сервере можно разместить агент для контроля нагрузки и работоспособности. Серверу может потребоваться сообщать о нагрузке, рабочем и административном состоянии независимо от того, что видят проверки работоспособности. Простой агент позволяет учитывать собственную оценку сервера в дополнение к проверкам всего пути.
Доступны разные методы проверки: соединение TCP, запрос HTTP, приветствие SMTP, приветствие SSL, LDAP, SQL, Redis, сценарии send/expect — все с SSL или без него.
Изменение состояния отражается в журналах и на странице статистики с указанием причины отказа, например полученного при обнаружении ошибки ответа HTTP. При изменении также можно отправлять письмо на настраиваемый адрес.
Состояние сервера отображается в интерфейсе статистики и может использоваться при маршрутизации: трафик можно направлять на разные фермы в зависимости от их размера и/или работоспособности, например при потере связи между ЦОД.
Через запросы проверки работоспособности HAProxy может передавать серверам сведения: их имена, вес, число других серверов в ферме и т. п. Серверы могут учитывать их при ответах и принятии решений, например отложить резервное копирование, чтобы сохранить больше ресурсов CPU.
Через проверки работоспособности серверы могут сообщать более подробное состояние, чем просто включён/выключен: например, запросить остановку направления новых посетителей перед своим выключением.
Сам HAProxy может сообщать состояние внешним компонентам — маршрутизаторам или другим балансировщикам, что позволяет строить полноценные инфраструктуры с несколькими путями и уровнями.
3.3.4. Базовые возможности: высокая доступность
Как любой серьёзный балансировщик нагрузки, HAProxy уделяет большое внимание доступности и максимальной непрерывности обслуживания:
Используются только работоспособные серверы, остальные автоматически исключаются из ферм балансировки. Однако при определённых условиях их всё же можно принудительно использовать.
Поддерживается плавный вывод серверов из фермы без воздействия на существующие соединения.
При отказе активных серверов автоматически используются резервные, заменяя их так, чтобы по возможности сохранить сеансы. Это также позволяет создать несколько путей к одному серверу, например через разные интерфейсы.
Можно сообщать об общем отказе фермы, если не работает слишком много серверов. Вместе с мониторингом это позволяет вышестоящему компоненту выбрать другой узел балансировки для данной службы.
Архитектура без сохранения состояния упрощает создание кластеров: HAProxy стремится обеспечить максимальную непрерывность обслуживания без хранения сведений, которые можно потерять при отказе. Благодаря этому передача обслуживания происходит максимально плавно.
Хорошая интеграция со стандартным демоном VRRP keepalived: HAProxy легко сообщает ему своё состояние и хорошо работает с плавающими виртуальными IP-адресами. Примечание: предпочитайте протоколы резервирования IP (VRRP/CARP) кластерным решениям (Heartbeat и т. п.), поскольку они обеспечивают наиболее быстрое, плавное и надёжное переключение.
3.3.5. Базовые возможности: балансировка нагрузки
HAProxy предлагает довольно полный набор средств балансировки нагрузки, многие из которых, к сожалению, отсутствуют в других продуктах:
Поддерживается не менее 10 алгоритмов балансировки, некоторые из которых используют входные данные и дают неограниченное число вариантов применения. Наиболее распространены round-robin — поочерёдный выбор серверов для коротких соединений; leastconn — выбор наименее недавно использовавшегося сервера среди серверов с минимальным числом соединений, подходящий для длительных соединений; source — прямой выбор по исходному адресу клиента для ферм SSL или терминальных серверов; URI — прямой выбор по URI HTTP для кешей HTTP; hdr — прямой выбор по содержимому определённого поля заголовка HTTP; first — сосредоточение всех соединений на минимальном числе серверов, чтобы неиспользуемые короткоживущие виртуальные машины можно было выключить.
Все перечисленные алгоритмы поддерживают вес каждого сервера, позволяя сочетать в ферме разные поколения серверов или направлять небольшую долю трафика на отдельные серверы для отладки, работы следующей версии программы и т. п.
Для round-robin, leastconn и согласованного хеширования поддерживаются динамические веса. Их можно менять на лету через CLI или даже с помощью агента на сервере.
Везде, где поддерживается динамический вес, доступен slow-start — постепенное принятие сервером трафика. Это важно для чувствительных серверов приложений, которым нужно компилировать классы во время работы, и холодных кешей, которые необходимо заполнить перед полной нагрузкой.
Хеширование может применяться к разным элементам: исходному адресу клиента, компонентам URL, элементу строки запроса, значениям полей заголовков, параметру POST, cookie RDP.
Согласованное хеширование защищает фермы от массового перераспределения нагрузки при добавлении или удалении серверов. Это особенно важно для больших кеширующих ферм и позволяет использовать slow-start для заполнения холодных кешей.
Внутренние метрики, например число соединений на сервер и бэкенд или число свободных мест для соединений в бэкенде, позволяют строить очень сложные стратегии балансировки.
3.3.6. Базовые возможности: привязка сеансов
Без привязки сеансов балансировка нагрузки приложений была бы бесполезна. HAProxy предоставляет широкий набор средств для закрепления посетителя за одним сервером даже при добавлении и удалении серверов, отказах и восстановлении. Некоторые методы устойчивы к расстояниям между узлами балансировки, поскольку не требуют репликации:
При необходимости сведения для привязки можно независимо сопоставлять и запоминать из разных источников. Например, JSESSIONID можно искать и в cookie, и в URL. Одновременно можно запоминать до 8 источников, каждый из которых может указывать на отдельную таблицу stick-table.
Источником привязки может быть всё, что видно в запросе или ответе: исходный адрес, смещение и длина полезной нагрузки TCP, элементы строки запроса HTTP, значения полей заголовков, cookie и т. п.
Таблицы stick-tables реплицируются между всеми узлами в режиме с несколькими ведущими узлами.
Часто используемые элементы, например SSL-ID или cookie RDP для ферм TSE, доступны непосредственно, что упрощает работу с ними.
Все правила привязки могут динамически зависеть от условий ACL.
Можно отказаться от привязки к определённым серверам, например резервным, чтобы после возвращения основного сервера нагрузка автоматически перешла к нему. Это часто используется в средах с несколькими путями.
В HTTP часто предпочитают ничего не запоминать, а управлять специальным cookie привязки. Такой cookie можно обнаруживать, переписывать, вставлять или дополнять префиксом, чтобы клиент запомнил назначенный сервер.
Сервер может изменить или очистить cookie привязки при выходе пользователя, автоматически снимая привязку уходящих посетителей.
Правила ACL позволяют выборочно игнорировать или принудительно применять привязку независимо от состояния сервера. Вместе с расширенными проверками работоспособности это помогает администратору убедиться, что устанавливаемый сервер работает, прежде чем открыть его всем.
Специальный механизм ограничения времени бездействия и срока действия cookie позволяет плавно прекращать привязку на устройствах, которые никогда не закрываются, — смартфонах, телевизорах, бытовой технике, — без хранения этих сведений в постоянном хранилище.
Несколько записей серверов могут иметь одинаковые ключи привязки, чтобы при отказе одного пути в многопутевой среде привязка сохранялась.
soft-stop гарантирует, что к назначенному серверу продолжат обращаться только пользователи, уже имеющие сведения о привязке, а новые туда не попадут.
3.3.7. Базовые возможности: ведение журнала
Ведение журнала исключительно важно для балансировщика нагрузки. Во-первых, его часто ошибочно обвиняют в проблемах, которые он лишь выявляет. Во-вторых, он находится в критической точке инфраструктуры, где нужно анализировать всю обычную и аномальную активность и сопоставлять её с другими компонентами.
HAProxy предоставляет очень подробные журналы с миллисекундной точностью и точным временем приёма соединения, которое можно найти в журналах межсетевого экрана, например для сопоставления NAT. По умолчанию журналы TCP и HTTP содержат все необходимые для устранения неполадок сведения: исходный IP-адрес и порт, фронтенд, бэкенд, сервер, таймеры получения запроса, ожидания в очереди, установки соединения, получения заголовков ответа и передачи данных; общее состояние процесса; число соединений; состояние очередей; число повторных попыток; подробные действия привязки и причины отключения; захваченные заголовки с безопасным кодированием вывода. Формат можно расширить или заменить, включив любые извлечённые образцы, переменные и захваченные значения, чтобы получить очень подробные сведения. Например, можно записывать суммарное число запросов клиента или число посещённых им разных URL.
Уровень журналирования можно настраивать для каждого запроса обычными ACL: автоматически подавлять шумные записи и повышать уровень до предупреждения при аномальном поведении небольшой части трафика, например при слишком большом числе URL или ошибок HTTP с одного исходного адреса. Административные сообщения также имеют свои уровни и сообщают, например, об отказе или восстановлении сервера.
Каждый фронтенд и бэкенд может использовать несколько независимых направлений вывода журналов, что упрощает обслуживание нескольких арендаторов. Журналы предпочтительно отправлять по UDP, возможно в JSON, обрезая строки до настраиваемой длины для гарантированной доставки. Их также можно отправлять в stdout/stderr, любой файловый дескриптор или кольцевой буфер, на который клиент может подписаться для получения записей.
3.3.8. Базовые возможности: статистика
HAProxy предоставляет веб-интерфейс статистики с аутентификацией, уровнями безопасности и областями видимости. Поэтому каждому заказчику хостинга можно дать отдельную страницу только с его экземплярами. Её можно разместить по скрытому URL обычного сайта, не открывая новый порт. Страница также может показывать доступность других узлов HAProxy, позволяя с первого взгляда оценить работоспособность всей системы. Представление компактно, но доступны многочисленные подробности: причины ошибок, время с последнего обращения и изменения и т. п. Те же данные доступны в виде таблицы CSV, которую другие инструменты могут импортировать для построения графиков. Страница может автоматически обновляться для использования как панели мониторинга на большом экране. В административном режиме она также позволяет менять состояние серверов, упрощая обслуживание.
Также предоставляется экспортёр Prometheus, позволяющий получать статистику в другом формате в зависимости от развёртывания.
4 - Стандартные возможности
В этом разделе перечислены возможности, широко используемые в HAProxy, но не обязательно присутствующие в других балансировщиках нагрузки.
3.4.1. Стандартные возможности: извлечение и преобразование сведений
HAProxy поддерживает получение сведений с помощью широкого набора функций извлечения образцов. Они извлекают отдельные сведения, называемые образцами, для немедленного использования. Это применяется для привязки сеансов, построения условий, вывода сведений в журналы или дополнения заголовков HTTP.
Образцы можно извлекать из разных источников:
Константы: целые числа, строки, IP-адреса, двоичные блоки.
Процесс: дата, переменные окружения, состояние сервера/фронтенда/бэкенда/процесса, число и интенсивность передачи байтов/соединений, длина очереди, генератор случайных чисел и т. п.
Переменные: на уровне сеанса, запроса или ответа.
Клиентское соединение: исходные и целевые адреса и порты и все связанные статистические счётчики.
Клиентский сеанс SSL: протокол, версия, алгоритм, шифр, размер ключа, идентификатор сеанса, все поля сертификатов клиента и сервера, серийный номер сертификата, SNI, ALPN, NPN, поддержка клиентом определённых расширений.
Содержимое буферов запроса и ответа: произвольная полезная нагрузка по смещению и длине, длина данных, cookie RDP, декодирование типа приветствия SSL, декодирование TLS SNI.
HTTP, запрос и ответ: метод, URI, путь, аргументы строки запроса, код состояния, значения заголовков, значение заголовка по позиции, cookie, захваченные значения, аутентификация, элементы тела.
Затем образец может пройти через операторы, называемые преобразователями. Преобразователь принимает образец и создаёт новый, возможно совершенно другого типа. Например, он может вернуть целочисленную длину входной строки или перевести строку в верхний регистр. До окончательного использования к образцу можно последовательно применить любое число преобразователей. Среди доступных чаще всего используются:
Арифметические и логические операторы для сложных вычислений над входными данными: отношений, процентов или просто перевода между единицами измерения.
Маски IP-адресов, полезные для объединения адресов в более крупные сети.
Представление данных: декодирование URL, base64, шестнадцатеричный формат, строки JSON, хеширование.
Преобразование строк: извлечение подстрок по фиксированным позиции и длине, отдельных полей по разделителям и определённых слов, смена регистра, замена по регулярным выражениям.
Преобразование дат: в формат даты HTTP, из местного времени в UTC и обратно, добавление и вычитание смещения.
Поиск записи в таблице привязок для получения статистики или назначенного сервера.
Преобразование ключа в значение по карте отображения из файла, преимущественно для геолокации.
3.4.2. Стандартные возможности: карты отображения
Карты отображения — мощный тип преобразователя. При запуске в память загружается файл с двумя столбцами, затем каждый входной образец ищется в первом столбце. Если запись найдена, возвращается соответствующее значение из второго столбца, иначе — значение по умолчанию. Результат тоже является образцом, поэтому к нему можно применять последующие преобразования, включая поиск в других картах. Чаще всего карты используют для преобразования IP-адреса клиента в номер AS или код страны, поскольку они поддерживают наиболее длинное совпадение сетевых адресов, но возможны и многие другие применения.
Одно из их преимуществ — обновление на лету через CLI или определённые действия с использованием других образцов. Это позволяет хранить и извлекать сведения между последовательными обращениями. Другое преимущество — индексирование на основе двоичных деревьев: даже при сотнях тысяч записей поиск чрезвычайно быстр, поэтому геолокация требует мало ресурсов и легко настраивается.
3.4.3. Стандартные возможности: ACL и условия
Большинство операций HAProxy может выполняться условно. Условия строятся объединением нескольких ACL логическими операторами AND, OR и NOT. Каждая ACL представляет собой последовательность проверок на основе следующих элементов:
Метод извлечения образца для получения проверяемого элемента.
Необязательная последовательность преобразователей элемента.
Список шаблонов для сопоставления.
Метод сопоставления, определяющий способ сравнения шаблонов с образцом.
Например, образец можно получить из заголовка HTTP «Host», перевести в нижний регистр, а затем сопоставить с несколькими регулярными выражениями соответствующим методом.
Технически ACL построены на той же основе, что карты отображения: у них одинаковые внутренние структуры, методы сопоставления шаблонов и производительность. Единственное существенное отличие: вместо образца они возвращают только «found» или «not found». Шаблоны ACL можно объявлять прямо в конфигурации, отдельный файл не требуется. Для удобства и понятности конфигурации ACL можно именовать. Именованную ACL можно объявить несколько раз: все определения будут проверяться по очереди до первого совпадения.
Предоставляется около 13 методов сопоставления шаблонов, включая маску IP-адреса, диапазоны целых чисел, подстроки и регулярные выражения. Они работают как функции, и, как в любом языке программирования, вычисляется только необходимое. Если условие с OR уже истинно, следующие части не вычисляются; если условие с AND уже ложно, оставшаяся часть также не вычисляется.
Практического ограничения на число объявленных ACL нет, и несколько часто используемых ACL предоставляются готовыми. Однако опыт показывает, что конфигурации с множеством именованных ACL трудно отлаживать. Иногда проще использовать анонимные ACL прямо в правилах, поскольку приходится реже обращаться к определениям вне анализируемой области.
3.4.4. Стандартные возможности: переключение содержимого
HAProxy реализует механизм переключения на основе содержимого. Соединение или запрос поступает во фронтенд, затем обрабатываются переданные с ним сведения. На их основе можно задать условия ACL для выбора бэкенда, который обработает запрос. Так трафик направляется в разные бэкенды в зависимости от содержимого запроса. Типичный пример — использование заголовка Host и/или частей пути (подкаталогов либо расширений файлов), чтобы определить, относится ли запрос HTTP к статическому объекту или приложению. Статические объекты направляются в бэкенд из быстрых лёгких серверов, а остальной трафик — на более сложный сервер приложений. Получается гибкая схема виртуального хостинга, удобная для объединения нескольких технологий в общее решение.
Другой вариант применения — выбор алгоритма балансировки по разным критериям. Например, кеш может использовать хеш URI, а приложение — round-robin.
Наконец, механизм позволяет нескольким заказчикам использовать небольшие доли общего ресурса, ограничивая число соединений для каждого бэкенда, а значит, и заказчика.
Правила переключения содержимого хорошо масштабируются, хотя производительность зависит от числа и сложности ACL. Можно также использовать динамические правила, в которых значение образца напрямую преобразуется в имя бэкенда, вообще без ACL. Сообщалось об успешной работе таких конфигураций в рабочей среде как минимум с 300000 бэкендов.
3.4.5. Стандартные возможности: таблицы привязок
Таблицы привязок обычно хранят сведения о привязке сеансов — ссылку на сервер, куда был направлен посетитель. Ключом служит связанный с посетителем идентификатор: исходный адрес, идентификатор SSL соединения, cookie HTTP или RDP, номер заказчика из URL или полезной нагрузки и т. п. Сохраняемое значение — идентификатор сервера.
Таблицы привязок поддерживают 3 типа образцов в ключах: целые числа, строки и адреса. В прокси можно ссылаться только на одну таблицу привязок, везде обозначаемую именем прокси. Параллельно можно отслеживать до 8 ключей. Идентификатор сервера фиксируется при обработке запроса или ответа, когда известны и ключ, и сервер.
Содержимое таблиц может реплицироваться в режиме active-active с другими узлами HAProxy, называемыми «peers», а при перезагрузке конфигурации — также с новым процессом. Тогда все узлы балансировки имеют одинаковые сведения и принимают одинаковые решения о маршрутизации, даже если запросы клиента распределяются между несколькими узлами.
Поскольку таблицы индексируются по признаку, позволяющему распознать клиента, в них часто хранят и дополнительные сведения, например статистику по клиентам. Дополнительная статистика занимает место и должна объявляться явно. Можно хранить входящую и исходящую пропускную способность, число одновременных соединений, интенсивность и число соединений за период, количество и частоту ошибок, специальные метки и счётчики и т. п. Чтобы сохранять такие сведения без обязательной привязки к серверу, реализована специальная функция отслеживания. Она позволяет одновременно отслеживать до 3 ключей из разных таблиц независимо от правил привязки. Любую сохраняемую статистику можно искать, выгружать и очищать через CLI, расширяя возможности устранения неполадок в реальном времени.
Хотя этот механизм позволяет повышать приоритет возвращающегося посетителя или менять качество обслуживания в зависимости от хорошего или плохого поведения, чаще всего его используют для борьбы со злоупотреблениями и DDoS. Он позволяет строить сложные модели выявления нежелательного поведения при высокой скорости обработки.
3.4.6. Стандартные возможности: форматированные строки
HAProxy работает со строками во многих местах: в журналах, перенаправлениях, добавляемых заголовках и т. п. Для максимальной гибкости введены форматированные строки, первоначально для журналирования, поэтому механизм до сих пор называется «log-format». Такие строки содержат управляющие последовательности для вставки динамических данных, включая переменные и выражения извлечения образцов, и даже изменения кодирования при преобразовании результата в строку, например добавления кавычек. Это мощное средство формирования заголовков, данных ответа и даже шаблонов ответов, а также настройки строк журнала. Чтобы обычные строки оставались простыми в составлении, предусмотрено около 50 специальных меток — сокращений для часто используемых в журналах сведений.
3.4.7. Стандартные возможности: переписывание HTTP и перенаправления
Установка балансировщика перед приложением, которое на это не рассчитано, без подходящих инструментов может оказаться сложной. Одна из самых частых задач — изменить заголовки запросов и ответов, чтобы балансировщик выглядел исходным сервером, и исправить жёстко заданные сведения. Сюда относятся изменение пути запроса (что настоятельно не рекомендуется), поля Host, поля Location в ответах перенаправления, атрибутов пути и домена cookie и т. п. Также многие серверы слишком многословны и раскрывают в ответах лишние сведения, повышая уязвимость к целевым атакам. Хотя теоретически очищать ответы не задача балансировщика, на практике он расположен в наиболее удобной точке инфраструктуры для гарантированной очистки.
Иногда балансировщику также нужно перехватить запрос и ответить перенаправлением на новый URL. Перенаправление и переписывание иногда путают, но это совершенно разные понятия: при переписывании клиент и сервер видят разные данные и по-разному представляют расположение страницы, а перенаправление просит клиента обратиться к новому URL, чтобы он видел то же расположение, что и сервер.
Для этого HAProxy поддерживает разные возможности переписывания и перенаправления, в том числе:
Переписывание URL и заголовков запросов и ответов по регулярным выражениям. Это самый распространённый способ изменения значений заголовков благодаря понятности и удобству регулярных выражений.
Добавление, удаление или замена заголовков на основе форматированных строк для передачи сведений, например алгоритма и шифра TLS на стороне клиента.
Перенаправления HTTP с любым кодом 3xx на относительный, абсолютный или полностью динамический URI из форматированной строки.
Дополнительные параметры перенаправлений: установка или удаление cookie, отбрасывание строки запроса, добавление отсутствующей завершающей косой черты и т. п.
Мощная директива «return», позволяющая настроить любую часть ответа — состояние, заголовки, тело — с динамическим содержимым или даже файлами шаблонов.
Условия на основе ACL для всех операций.
3.4.8. Стандартные возможности: защита серверов
HAProxy стремится максимально повысить доступность службы и для этого защищает серверы от перегрузки и атак. Первый и самый важный принцип: серверам пересылаются только полные корректные запросы. Прежде всего HAProxy должен найти элементы протокола, необходимые для синхронизации с потоком байтов. Кроме того, пока запрос не получен полностью, нельзя знать, не изменят ли некоторые элементы его смысл. Прямое преимущество — серверы не получают некорректные или неполные запросы. Это очень эффективная защита от атак slowloris, практически не влияющих на HAProxy.
Другой важный момент — буферы HAProxy для запросов и ответов. Отправляя запрос серверу только после полного получения и быстро считывая весь ответ из локальной сети, HAProxy занимает соединение с сервером на очень короткое время, максимально сохраняя его ресурсы.
Из этого непосредственно следует возможность искусственно ограничивать число одновременных соединений или незавершённых запросов к серверу. Это гарантирует отсутствие перегрузки, даже если во время всплесков трафика сервер непрерывно работает на 100% мощности. Все лишние запросы просто ждут в очереди освобождения места. Такая огромная экономия ресурсов обычно настолько улучшает время ответа, что работа оказывается быстрее, чем при перегрузке сервера. Запросы из очереди можно перераспределять на другие серверы или даже отменять в очереди при отказе клиента от запроса. Это защищает и от «эффекта обновления страницы»: каждый щелчок «обновить» на медленно загружаемой странице обычно создаёт новый запрос и поддерживает перегрузку.
Механизм slow-start также защищает перезапускаемые серверы от интенсивного трафика, пока они ещё завершают запуск или компилируют классы.
На уровне протокола парсер HTTP можно ослабить, чтобы принимать не соответствующие стандарту, но безвредные запросы и ответы и даже исправлять их. Это сохраняет доступность ошибочных приложений на время разработки исправления. Одновременно проблемные сообщения полностью захватываются с подробным отчётом, помогающим разработчикам найти ошибку. Наиболее опасные нарушения протокола корректно выявляются, обрабатываются и исправляются. Например, некорректный запрос или ответ с двумя заголовками Content-length исправляется, если их значения в точности совпадают, и отклоняется при различии, поскольку это уже угроза безопасности. Анализ протокола не ограничен HTTP: он доступен и для других протоколов, например TLS или RDP.
При обнаружении нарушения протокола или атаки возможны разные реакции: обычный ответ «HTTP 400 bad request», закрытие соединения сбросом TCP или имитация ошибки после длительной задержки — ловушка соединений («tarpit»), сбивающая атакующего с толку. Всё это защищает серверы, делая продолжение атаки слишком затратным для нарушителя.
HAProxy также предлагает более сложные средства защиты от случайных утечек данных и смешения сеансов. Он может не только записывать подозрительные ответы сервера, но и журналировать и при необходимости блокировать ответ, угрожающий конфиденциальности посетителя. Например, кешируемый cookie в кешируемом ответе может быть выдан промежуточным кешем другому посетителю, случайно предоставив общий доступ к сеансу.
5 - Расширенные возможности
3.5.1. Расширенные возможности: управление
HAProxy спроектирован для исключительно стабильной работы и безопасного управления в обычной рабочей среде. Он поставляется одним исполняемым файлом и не требует процедуры установки. Несколько версий легко могут сосуществовать: экземпляры можно и рекомендуется обновлять постепенно, в порядке важности, вместо одновременного переноса всех экземпляров. Файлы конфигурации удобно хранить под контролем версий. Проверка конфигурации выполняется отдельно от работающей службы, поэтому не нужно перезапускать службу, рискуя получить сбой. При проверке могут обнаруживаться сложные ошибки (например, правило, скрывающее другое правило, или неработоспособная привязка сеансов); для их устранения выдаются подробные предупреждения и рекомендации. Обратная совместимость конфигурации охватывает очень давние версии: версия 1.5 полностью поддерживала конфигурации версии 1.1, написанные 13 лет назад, а в 1.6 прекращена поддержка лишь почти неиспользуемых устаревших директив, которые можно заменить другими средствами. Обновление конфигурации и программы происходит плавно и без прерывания обслуживания: старые и новые процессы могут сосуществовать в системе, каждый обрабатывая свои соединения. При запуске выводятся состояние системы, параметры сборки и сведения о совместимости библиотек.
Некоторые расширенные возможности позволяют администратору приложения плавно вывести сервер из обслуживания, определить момент прекращения активности, отключить его, остановить, обновить, обеспечить отсутствие трафика во время обновления, а затем снова проверить его через обычный путь доступа, не открывая доступ публике. Всё это не требует вмешательства в HAProxy. Благодаря этому даже сложные операции в рабочей среде можно выполнять в рабочее время, когда доступны все технические специалисты.
Процесс старается максимально экономить ресурсы: использует пулы памяти для сокращения времени выделения и ограничения фрагментации, освобождает буферы полезной нагрузки сразу после отправки их содержимого и поддерживает жёсткие пределы памяти. При достижении такого предела соединения ждут освобождения буфера вместо выделения дополнительной памяти. Этот механизм позволяет гарантировать потребление памяти в средах со строгими ограничениями.
Интерфейс командной строки (CLI) доступен через сокет UNIX или TCP и позволяет выполнять различные операции и получать сведения для устранения неполадок. Действия через этот сокет не требуют изменения конфигурации, поэтому его в основном используют для временных изменений. Через интерфейс можно менять адрес, вес и состояние сервера; просматривать статистику и сбрасывать счётчики; выгружать и очищать таблицы привязок, в том числе выборочно по критериям ключей; выводить и принудительно закрывать соединения со стороны клиентов и серверов; выгружать сохранённые ошибки с подробным анализом точной причины и места; выводить, добавлять и удалять записи ACL и карт отображения; обновлять общие секреты TLS; на лету ограничивать число соединений и их интенсивность для произвольных фронтендов (полезно в средах совместного хостинга); отключать отдельный фронтенд, освобождая прослушиваемый порт (полезно, если операции в дневное время запрещены, но исправление всё же необходимо). Также разрешены обновление сертификатов и их конфигурации на лету, включение и просмотр трассировки каждого этапа обработки трафика.
Для сред, где обязателен SNMP, существуют как минимум два агента. Один поставляется с исходным кодом HAProxy и использует модуль Perl Net-SNMP. Другой входит в коммерческие пакеты и не требует Perl. По охвату возможностей они примерно эквивалентны.
На машине с HAProxy часто рекомендуется установить 4 утилиты:
socat — для подключения к CLI, хотя некоторые варианты netcat тоже в определённой мере это умеют;
halog из последней версии HAProxy — инструмент анализа журналов, который чрезвычайно быстро (от 1 до 2 GB в секунду) разбирает собственные журналы TCP и HTTP и извлекает полезные сведения и статистику: запросы по URL и исходным адресам, URL, отсортированные по времени ответа или частоте ошибок, коды завершения и т. п. Он предназначен для установки на рабочих серверах и устранения неполадок в реальном времени, поэтому должен быть установлен и готов к использованию;
tcpdump — настоятельно рекомендуется для получения сетевых трассировок при исследовании проблем, замеченных в журналах. В какой-то момент анализ приложения и haproxy может разойтись, и только сетевые трассировки позволяют определить, кто прав. С помощью tcpdump также довольно часто обнаруживают ошибки сетевых стеков и гипервизоров;
strace — дополнение к tcpdump. Он показывает, что в действительности видит HAProxy, и помогает отделить проблемы операционной системы от проблем самого HAProxy. Strace часто запрашивают при подозрении на ошибку в HAProxy.
3.5.2. Расширенные возможности: системные функции
В зависимости от операционной системы, на которой развёрнут HAProxy, могут быть доступны или необходимы дополнительные возможности. Хотя HAProxy поддерживает ряд платформ, в основном его разрабатывают на Linux, поэтому некоторые функции доступны только на этой платформе.
Прозрачная привязка и установка соединений, привязка соединений к определённому сетевому интерфейсу, а также привязка нескольких процессов к одним IP-адресам и портам доступны только в Linux и BSD. При этом лишь Linux распределяет входящие запросы между доступными процессами средствами ядра.
Linux также предоставляет дополнительные возможности и оптимизации: поддержку сетевых пространств имён (также известных как «контейнеры»), позволяющую HAProxy служить шлюзом между всеми контейнерами; установку MSS, меток Netfilter и поля IP TOS для клиентского соединения; поддержку TCP FastOpen на стороне прослушивания; пользовательские тайм-ауты TCP, позволяющие ядру быстро закрыть соединение, если оно обнаружило исчезновение клиента до истечения заданных тайм-аутов; TCP splicing, при котором ядро пересылает данные между сторонами соединения без многократного копирования памяти; параметр привязки «defer-accept», чтобы получать уведомление о входящем соединении только после появления данных в буферах ядра; отправку запроса вместе с ACK, подтверждающим установку соединения (иногда называемую «piggy-back»), включаемую параметром «tcp-smart-connect». Кроме того, в Linux HAProxy тщательно управляет отложенными ACK TCP, чтобы максимально сократить число пакетов в сети.
В некоторых системах часы ненадёжны и скачут то назад, то вперёд. Раньше это встречалось на отдельных системах NUMA, где процессоры видели немного разное время. В последнее время проблема чаще возникает в виртуализированных средах, где виртуальные часы не связаны с реальными, из-за чего возможны огромные скачки времени — наблюдались даже скачки до 30 секунд. Это создаёт серьёзные проблемы с соблюдением тайм-аутов. Чтобы обойти этот недостаток, HAProxy поддерживает собственные монотонные часы, основанные на системных, но с измерением и компенсацией отклонения. Благодаря этому даже при очень плохих системных часах таймеры остаются достаточно точными, а тайм-ауты продолжают работать. Учтите, что проблема затрагивает все программы в такой системе и не специфична для HAProxy. Типичные проявления — ложные тайм-ауты или зависания приложений. Поэтому при обнаружении такого поведения систему необходимо исправить, даже несмотря на защиту HAProxy.
В Linux новый запускаемый процесс может связаться с предыдущим и повторно использовать его прослушивающие файловые дескрипторы, чтобы при замене процесса работа прослушивающих сокетов никогда не прерывалась.
3.5.3. Расширенные возможности: скрипты
HAProxy можно собрать с поддержкой встроенного языка Lua. Это открывает широкие возможности сложной обработки запросов и ответов, принятия решений о маршрутизации, обработки статистики и многого другого. Через Lua можно даже устанавливать параллельные соединения с другими серверами для обмена сведениями. Так можно, например, разработать систему аутентификации, хотя это и непросто. Подробнее об использовании Lua см. документацию в файле «doc/lua-api/index.rst».
3.5.4. Расширенные возможности: трассировка
Администратор в любой момент может подключиться к CLI и включить трассировку различных внутренних подсистем. По умолчанию доступны разные уровни детализации: на практике можно получать от одной строки до 500 строк на запрос. Доступны фильтры и механизм автоматического включения, выключения и приостановки захвата, позволяющие дождаться определённого события и подробно изучить его. Это исключительно удобно для диагностики нарушений протокола неисправными серверами и клиентами или атак отказа в обслуживании.
6 - Расчёт ресурсов и производительность
Типичные показатели использования CPU: в режиме TCP или HTTP с закрытием соединений на HAProxy приходится 15% времени обработки, а на ядро — 85%; в режиме постоянных соединений HTTP на HAProxy приходится около 30%, а на ядро — 70%. Это означает, что операционная система и её настройка сильно влияют на общую производительность.
Сценарии использования сильно различаются: одни пользователи ориентируются на пропускную способность, другие — на интенсивность запросов, число одновременных соединений или производительность SSL. В этом разделе приведены некоторые сведения, помогающие оценить необходимые ресурсы.
Важно помнить, что любая операция требует затрат: накладные расходы каждой операции прибавляются к остальным. В одних обстоятельствах они могут быть пренебрежимо малы, а в других — преобладать.
При обработке запросов в рамках соединения можно утверждать следующее:
Пересылка данных требует меньше ресурсов, чем разбор заголовков запроса или ответа.
Разбор заголовков запроса или ответа требует меньше ресурсов, чем установка и последующее закрытие соединения с сервером.
Установка и закрытие соединения требуют меньше ресурсов, чем возобновление TLS.
Возобновление TLS требует меньше ресурсов, чем полное рукопожатие TLS с вычислением ключа.
Бездействующее соединение потребляет меньше CPU, чем соединение, в буферах которого есть данные.
Контекст TLS требует ещё больше памяти, чем соединение с данными.
На практике обработка байтов полезной нагрузки обходится дешевле обработки байтов заголовков, поэтому высокой пропускной способности сети проще добиться с большими объектами (мало запросов на единицу объёма), чем с маленькими (много запросов на единицу объёма). Этим объясняется, почему максимальную пропускную способность всегда измеряют на больших объектах, а интенсивность запросов или соединений — на маленьких.
Некоторые операции хорошо масштабируются при использовании нескольких процессов на разных CPU, другие — хуже. Пропускная способность сети масштабируется лишь до определённого предела, поскольку для больших объектов узким местом редко бывает CPU: обычно ограничение задают сеть и шины данных, по которым передаются данные к сетевым интерфейсам. Интенсивность соединений плохо масштабируется на несколько процессоров из-за ряда системных блокировок при работе с таблицей локальных портов. Интенсивность запросов по постоянным соединениям масштабируется очень хорошо: такие запросы не требуют большого объёма памяти или пропускной способности сети и не обращаются к структурам с блокировками. Вычисление ключей TLS также отлично масштабируется, поскольку полностью ограничено ресурсами CPU. Возобновление TLS масштабируется умеренно хорошо, но примерно на 4 процессах достигает предела: накладные расходы доступа к общей таблице нивелируют небольшой выигрыш от дополнительных вычислительных ресурсов.
От хорошо настроенной системы можно ожидать показателей производительности в приведённых ниже пределах. Их важно воспринимать как порядок величин и учитывать возможные значительные отклонения в обе стороны в зависимости от процессора, настройки IRQ, типа памяти и сетевого интерфейса, настройки операционной системы и прочих факторов.
Следующие результаты получены на Core i7 с частотой 3.7 GHz и двухпортовыми сетевыми адаптерами 10 Gbps под управлением ядра Linux 3.10, HAProxy 1.6 и OpenSSL 1.0.2. HAProxy работал одним процессом на одном выделенном ядре CPU, а ещё два ядра были выделены для сетевых прерываний:
Максимальная пропускная способность сети без шифрования — 20 Gbps для объектов размером 256 kB и больше, 10 Gbps для объектов размером 41kB и больше.
4.6 Gbps трафика TLS с шифром AES256-GCM на больших объектах.
83000 соединений TCP в секунду от клиента до сервера.
82000 соединений HTTP в секунду от клиента до сервера.
97000 запросов HTTP в секунду в режиме server-close (постоянное соединение с клиентом, закрытие соединения с сервером).
243000 запросов HTTP в секунду в режиме постоянных соединений на всём пути.
300000 отфильтрованных соединений TCP в секунду (защита от DDoS).
160000 запросов HTTPS в секунду в режиме постоянных соединений поверх постоянных соединений TLS.
13100 запросов HTTPS в секунду с возобновляемыми соединениями TLS.
1300 соединений HTTPS в секунду с повторным согласованием соединений TLS с использованием RSA2048.
20000 одновременных полностью загруженных соединений на GB оперативной памяти, включая память системных буферов. Тщательная настройка позволяет улучшить этот показатель, но такого результата легко достичь.
Около 8000 одновременных соединений TLS (только со стороны клиента) на GB оперативной памяти, включая память системных буферов.
Около 5000 одновременных сквозных соединений TLS (с обеих сторон) на GB оперативной памяти, включая память системных буферов.
В более новом тесте многопоточный HAProxy 2.4 на 64-ядерном процессоре ARM Graviton2 в AWS достиг 2 миллионов запросов HTTPS в секунду при времени ответа менее миллисекунды и объёме трафика 100 Gbps:
Полезный практический ориентир: интенсивность запросов уменьшается в 10 раз при переходе от постоянных соединений TLS к возобновлению TLS и от возобновления TLS к повторному согласованию TLS, тогда как при переходе от постоянных соединений HTTP к закрытию соединений HTTP она уменьшается лишь в 3 раза. Ещё один ориентир: высокочастотное ядро с инструкциями AES может обрабатывать около 20 Gbps AES-GCM на ядро.
Также полезно учитывать, что на том же сервере HAProxy способен полностью загрузить:
около 5-10 серверов статических файлов или кеширующих прокси;
около 100 антивирусных прокси;
около 100-1000 серверов приложений в зависимости от используемой технологии.
7 - Выпуски, пакеты и обновления
HAProxy — проект с открытым исходным кодом под лицензией GPLv2. Это означает, что его разрешено распространять при условии предоставления доступа к исходному коду по запросу, особенно если в него внесены изменения.
HAProxy развивается в основной ветке разработки «master» или «mainline», от которой создают новые ветки, когда код считается стабильным. Многие сайты добровольно используют ветки разработки в рабочей среде — чтобы участвовать в проекте или потому, что им нужна самая новая функция. Их обратная связь очень ценна для исправления ошибок и оценки общего качества и стабильности разрабатываемой версии.
Новые ветки, создаваемые после достижения достаточной стабильности кода, образуют стабильную версию и обычно сопровождаются несколько лет. Поэтому даже при использовании не самой новой ветки срочно переходить на следующую не требуется. После выпуска стабильная ветка получает только исправления ошибок и очень редко небольшие обновления функций, облегчающие жизнь пользователям. Все исправления в стабильной ветке обязательно происходят из ветки master. Это гарантирует, что после обновления ни одно исправление не потеряется. Поэтому, исправляя ошибку, готовьте патч для master, а не для стабильной ветки. Возможно, вы обнаружите, что ошибка уже исправлена. Этот процесс также делает регрессии в стабильной ветке исключительно редкими, поэтому нет причин отказываться от обновления до последней версии текущей ветки.
Номер ветки состоит из двух чисел, разделённых точкой, например «1.6». Начиная с 1.9 ветки с нечётным вторым числом в основном предназначены для существенных технических изменений и опытных пользователей, поскольку в них вероятнее появление ошибок. Они сопровождаются лишь около года, и их нельзя развёртывать там, где невозможно экстренно откатить обновление. Полный номер версии включает один или два номера подверсии, обозначающих уровень исправлений. Например, 1.5.14 — это 14-й корректирующий выпуск ветки 1.5 после выхода 1.5.0. Он содержит 126 исправлений отдельных ошибок, 24 обновления документации и 75 других перенесённых патчей, большинство из которых требовалось для исправления указанных 126 ошибок. Существующую функцию в стабильной ветке нельзя изменять или удалять: это гарантирует безопасность обновлений в пределах одной ветки.
HAProxy доступен из нескольких источников с разной частотой выпусков:
Официальный сайт сообщества http://www.haproxy.org/ предоставляет исходный код последнего выпуска разработки, всех стабильных выпусков и ночные снимки каждой ветки. Цикл выпусков небыстрый: между стабильными выпусками или снимками разработки проходит несколько месяцев. Там по-прежнему поддерживаются очень старые версии. Всё предоставляется только в виде исходного кода, поэтому полученное оттуда нужно собирать и/или упаковывать заново.
GitHub https://github.com/haproxy/haproxy/ — зеркало только ветки разработки, обеспечивающее интеграцию с системой отслеживания задач, непрерывной интеграцией и инструментами покрытия кода. Оно предназначено исключительно для участников разработки.
Ряд операционных систем, например дистрибутивы Linux и порты BSD, обычно предоставляют версии с длительным сопровождением. В них не всегда есть все исправления официальных выпусков, но как минимум критические исправления присутствуют. Часто это хороший вариант для большинства пользователей, которым не нужны сложные конфигурации и важно простое обновление.
Коммерческие версии с http://www.haproxy.com/ — профессиональные пакеты с поддержкой, собранные для разных операционных систем или поставляемые как готовые устройства. Они основаны на последних стабильных версиях и включают востребованные функции, перенесённые из следующего выпуска. Это лучший вариант для пользователей, которым нужны новейшие функции с надёжностью стабильной ветки, максимально быстрое исправление ошибок либо просто договор поддержки продукта с открытым исходным кодом.
Чтобы убедиться, что используется последняя версия своей ветки, действуйте следующим образом:
Проверьте, какой исполняемый файл HAProxy запускается. В некоторых системах он поставляется по умолчанию, а администраторы устанавливают свои версии в другом месте. Поэтому важно проверить используемый файл в сценариях запуска.
Определите источник своей версии HAProxy. Обычно достаточно команды «haproxy -v». Версия разработки выглядит следующим образом: после номера ветки стоит слово «dev».
A stable version will appear like this, as well as unmodified stable
версии, поставляемые производителями операционных систем:
And a nightly snapshot of a stable version will appear like this with an
hexadecimal sequence after the version, and with the date of the snapshot
вместо даты выпуска:
Any other format may indicate a system-specific package with its own
patch set. For example HAProxy Enterprise versions will appear with the
следующим форматом (<branch>-<latest commit>-<revision>):
Please note that historically versions prior to 2.4 used to report the
process name with a hyphen between "HA" and "Proxy", including those above
which were adjusted to show the correct format only, so better ignore this
word or use a relaxed match in scripts. Additionally, modern versions add
a URL linking to the project's home.
Finally, versions 2.1 and above will include a "Status" line indicating
whether the version is safe for production or not, and if so, till when, as
well as a link to the list of known bugs affecting this version.
- Для системных пакетов проверьте репозиторий пакетов или систему обновлений поставщика, чтобы убедиться, что система всё ещё поддерживается и для вашей ветки выпускаются исправления. Для версий сообщества с haproxy.org посетите сайт, проверьте состояние ветки и сравните последнюю версию со своей. Если ваша версия не последняя, её можно обновить. Если ветка больше не сопровождается, вы сильно отстали и должны рассмотреть переход на более новую ветку, внимательно прочитав README.
HAProxy следует обновлять способом, соответствующим его источнику. Обычно это стандартная процедура обновления пакета у поставщика системы. Если HAProxy собран из исходного кода, после распаковки прочитайте README в каталоге исходников и следуйте инструкциям для своей операционной системы.
8 - Сопутствующие продукты и альтернативы
HAProxy хорошо сочетается с некоторыми перечисленными ниже продуктами. Поэтому они упомянуты здесь, хотя и не связаны непосредственно с HAProxy.
4.1. HTTP-сервер Apache
Apache — фактический стандарт среди серверов HTTP. Это очень функциональный модульный проект, поддерживающий как выдачу файлов, так и динамическое содержимое. Он может служить фронтендом для серверов приложений, а также проксировать запросы и кешировать ответы. Во всех этих сценариях перед ним обычно требуется балансировщик нагрузки. Apache может работать в разных режимах, одни из которых требуют больше ресурсов, чем другие. Некоторые модули до сих пор требуют более тяжёлой модели с заранее созданными процессами, что мешает Apache эффективно работать с большим числом соединений. В таком случае HAProxy может значительно помочь: он ограничивает число соединений с каждым сервером безопасным значением, заметно ускоряя сервер и сохраняя его ресурсы для приложения.
Apache может извлекать адрес клиента из заголовка X-Forwarded-For с помощью расширения «mod_rpaf». HAProxy автоматически заполняет этот заголовок, если в конфигурации задано «option forwardfor». HAProxy также может хорошо защищать Apache, доступный из интернета, поскольку лучше противостоит многим видам атак DoS.
4.2. NGINX
NGINX — второй фактический стандарт среди серверов HTTP. Как и Apache, он предоставляет широкий набор функций. NGINX построен по модели, сходной с HAProxy, поэтому без труда обрабатывает десятки тысяч одновременных соединений. При использовании в качестве шлюза к приложениям (например, через включённый PHP FPM) часто полезно ограничить число соединений на входе, чтобы снизить нагрузку на приложение PHP. Здесь HAProxy пригодится и как обычный балансировщик нагрузки, и как регулятор трафика, ускоряющий PHP за счёт устранения перегрузки. Кроме того, благодаря событийной архитектуре оба продукта потребляют мало CPU, и их часто легко разместить в одной системе. NGINX поддерживает протокол PROXY от HAProxy, поэтому HAProxy легко передаёт ему сведения о клиентском соединении, необходимые приложению. Некоторые тесты также показали, что при выдаче больших статических файлов согласованное хеширование в HAProxy перед NGINX повышает долю попаданий в кеш операционной системы, фактически умножая её на число серверных узлов.
4.3. Varnish
Varnish — интеллектуальный кеширующий обратный прокси, который, пожалуй, точнее всего назвать ускорителем веб-приложений. Varnish не реализует SSL/TLS, предпочитая отдавать все ресурсы CPU тому, что умеет лучше всего. Он также поддерживает протокол PROXY от HAProxy, поэтому HAProxy легко развернуть перед Varnish для обработки SSL и балансировки нагрузки с передачей всех необходимых сведений о клиенте. Кроме того, Varnish умеет распаковывать объекты из кеша, если сервер передал их сжатыми, но сам сжатие не выполняет. Если серверы бэкенда не поддерживают сжатие, исходящие данные можно сжимать в HAProxy, хотя делать это на балансировщике редко бывает хорошей идеей, кроме случаев небольшого трафика.
При построении больших кеширующих ферм из нескольких узлов HAProxy может применять согласованное хеширование URL для разумного распределения нагрузки между кеширующими узлами и предотвращения дублирования кеша. Тогда общий размер кеша равен сумме кешей всех узлов. Кроме того, кратковременное кеширование очень маленьких простых объектов в HAProxy иногда позволяет избежать сетевых обменов и снизить нагрузку на CPU как узлов HAProxy, так и Varnish. Это возможно только тогда, когда Varnish никак не обрабатывает эти объекты. Такой подход часто называют «кешем favicon»: иногда он позволяет исключить заметную долю бесполезных запросов к следующему уровню. Однако не включайте длительное кеширование в HAProxy (более нескольких секунд) перед другим кешем: это значительно усложнит устранение неполадок без существенной экономии ресурсов.
4.4. Альтернативы
Linux Virtual Server (LVS или IPVS) — балансировщик нагрузки уровня 4, встроенный в ядро Linux. Он работает на уровне пакетов и обрабатывает TCP и UDP. В большинстве случаев он скорее дополняет HAProxy, чем заменяет его, поскольку совершенно не понимает уровень 7.
Pound — ещё один известный балансировщик нагрузки. Он значительно проще HAProxy и обладает гораздо меньшим числом функций, но для многих простейших конфигураций подходят оба продукта. Автор Pound всегда ставил на первое место возможность аудита кода и стремится сохранять небольшой набор функций. Его архитектура на основе потоков хуже масштабируется при большом числе соединений, но это хороший продукт.
Pen — довольно лёгкий балансировщик нагрузки. Он поддерживает SSL и сохраняет привязку с помощью таблицы фиксированного размера с IP-адресами клиентов. У него есть режим работы с пакетами, позволяющий в определённых пределах поддерживать прямой ответ сервера и UDP. Он рассчитан на небольшие нагрузки: таблица привязок содержит всего 2048 записей.
NGINX в определённой мере умеет балансировать нагрузку, хотя это явно не его основное назначение. Сбои серверов выявляются по рабочему трафику, набор алгоритмов балансировки более ограничен, а поддержка привязки сеансов очень невелика. Но он может быть уместен в простых схемах развёртывания, где уже используется. Поскольку NGINX отлично сочетается с HAProxy, ничто не мешает добавить HAProxy позже, когда возможности NGINX будут исчерпаны.
Varnish также балансирует нагрузку между своими серверами бэкенда и поддерживает полноценные проверки работоспособности. Однако привязку сеансов он не реализует, поэтому, как и в случае NGINX, его может быть достаточно для начала, если привязка не нужна. И аналогично, благодаря хорошей совместимости HAProxy и Varnish, HAProxy легко добавить позже, чтобы расширить набор возможностей.
9 - Документация и сообщество
1. Доступная документация
Полная документация HAProxy содержится в перечисленных ниже документах. Обращайтесь к соответствующей документации, чтобы сэкономить время и получить наиболее точный ответ на свой вопрос. Также воздержитесь от отправки в список рассылки вопросов, ответы на которые уже есть в этих документах.
intro.txt(этот документ): здесь представлены основы балансировки нагрузки, HAProxy как продукт, его возможности и ограничения, известные подводные камни, которых следует избегать, некоторые ограничения конкретных ОС, способы получения, развитие проекта, способы убедиться, что используются все известные исправления, обновление, дополнения и альтернативы.management.txt: объясняет, как запускать haproxy, управлять им во время выполнения, управлять им на нескольких узлах и выполнять обновления без перерыва в обслуживании.configuration.txt: справочное руководство подробно описывает все ключевые слова конфигурации и их параметры. Оно используется, когда требуется изменить конфигурацию.coding-style.txt: предназначен для разработчиков, которые хотят предложить проекту свой код. В нём объясняется стиль, которого следует придерживаться при написании кода. Правила не очень строгие, и не вся кодовая база полностью им соответствует, но изменения, слишком сильно от них отклоняющиеся, будут отклонены.
proxy-protocol.txt: фактическая спецификация протокола PROXY, реализованного в HAProxy и ряде сторонних продуктов.
security.txt: как сообщить о проблеме безопасности и что считается или не считается уязвимостью.
README: как собрать HAProxy из исходного кода
5. Контакты
Если требуется связаться с разработчиками или любым участником сообщества по какому-либо вопросу, обычно лучше всего воспользоваться списком рассылки, отправив сообщение на haproxy@formilux.org . Учтите, что список рассылки и его архивы общедоступны, поэтому следует избегать раскрытия конфиденциальной информации. В нём участвует тысяча пользователей с разным уровнем опыта, и даже на самые сложные вопросы обычно удаётся сравнительно быстро найти оптимальный ответ. Предложения тоже приветствуются. Для пользователей, которым сложно пользоваться электронной почтой, доступна платформа Discourse по адресу http://discourse.haproxy.org/ . Однако учитывайте, что вопросы там читает меньше людей и на большинство из них отвечает очень небольшая команда. В любом случае проявляйте терпение и уважение к тем, кто посвящает своё свободное время помощи другим.
Если кажется, что обнаружена ошибка, но уверенности нет, лучше сообщить об этом в список рассылки. Если есть твёрдая уверенность, что обнаружена ошибка, используется актуальная версия своей ветки и уже есть учётная запись GitHub, можно сразу перейти на https://github.com/haproxy/haproxy/ и создать сообщение об ошибке со всеми доступными подробностями. Этот ресурс тоже общедоступен, поэтому не публикуйте информацию, о раскрытии которой впоследствии можно пожалеть. Поскольку система отслеживания ошибок представляет обсуждение в виде очень длинной ветки, не вставляйте очень длинные дампы (несколько сотен строк и более) в текст, а прикладывайте их как вложения.
Если есть основания полагать, что обнаружена проблема безопасности, обратитесь к файлу doc/security.txt. Он объясняет, что считается или не считается уязвимостью HAProxy и как конфиденциально сообщить о настоящей уязвимости. Большинство предполагаемых проблем безопасности оказываются обычными ошибками, о которых лучше сообщать описанным выше способом.
Полный комплект локальных руководств
Происхождение издания
- Издание: HAProxy 3.4.4, тег
v3.4.4 - Коммит исходного кода:
7f03ae65c286 - Опубликованный комплект проекта: docs.haproxy.org/3.4/
- Локальные копии лицензий: лицензионное уведомление HAProxy и GPLv2
10 - 1. Краткое напоминание об HTTP
Этот документ описывает язык конфигурации в реализации указанной выше версии. Он не содержит подсказок, примеров или рекомендаций. За такими сведениями обращайтесь к справочному руководству или руководству по архитектуре. Пронумерованные главы расположены в плоской боковой панели HAProxy для прямого перехода.
Когда HAProxy работает в режиме HTTP, и запрос, и ответ полностью анализируются и индексируются. Это позволяет строить критерии сопоставления практически по любым элементам содержимого.
Однако важно понимать устройство запросов и ответов HTTP и то, как HAProxy разбирает их на части. Тогда будет проще писать корректные правила и отлаживать существующие конфигурации.
Прежде всего, HTTP стандартизован серией RFC, которым HAProxy следует максимально точно:
- RFC 9110: семантика HTTP (объясняет смысл элементов протокола).
- RFC 9111: кеширование HTTP (описывает правила, которым должен следовать кеш HTTP).
- RFC 9112: HTTP/1.1 (представление, правила взаимодействия, безопасность).
- RFC 9113: HTTP/2 (представление, правила взаимодействия, безопасность).
- RFC 9114: HTTP/3 (представление, правила взаимодействия, безопасность).
Кроме того, RFC с 8999 по 9002 определяют транспортный уровень QUIC, используемый протоколом HTTP/3.
1.1. Модель транзакций HTTP
Протокол HTTP основан на транзакциях. Это означает, что каждый запрос приводит ровно к одному ответу. Изначально, в версии 1.0, на соединение приходился один запрос: клиент устанавливал соединение TCP с сервером, отправлял по нему запрос, сервер отвечал, после чего соединение закрывалось. Для нового запроса требовалось новое соединение:
В этом режиме, часто называемом «HTTP close», число установок соединений равно числу транзакций HTTP. Поскольку сервер закрывает соединение после ответа, клиенту не нужно знать длину содержимого: он считает ответ завершённым при закрытии соединения. Это также означает, что при обрыве ответа из-за сетевой ошибки клиент мог ошибочно счесть его полным; раньше это иногда приводило к отображению обрезанных изображений.
Транзакционная природа протокола позволила усовершенствовать его, исключив закрытие соединения между двумя последовательными транзакциями. Однако в таком режиме сервер обязан указывать длину содержимого каждого ответа, чтобы клиент не ждал бесконечно. Для этого используется специальный заголовок «Content-length». Этот режим называется «keep-alive» и появился в HTTP/1.1 (его поддерживают некоторые агенты HTTP/1.0), а соединения, повторно используемые между запросами, называются постоянными:
Преимущества — меньшая задержка между транзакциями, меньшие затраты вычислительных ресурсов сервера и возможность обнаруживать обрезанные ответы. Обычно этот режим быстрее режима закрытия соединений, но не всегда: некоторые клиенты ограничивают число одновременных соединений меньшим значением и потому хуже компенсируют низкое качество сети. Кроме того, некоторым серверам приходится долго держать соединения открытыми в ожидании нового запроса, что при большом числе соединений может потреблять много памяти. Слишком быстрое закрытие может нарушить обработку запросов, пришедших в момент закрытия соединения.
В этом режиме размер ответа нужно знать заранее, что не всегда возможно для динамически формируемого или сжатого содержимого. Поэтому был реализован другой режим — «chunked mode». Вместо объявления полного размера отправитель сообщает только размер следующего фрагмента ответа, уже находящегося в буфере, и может завершить передачу в любой момент фрагментом нулевого размера. В этом режиме заголовок Content-Length не используется.
Ещё одно улучшение обмена — конвейерный режим. Он по-прежнему использует постоянные соединения, но клиент не ждёт первого ответа, чтобы отправить второй запрос. Это удобно при загрузке большого числа изображений страницы:
Очевидно, что устранение сетевой задержки между последовательными запросами может значительно повысить производительность. Многие агенты HTTP некорректно поддерживают конвейерную обработку, поскольку HTTP не позволяет явно связать ответ с соответствующим запросом. Поэтому сервер обязан отвечать строго в порядке получения запросов. На практике после нескольких попыток внедрения в разных клиентах от этого режима полностью отказались из-за ненадёжной работы с некоторыми серверами. Однако серверы обязаны его поддерживать.
Следующее усовершенствование — мультиплексирование, реализованное в HTTP/2 и HTTP/3. В этом режиме несколько транзакций, то есть пар «запрос — ответ», передаются параллельно по одному соединению и продвигаются независимо, каждая со своей скоростью. Для описания таких параллельных обменов в одном соединении протоколы с мультиплексированием ввели понятие потока. Каждому потоку обычно назначается уникальный в рамках соединения идентификатор, по которому обе стороны определяют, куда направлять данные. Клиенты довольно часто запускают множество потоков (до 100, иногда больше) параллельно по одному соединению, позволяя серверу обрабатывать их и отвечать в любом порядке по мере готовности ответов. Главное преимущество мультиплексирования — значительное сокращение числа сетевых обменов и ускорение загрузки страниц в сетях с высокой задержкой. Иногда это заметно на сайтах с большим числом изображений, где все изображения будто загружаются одновременно.
Эти протоколы также повысили эффективность за счёт механизмов сжатия полей заголовков, уменьшающих число передаваемых байтов. Поэтому без соответствующих инструментов их практически невозможно обрабатывать вручную или читать невооружённым глазом, как HTTP/1. По этой причине в литературе, включая этот документ, примеры сообщений HTTP продолжают представлять в синтаксисе HTTP/1 даже для новых версий протокола.
У HTTP/2 есть ограничения архитектуры: например, потеря пакетов затрагивает сразу все потоки. Если клиент слишком долго получает объект, например записывает его на диск, он может замедлить получение и тем самым временно сделать недоступными данные, ожидающие за этим объектом. Это называется блокировкой начала очереди — «head of line blocking», «HoL blocking» или просто «HoL».
HTTP/3 реализован поверх QUIC, который, в свою очередь, работает поверх UDP. QUIC устраняет блокировку начала очереди на транспортном уровне за счёт независимой обработки потоков. При потере данных затронутый поток не влияет на остальные, и все потоки доступны параллельно. QUIC также поддерживает миграцию соединений, но в настоящее время haproxy её не поддерживает.
По умолчанию HAProxy использует режим постоянных соединений: для каждого соединения он обрабатывает запросы и ответы и оставляет соединение открытым, но бездействующим с обеих сторон между окончанием ответа и началом следующего запроса. При получении клиентского соединения HTTP/2 он параллельно обрабатывает все запросы и оставляет соединение в ожидании новых, как обычное постоянное соединение HTTP.
В основном HAProxy поддерживает 3 режима соединений:
keep alive: обрабатываются все запросы и ответы, а соединения со стороны клиента и сервера сохраняются для новых запросов. Это режим по умолчанию, подходящий для современного веба и современных протоколов HTTP/2 и HTTP/3.
server close: соединение с сервером закрывается после ответа.
close: после завершения ответа соединение активно закрывается с обеих сторон.
Кроме того, по умолчанию соединение с сервером может повторно использоваться любым запросом любого клиента, как требует спецификация HTTP. Поэтому необходимые сведения о конкретном клиенте, например исходный адрес, нужно передавать с каждым запросом. При использовании HTTP/2 с сервером HAProxy по умолчанию выделяет это соединение одному клиенту, чтобы избежать риска блокировки начала очереди между клиентами.
1.2. Терминология
Терминология HAProxy со временем немного менялась вслед за развитием протокола HTTP и способов его использования. Изначально существенных различий между соединением, сеансом, потоком и транзакцией не было. Со временем понятия уточнили в соответствии с современными версиями HTTP, хотя ради исторической совместимости некоторые термины сохранились в конфигурации и интерфейсе командной строки.
Следующие определения относятся к текущей версии HAProxy:
Соединение: отдельный двунаправленный канал связи между удалённым агентом (клиентом или сервером) и haproxy на самом низком возможном уровне. Обычно это сокет TCP между парой IP-адресов и портов. На клиентской стороне соединения создаются самыми первыми при подключении клиента к haproxy, и правила уровня соединения применяются раньше всех остальных.
Сеанс: добавляет к соединению контекстные сведения, в том числе информацию транспортного уровня (например, ключи TLS) или переменные. Долгое время этот термин в HAProxy обозначал сквозной обмен HTTP/1.0 между двумя сторонами. Поэтому он сохранился в именах некоторых команд CLI и статистических показателей, хотя теперь они представляют потоки; справка и описания стараются устранить неоднозначность. Термин по-прежнему уместен на сетевом уровне (например, сеансы TCP в операционной системе или через межсетевой экран) и в пользовательских приложениях, не использующих HTTP (например, сеанс telnet или SSH). Его нельзя путать с сеансами приложения, которые хранят полный контекст пользователя в cookie и требуют направления запросов на один сервер.
Поток: в точности соответствует сквозному двунаправленному обмену на уровне приложения, где могут применяться анализ и преобразования. В HTTP он содержит один запрос и связанный с ним ответ, создаётся при поступлении запроса и завершается по окончании доставки ответа. В этом контексте между таким потоком и потоком мультиплексируемого протокола существует соответствие 1:1. При обмене по TCP на соединение приходится один поток.
Транзакция: только пара из запроса и связанного с ним ответа. До появления потоков термин использовали вместе с сеансами, но теперь транзакция и поток находятся в отношении 1:1. Главным образом он встречается в области видимости переменных «txn», действующей на протяжении всей транзакции, а значит, и потока.
Запрос: трафик от клиента к серверу. Термин преимущественно используется в HTTP для указания направления выполнения операций. Он также применяется к операциям TCP, обозначая направление обработки данных. Запросы часто используются в счётчиках как единица трафика или активности. Не каждый запрос получает ответ, например из-за ошибок, но поскольку самопроизвольных ответов без запросов не бывает, запросы остаются подходящей мерой общей активности. В TCP число запросов равно числу соединений.
Ответ: трафик от сервера к клиенту, а иногда от HAProxy к клиенту, если HAProxy сам формирует ответ, например перенаправление HTTP.
Служба: обычно внутренняя обработка в HAProxy, не требующая сервера, например страница статистики, кеш или код Lua, реализующий небольшое приложение. Как правило, служба читает запрос, выполняет операции и формирует ответ.
1.3. Запрос HTTP
Сначала рассмотрим следующий запрос HTTP:
1.3.1. Строка запроса
Строка 1 — это строка запроса. Она всегда состоит из 3 полей:
- Метод: GET.
- URI: /serv/login.php?lang=en&profile=2.
- Метка версии: HTTP/1.1.
Все поля разделяются тем, что стандарт называет LWS — линейными пробельными символами. Обычно это пробелы, но возможны также табуляции либо переводы строки/возвраты каретки с последующими пробелами или табуляциями. Сам метод не может содержать двоеточие (’:’) и состоит только из букв алфавита. Из-за множества комбинаций лучше, чтобы HAProxy сам разбивал строку на части, а не заставлял пользователя писать сложное или неточное регулярное выражение.
URI может иметь несколько форм:
- Относительный URI:
- Абсолютный URI, также называемый URL:
Звёздочка (’*’): эта форма разрешена только с методом OPTIONS и не подлежит ретрансляции. Она используется для запроса возможностей следующего узла.
Сочетание адреса и порта: 192.168.0.12:80. Используется с методом CONNECT для установки туннелей TCP через прокси HTTP, обычно для HTTPS, но иногда и для других протоколов.
В относительном URI выделяют две части. Часть до вопросительного знака называется путём. Обычно это относительный путь к статическим объектам на сервере. Часть после вопросительного знака называется строкой запроса. Она в основном используется в запросах GET к динамическим скриптам и сильно зависит от языка, фреймворка или приложения.
HTTP/2 и HTTP/3 не передают сведения о версии вместе с запросом: предполагается версия используемого протокола, например «HTTP/2». Кроме того, эти протоколы не передают строку запроса целиком, а разбивают её на отдельные поля — псевдозаголовки, имена которых начинаются с двоеточия. HAProxy для удобства собирает их в эквивалентную строку запроса. Поэтому строки запросов в журналах могут немного различаться для HTTP/1.x и HTTP/2 или HTTP/3.
1.3.2. Заголовки запроса
Заголовки начинаются со второй строки. В начале строки находится имя, сразу за ним — двоеточие (’:’). Традиционно после двоеточия добавляют LWS, но это не обязательно. Далее идут значения. Несколько одноимённых заголовков можно объединить в одну строку, разделяя значения запятыми и сохраняя их порядок. Это часто встречается в поле «Cookie:». Заголовок может занимать несколько строк, если последующие строки начинаются с LWS. В примере из 1.3 строки 4 и 5 задают суммарно 3 значения заголовка «Accept:». Наконец, согласно спецификации все LWS в начале и конце заголовка игнорируются и не входят в значение.
Вопреки распространённому заблуждению, имена заголовков нечувствительны к регистру. Их значения также нечувствительны к регистру, если ссылаются на имена других заголовков, как в «Connection:». В HTTP/2 и HTTP/3 имена заголовков всегда передаются в нижнем регистре, что видно в режиме отладки. Внутри HAProxy все имена заголовков приводятся к нижнему регистру, чтобы HTTP/1.x и HTTP/2 или HTTP/3 использовали одно и то же представление, и в таком виде передаются другой стороне. Поэтому запрос HTTP/1.x, введённый с именами в смешанном регистре, доставляется с именами в нижнем регистре.
Первая пустая строка обозначает конец заголовков. Часто говорят о двойном переводе строки, что неточно, хотя двойной перевод строки — одна из допустимых форм пустой строки.
К счастью, HAProxy сам обрабатывает все эти сложные сочетания при индексации заголовков, проверке значений и подсчёте. Поэтому об их конкретном оформлении можно не беспокоиться, но важно не обвинять приложение в ошибке, если оно использует необычные, но допустимые конструкции.
Важное примечание:
1.4. Ответ HTTP
Ответ HTTP очень похож на запрос HTTP. И тот и другой называют сообщениями HTTP. Рассмотрим следующий ответ:
Особый случай в HTTP — так называемые информационные ответы с кодами состояния 1xx. Они не содержат никакой части ответа, а служат сигнальными сообщениями, например чтобы попросить клиента продолжить отправку запроса. При коде 100 запрошенные сведения содержатся в следующем после информационного сообщении ответа с кодом, отличным от 100. Это означает, что на один запрос может быть отправлено несколько ответов и что такое возможно только при включённых постоянных соединениях (сообщения 1xx появились в HTTP/1.1). HAProxy умеет корректно пересылать и пропускать эти сообщения, обрабатывая лишь следующий ответ с кодом, отличным от 100. Поэтому такие сообщения не записываются в журнал и не преобразуются, если явно не указано иное. Сообщения с кодом 101 означают смену протокола в том же соединении, и HAProxy должен перейти в туннельный режим, как после CONNECT. Заголовок Upgrade в таком случае содержит дополнительные сведения о протоколе, на который переключается соединение.
1.4.1. Строка ответа
Строка 1 — это строка ответа. Она всегда состоит из 3 полей:
- Метка версии: HTTP/1.1.
- Код состояния: 200.
- Причина: OK.
Код состояния всегда состоит из 3 цифр. Первая обозначает общую категорию:
- 1xx = информационное сообщение, которое следует пропустить (например, 100, 101).
- 2xx = OK, далее следует содержимое (например, 200, 206).
- 3xx = OK, далее содержимого нет (например, 302, 304).
- 4xx = ошибка по вине клиента (например, 401, 403, 404).
- 5xx = ошибка по вине сервера (например, 500, 502, 503).
Коды состояния выше 599 запрещено передавать при обмене, хотя некоторые агенты могут записывать их в журналы для обозначения внутренних состояний. Подробное значение всех кодов описано в RFC9110. В HTTP/2 и новее нет метки версии, а код состояния передаётся в псевдозаголовке «:status».
Поле причины служит лишь подсказкой и не разбирается клиентами. В нём может быть что угодно, но принято использовать общеизвестные сообщения. Оно может состоять из одного или нескольких слов, например «OK», «Found» или «Authentication Required». В HTTP/2 и новее этого поля нет и оно не передаётся. При передаче ответа из HTTP/2 или новее клиенту HTTP/1 HAProxy формирует стандартное поле причины, соответствующее коду состояния.
HAProxy может самостоятельно выдавать следующие коды состояния:
Приведённые выше ответы с кодами ошибок 4xx и 5xx можно настраивать (см. «errorloc» в разделе 4.2 ). Другие коды состояния можно выдавать намеренно с помощью специальных действий (например, «deny», «return» и «redirect» в разделе 4.3 ).
1.4.2. Заголовки ответа
Заголовки ответа устроены точно так же, как заголовки запроса, поэтому HAProxy использует для обоих одну функцию разбора. Подробнее см. пункт 1.3.2.
11 - 2. Настройка HAProxy
2.1. Формат файла конфигурации
Процесс конфигурации HAProxy включает 3 основных источников параметров:
- аргументы из командной строки, которые всегда имеют приоритет
- конфигурационный файл, формат которого описан здесь
- окружение запущенного процесса, в случае если явно указаны переменные среды
Конфигурационный файл следует довольно простому иерархическому формату, который соблюдает несколько базовых правил:
Это всё, что нужно знать, чтобы написать простой, но надёжный генератор конфигурации, но это недостаточно для надёжного парсинга любой конфигурации и для определения того, как обрабатывать определённые крайние случаи.
Во-первых, существуют несколько следствий из вышеуказанных правил. Правило 6 и 7 означает, что ключевые слова, используемые для определения новой секции, действительны повсюду и не могут иметь иного смысла в конкретной секции. Эти ключевые слова всегда являются одним словом (в отличие от последовательности слов), и традиционно секция, следующая за ними, обозначается тем же именем. Например, при упоминании «секции глобального уровня» имеется в виду секция конфигурации, следующая за ключевым словом “global”. Такое обозначение часто используется в сообщениях об ошибках для определения частей, которые необходимо исправить.
Некоторые секции создают внутренний объект или пространство конфигурации, которое необходимо отличать от других. В таких случаях они будут использовать дополнительное слово, устанавливающее имя этой конкретной секции. В некоторых случаях имя секции является обязательным. Например, “frontend foo” создаёт новую секцию типа “frontend” с именем «foo». Обычно имя является специфичным для своей секции, и две секции разных типов могут использовать одно и то же имя, однако это не рекомендуется, поскольку приводит к усложнению управления конфигурацией.
Прямое следствие правила 7 заключается в том, что при одновременном чтении нескольких файлов каждый из них должен начинаться с новой секции, а завершение каждого файла должно завершать соответствующую секцию. Файл не может содержать вложенные секции и не может завершать существующую секцию, чтобы начать новую.
Правило 1 уточняет, что порядок имеет значение. Действительно, некоторые ключевые слова создают директивы, которые могут повторяться несколько раз, чтобы сформировать упорядоченные последовательности правил, применяемых в определённом порядке. Например, “tcp-request” может использоваться для альтернативы правил “accept” и “reject” в зависимости от критериев. Следовательно, обработчик конфигурации должен всегда сохранять порядок секции при редактировании файла. Порядок секций обычно не имеет значения, за исключением глобальной секции, которая должна располагаться перед другими секциями, но может повторяться при необходимости. Кроме того, некоторые автоматические идентификаторы могут автоматически присваиваться некоторым из создаваемых объектов (например, прокси), и при перестановке секций их идентификаторы изменяются. Такие идентификаторы отображаются, например, в статистике. Следовательно, конфигурация ниже присвоит “foo” номер идентификатора, меньший, чем у “bar”. Этот порядок будет изменён, если секции “foo” и “bar” будут переставлены:
Важным моментом является то, что в соответствии с правилами 2 и 3 выше, пустые строки, пробелы, табуляции и
комментарии, следующие за и не защищённым символом “#”, не входят в конфигурацию, поскольку они используются только как разделители. Это означает, что следующие конфигурации строго эквивалентны:
и:
Общая практика — выравнивать слева только ключевое слово, инициирующее новую секцию, и отступать (то есть добавлять символ табуляции или несколько пробелов) все остальные ключевые слова, чтобы было сразу видно, что они относятся к той же секции (как в втором примере выше). Размещение комментариев перед новой секцией помогает читателю определить, является ли это нужной секцией. Оставление пустой строки в конце секции также визуально помогает определить её конец при редактировании.
Табуляция удобна для отступов, но плохо переносится при копировании и вставке. Если вместо неё используются пробелы, рекомендуется ограничиться небольшим числом (от 2 до 4), чтобы редактирование на месте не становилось обременительным в простых редакторах без автоматических отступов.
В ранние времена было обычным видеть аргументы разделяемые на фиксированных позициях табуляции, поскольку большинство ключевых слов принимало не более двух аргументов. В современных версиях, оснащённых сложными выражениями, такая практика больше не актуальна и не рекомендуется.
2.2. Кавычки и экранирование
В современных конфигурациях некоторые аргументы требуют использования некоторых символов, ранее считавшихся чистыми разделителями. Для реализации этого HAProxy поддерживает экранирование символов путём предварительного помещения обратной слеша (’\’) перед символом, который необходимо экранировать, слабое кавычирование текста с помощью двойных кавычек ("") и сильное кавычирование текста с помощью одинарных кавычек (’’).
Это очень похоже на то, что делается в ряде языков программирования и близко к тому, что обычно встречается в Bourne shell. Принцип заключается в следующем: при разборе конфигурации парсер разделяет строки на слова и одновременно учитывает кавычки и обратные слеши для определения того, является ли символ разделителем или является это прямым представлением символа в текущем слове. Обратный слеш удаляется, кавычки удаляются, и оставшееся слово используется как есть в качестве ключа или аргумента.
Если в слове требуется обратный слеш, он должен либо быть экранирован самим собой (то есть двойной обратный слеш), либо быть заключён в сильные кавычки.
Экранирование вне кавычек достигается путём предварительного размещения специального символа перед обратным слешом (’\’):
Кроме того, несколько непечатаемых символов могут быть выведены с помощью их обычного представления на языке C:
Слабое кавычирование достигается за счёт окружения двойных кавычек ("") вокруг символа или последовательности символов для защиты. Слабое кавычирование предотвращает интерпретацию следующего:
Слабое кавычевание позволяет интерпретировать переменные среды (которые не оцениваются вне кавычек) путем предварительного размещения перед ними знака доллара (’$’). Если требуется знак доллара внутри двойных кавычек, он должен быть экранирован с помощью обратной косынки.
Сильное кавычевание достигается путем окружения символа или последовательности символов кавычками (’’). Внутри одинарных кавычек ничего не интерпретируется, это эффективный способ кавычевания регулярных выражений.
В результате, приведена матрица, показывающая, как вводить специальные символы в различных контекстах (непечатаемые символы заменяются на их название в угловых скобках). Примечание, что некоторые символы, которые могут быть представлены только в виде экранирования, не имеют возможного представления внутри одинарных кавычек, поэтому их отсутствие там.
Пример:
Существует один особый случай, когда может потребоваться второе уровневое кавычковое или экранирование. Некоторые ключевые слова принимают аргументы в скобках, иногда разделённые запятыми. Эти аргументы обычно являются целыми числами или заранее определёнными словами, но при наличии произвольных строк может потребоваться отдельное экранирование, чтобы различать символы, принадлежащие аргументу, от символов, используемых для разделения аргументов. Очень распространённый случай — это преобразователь “regsub”. Он принимает регулярное выражение в качестве аргумента, и если внутри требуется закрывающая скобка, то она должна быть экранирована отдельно.
Парсер аргументов ключевых слов идентичен верхнему уровню по вопросам кавычек, за исключением того, что экранирования \#, \$, и \xNN не обрабатываются. Однако то, что не всегда очевидно, заключается в том, что разделители внутри должны быть сначала экранированы или заключены в кавычки, чтобы они не распознавались на верхнем уровне.
Рассмотрим следующий пример, использующий преобразователь “regsub”, который принимает аргументы 3: одно регулярное выражение, строку замены и набор флагов:
Здесь не требовалось специальное кавычевание. Но если сейчас мы хотим заменить либо “foo”, либо “bar” на “blah”, нам потребуется регулярное выражение “(foo|bar)”. Нельзя написать:
потому что мы хотим, чтобы строка была разрезана так:
но на самом деле передаётся строка между открывающей и закрывающей скобками, затем мусор:
Ясное решение здесь состоит в том, что закрывающая скобка должна быть заключена в кавычки, но это сам по себе не сработает, поскольку, как указано выше, кавычки обрабатываются верхним парсером, который разрешит их до обработки этого слова:
Таким образом, мы не изменили ничего в парсере аргументов на втором уровне, который по-прежнему видит обрезанное регулярное выражение как единственный аргумент, и мусор в конце строки. При экранировании кавычек они будут переданы без изменений на второй уровень:
Другой подход заключается в использовании одинарных кавычек снаружи всей строки и двойных кавычек внутри (таким образом, двойные кавычки не удаляются повторно):
Но в этом случае важно отметить, что разделители, встроенные в более высокий уровень строки, остаются чистыми символами и уже не являются разделителями. В частности, это означает, что пробелы и табуляции вокруг запятых являются частью строки. Пример ниже содержит ошибки на нескольких пунктах:
Факт наличия пробелов вокруг запятых привел к тому, что пробелы стали частью самого поля, поэтому преобразователь " regsub" (начинающийся с пробела), который не будет найден и вызовет ошибку, но более тонко, строка замены " blah" вставит пробел в выходные данные. Хорошим правилом является никогда не вставлять ненужные пробелы внутри выражений.
При использовании регулярных выражений может возникнуть ситуация, когда символ доллара (’$’) присутствует в выражении или используется обратный слеш (’\’) в строке замены. В таком случае эти символы будут обработаны внутри двойных кавычек, поэтому предпочтительны одинарные кавычки (или двойное экранирование). Пример:
Помните, что обратные слэши не являются экранирующими символами внутри одинарных кавычек, и что вся указанная выше строка уже защищена от них с помощью одинарных кавычек. Напротив, если бы были использованы двойные кавычки вокруг всего выражения, символ доллара и обратные слэши были бы разрешены на верхнем уровне, что привело бы к разбиению содержимого аргумента на втором уровне.
К сожалению, поскольку одинарные кавычки не могут быть экранированы внутри сильных кавычек, если вам нужно включить одинарные кавычки в аргумент, вам нужно экранировать или кавычить их дважды. Существует несколько способов это сделать:
Когда в сомнении, просто не используйте кавычки вовсе, и начните обрамлять аргументы в одинарные или двойные кавычки, если они требуют запятой или закрывающей скобки, и подумайте о том, чтобы экранировать эти кавычки с помощью обратной кавычки, если строка содержит символ доллара или обратную кавычку. Опять же, это очень похоже на то, что используется в оболочке Bourne при двойной экранировке команды, передаваемой функции “eval”. Для API разработчиков, вероятно, лучше всего обрамлять каждый аргумент в экранированные кавычки, независимо от содержимого. Пользователи, скорее всего, обнаружат, что использование одинарных кавычек вокруг всего выражения и двойных кавычек вокруг каждого аргумента обеспечивает более читаемые конфигурации.
2.3. Переменные окружения
Конфигурация HAProxy поддерживает переменные среды. Эти переменные интерпретируются только в двойных кавычках. Переменные расширяются во время парсинга конфигурации. Названия переменных должны начинаться с символа доллара ("$") и, при необходимости, быть заключёнными в фигурные скобки ("{}"), как это делается в оболочке Bourne. Названия переменных могут содержать алфавитно-цифровые символы или знак подчёркивания ("_"), но не должны начинаться с цифры. Если переменная содержит список нескольких значений, разделённых пробелами, она может быть расширена как отдельные аргументы, заключив переменную в фигурные скобки и добавив суффикс ‘[*]’ перед закрывающей скобкой. Также возможно указать значение по умолчанию, которое будет использоваться при отсутствии переменной, добавив это значение после дефиса (’-’) рядом с именем переменной. Примечание: значение по умолчанию заменяет только несуществующие переменные, а не пустые.
Пример:
Некоторые переменные определяются HAProxy, они могут использоваться в конфигурации. Эти переменные приведены в матрице ниже и классифицируются по четырём категориям:
используемые: переменная доступна в конфигурации, либо может быть разрешена как есть, либо использована в блоках условий или предикатах для включения или отключения некоторых фрагментов конфигурации, как описано в секции 2.4 “Conditional blocks”.
modifiable: переменная может быть переопределена или удалена в конфигурации через “setenv”/“unsetenv”
keywords.listed: переменная присутствует в выводе команды CLI, описанной в секции “show env” section 9.3 “Unix
Sockets commands” руководства по управлению.
Также есть две подкатегории «master» и «worker», соответственно отмеченные ‘M’ и ‘W’ в таблице ниже, демонстрирующие различия между двумя процессами при запуске HAProxy в master-worker режиме.
master: переменная задана и доступна из процесса master. Следовательно, она будет отображаться в
master CLI’s “show env” выводе и может использоваться в условных блоках или директивах для включения
некоторых специальных настроек для master (см. примеры в секции 2.4 “Условные блоки”).worker: переменная задана и доступна из процесса worker. Она будет отображаться в worker
CLI’s “show env” (или в выводе master CLI’s “@1 show env”) и может использоваться для
условного настройки параметров процесса worker (см. примеры из секции 2.4 “Условные блоки”).
В режиме standalone (без опции “-W” и без ключевого слова “master-worker”) процесс ведёт себя как worker,
кроме переменных “HAPROXY_MASTER_CLI” и “HAPROXY_MWORKER”, которые не определены.
Некоторые переменные помечены как недоступные и неизменяемые:
- HAPROXY_CFGFILES
- HAPROXY_MWORKER
- HAPROXY_CLI
- HAPROXY_MASTER_CLI
- HAPROXY_LOCALPEER
При разборе конфигурации их значения не определены: они устанавливаются позднее, на этапе инициализации. Поэтому рекомендуется не использовать эти переменные в условных блоках и не ссылаться на них в директивах “setenv”/“resetenv”/“unsetenv” секции global.
Таблица ниже содержит краткое описание состояния каждой переменной для различных режимов работы:
Речь идёт о следующих переменных:
HAPROXY_LOCALPEER: определяется при запуске процесса и содержит имя локального однорангового узла. См. “-L” в руководстве по управлению.
HAPROXY_CFGFILES: список файлов конфигурации, загруженных HAProxy, разделённых точками с запятой. Полезен, если при запуске был указан каталог.
HAPROXY_HTTP_LOG_FMT: содержит значение формата журнала HTTP по умолчанию, описанного в разделе 8.2.3 “Формат журнала HTTP”. Позволяет переопределить формат журнала по умолчанию без копирования всего исходного определения.
HAPROXY_HTTP_CLF_LOG_FMT: содержит значение формата журнала HTTP CLF по умолчанию, описанного в разделе 8.2.3 “Формат журнала HTTP”. Позволяет переопределить формат журнала по умолчанию без копирования всего исходного определения.
Пример:
HAPROXY_HTTPS_LOG_FMT: аналогичен HAPROXY_HTTP_LOG_FMT, но для формата ведения журнала HTTPS, определенного в
секции 8.2.4 “формат ведения журнала HTTPS”.HAPROXY_TCP_LOG_FMT: аналогичен HAPROXY_HTTP_LOG_FMT, но для формата ведения журнала TCP, определенного в секции
8.2.2 “формат ведения журнала TCP”.HAPROXY_TCP_CLF_LOG_FMT: аналогичен HAPROXY_HTTP_CLF_LOG_FMT, но для TCP CLF формата ведения журнала, определенного
в секции 8.2.2 “TCP формат ведения журнала”.HAPROXY_KEYLOG_FC_LOG_FMT: содержит формат ключевого ведения журнала для фронтенда (клиентской стороны) TLS
соединения, с ключевыми полями, разделенными переносами строк, поэтому он может быть несовместим с вашим сервером ведения журнала syslog. “tune.ssl.keylog on” обязательен.HAPROXY_KEYLOG_BC_LOG_FMT: аналогичен HAPROXY_KEYLOG_FC_LOG_FMT, но для бэкенда
(с сервера) TLS соединения. Ключевые записи разделяются переносами строк, поэтому может не быть совместимы с вашим сервером syslog. “tune.ssl.keylog on” необходим.HAPROXY_MWORKER: В режиме master-worker, эта переменная устанавливается в 1.
HAPROXY_CLI: настроенные адреса слушателей сокета статистики каждого процесса, эти адреса
разделяются точками с запятой.HAPROXY_MASTER_CLI: В режиме master-worker, адреса слушателей главного CLI, разделённые точками с запятой.
HAPROXY_STARTUP_VERSION: содержит версию, использованную при запуске, в режиме master-worker это версия, использованная при запуске главного узла, даже после обновления бинарника и перезагрузки.
HAPROXY_BRANCH: содержит версию ветки HAProxy (например, “2.8”). В ней не содержится полная версия. Может быть полезна при миграции, если ресурсы (например, карты или сертификаты) находятся в пути, содержащем номер ветки.
Кроме того, некоторые псевдопеременные разрешаются внутренне и могут использоваться как обычные переменные.
Псевдопеременные всегда начинаются с точки (’.’), и являются единственными переменными, где разрешение точки допускается.
Текущий список псевдопеременных:
.FILE: имя конфигурационного файла, который сейчас разрешается.
.LINE: номер строки конфигурационного файла, который сейчас разрешается, начиная с единицы.
.SECTION: имя секции, которая сейчас разрешается, или её тип, если секция не имеет имени (например, “global”), или пустая строка до первой секции.
Эти переменные разрешаются на месте их разрешения. Например, если используется переменная “.LINE” в директиве “log-format”, расположенной в секции по умолчанию, её номер строки будет разрешён до разбора и компиляции директивы “log-format”, поэтому этот же номер строки будет повторно использоваться последующими прокси.
Таким образом, возможно передавать информацию для определения местоположения правила в переменных, логах, статусах ошибок, проверках работоспособности, значениях заголовков или даже использовать номера строк для названия некоторых объектов конфигурации, например, серверов.
2.4. Условные блоки
Иногда бывает удобно условно включать или отключать некоторые произвольные части конфигурации, например, включать/отключать SSL или шифры, включать или отключать некоторые слушатели, предназначенные для предварительной эксплуатации, не изменяя конфигурацию, или изменять синтаксис конфигурации для поддержки двух различных версий HAProxy в процессе миграции. HAProxy предоставляет набор вложимых директив, похожих на препроцессор, которые позволяют интегрировать или игнорировать определённые блоки текста. Эти директивы должны располагаться на отдельной строке и действуют на последующие строки. Две из них поддерживают выражение, остальные лишь переключаются на альтернативный блок или завершают текущий уровень. Определены следующие директивы 4 для формирования условных блоков:
- .if
<condition> - .elif
<condition> - .else
- .endif
Директива “.if” вкладывает новый уровень, “.elif” остается на том же уровне, “.else” также остаётся на том же уровне, и
“.endif” закрывает уровень. Каждая “.if” должна быть завершена соответствующей “.endif”. Директива “.elif” может быть размещена только после “.if” или “.elif”, и на число “.elif” в цепочке не налагается ограничений. Можно иметь только одну “.else” на “.if” и она всегда должна находиться после “.if” или последней “.elif” блока.
Комментарии могут быть размещены на той же строке, если необходимо, после ‘#’, они будут проигнорированы. Директивы токенизируются так же, как и другие директивы конфигурации, и, следовательно, возможно использование переменных среды в условиях.
Условия также могут быть оценены при запуске с параметром -cc. См. «3. Запуск HAProxy» в документации по управлению.
Условия могут быть либо пустой строкой (в этом случае возвращается ложь), либо выражением, состоящим из любой комбинации:
- целое нулевое значение (‘0’), всегда возвращает “false”
- ненулевое целое значение (например, ‘1’), всегда возвращает “true”.
- предикат, опционально за которым следует один или несколько аргументов в скобках.
- условие, расположенное между парой скобок ‘(’ и ‘)’
- знак восклицания (’!’), стоящий перед любым из непустых элементов выше, и который отрицает его
статус. - выражения, объединённые с логическим И (’&&’), которые оцениваются слева направо до тех пор,
пока одно из них не вернёт ложь - выражения, объединённые с логическим ИЛИ (’||’), которые оцениваются справа налево до тех пор,
пока одно из них не вернёт истина
Тот же токенизатор строк и парсер аргументов используется, как и в остальной части языка конфигурации.
Слова разделяются вокруг последовательностей одного или более незапятых пробелов или табуляций, и затем
составляются вместе с использованием одного пробела в качестве разделителя перед оценкой, чтобы избежать
необходимости кавычек для всей строки. Однако это означает, что пробелы вокруг запятых или скобок
определённо входят в значение, что не всегда ожидается. Например, выражение ниже:
проверит наличие переменной " HAPROXY_MWORKER " (с пробелами), и это:
сравнивает переменную окружения “ENABLE_SSL” со значением " 1" (с одним ведущим пробелом).
Причина заключается в том, что строка сначала разбивается на слова так:
затем применяется слабое кавычевание и разрешается переменная среды “$ENABLE_SSL” (предположим, что ENABLE_SSL=0), и, наконец, слова собираются в одну строку, разделяя их одним пробелом:
и только тогда он интерпретируется как одно выражение. Пробел, вставленный между запятой и
“1”, остаётся частью значения аргумента, что делает этот аргумент « 1»:
Здесь видно, что даже если ENABLE_SSL был равен “1”, это не совпадало с " 1", поскольку строка отличалась одним пробелом.
Примечание: как объяснено в секции “2.2. Цитирование и экранирование”, хорошим правилом является никогда не вставлять ненужные пробелы внутри выражений.
Примечание, что, как в других языках, оператор И имеет приоритет над оператором ИЛИ, поэтому “A && B || C && D” оценивается как “(A && B) || (C && D)”.
Список поддерживаемых на данный момент предикатов следующий:
awslc_api_atleast(
<ver>): возвращает true, если текущее значение awslc API не старше<ver>, иначе false. Пример: awslc_api_atleast(35)awslc_api_before(
<ver>): возвращает true, если текущий номер awslc API строго старше<ver>иначе false. Пример: awslc_api_before(26)defined(
<name>) : возвращает true, если переменная среды<name>существует, независимо от её
содержимогоfeature(
<name>) : возвращает true, если функция<name>присутствует в списке функций, отчётно предоставленных “haproxy -vv” (что означает, что<name>появляется после ‘+’)openssl_version_atleast(
<ver>): возвращает true, если текущая версия OpenSSL не старше<ver>, в противном случае — false. Библиотеки, такие как LibreSSL, AWS-LC и WolfSSL, также предоставляют псевдо-версию OpenSSL. Пример:
openssl_version_before(
<ver>): возвращает true, если текущая версия OpenSSL строго старше<ver>, иначе false. Библиотеки, такие как LibreSSL, AWS-LC и WolfSSL, также предоставляют псевдоверсию OpenSSL. Пример: openssl_version_before(3.5.0)ssllib_name_startswith(
<name>) : возвращает true, если имя библиотеки HAProxy содержит SSL, начинается с<name>. Пример: ssllib_name_startswith(wolfSSL)streq(
<str1>,<str2>) : возвращает true только в случае равенства двух строкstrneq(
<str1>,<str2>): возвращает true только если две строки различаютсяstrstr(
<str1>,<str2>): возвращает true только если вторая строка содержится в первой.version_atleast(
<ver>): возвращает true, если текущая версия HAProxy не старше<ver>, в противном случае — false. Синтаксис версии совпадает с тем, что показано командой “haproxy -v”, отсутствующие компоненты считаются равными нулю.version_before(
<ver>): возвращает true, если текущая версия HAProxy строго старше<ver>в противном случае — false. Синтаксис версии соответствует тому, что показывает “haproxy -v” и отсутствующие компоненты считаются нулевыми.enabled(
<opt>) : возвращает true, если опция<opt>включена на этапе запуска. Поддерживаются только часть опций:
Пример:
.если определено(HAPROXY_MWORKER) слушать mwcli_px привязка:1111 … .конецесли
.если streq("$HAPROXY_BRANCH",3.1) mworker-max-reloads 5 .конец
.если не равны("$SSL_ONLY",yes) привязка:80 .конец
.если streq("$WITH_SSL",yes) .если feature(OPENSSL) bind:443 ssl crt … .конецесли .конецесли
.если функция(OPENSSL) && (streq("$WITH_SSL",yes) || streq("$SSL_ONLY",yes)) привязка:443 ssl crt …
.конец
.если version_atleast(2.4-dev19) profiling.memory на .конец
.если !feature(OPENSSL) .предупреждение “поддержка SSL обязательна” .конецесли
Четыре другие директивы предоставляются для отображения некоторых состояний:
- .diag “message” : выдавать это сообщение только при включении режима диагностики (-dD)
- .notice “message” : выдавать это сообщение на уровне NOTICE
- .warning “message”: выдавать это сообщение на уровне ПРЕДУПРЕЖДЕНИЕ
- .alert “message” : выдавать это сообщение на уровне ALERT
Сообщения, выдаваемые на уровне предупреждения, могут привести к тому, что процесс не запустится, если “zero-warning” включён. Сообщения, выдаваемые на уровне ALERT, всегда приводят к критической ошибке. Эти сообщения могут быть использованы для обнаружения некоторых неправильных условий и предоставления рекомендаций пользователю.
Пример:
2.5. Формат времени
Некоторые параметры включают значения, представляющие время, такие как тайм-ауты. Эти значения обычно выражаются в миллисекундах (если не указано иное), но могут быть выражены в любой другой единице путём добавления этой единицы к числовому значению. Важно учитывать это, поскольку оно не будет повторяться для каждого ключевого слова. Поддерживаемые единицы:
- us: микросекунды. 1 микросекунда = 1/1000000 секунда
- ms: миллисекунды. 1 миллисекунда = 1/1000 секунда. Это значение по умолчанию.
- s : секунды. 1s = 1000ms
- m : минуты. 1m = 60s = 60000ms
- h : часы. 1h = 60m = 3600s = 3600000ms
- d : дни. 1d = 24h = 1440m = 86400s = 86400000ms
2.6. Формат размера
Некоторые параметры включают значения, представляющие объём, такие как ограничения пропускной способности. Эти значения обычно выражаются в байтах (кроме случаев, когда это явно указано иначе), но могут быть выражены в любой другой единице путём добавления суффикса единицы к числовому значению. Важно учитывать это, поскольку оно не будет повторяться для каждого ключевого слова. Поддерживаемые единицы являются нечувствительными к регистру:
- k: килобайты. 1 килобайт = 1024 байт
- m: мегабайты. 1 мегабайт = 1048576 байт
- g: гигабайты. 1 гигабайт = 1073741824 байт
Оба формата времени и объёма требуют целых чисел; дробная запись не допускается.
2.7. Формат имён карт отображения и ACL
Возможно использовать список шаблонов для карт или ACL. Список шаблонов определяется его именем и может использоваться в разных местах конфигурации. Списки шаблонов делятся на три категории в зависимости от формата имени:
Списки шаблонов, основанные на регулярных файлах: это стандартный случай. Имя файла, абсолютное или относительное, используется как имя. Файл должен существовать иначе возникает ошибка. Однако он может быть пустым. Можно указывать префикс “file@”, но он не входит в идентификатор списка. Имя файла с префиксом или без него ссылается на один и тот же список шаблонов.
Списки шаблонов, основанные на опциональных файлах: имя файла должно предшествовать префиксу “opt@”. Существование файла является опциональным. Если файл существует, его содержимое загружается, но при отсутствии файла не сообщается об ошибке. Префикс не входит в идентификатор списка. Это означает, что для заданного имени файла опциональные файлы и регулярные файлы ссылаются на один и тот же список шаблонов.
Списки шаблонов, основанные на виртуальных файлах: имя служит лишь идентификатором. Оно не ссылается на какой-либо файл. Обязательно использовать префикс “virt@”. Он входит в идентификатор. Следовательно, такие списки не могут смешиваться с другими типами списков.
Виртуальные файлы полезны при полной динамической управлении шаблонами без шаблонов при запуске и при перезагрузке. Опциональные файлы могут использоваться при таких условиях. Однако шаблоны могут сохраняться в файле через внешний скрипт, основанный на команде “show map” CLI, например. Таким образом, возможно сохранять шаблоны при перезагрузке.
Примечание: Даже если это маловероятно, это означает, что регулярные файлы, начинающиеся с “file@”, “opt@” или “virt@”, не могут быть загружены, кроме добавления “./” в начало имени файла (например, “file@./virt@map”).
2.8. Переменные
В конфигурации HAProxy переменные могут использоваться в функциях извлечения образца, преобразователях, log-format
строках или TCP/HTTP действиях. Переменные, охватывающие весь процесс, могут быть определены и доступны во всём жизненном цикле процесса. Некоторые из них имеют более короткий срок существования. Переменные схожи с теми, что встречаются в скриптах на языке shell. Это символическое имя для фрагмента памяти. Размер переменной не ограничен и динамически выделяется. Поэтому их следует использовать с осторожностью, особенно при интенсивном использовании. Однако возможно ограничить максимальное количество памяти, используемое переменными, задав “tune.vars” глобальные параметры.
Переменные должны обозначаться в формате “<scope>.<name>”. Часть <scope> указывает на срок жизни переменной. Часть <name>, находящаяся в области, может содержать только символы ‘a-z’, ‘A-Z’, ‘0-9’ и ‘_’. Она уникальна в этой области, но одинаковое имя в разных областях может использоваться и относится к разным переменным. Поддерживаемые области:
proc : для переменных, известных на протяжении всего жизненного цикла процесса и доступных глобально. Переменные “proc” могут быть изменены с помощью CLI с помощью команд “get var” и “set var”. Они также могут быть установлены в секциях “global” с помощью директив “set-var” и “set-var-fmt”.
sess : для переменных, известных на протяжении всего жизненного цикла сессии. Переменные “sess” являются приватными для сессии, недоступными снаружи и не делятся между сессиями.
txn : для переменных, известных на протяжении всего жизненного цикла транзакции. Переменные “txn” являются приватными для потока, недоступными снаружи и не делятся между потоками.
req : для переменных, известных в процессе обработки запроса для конкретного потока. Переменные “req” доступны с момента создания потока и до первого попытки соединения с сервером. Они являются приватными для потока, недоступными снаружи и не делятся между потоками. Между переменными “req” и “res” нет пересечений вовсе.
res : для переменных, известных во время обработки ответа для конкретного потока. Переменные “res” видны с первого попытки соединения с сервером и до уничтожения потока. Они являются приватными для потока, недоступными снаружи и не делятся между другими потоками. Между переменными “req” и “res” нет никакого пересечения.
check: для переменных, известных во время выполнения проверки работоспособности. “check” переменные являются приватными для проверки работоспособности, недоступными снаружи и не делятся между другими проверками работоспособности. Их можно задавать с помощью специализированных “tcp-check” или “http-check” директив.
В зависимости от контекста, могут использоваться дополнительные области, отражающие родительский поток текущего потока:
psess: то же, что и “sess”, но с использованием сессии родительского потока, если такой имеется.
ptxn : то же, что и “txn”, но с использованием транзакции родительского потока, если такой имеется.
preq : то же, что и “req”, но с использованием родительского потока, если такой имеется. Переменные “preq” доступны только во время обработки запроса родительского потока.
pres : то же, что и “res”, но с использованием родительского потока, если такой имеется. Переменные “pres” доступны только во время обработки ответа родительского потока.
Области, отражающие родительский поток, доступны с момента определения потока. В большинстве случаев отсутствует родительский поток. Однако, если это применимо, такой факт будет явно указан. В настоящее время возможно только извлечение значений переменных, определённых в области родительского потока. Установка или удаление таких переменных невозможны. Обычно дочерний поток выполняет обработку для родительского потока в определённый момент и останавливает его выполнение до завершения операции. Это означает, что родительский поток может быть остановлен на этапе обработки запроса или ответа. В связи с этим, определённые области недоступны из дочернего потока. Например, если запрос подвергается анализу в дочернем потоке, дочерний поток не найдёт переменные в области “pres”, поскольку родительский поток не обрабатывает ответ, и, следовательно, не имеет переменных в его области “res”.
Содержимое переменной является результатом оценки выражения извлечения образца и наследует тип вывода этого выражения. Это важно при использовании переменной, поскольку её тип должен быть совместим с её применением. Например, переменная, содержащая строку, используемая в “add()” преобразователе, должна быть преобразуема в действительное целое число для успешного выполнения. Это особенно актуально при сравнении переменных с статическими значениями. Должен быть использован правильный метод соответствия.
2.9. Форматы адресов
Несколько утверждений в виде «bind», «server», “nameserver” и “log” требует адреса.
Этот адрес может быть доменным именем, IPv4-адресом, IPv6-адресом или ‘’. Адрес ‘’ равен специальному адресу “0.0.0.0” и может использоваться при “bind” или “dgram-bind” для прослушивания всех IPv4-адресов system.The; эквивалент IPv6 — ‘::’.
В зависимости от утверждения, после адреса IP следует порт или диапазон портов. Это обязательное требование для утверждения ‘bind’, необязательное для утверждения ‘server’.
Этот адрес также может начинаться со слэша ‘/’. Он считается из семейства “unix”, и ‘/’ и последующие символы должны быть указаны как путь.
Тип сокета или метод передачи по умолчанию “datagram” или “stream” зависит от конфигурации, указанной для адреса. В самом деле, ‘bind’ и ‘server’ будут использовать тип сокета “stream” по умолчанию, в то время как ’log’, ’nameserver’ или ‘dgram-bind’ будут использовать тип “datagram”.
Опционально, может быть использован префикс для принудительного указания семейства адреса и/или типа сокета и метода передачи.
2.9.1. Префиксы семейств адресов
‘abns@<name>’ после <name> следует абстрактное пространство имен (для Linux только).
‘abnsz@<name>’ после <name> — это нулевое завершающее абстрактное пространство имен (для Linux только).
‘fd@<n>’ после адреса — это файловый дескриптор <n>, наследуемый от родительского процесса. Дескриптор должен быть привязан и может быть уже слушающим или нет.
‘ip@<address>[:port1[-port2]]’ после <address> считается адресом IPv4 или IPv6 в зависимости от синтаксиса. В зависимости от используемого в этом случае утверждения, может быть указан порт или диапазон портов, и это может быть обязательно или не обязательно.
‘ipv4@<address>[:port1[-port2]]’ после <address> всегда считается адресом IPv4. В зависимости от используемого в этом случае утверждения, может быть указан порт или диапазон портов, и это может быть обязательно или не обязательно.
‘ipv6@<address>[:port1[-port2]]’ после <address> всегда считается адресом IPv6. В зависимости от используемого в этом случае утверждения, может быть указан порт или диапазон портов, и это может быть обязательно или не обязательно.
‘sockpair@<n>’ следующий дескриптор — это дескриптор файла подключённого Unix-сокета или сокет-пары. В ходе соединения инициатор создаёт пару подключённых сокетов и передаёт один из них через дескриптор другому концу. Слушатель ожидает получение дескриптора от Unix-сокета и использует его, как если бы это был дескриптор соединения accept(). Должен использоваться с осторожностью.
Ошибки: Этот протокол известен как нестабильный на macOS из-за недостатка в реализации функции sendmsg(2) в macOS. Соединение может не быть корректно принято.
‘unix@<path>’ следующая строка считается сокетом UNIX <path>. этот префикс полезен для объявления пути сокета UNIX, который не начинается слешом ‘/’.
2.9.2. Префиксы типов сокетов
Предыдущие префиксы “адресных семей” также могут быть приставлены для принудительного выбора типа сокета и метода передачи. По умолчанию значение определяется соответствующим утверждением, однако в некоторых случаях пользователь может принудительно задать другое значение. Это касается утверждения “log”, где по умолчанию используется syslog через UDP, но возможно принудительное использование syslog через TCP.
Эти префиксы были разработаны для внутреннего использования и пользователи должны вместо этого использовать алиасы секции “2.9.3 Протокольные префиксы”. Однако такие префиксы могут быть удобны в определённых случаях, например, при использовании наследуемых сокетов, известных по их номеру файлового описателя, в котором адресная семья равна “fd”, а тип сокета должен быть указан явно.
Если пользователи сталкиваются с необходимостью использования этих префиксов для достижения ожидаемого результата, поскольку настройка аналогичного поведения через протокольные префиксы невозможна, они должны сообщить об этом разработчикам.
‘stream+<family>@<address>’ задаёт тип сокета и метод передачи к “stream”.
‘dgram+<family>@<address>’ задаёт тип сокета и метод передачи к “datagram”.
‘quic+<family>@<address>’ задаёт тип сокета к “datagram” и метод передачи к “stream”.
2.9.3. Префиксы протоколов
‘quic4@<address>[:port1[-port2]]’ следующий <address> всегда считается IPv4-адресом, но тип сокета принудительно устанавливается в “datagram”, а метод транспорта — в “stream”. В зависимости от утверждения, использующего этот адрес, может или должен быть указан порт или диапазон портов UDP. Эквивалентно “quic+ipv4@”.
‘quic6@<address>[:port1[-port2]]’ после <address> всегда считается как IPv6-адрес, но тип сокета вынужден быть “datagram”, а метод передачи — “stream”. В зависимости от используемого в этом адресе утверждения, может или должно быть указано UDP порт или диапазон портов. Это эквивалентно “quic+ipv6@”.
’tcp@<address>[:port1[-port2]]’ следующее <address> считается адресом IPv4 или IPv6
в зависимости от синтаксиса, но тип сокета и метод передачи вынуждены быть “stream”. В зависимости от
используемого утверждения с этим адресом, может или должно указываться порт или диапазон портов. Оно считается алиасом ‘stream+ip@’.
’tcp4@<address>[:port1[-port2]]’ после <address> всегда считается как IPv4-адрес
но тип сокета и метод передачи вынуждены быть “stream”. В зависимости от используемого в этом случае утверждения, может или должно быть указано порт или диапазон портов. Рассматривается как алиас ‘stream+ipv4@’.
’tcp6@<address>[:port1[-port2]]’ после <address> всегда считается как IPv6-адрес
но тип сокета и метод передачи вынуждены быть “stream”. В зависимости от используемого в этом случае утверждения, может или должно быть указано порт или диапазон портов. Рассматривается как алиас ‘stream+ipv4@’.
‘mptcp@<address>[:port1[-port2]]’ после <address> считается как IPv4 или IPv6-адрес в зависимости от синтаксиса, но тип сокета и метод передачи вынуждены быть “stream”, с протоколом MPTCP. В зависимости от используемого в этом случае утверждения, может или должно быть указано порт или диапазон портов.
‘mptcp4@<address>[:port1[-port2]]’ после <address> всегда считается адресом IPv4, но тип сокета и метод передачи вынуждены быть “stream”, с протоколом MPTCP.
В зависимости от используемого в этом адресе утверждения, может или должно быть указано порт или диапазон портов.
‘mptcp6@<address>[:port1[-port2]]’ после <address> всегда считается адресом IPv6, но тип сокета и метод передачи вынуждены быть “stream”, с протоколом MPTCP.
В зависимости от используемого в этом адресе утверждения, может или должно быть указано порт или диапазон портов.
‘udp@<address>[:port1[-port2]]’ после <address> считается адресом IPv4 или IPv6 в зависимости от синтаксиса, но тип сокета и метод передачи вынуждены быть “datagram”. В зависимости от используемого в этом адресе утверждения, может или должно быть указано порт или диапазон портов. Оно считается алиасом ‘dgram+ip@’.
‘udp4@<address>[:port1[-port2]]’ после <address> всегда считается адресом IPv4, но тип сокета и метод передачи вынуждены быть “datagram”. В зависимости от используемого в этом адресе утверждения, может или должно быть указано порт или диапазон портов. Оно считается алиасом ‘dgram+ipv4@’.
‘udp6@<address>[:port1[-port2]]’ после <address> всегда считается адресом IPv6, но тип сокета и метод передачи вынуждены быть “datagram”. В зависимости от используемого в этом адресе утверждения, может или должно быть указано порт или диапазон портов. Оно считается алиасом ‘dgram+ipv4@’.
‘uxdg@<path>’ после строки считается unix-сокетом <path>, но метод передачи вынужден быть “datagram”. Оно считается алиасом ‘dgram+unix@’.
‘uxst@<path>’ после строки считается unix-сокетом <path>, но метод передачи вынужден быть “stream”. Оно считается алиасом ‘stream+unix@’.
В будущих версиях могут быть использованы другие префиксы для указания протоколов, как QUIC, который предлагает передачу на основе сокета типа “datagram”.
2.10. Примеры
Предполагая, что HAProxy находится в $PATH, проверяйте эти конфигурации в терминале с:
12 - 5. Параметры bind и server
Ключи “bind”, “server” и “default-server” поддерживают ряд настроек, зависящих от некоторых опций сборки и от системы, на которой был собран HAProxy. Эти настройки в целом состоят из одного слова, иногда сопровождаемого значением, записанным на той же строке, что и строка “bind” или “server”. Все эти опции описаны в этой секции.
5.1. Параметры bind
Ключ “bind” поддерживает определённое количество настроек, которые передаются как аргументы на той же строке. Порядок, в котором эти аргументы приводятся, не имеет значения, при условии, что они находятся после адреса привязки. Все эти параметры являются необязательными. Некоторые из них состоят из одного слова (логические значения), в то время как другие ожидает значение после них. В этом случае значение должно быть указано немедленно после имени настройки.
Текущие настройки, поддерживаемые в данный момент, следующие.
accept-netscaler-cip <magic number>
Обязательно используется протокол вставки IP-адреса клиента NetScaler при любом соединении, принятом любым из сокетов TCP, объявленных на той же строке. Протокол вставки IP-адреса клиента NetScaler определяет использование адресов слоя 3/4 входящего соединения во всех случаях, где используется адрес, с единственным исключением — правила “tcp-request connection”, которые увидят только реальный адрес соединения. В логах будут отражаться адреса, указанные в протоколе, за исключением случаев нарушения, в которых будет использоваться реальный адрес. Данное ключевое слово в сочетании с поддержкой внешних компонентов может быть использовано как эффективное и надежное решение в качестве альтернативы механизму X-Forwarded-For, который не всегда надежен и не всегда может быть использован. См. также “tcp-request connection expect-netscaler-cip” для более тонкой настройки того, какие клиенты могут использовать протокол.
accept-proxy
Требует использования протокола PROXY для любого соединения, принятого любым сокетом, объявленным в той же строке. Версии 1 и 2 протокола PROXY поддерживаются и корректно определяются. Протокол PROXY задаёт адреса уровня 3/4 входящего соединения, которые используются везде, где требуется адрес, за единственным исключением правил “tcp-request connection”: они видят только реальный адрес соединения. В журналах отражаются адреса, указанные в протоколе, если только он не нарушен; при нарушении используется реальный адрес. Эта директива совместно с поддержкой внешних компонентов может эффективно и надёжно заменять механизм X-Forwarded-For, который не всегда надёжен и даже не всегда применим. Для более точного определения клиентов, которым разрешено использовать протокол, см. также “tcp-request connection expect-proxy”.
allow-0rtt
Разрешает приём ранних данных при использовании TLSv1.3. По соображениям безопасности эта возможность по умолчанию отключена. Она уязвима к атакам повторного воспроизведения, поэтому её следует разрешать только для запросов, которые безопасно повторять, то есть идемпотентных запросов. Для любого запроса, небезопасного при использовании ранних данных, можно применять действие “wait-for-handshake”. Для QUIC режим 0rtt поддерживается с QuicTLS, OpenSSL >= 3.5.2 и AWS-LC. Для TCP/TLS режим 0rtt поддерживается только с OpenSSL и требует передачи ALPN клиентом; иначе ранние данные не рассматриваются до выполнения рукопожатия.
alpn <protocols>
Это включает расширение TLS ALPN и объявляет указанный список протоколов как поддерживаемый в дополнение к ALPN. Список протоколов состоит из запятой-разделённого списка названий протоколов, например:
“http/1.1,http/1.0” (без кавычек). Это требует, чтобы библиотека SSL была собрана с включённой поддержкой
расширений TLS (проверьте с помощью haproxy -vv). Расширение ALPN заменяет инициальное расширение NPN. На уровне протокола требуется ALPN для включения HTTP/2 на фронтенде HTTPS и HTTP/3 на фронтенде QUIC. Однако, когда такие фронтенды не имеют установленных значений “npn”, “alpn” и “no-alpn”, будет использован по умолчанию значение “h2,http/1.1” для обычного фронтенда HTTPS и “h3” для фронтенда QUIC. Версии OpenSSL до 1.0.2 не поддерживали ALPN и использовали теперь устаревшее расширение NPN. В момент написания этого текста большинство браузеров всё ещё поддерживают оба протокола ALPN и NPN для HTTP/2, поэтому переключение на NPN может продолжаться ещё некоторое время. Однако следует использовать ALPN в любом случае. Протоколы, не объявленные в списке, не договариваются. Например, возможно принять только соединения HTTP/2 с помощью этого:
QUIC поддерживает только h3 и hq-interop как ALPN. h3 предназначен для HTTP/3 и hq-interop используется для http/0.9 и QUIC interop runner (см. https://interop.seemann.io ). Каждое утверждение “alpn” заменяет предыдущее. Для их удаления используйте “no-alpn”.
Примечание, что некоторые старые браузеры, такие как Firefox 88, ранее испытывали проблемы с WebSocket через H2, и в случае такого настроения может потребоваться явно отключить HTTP/2 в строке “alpn”, установив её в “http/1.1” или “no-alpn”, или включить “h2-workaround-bogus-websocket-clients” глобально.
backlog <backlog>
Устанавливает размер очереди сокета в указанное значение. Если значение не указано или 0, используется значение очереди фронтенда, что в целом по умолчанию соответствует значению maxconn.
ca-file <cafile>
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он указывает на файл PEM, из которого загружаются сертификаты CA, используемые для проверки сертификата клиента. Возможна загрузка каталога, содержащего несколько CA, в этом случае HAProxy попытается загрузить каждый “.pem”, “.crt”, “.cer” и .crl в каталоге, файлы, начинающиеся с точки, игнорируются.
Предупреждение: Параметр “@system-ca” может быть использован вместо cafile для использования доверенных CA системы, как это делается с директивой server. Но его использование не рекомендуется, если вы не понимаете, что делаете. Настройка таким образом означает, что подключение будет принимать любой сертификат клиента, сгенерированный на одном из CA, находящихся на вашей системе, что является чрезвычайно небезопасным.
ca-ignore-err [all|<errorID>,...]
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Устанавливает запятую разделённый список errorIDs для игнорирования при проверке на глубине > 0. Может быть числовым идентификатором или именем константы (X509_V_ERR), доступным в документации OpenSSL:
https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES
Рекомендуется использовать имя константы, так как числовое значение может изменяться в новых версиях OpenSSL. При установке в ‘all’ игнорируются все ошибки. SSL если ошибка игнорируется, сессия рукопожатия не завершается.
ca-sign-file <cafile>
Этот параметр доступен только тогда, когда в HAProxy включена поддержка OpenSSL. Он обозначает файл PEM, содержащий как сертификат доверенного центра (CA), так и приватный ключ этого центра, используемый для создания и подписи сертификатов серверов. Этот параметр является обязательным при включении динамической генерации сертификатов. См. ‘generate-certificates’ для подробностей.
ca-sign-pass <passphrase>
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Это пароль от приватного ключа CA. Параметр является необязательным и используется только при включении динамической генерации сертификатов. См. ‘generate-certificates’ для подробностей.
ca-verify-file <cafile>
Этот параметр указывает на файл PEM из которого загружаются сертификаты CA, используемые для проверки сертификата клиента. Он указывает на сертификаты CA, которые не должны содержаться в названиях CA, передаваемых в сообщении server hello. Обычно “ca-file” должен быть задан сертификатами промежуточных узлов, а “ca-verify-file” — сертификатами, завершающими цепочку, такими как корневой CA.
cc <algo>
Этот параметр доступен только на системах, которые определяют TCP_CONGESTION, и был протестирован на Linux и FreeBSD. Он принимает имя алгоритма управления перегрузкой TCP и настраивает слушатель на использование этого алгоритма для всех соединений, принимаемых через данный слушатель. Типичные имена включают “reno”, “cubic” и зависят от операционной системы. На некоторых системах для настройки определённых алгоритмов могут потребоваться специальные разрешения. На Linux список доступных алгоритмов можно найти в sysctl “net.ipv4.tcp_available_congestion_control”, а список разрешённых без привилегий — в “net.ipv4.tcp_allowed_congestion_control”. Для доступа к алгоритмам, требующим дополнительных разрешений, может потребоваться возможность “cap_net_admin” (см. “setcap” в глобальной секции). В случае неудачи при настройке конкретного алгоритма управления перегрузкой используется значение по умолчанию, и выводится предупреждение, сообщающее об ошибке. См. также: ключевое слово сервера “cc” ( секция 5.2 ). Пример:
ciphers <ciphers>
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он задаёт строку, описывающую список алгоритмов шифрования (“cipher suite”), которые участвуют в обмене во время SSL/TLS-рукопожатия до TLSv1.2. Формат строки определён в документации “man 1 ciphers” от OpenSSL. Для дополнительной информации и рекомендаций см. например,
(https://wiki.mozilla.org/Security/Server_Side_TLS
) и
(https://mozilla.github.io/server-side-tls/ssl-config-generator/
). Для настройки алгоритмов шифрования в TLSv1.3, см. ключевое слово “ciphersuites”.
ciphersuites <ciphersuites>
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена, и использовалась версия OpenSSL 1.1.1 или новее. Он задаёт строку, описывающую список алгоритмов шифрования (“комплект шифрования”), которые устанавливались во время обмена TLSv1.3. Формат строки определён в разделе “ciphersuites” в документации OpenSSL “man 1 ciphers”. Для настройки шифрования в TLSv1.2 и более ранних версиях, см. ключевое слово “ciphers”. Этот параметр может принимать комплекты шифрования TLSv1.2, однако это неофициальное поведение и не рекомендуется, так как может быть нестабильным или багоносным. По умолчанию OpenSSL использует следующие комплекты шифрования TLSv1.3: “TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”
TLSv1.3 поддерживает только 5 симметрических ключей:
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_CCM_SHA256
- TLS_AES_128_CCM_8_SHA256
Пример:
client-sigalgs <sigalgs>
Этот параметр доступен только тогда, когда в HAProxy был включён поддержка OpenSSL. Он задаёт строку, описывающую список алгоритмов подписи, связанных с аутентификацией клиента, которые согласовываются. Формат строки определён в «man 3 SSL_CTX_set1_client_sigalgs» из страниц справки OpenSSL. Не рекомендуется использовать этот параметр, если не было идентифицировано конкретного сценария использования.
crl-file <crlfile>
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Он обозначает файл PEM из которого необходимо загрузить список отмены сертификатов, используемый для проверки сертификата клиента. Для каждого сертификата вашей цепочки сертификатов доверия необходимо предоставить список отмены сертификатов.
crt <cert>
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL.
HAProxy использует систему кэширования, файлы загружаются только один раз в хранилище сертификатов, и каждый последующий ключ “crt” будет использовать эту кэшированную версию. Когда сертификат указан в виде “crt-store”, хранилище сертификатов заполняется из этого источника и не пытается загружать дополнительные файлы путём определения расширений файлов.
Он обозначает файл PEM, содержащий необходимые сертификаты и любые связанные приватные ключи.
Этот файл может быть создан путём конкатенации нескольких файлов PEM в один (например, cat cert.pem key.pem > combined.pem). Если ваша СА требует промежуточного сертификата, его также можно конкатенировать в этот файл. Промежуточный сертификат также может быть размещён в каталоге через директиву “issuers-chain-path”.
Если файл не содержит приватного ключа, HAProxy попытается загрузить ключ по тому же пути, дополненному суффиксом “.key”.
Если в используемом OpenSSL поддерживается Diffie-Hellman, параметры, присутствующие в этом файле, загружаются.
Если вместо файла PEM используется имя каталога, то все файлы, найденные в этом каталоге, будут загружены в алфавитном порядке, за исключением тех, названия которых заканчиваются на ‘.key’, ‘.issuer’, ‘.ocsp’ или ‘.sctl’ (зарезервированные расширения). Файлы, начинающиеся с точки, также игнорируются. Данная директива может быть указана несколько раз для загрузки сертификатов из нескольких файлов или каталогов. Сертификаты будут представлены клиентам, предоставляющим действительное поле TLS Server Name Indication, соответствующее одному из их CN или альтернативных подъектов. Поддерживаются шаблоны, где символ ‘*’ используется вместо первого компонента имени хоста (например, *.example.org соответствует www.example.org , но не www.sub.example.org ). Если используется пустой каталог, HAProxy не запустится, если не используется ключевое слово “strict-sni”.
Если клиент не предоставляет SNI или если библиотека SSL не поддерживает расширения TLS, или если клиент предоставляет имя хоста SNI, которое не соответствует никакому сертификату, то будет представлен первый загруженный сертификат. Это означает, что при загрузке сертификатов из каталога крайне рекомендуется загружать по умолчанию один как файл или обеспечивать, чтобы он всегда был первым в каталоге. Для выбора нескольких по умолчанию сертификатов (1 rsa и 1 ecdsa), существуют 3 опции:
- Многосертификатный пакет может быть настроен как первый сертификат (
crt foobar.pemв конфигурации, где существующие файлы являютсяfoobar.pem.ecdsaиfoobar.pem.rsa). - Или фильтр ‘*’ для каждого сертификата в строке crt-list.
- Можно использовать ключевое слово ‘default-crt’.
Примечание, что один и тот же сертификат может быть загружен несколько раз без побочных эффектов.
Некоторые CA (например, GoDaddy) предлагают выпадающий список типов серверов, в котором HAProxy не включён при получении сертификата. Если такое происходит, убедитесь, что выбран тип веб-сервера, который по мнению CA требует промежуточного CA (для GoDaddy выбор Apache Tomcat обеспечит правильный пакет, в то время как многие другие, например nginx, приводят к неправильному пакету, который не будет работать для некоторых клиентов).
Для каждого файла PEM HAProxy проверяет наличие файла по тому же пути, дополняемого суффиксом “.ocsp”. Если такой файл найден, поддержка расширения запроса статуса сертификата TLS (также известного как «OCSP stapling») включается автоматически. Содержимое этого файла является необязательным. Если оно не пустое, оно должно содержать действительный ответ OCSP в формате DER. Для того чтобы ответ OCSP был действительным, он должен соответствовать следующим правилам: он должен указывать хороший статус, должен быть единственным ответом на сертификат файла PEM и должен быть действительным в момент добавления. Если эти правила не соблюдены, ответ OCSP игнорируется и выдается предупреждение. Для определения того, к какому сертификату относится ответ OCSP, необходим сертификат издающего. Если сертификат издающего не найден в файле PEM, он будет загружен из файла по тому же пути, что и файл PEM, дополняемого суффиксом “.issuer”, если такой файл существует, иначе будет выдано сообщение об ошибке.
Для каждого файла PEM HAProxy также проверяет наличие файла по тому же пути, дополняемого суффиксом “.sctl”. Если такой файл найден, поддержка расширения прозрачности сертификатов (RFC6962) TLS включается. Файл должен содержать действительный список подписанного времени сертификата, как описано в RFC. Файл анализируется для проверки базовой синтаксической корректности, но подписи не проверяются.
В некоторых случаях желательно поддерживать несколько типов ключей, например, RSA и ECDSA в наборах шифров, предлагаемых клиентам. Это позволяет клиентам, поддерживающим сертификаты на основе EC, использовать шифры на основе EC, при этом одновременно поддерживать более старые клиенты, RSA только.
Для достижения этого требуется OpenSSL 1.1.1. Это поведение можно настроить путём указания одного записи crt на каждый тип сертификата или настройкой «пакета сертификатов», как это требовалось ранее в HAProxy 1.8. См. “ssl-load-extra-files”.
crt-ignore-err <errors>
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Устанавливает запятую разделённый список errorIDs для игнорирования при проверке на уровне == 0. Может быть числовое значение или имя константы (X509_V_ERR), доступное в документации OpenSSL:
https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES
Рекомендуется использовать имя константы, так как числовое значение может изменяться в новых версиях OpenSSL. При установке в ‘all’ игнорируются все ошибки. SSL ручной обмен не прерывается, если ошибка игнорируется.
crt-list <file>
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он обозначает список PEM файла с опциональной конфигурацией ssl и фильтром SNI на каждый сертификат, с следующим форматом для каждой строки:
Пустые строки, а также строки, начинающиеся с символа решётки (’#’), будут игнорироваться.
Фронтенд crt-list может быть изменён динамически через сокет статистики. (См. “add ssl crt-list”, “del ssl crt-list”, “show ssl crt-list” в руководстве по управлению).
crt-list обычно являются отдельными файлами, однако каталог, загруженный с помощью директивы “crt”, представляется внутренне как crt-list. Директива “ssl-f-use” в фронтенде также объявляет crt-list, связанную с этим фронтенда.
crtfile:
sslbindconf:
snifilter:
Пример:
default-crt <cert>
Этот параметр выполняет то же самое, что и параметр “crt”, с тем отличием, что этот сертификат будет использоваться и как по умолчанию. Возможна добавление нескольких сертификатов по умолчанию, чтобы иметь один ECDSA и один RSA, но наличие большего количества не является особенно полезным.
Этот параметр не отключает скрытые по умолчанию сертификаты; если сертификат ‘crt’ указан первым, до любого ‘default-crt’ или других ‘crt’, он всё ещё будет использоваться как сертификат по умолчанию.
Используется стандартный сертификат, когда в строке bind не указано “strict-sni”. Стандартный сертификат предоставляется тогда, когда расширение servername не использовалось клиентом, или когда значение servername не совпадает с настроенным сертификатом.
Пример:
См. также ключевое слово “crt”.
curves <curves>
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он задаёт строку, описывающую список алгоритмов эллиптических кривых (“набор кривых”), которые устанавливаются в ходе SSL/TLS-обмена с ECDHE. Формат строки — это список названий кривых, разделённых двоеточием. Пример: “X25519:P-256” (без кавычек). При задании “curves” параметр “ecdhe” игнорируется.
defer-accept
Является опциональным ключевым словом, поддерживающимся только на определённых ядрах Linux. Оно означает, что соединение будет принято только после поступления каких-либо данных на него, или в худшем случае — после первого повторного передачи. Это следует использовать только для протоколов, в которых клиент говорит первым (например, HTTP). Оно может немного улучшить производительность, обеспечивая, что большая часть запроса уже доступна к моменту принятия соединения. С другой стороны, оно не сможет обнаруживать соединения, в которых клиент не говорит. Важно отметить, что данная опция не работает в всех ядрах до 2.6.31, поскольку соединение никогда не принимается до того, как клиент начнёт говорить. Это может привести к проблемам с передовыми фильтрами, которые увидят установленное соединение, в то время как прокси увидит его только в SYN_RECV. Данная опция поддерживается только для сокетов TCPv4/TCPv-6 и игнорируется другими.
ecdhe <named curve>
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Он задаёт имя кривой (RFC 4492), используемой для генерации ECDH временных ключей. По умолчанию используется кривая prime256v1.
ech <dir> [ EXPERIMENTAL ]
Применяйте все ключи ECH из <dir> к строке привязки. Файлы должны иметь расширение .ech и должны использовать формат файла PEM для ECH. ( https://datatracker.ietf.org/doc/draft-farrell-tls-pemesni/
)
Этот ключ включает ECH в режиме shared. при работе HAProxy как конца TLS и как конца ECH. См. https://datatracker.ietf.org/doc/draft-ietf-tls-esni/
Это экспериментальная функция, которая требует опции “expose-experimental-directives” в секции global. Она также требует версии OpenSSL, поддерживающей ECH (https://github.com/openssl/openssl/tree/feature/ech ), и HAProxy должен быть скомпилирован с USE_ECH=1. Функция ECH API в AWS-LC не поддерживается.
Пример:
expose-fd listeners
Этот параметр применим только к сокету статистики. Он предоставляет сокету статистики возможность передавать файловые описатели слушателей в другой процесс HAProxy. В режиме master-worker такая передача уже не требуется, файловые описатели слушателей передаются через внутренние сокет-пары между мастером и рабочими процессами. См. также “-x” в руководстве по управлению.
force-sslv3
Этот параметр обеспечивает использование только SSLv3 для соединений SSL, созданных из этого слушателя. SSLv3 в целом менее затратен, чем соответствующие варианты TLS, при высокой интенсивности соединений. Данный параметр также доступен в глобальном утверждении “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.
force-tlsv10
Этот параметр обеспечивает использование только TLSv1.0 на соединениях SSL, созданных из этого слушателя. Данный параметр также доступен в глобальном утверждении “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.
force-tlsv11
Этот параметр обеспечивает использование только TLSv1.1 на соединениях SSL, созданных из этого слушателя. Данный параметр также доступен в глобальном утверждении “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.
force-tlsv12
Этот параметр обеспечивает использование TLSv1.2 только на соединениях SSL, созданных из этого слушателя. Данный параметр также доступен в глобальном утверждении “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.
force-tlsv13
Этот параметр обеспечивает использование TLSv1.3 только на соединениях SSL, созданных из этого слушателя. Данный параметр также доступен в глобальном утверждении “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.
generate-certificates
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он включает динамическое создание SSL
сертификатов. Необходимо наличие сертификата CA и его приватного ключа (см. ‘ca-sign-file’).
Когда HAProxy настроен как прозрачный прокси, SSL запросы генерируют ошибки из-за несоответствия имени общего имени в сертификате, представленном клиенту. При включении данного параметра HAProxy пытается создать сертификат, используя имя хоста SNI, указанное клиентом. Это происходит только в случае, если нет сертификата, соответствующего имени хоста SNI (см. ‘crt-list’).
В случае ошибки при создании сертификата соединение переключается на стандартный сертификат. При использовании ‘strict-sni’ стандартный сертификат не используется и соединение приводит к сбою рукопожатия.
Данный параметр также может использоваться при настройке HAProxy как обратного прокси для упрощения развёртывания архитектуры с множеством бэкендов.
Создание SSL сертификата — дорогостоящая операция, поэтому используется LRU кэш для хранения сгенерированных сертификатов (см. ’tune.ssl.ssl-ctx-cache-size’). Это увеличивает потребление памяти HAProxy с целью сокращения задержки при многократном использовании одного сертификата.
gid <gid>
Устанавливает группу сокетов UNIX на указанный системный идентификатор группы. Этот параметр также может быть задан по умолчанию в утверждении секции “unix-bind” глобальной секции. Примечание: на некоторых платформах этот параметр игнорируется. Данное настройка эквивалентно настройке “group”, за исключением того, что используется идентификатор группы вместо её имени. Данное настройка игнорируется для не UNIX сокетов.
group <group>
Устанавливает группу сокетов UNIX на указанную системную группу. Она также может быть задана по умолчанию в утверждении секции global “unix-bind”. Примечание, что на некоторых платформах эта настройка игнорируется. Эта настройка эквивалентна настройке “gid”, за исключением того, что используется имя группы вместо её идентификатора. Эта настройка игнорируется для не UNIX сокетов.
guid-prefix <string>
Генерируйте уникальные и чувствительные к регистру идентификаторы для каждого слушателя, выделенного на данной строке привязки.
Предфикс будет сконкатенирован к индексу позиции слушателей на текущей строке привязки, с использованием символа ‘-’ в качестве разделителя. См. описание ключевого слова “guid” прокси для получения дополнительной информации о его формате. См. также “shm-stats-file”.
id <id>
Исправляет идентификатор сокета. По умолчанию идентификаторы сокетов автоматически присваиваются, но в некоторых случаях удобнее их фиксировать для упрощения мониторинга. Значение должно быть строго положительным и уникальным в пределах слушателя/фронтенда. Данное опция может быть использована только при определении единственного сокета.
idle-ping <delay>
Может использоваться в следующих контекстах: tcp, http, log
Задаёт интервал периодической проверки работоспособности простаивающих соединений фронтенда. Если другая сторона не отвечает до следующей запланированной проверки, соединение закрывается. Иначе тайм-аут клиента обновляется, а соединение сохраняется. Учтите: таймеры http-request/http-keep-alive работают параллельно и не обновляются через idle-ping.
Для этой возможности требуется поддержка нижележащего протокола. Пока она реализована только в мультиплексоре H2. Остальные протоколы просто игнорируют idle-ping.
Параметр особенно полезен при использовании обратного HTTP. Его указание в строке bind полезно для узла, который активно устанавливает соединения, а затем получает по ним входящий трафик.
interface <interface>
Ограничивает сокет до определённого интерфейса. При указании сокет обрабатывает только пакеты, полученные с указанного интерфейса. Данный функционал доступен только на Linux. Интерфейс должен быть первичным системным интерфейсом, а не алиасированным интерфейсом. Возможна привязка нескольких фронтендов к одному адресу, если они привязаны к разным интерфейсам. Примечание: привязка к сетевому интерфейсу требует прав root. Данный параметр совместим только с сокетами TCPv4/TCPv6. При указании, выходной трафик использует тот же интерфейс, что и входной трафик, и соответствующую таблицу маршрутизации, даже если настроены явные маршруты через другие интерфейсы. Это может быть полезно для устранения проблем асимметричной маршрутизации, когда одинаковые IP-адреса клиентов должны быть способны доставлять запросы к фронтендам, размещённым на разных интерфейсах.
ktls <on|off> [ EXPERIMENTAL ]
Включает или отключает ktls для соответствующих сокетов. При включении kTLS будет использоваться, если ядро поддерживает это и шифрование совместимо. Доступно только для ядра Linux 4.17 и выше. Примечание: некоторые сетевые драйверы и/или TLS стеки могут ограничивать использование kTLS только для TLS v1.2. См. также “force-tlsv12”.
label <label>
Устанавливает опциональную метку для этих сокетов. Может быть использован для группировки сокетов по метке, независимо от того, где были объявлены строки bind.
level <level>
Этот параметр используется только с сокетами статистики для ограничения характера команд, которые можно отправить по сокету. Он игнорируется другими сокетами. <level> может принимать одно из следующих значений:
- “user” — наименее привилегированный уровень; допускается только чтение нечувствительных статистик, изменений не допускается. Подходит для систем, где ограничение доступа к сокету затруднено.
- “operator” — стандартный уровень и подходит для большинства распространённых случаев. Допускается чтение всех данных, разрешены только нечувствительные изменения (например, очистка максимальных счётчиков).
- “admin” следует использовать с осторожностью, так как разрешены все действия (например, очистка всех счётчиков).
maxconn <maxconn>
Ограничивает сокеты количеством одновременных соединений. Дополнительные соединения остаются в очереди системы до того, как соединение будет освобождено. Если не указано иное, ограничение будет таким же, как у фронтенда maxconn. Примечание: в случае диапазонов портов или нескольких адресов одинаковое значение будет применено к каждому сокету. Эта настройка позволяет устанавливать различные ограничения для дорогостоящих сокетов, например SSL записей, которые могут легко занять всю память.
mode <mode>
Устанавливает восьмеричный режим, используемый для определения разрешений доступа к сокету UNIX. Этот параметр также может быть задан по умолчанию в команде “unix-bind” секции глобальной конфигурации. Примечание: на некоторых платформах этот параметр просто игнорируется. Данное настройка игнорируется для не UNIX сокетов.
mss <maxseg>
Задаёт значение максимального размера сегмента (MSS) для TCP, которое будет объявляться при входящих соединениях. Это может использоваться для принудительного установления меньшего MSS для определённых портов, например, при соединениях, проходящих через VPN. Обратите внимание, что эта функция зависит от функции ядра, которая теоретически поддерживается в Linux, но была нестабильной во всех версиях до 2.6.28. Она может не работать на других операционных системах. Также возможно, что значение не изменится, но изменится эффективный размер исходящих сегментов. Обычно объявляемое значение TCPv4 в сетях Ethernet составляет 1460 = 1500(MTU) - 40(IP+TCP). Если это значение положительное, оно будет использоваться как объявляемое MSS. Если отрицательное — оно указывает, на сколько следует уменьшить объявляемое MSS входящего соединения для исходящих сегментов. Этот параметр совместим только с сокетами TCP v4/v6.
name <name>
Устанавливает опциональное имя для этих сокетов, которое будет отображаться на странице статистики.
namespace <name>
На Linux возможно указать, к какому сетевому пространству принадлежит сокет. Эта директива позволяет явно привязать слушатель к пространству имен, отличному от стандартного. См. документацию операционной системы для получения дополнительной информации о сетевых пространствах имен.
nbconn <nbconn> [ EXPERIMENTAL ]
Этот параметр действует только для экземпляров слушателей, использующих обратный HTTP. Он определяет количество соединений, которые будут размещаться параллельно. Если параметр не указан, используется значение по умолчанию 1.
Обратный HTTP в настоящее время всё ещё находится на стадии активного развития. Механизм конфигурации может измениться в будущем. Поэтому он внутренне помечен как экспериментальный, что означает, что “expose-experimental-directives” должен быть указан на строке перед этим директивой.
nice <nice>
Устанавливает «дружелюбность» соединений, инициируемых из сокета. Значение должно находиться в диапазоне -1024..1024
включительно и по умолчанию равно нулю. Положительные значения означают, что такие соединения более дружелюбны к другим и легко предоставляют место в планировщике. Напротив, отрицательные значения означают, что соединения хотят работать с более высоким приоритетом по сравнению с другими. Разница проявляется только при высоких нагрузках, когда система приближается к насыщению. Отрицательные значения подходят для служб с низкой задержкой или администрирования, а высокие значения в целом рекомендуются для CPU интенсивных задач, таких как SSL обработка или массовые передачи, которые менее чувствительны к задержке. Например, может быть оправдано использование положительного значения для сокета SMTP и отрицательного значения для сокета RDP.
no-alpn
Отключает обработку ALPN (с технической точки зрения это устанавливает строку ALPN в пустую, которая не будет объявляться). Это позволяет отменить предыдущее значение настройки “alpn” и отключить переговоры по протоколу приложения. Может также использоваться для предотвращения переговоров ALPN с клиентом на слушателе HTTPS или QUIC; по умолчанию слушатели HTTPS объявляют “h2,http/1.1” и слушатели QUIC — “h3”. См. также “alpn” выше. Примечание: при использовании “crt-list” сертификат может перекрыть настройку “alpn” и включить повторную обработку.
no-ca-names
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Он предотвращает отправку имён СА в сообщении сервера hello при использовании ca-file. Используйте “ca-verify-file” вместо “ca-file” с “no-ca-names”.
no-sslv3
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку SSLv3 на любых сокетах, создаваемых из слушателя, при наличии SSL. Примечание: поддержка SSLv2 принудительно отключена в коде и не может быть включена с помощью настроек конфигурации. Этот параметр также доступен в глобальном утверждении “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
no-strict-sni
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает strict-sni внедрение из предыдущего директивы “strict-sni”. Может быть необходим для селективного отключения использования strict-sni на строке “bind”, когда оно уже было глобально включено через “ssl-default-bind-options”. См. также опцию привязки “strict-sni”.
no-tls-tickets
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает состояние-независимое восстановление сессии (RFC 5077 TLS Ticket extension) и вынуждает использовать состояние-зависимое восстановление сессии. Состояние-независимое восстановление сессии более затратно в CPU использовании. Этот параметр также доступен в глобальном утверждении “ssl-default-bind-options”. Механизм TLS ticket используется только до TLS 1.2. Прямая безопасность нарушается при использовании TLS тикетов, если ключи тикетов не периодически пересылаются (через перезагрузку или с помощью “tls-ticket-keys”).
no-tlsv10
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку TLSv1.0 на любых сокетах, создаваемых из слушателя, при наличии поддержки SSL. Примечание: SSLv2 выключена в коде и не может быть включена с помощью любого параметра конфигурации. Этот параметр также доступен в глобальном утверждении “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
no-tlsv11
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку TLSv1.1 на любых сокетах, создаваемых из слушателя, при наличии поддержки SSL. Примечание: SSLv2 принудительно отключена в коде и не может быть включена с помощью любого параметра конфигурации. Этот параметр также доступен в глобальном утверждении “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
no-tlsv12
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку TLSv1.2 на любых сокетах, создаваемых из слушателя, при наличии поддержки SSL. Примечание: SSLv2 выключена в коде и не может быть включена с помощью любого параметра конфигурации. Этот параметр также доступен в глобальном утверждении “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
no-tlsv13
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку TLSv1.3 на любых сокетах, создаваемых из слушателя, при наличии поддержки SSL. Примечание: SSLv2 принудительно отключена в коде и не может быть включена с помощью любого параметра конфигурации. Этот параметр также доступен в глобальном утверждении “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
npn <protocols>
Это включает расширение NPN TLS и объявляет указанный список протоколов как поддерживаемый в дополнение к NPN. Список протоколов состоит из запятой-разделённого списка названий протоколов, например:
“http/1.1,http/1.0” (без кавычек). Требуется, чтобы библиотека SSL была собрана с включённой поддержкой расширений TLS (проверьте с помощью haproxy -vv). Примечание, что расширение NPN было заменено расширением ALPN (см. ключевое слово “alpn”), хотя последнее доступно только начиная с OpenSSL 1.0.2. Если требуется поддержка HTTP/2 на более ранней версии OpenSSL, возможно, всё ещё можно использовать NPN, поскольку большинство клиентов по-прежнему поддерживают его на момент написания этого текста. Возможна одновременная включение как NPN, так и ALPN, хотя, вероятно, это не имеет смысла при тестировании.
prefer-client-ciphers
Используйте предпочтения клиента при выборе набора шифров, по умолчанию предпочтения сервера применяются. Эта опция доступна также в глобальном утверждении “ssl-default-bind-options”.
Примечание: при использовании OpenSSL >= 1.1.1 ChaCha20-Poly1305 автоматически приоритизируется (без настройки данного параметра), если шифр ChaCha20-Poly1305 находится на вершине списка шифров клиента.
При использовании настройки с двумя алгоритмами (RSA + ECDSA) алгоритм выбора будет выбирать между RSA и ECDSA и всегда будет приоритизировать ECDSA. После выбора правильного сертификата, библиотека SSL будет приоритизировать шифры, кривые и т.д. Следовательно, данный параметр не может быть использован для приоритизации сертификата RSA над сертификатом ECDSA.
proto <name>
Обязательно заставляет мультиплексер использовать протокол для входящих соединений. Он должен быть совместим с режимом фронтенда (TCP или HTTP). Он также должен быть применим с точки зрения фронтенда. Список доступных протоколов приведён в haproxy -vv.. Свойства протоколов приведены: режим (TCP/HTTP), сторона (FE/BE), имя мультиплексера и его флаги.
Некоторые протоколы подвержены блокировке на стороне сервера (флаг=HOL_RISK). Наконец, некоторые протоколы не поддерживают обновление (флаг=NO_UPG). Также отображается совместимость HTX (флаг=HTX).
Вот протоколы, которые могут использоваться в качестве аргумента директивы “proto” на строке bind:
Понятие за счёт этого параметра — обойти выбор оптимального протокола мультиплексера для всех соединений, создаваемых из этого слушающего сокета. Например, возможно принудительно задать протокол http/2 на прозрачном канале TCP, указав “proto h2” в строке привязки.
Если настроены параметры ALPN или NPN, указанные протоколы должны быть совместимы с протоколом мультиплексера, чтобы избежать проблем. Например, если задан “proto h1”, то ALPN не должен быть установлен в значение “h2”.
QMux — подмножество QUIC, работающее над TCP. Оно соответствует следующему черновому протоколу https://www.ietf.org/archive/id/draft-ietf-quic-qmux-01.html . На данный момент оно считается экспериментальным в HAProxy.
quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]
Это QUIC специфичное настройка для выбора алгоритма контроля перегрузки для любых попыток соединения к настроенным QUIC слушателям. Они аналогичны тем, которые используются в TCP.
Пакетирование активируется поверх алгоритма перегрузки для снижения потерь и повышения пропускной способности. Его можно отключить с помощью глобального ключевого слова “tune.quic.fe.tx.pacing”. В большинстве случаев пакетирование должно оставаться включённым, особенно при использовании BBR, поскольку оно зависит от него для корректной работы. Использование BBR без пакетирования может привести к замедлению или высокой доле потерь при передаче.
Значение по умолчанию: cubic
Для дополнительной настройки можно указать список параметров после токена алгоритма. Он должен быть записан между скобками, разделёнными запятой. Каждый аргумент является необязательным и может быть пустым, если необходимо. Ниже приведён обязательный порядок параметров:
- максимальный размер окна в байтах. Должен превышать 10 кб и быть меньше 4 гб. По умолчанию
“tune.quic.fe.cc.max-win-size” значение используется.
Пример:
Значение «nocc» может быть использовано для принудительного установления окна перегрузки в фиксированном режиме, при котором оно всегда будет равно максимальному размеру. Оно предназначено исключительно для случаев отладки с целью исключения любых побочных эффектов, вызванных контроллером перегрузки. Оно не должно использоваться в производственной среде, поскольку может быстро привести к сетевым проблемам, таким как высокий уровень потерь.
quic-force-retry
Специальный параметр QUIC, принудительно включающий QUIC Retry для всех попыток подключения к настроенным слушателям QUIC. Он проверяет, способны ли удалённые узлы получать пакеты по транспортному адресу, с которого они начали новое соединение: им отправляется пакет Retry с токеном. Токен должен быть возвращён отправителю Retry, поскольку только тот может проверить его. Учтите, что QUIC Retry будет использоваться всегда, даже если задан порог Retry (см. “tune.quic.fe.sec.retry-threshold”).
Для этого параметра должен быть задан секрет кластера, иначе при запуске будет выдана ошибка (см. “cluster-secret”).
Дополнительные сведения о QUIC retry см. в https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2 .
quic-socket [ connection | listener ]
Этот QUIC специфический настройка позволяет определить режим распределения сокетов для конкретных слушателей.
См. “tune.quic.fe.sock-per-conn” для полного описания преимуществ и недостатков каждого режима.
Эта настройка применяется в сочетании с глобальным опцией “tune.quic.fe.sock-per-conn”. Если
режим “default-on” активен на глобальном настройке (это значение по умолчанию), каждое соединение QUIC
использует свой собственный сокет, за исключением слушателей с “quic-socket listener”. Однако, если глобальный
режим установлен в “force-off”, настройка отдельных слушателей будет игнорироваться.
severity-output <format>
Этот параметр используется только с сокетами статистики для настройки уровня серьёзности, добавляемого к информационным сообщениям о ответах. Уровень серьёзности сообщений может варьироваться от 0 до 7, в соответствии с rfc5424. Запросы к сокетам, которые успешно требуют данных (например, “show map”, “get acl foo” и т.д.), никогда не получают добавленного уровня серьёзности. Другие сокеты игнорируют этот параметр. <format> может быть одним из следующих:
- “none” (по умолчанию) к сообщениям не добавляется уровень серьёзности.
- “number” уровень серьёзности добавляется как число.
- “string” уровень серьёзности добавляется как строка в соответствии с конвенцией rfc5424.
shards { <number> | by-thread | by-group }
В режиме многопоточности на операционных системах, поддерживающих несколько слушателей на один IP:порт, автоматически создаются такое же количество идентичных слушателей для одной строки, все привязанные к равномерному распределению количества потоков, присоединённых к этому слушателю. Это может быть полезно при использовании очень больших количеств потоков, когда блокировка на уровне ядра для одного сокета начинает вызывать значительную нагрузку. В этом случае входящий трафик распределяется по нескольким сокетам, а конкуренция снижается. Примечание: выполнение этого может легко увеличить использование CPU за счёт того, что больше потоков работают немного.
Если количество шардов превышает количество доступных потоков, оно автоматически будет сокращено до количества потоков (то есть один шард на поток). Специальное значение «by-thread» также создаёт столько шардов, сколько потоков на строке “bind”. Поскольку система равномерно распределяет входящий трафик между всеми этими шардами, важно, чтобы это число было целым делителем количества потоков. Альтернативно, другое специальное значение «by-group» создаёт один шард на группу потоков. Это может быть полезно при работе с большим количеством потоков и желании избежать создания слишком большого числа сокетов. Распределение нагрузки будет немного менее оптимальным, но конкуренция (особенно в системе) всё ещё будет ниже, чем при использовании одного сокета.
На операционных системах, не поддерживающих несколько сокетов, привязанных к одному адресу, «by-thread» и «by-group» автоматически переходят к одному шарду. Для «by-group» это делается без предупреждения, поскольку это не меняет ничего в случае одной группы, и сокеты всё равно будут дублироваться для каждой группы. Однако для «by-thread» при этом будет выдано диагностическое предупреждение, поскольку итоговое количество слушателей не будет соответствовать ожидаемому.
sigalgs <sigalgs>
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он задаёт строку, описывающую список алгоритмов подписи, устанавливаемых во время переговоров TLSv1.2 и TLSv1.3. Формат строки определён в «man 3 SSL_CTX_set1_sigalgs» из справочной документации OpenSSL. Использование этого параметра не рекомендуется, если не требуется совместимость с промежуточным устройством.
ssl
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он включает расшифровку SSL на соединениях, создаваемых из этого слушателя. Необходим сертификат (см. “crt” выше). Все содержимое в буферах будет отображаться в открытом виде, поэтому ACLs и обработка HTTP будут иметь доступ только к расшифрованному содержимому. Поддержка SSLv3 отключена по умолчанию; для включения используйте “ssl-min-ver SSLv3”.
ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
Этот параметр обеспечивает использование <version> или ниже на соединениях SSL, создаваемых из этого слушателя.
Использование этого настройки без “ssl-min-ver” может быть неясным, поскольку значение по умолчанию ssl-min-ver может измениться в будущих версиях HAProxy. Этот параметр также доступен в глобальном утверждении “ssl-default-bind-options”. См. также “ssl-min-ver”.
ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
Этот параметр обеспечивает использование <version> или выше на соединениях SSL, создаваемых из этого слушателя.
Значение по умолчанию — “TLSv1.2”. Этот параметр также доступен в глобальном утверждении “ssl-default-bind-options”. См. также “ssl-max-ver”.
strict-sni
Этот параметр доступен только при включённой поддержке OpenSSL. Согласование SSL/TLS разрешено только в том случае, если клиент предоставил SNI, соответствующий сертификату. По умолчанию сертификат не используется. Этот параметр также позволяет запускаться без сертификата на строке bind, поэтому может использоваться пустая директория, которая позже будет заполнена через статический сокет. Этот параметр также доступен в глобальном блоке “ssl-default-bind-options” и может быть отключён по отдельности на строке “bind” с помощью “no-strict-sni”. Дополнительную информацию см. в опции “crt”. См. команду “add ssl crt-list” в руководстве по управлению.
tcp-md5sig <password>
Включает подпись TCP MD5 (RFC 2385 Защита сессий BGP через опцию подписи TCP MD5) для всех входящих соединений, инициированных из этого прослушиваемого сокета. Эта опция доступна только на Linux. При включении используется строка <password> для подписи каждого сегмента TCP с помощью 16-байтового MD5 хэша. Это обеспечивает защиту соединения TCP от фальшивизации. Основное применение этой опции — защита BGP от введения фальшивых сегментов TCP в поток соединения. Однако она может быть полезна для любых очень долговременных соединений TCP.
tcp-ss <mode>
Задаёт параметр TCP Save SYN для всех входящих соединений, создаваемых этим прослушивающим сокетом. Он доступен в Linux начиная с версии 4.3 и предписывает ядру попытаться сохранить копию входящего пакета IP с флагом TCP SYN для последующего анализа через функцию извлечения образцов “fc_saved_syn”. Поддерживаются 3 режима: 0 — сохранение пакета SYN отключено, это значение по умолчанию; 1 — сохранение пакета SYN включено, сохраняются заголовки IP и TCP; 2 — сохранение пакета SYN включено, сохраняются заголовки ETH, IP и TCP.
Это работает только для обычных соединений TCP и игнорируется для других протоколов (например, UNIX сокетов).
См. также “fc_saved_syn”.
tcp-ut <delay>
Устанавливает тайм-аут пользователя TCP для всех входящих соединений, создаваемых из этого слушающего сокета. Опция доступна на Linux с версии 2.6.37. Позволяет HAProxy настроить тайм-аут для сокетов, содержащих данные, не получающие подтверждения в течение заданного периода. Особенно полезна в случае долговременных соединений с длительными периодами бездействия, таких как удалённые терминалы или пулы соединений с базами данных, где тайм-ауты клиента и сервера должны быть высокими, чтобы допускать длительный период бездействия, но при этом важно обнаруживать исчезновение клиента для освобождения всех ресурсов, связанных с его соединением (и сессией сервера). Аргумент — задержка, выраженная в миллисекундах по умолчанию. Работает только для обычных TCP соединений и игнорируется для других протоколов.
tfo
Является опциональным ключевым словом, поддерживающимся только на ядрах Linux >= 3.7. Включает TCP Fast Open на слушающем сокете, что означает, что клиенты, поддерживающие данную функцию, смогут отправлять запрос и получать ответ в ходе 3-стороннего рукопожатия, начиная с второго соединения, тем самым экономя один круг-проход после первого соединения. Это имеет смысл только в протоколах с высокой интенсивностью соединений, где каждый круг-проход имеет значение. Это может привести к проблемам с большинством фильтров, которые не принимают данные в SYN пакетах, поэтому данное опция следует включать только после тщательного тестирования. Данная опция поддерживается только для сокетов TCPv4/TCPv6 и игнорируется для других типов сокетов. Возможно, потребуется собрать HAProxy с USE_TFO=1, если ваша libc не определяет TCP_FASTOPEN.
thread [<thread-group>/]<thread-set>[,...]
Это ограничивает список потоков, на которых разрешено запускать данный слушатель. Оно не обеспечивает выполнение ни одного из них, но исключает те, которые не соответствуют. Оно ограничивает потоки, разрешённые для обработки входящих соединений для данного слушателя.
Существует два схемы нумерации. По умолчанию номера потоков являются абсолютными в процессе и варьируются от 1 до значения, указанного в global.nbthread. Также возможно указать номер потока с помощью его относительного номера внутри группы потоков, указав сначала номер группы потоков, затем слэш (’/’) и относительный номер потока(ов). В этом случае номера потоков также начинаются с 1 и заканчиваются на 32 или 64 в зависимости от платформы. При указании абсолютных номеров потоков они автоматически переводятся в относительные номера после того, как известны группы потоков. Обычно для простых конфигураций предпочтительны абсолютные номера, а для сложных конфигураций, где CPU расстановка имеет значение для производительности, — относительные.
После необязательного номера группы потоков формат спецификации «множества потоков» должен быть следующим:
Как их названия подразумевают, «все» проверяет все потоки в наборе (все потоки группы при наличии группы или все потоки процесса), “odd” проверяет все нечётные потоки (каждый второй поток, начиная с 1) либо для процесса, либо для группы, и “even” проверяет все чётные потоки (каждый второй поток, начиная с 2). Если вместо этого используются диапазоны номеров потоков, то проверяются все потоки, включённые в диапазон от первого до последнего номера потока. Номера могут быть относительными к группе или абсолютными в зависимости от наличия номера группы потоков. Если первый номер потока не указан, используется “1”, представляющий либо первый поток группы, либо первый поток процесса. Если последний номер потока не указан, используется либо последний номер потока группы (32 или 64), либо последний номер потока процесса (global.nbthread).
Такие диапазоны могут повторяться и разделяться запятой, чтобы можно было указывать несмежные наборы потоков, и при этом группа, если она присутствует, должна указываться заново для каждого нового диапазона. Примечание: разрешено не смешивать относительных и абсолютных обозначений, поскольку вся строка “bind” должна использовать либо абсолютную, либо относительную запись, так как неустановленные значения будут разрешены в конце парсинга.
Важно понимать, что каждый слушатель, описанный строкой “bind”, создаёт как минимум один сокет, представленный как минимум одним файловым описателем. Поскольку файловые описатели не могут охватывать несколько групп потоков, если строка “bind” указывает диапазон потоков, охватывающий более одной группы, автоматически создаются несколько файловых описателей, чтобы для каждой группы был хотя бы один. Технически все они ссылаются на один и тот же сокет в ядре, но они получат отдельный идентификатор в HAProxy и даже будут иметь отдельную запись в статистике, если используется “option socket-stats”.
Основная цель — иметь несколько строк bind, использующих одинаковый IP:порт, но разные потоки в слушателе, чтобы система могла распределять входящие соединения по нескольким очередям, обходя внутреннюю балансировку нагрузки очередей HAProxy. В настоящее время поддержка такой конфигурации известна для Linux 3.9 и выше. См. также ключевое слово “shards”, описанное выше, которое автоматически дублирует строки “bind” и присваивает их нескольким группам потоков.
Этот ключевое слово совместим с обратными HTTP привязками. Однако запрещено указывать набор потоков, охватывающий несколько групп потоков для такого слушателя, поскольку это может привести к тому, что “nbconn” не работает как задумано.
tls-tickets
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он включает механизм Stateless session resumption (RFC 5077 TLS Ticket extension). Он является стандартным, но может потребоваться для целенаправленного включения этой функции на строке “bind”, если она была глобально отключена через “no-tls-tickets”, упомянутую в “ssl-default-bind-options”. См. также параметр bind “no-tls-tickets”.
tls-ticket-keys <keyfile>
Устанавливает файл ключей TLS для загрузки ключей. Ключи должны быть длиной 48 или 80 байт,
в зависимости от того, используется aes128 или aes256, закодированные с помощью base64, один ключ на строку (например, OpenSSL rand 80 | OpenSSL base64 -A | xargs echo). Первый ключ определяет длину ключа, используемую для последующих ключей: нельзя смешивать ключи aes128 и aes256. Количество ключей задаётся опцией сборки TLS_TICKETS_NO (по умолчанию 3) и в файле должно быть не менее такого количества ключей. Последние TLS_TICKETS_NO ключей будут использоваться для дешифровки, а предпоследний — для шифрования. Это позволяет легко выполнять вращение ключей, просто добавляя новые ключи в файл и перезагружая процесс. Ключи должны периодически вращаться (например, каждые 12h), иначе нарушается совершенная передача секретности. Также рекомендуется хранить ключи вне любых постоянных носителей, таких как жесткие диски (см. подсказку: использовать tmpfs и не использовать обменные файлы). Срок службы может быть изменён с помощью tune.ssl.timeout.
transparent
Является опциональным ключевым словом, поддерживающимся только на определённых версиях ядра Linux. Оно указывает на то, что адреса будут привязаны даже в случае, если они не принадлежат локальной машине, и пакеты, направляемые к этим адресам, будут перехвачены так же, как если бы эти адреса были настроены локально. Обычно требуется включение пересылки IP-пакетов. Внимание! не используйте это в сочетании с стандартным адресом ‘*’, иначе произойдёт перенаправление всего трафика на указанном порту. Это ключевое слово доступно только при сборке HAProxy с USE_LINUX_TPROXY=1. Этот параметр совместим только с сокетами TCPv4 и TCPv6, в зависимости от версии ядра. Некоторые дистрибутивы ядер включают бэкпорт данной функции, поэтому проверьте поддержку у поставщика.
uid <uid>
Устанавливает владельца сокетов UNIX в указанный идентификатор пользователя системы. Этот параметр также может быть задан по умолчанию в утверждении секции “unix-bind” глобальной секции. Примечание: на некоторых платформах этот параметр игнорируется. Этот параметр эквивалентен параметру “user”, за исключением того, что используется числовое значение идентификатора пользователя вместо его имени. Этот параметр игнорируется для не UNIX сокетов.
user <user>
Устанавливает владельца сокетов UNIX для указанного системного пользователя. Этот параметр также может быть задан по умолчанию в утверждении секции глобальной “unix-bind”. Примечание: на некоторых платформах этот параметр просто игнорируется. Этот параметр эквивалентен настройке “uid”, за исключением того, что используется имя пользователя вместо его идентификатора. Этот параметр игнорируется для не UNIX сокетов.
v4v6
Является опциональным ключевым словом, поддерживающимся только на наиболее новых системах, включая ядра Linux >=
2.4.21. Используется для привязки сокета к как IPv4, так и к IPv6 при использовании стандартного адреса. Такая настройка иногда необходима на системах, которые по умолчанию привязываются только к IPv6. Не оказывает влияния на сокеты, не относящиеся к IPv6, и подавляется опцией “v6only”.
v6only
Является опциональным ключевым словом, поддерживающимся только на последних системах, включая ядра Linux >=
2.4.21. Используется для привязки сокета к IPv6 только в случае использования адреса по умолчанию. Такое действие иногда предпочтительнее выполнения системно в целом, поскольку оно действует на уровне слушателя. Не влияет на сокеты, не относящиеся к IPv6, и имеет приоритет перед опцией “v4v6”.
verify [none|optional|required]
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Если установлено значение ’none’, запрос сертификата клиента не требует. Это значение по умолчанию. В остальных случаях требуется сертификат клиента. Если клиент не предоставляет сертификат после запроса и если ‘verify’ установлено в ‘required’, то рукопожатие прерывается, в то время как оно успешно завершится, если значение установлено в ‘optional’. Сертификат, предоставляемый клиентом, всегда проверяется с помощью ЦА из ‘ca-file’ и опциональных CRL из ‘crl-file’. При неудаче проверки рукопожатие прерывается независимо от значения ‘verify’, если ошибка не соответствует ни одному из кодов ошибок, перечисленных в ‘ca-ignore-err’ или ‘crt-ignore-err’.
5.2. Параметры server и default-server
Ключевые слова “server” и “default-server” поддерживают определённое количество настроек, которые передаются как аргументы на строке сервера. Порядок, в котором эти аргументы приводятся, не имеет значения, и они все являются необязательными. Некоторые из этих настроек — одиночные слова (логические значения), в то время как другие ожидает один или несколько значений после них. В этом случае значения должны сразу следовать за названием настройки. В случае использования всех настроек, кроме default-server, они должны быть указаны после адреса сервера:
Примечание: все эти настройки поддерживаются как для “server”, так и для “default-server”, за исключением “id”, который поддерживается только для “server”.
На данный момент поддерживаются следующие настройки.
addr <ipv4|ipv6>
Допустимые контексты: tcp, http, log
Используя параметр “addr”, становится возможным отправку проверок работоспособности или пробы на agent-check с другого IP-адреса. На некоторых серверах может быть желательно выделить IP-адрес для конкретного компонента, способного выполнять сложные тесты, более подходящие для проверок работоспособности, чем приложение. Параметр игнорируется, если параметр “check” не задан. См. также параметр “port”.
agent-check
Допустимые контексты: tcp, http, log
Включить проверку работоспособности вспомогательного агента, выполняемую независимо от обычной проверки работоспособности. Проверка работоспособности агента осуществляется путём установления соединения TCP на порт, заданный параметром “agent-port”, и чтения строки ASCII, завершающейся первым вхождением ‘\r’ или ‘\n’. Строка состоит из ряда слов, разделённых пробелами, табуляциями или запятыми в любом порядке, каждое из которых состоит из:
Представление ASCII положительного целого процента, например, “75%”. Значения в этом формате будут
устанавливать вес пропорционально начальному весу сервера, заданному при запуске HAProxy.
Примечание: нулевой вес отображается на странице статистики как “DRAIN”, поскольку он оказывает одинаковое влияние на сервер (сервер удаляется из группы балансировки). Это устаревший способ установки веса сервера.
Рекомендуется использовать установку с префиксом “weight:”.Строка “weight:” за которой следует положительное целое число или положительное целое число в процентах, без пробела. Если значение заканчивается знаком ‘%’, то новый вес будет пропорционален первоначальному весу сервера. В противном случае значение считается абсолютным весом и должно находиться в диапазоне 0 до 256. Серверы, входящие в ферму, работающую по статическому алгоритму балансировки нагрузки, имеют более жесткие ограничения, поскольку вес не может изменяться после установки. Таким образом, для этих серверов допускаются только значения 0 и 100% (или 0 и первоначальный вес). Изменения вступают в силу немедленно, хотя некоторые алгоритмы балансировки нагрузки требуют определённого количества запросов, чтобы учесть изменения. Примечание: нулевой вес отображается на странице статистики как “DRAIN”, поскольку он оказывает такое же влияние на сервер (сервер удаляется из фермы балансировки нагрузки).
Строка “maxconn:” за которой следует целое число (без пробела). Значения в таком формате устанавливают
параметр maxconn сервера. Максимальное количество соединений, объявленное в этом параметре, должно быть умножено на
количество балансировщиков нагрузки и различных бэкендов, использующих эту проверку работоспособности, чтобы получить
общее количество соединений, которое может получить сервер. Пример: maxconn:30Слово “ready”. Это изменит административное состояние сервера на режим READY, тем самым
отменяя любые состояния DRAIN или MAINTСлово “drain”. Это изменит административное состояние сервера на режим DRAIN, тем самым
он не будет принимать новые соединения, кроме тех, которые принимаются через сохранение соединения.Слово “maint”. Это установит административное состояние сервера в режиме MAINT, таким образом, он не будет принимать никакие новые соединения, и проверки работоспособности будут остановлены.
Слова “down”, “fail” или “stopped”, опционально сопровождаемые описательной строкой после знака решетки (’#’). Все эти слова указывают на состояние работы сервера как DOWN, но поскольку само слово отображается на странице статистики, различие позволяет администратору понять, было ли это ожидаемым или нет: сервис может быть намеренно остановлен, может быть в состоянии “up”, но не проходить некоторые проверки работоспособности, или может быть отмечен как “down” (например, отсутствует процесс, или порт не отвечает).
Слово “up” устанавливает состояние работы сервера как UP, если проверки работоспособности также сообщают, что сервис доступен.
Параметры, которые не объявляются агентом, не изменяются. Например, агент может быть спроектирован для мониторинга CPU и отчётности только о относительном весе, не взаимодействуя с состоянием работы. Аналогично, агент может быть спроектирован как интерфейс для конечного пользователя с 3 кнопками радио, позволяющими администратору изменять только административное состояние. Однако важно учитывать, что только сам агент может отменить свои действия, поэтому если сервер установлен в режим DRAIN или в состояние DOWN с помощью агента, то агент должен реализовать другие эквивалентные действия для возврата сервиса в рабочее состояние.
Невозможность подключения к агенту не считается ошибкой, поскольку подключение проверяется через регулярную проверку работоспособности, включаемую с помощью параметра “check”. Предупреждение: не рекомендуется останавливать агент после того, как он сообщает «down», поскольку только агент, отчётно сообщающий «up», сможет включить сервер. Примечание: CLI на Unix-сокете статистики также может принудительно установить результат агента для обхода ошибочного агента, если это необходимо.
Требуется установить параметр “agent-port”. См. также параметры “agent-inter” и “no-agent-check”.
agent-send <string>
Допустимые контексты: tcp, http, log
Если указано это опция, HAProxy отправит заданную строку (без изменений) агенту серверу при соединении. Например, можно закодировать имя бэкенда в эту строку, что позволит агенту отправлять разные ответы в зависимости от бэкенда. Убедитесь, что включена строка ‘\n’, если вы хотите завершить запрос символом переноса строки.
agent-inter <delay>
Допустимые контексты: tcp, http, log
Параметр “agent-inter” задаёт интервал между двумя проверками агента в <delay> миллисекунд. Если параметр не указан, задержка по умолчанию равна 2000 ms.
Так же, как и для любого другого параметра, зависящего от времени, значение может быть указано в любой из явных единиц: { us, ms, s, m, h, d }. Параметр “agent-inter” также служит тайм-аутом для проверок работоспособности агента, если “timeout check” не задан. Чтобы снизить эффекты «резонанса» при размещении нескольких серверов на одном оборудовании, запуск агентов и проверок работоспособности всех серверов производится с небольшим временным сдвигом между ними. Также возможно добавить некоторую случайную погрешность в интервалы агентов и проверок работоспособности с помощью глобального параметра “spread-checks”. Это имеет смысл, например, когда большое количество бэкендов использует одни и те же серверы.
См. также параметры “agent-check” и “agent-port”.
agent-addr <addr>
Допустимые контексты: tcp, http, log
Параметр “agent-addr” задаёт адрес проверки агента.
Вы можете передать agent-check на другой целевой узел, чтобы обеспечить централизованное управление статусом и весами серверов, заданных в HAProxy, в случае, если невозможно реализовать самоосознаваемые и самоуправляющие сервисы. Вы можете указать как IP-адрес, так и имя хоста, оно будет разрешено.
agent-port <port>
Допустимые контексты: tcp, http, log
Параметр “agent-port” задаёт порт TCP, используемый для проверок агента.
См. также параметры “agent-check” и “agent-inter”.
allow-0rtt
Может быть использован в следующих контекстах: tcp, http, log, peers, ring
Разрешает отправку ранних данных серверу при использовании TLS 1.3. Примечание: ранние данные будут отправлены только если клиент использовал ранние данные, или если бэкенд использует “retry-on” с ключевым словом “0rtt-rejected”. С QUIC, 0rtt поддерживается с QuicTLS, OpenSSL >= 3.5.2 и AWS-LC. С TCP/TLS, 0rtt поддерживается только с OpenSSL.
alpn <protocols>
Допустимые контексты: tcp, http
Это включает расширение TLS ALPN и объявляет указанный список протоколов как поддерживаемый в дополнение к ALPN. Список протоколов состоит из запятой-разделённого списка названий протоколов, например:
“http/1.1,http/1.0” (без кавычек). Это требует, чтобы библиотека SSL была собрана с включённой поддержкой
расширений TLS (проверьте с помощью haproxy -vv). Расширение ALPN заменяет первоначальное расширение NPN. Расширение ALPN необходимо для подключения к серверам HTTP/2. Оно также необходимо для использования HTTP/3 через сервер QUIC. Значение по умолчанию для серверов QUIC без настройки “alpn” — “h3”. Версии OpenSSL до 1.0.2 не поддерживали ALPN и использовали теперь устаревшее расширение NPN. Если ожидается поддержка как HTTP/2, так и HTTP/1.1, оба варианта могут быть объявлены в порядке предпочтения, как указано ниже:
См. также “ws” для использования альтернативного ALPN для потоков WebSocket.
backup
Допустимые контексты: tcp, http, log
Когда на строке сервера присутствует “backup”, сервер используется только при балансировке нагрузки, если все остальные серверы, не являющиеся резервными копиями, недоступны. Запросы, поступающие с cookie-памятью, указывающей на этот сервер, будут всегда обслуживаться. По умолчанию используется только первый работающий сервер-резервная копия, если в бэкенде не установлен параметр “allbackups”. См. также параметры “no-backup” и “allbackups”.
ca-file <cafile>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только тогда, когда в HAProxy включена поддержка OpenSSL. Он указывает на файл PEM из которого загружаются сертификаты CA, используемые для проверки сертификата сервера. Возможна загрузка каталога, содержащего несколько CA, в этом случае HAProxy попытается загрузить каждый “.pem”, “.crt”, “.cer” и .crl, доступный в каталоге, файлы, начинающиеся с точки, игнорируются.
Чтобы использовать доверенные CA вашей системы, параметр “@system-ca” может быть использован вместо cafile. Путь к этому каталогу может быть перезаписан с помощью установки переменной среды SSL_CERT_DIR.
cc <algo>
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр доступен только на системах, которые определяют TCP_CONGESTION, и был протестирован на Linux и FreeBSD. Он принимает имя алгоритма управления перегрузкой TCP и настраивает исходящие соединения на использование этого алгоритма. Типичные имена включают “reno” или “cubic” и зависят от операционной системы. На некоторых системах для настройки определённых алгоритмов могут потребоваться специальные разрешения. На Linux доступные алгоритмы перечислены в sysctl “net.ipv4.tcp_available_congestion_control”, а разрешённые без прав доступа — в “net.ipv4.tcp_allowed_congestion_control”. Для доступа к алгоритмам, требующим дополнительных разрешений, может потребоваться возможность “cap_net_admin” (см. “setcap” в глобальной секции). В случае неудачи при настройке конкретного алгоритма управления перегрузкой используется алгоритм по умолчанию. См. также: ключевое слово bind “cc” ( секция 5.1 ).
check
Допустимые контексты: tcp, http, log
Этот параметр включает проверку работоспособности сервера: — при отсутствии настройки проверка работоспособности не выполняется, и сервер считается всегда доступным. — при наличии настройки и отсутствии других методов проверки работоспособности, сервер считается доступным, если на наивысшем настроенным уровне транспортного слоя удалось установить соединение. Это означает TCP по умолчанию, или SSL/TLS при настройке “ssl” или “check-ssl”, оба возможных в сочетании с префиксами соединения, такими как заголовок протокола PROXY при настройке “send-proxy” или “check-send-proxy”. Это поведение немного отличается для динамических серверов, см. следующие абзацы для дополнительной информации. — при наличии настройки и определении проверки работоспособности на уровне приложения, обмены на уровне приложения выполняются на основе настроенного уровня транспортного слоя, и сервер считается доступным, если все обмены успешно завершились.
По умолчанию проверки работоспособности выполняются на том же адресе и порту, что настроено для сервера, используя те же параметры оболочки (SSL/TLS, заголовок прокси-протокола и т.д.). Возможность изменить адрес назначения с помощью “addr” и порт с помощью “port”. При этом предполагается, что сервер не проверяется на порту сервиса, и настроенные параметры оболочки не повторяются. Обязательно нужно явно установить “check-send-proxy” для отправки заголовков соединения, “check-ssl” для использования SSL/TLS.
Примечание: не выполняется скрытая конфигурация ssl и протокола PROXY для динамических серверов.
В этом случае требуется явно использовать “check-ssl” и “check-send-proxy” при необходимости, даже
если порт проверки не переопределён.
Когда “sni” или “alpn” заданы на строке сервера, их значение не используется для проверки работоспособности и необходимо использовать “check-sni” или “check-alpn”.
По умолчанию адрес источника для трафика проверки работоспособности совпадает с тем, который определён в бэкенде.
Он может быть изменён с помощью ключевого слова “source”.
Интервал между проверками можно задать с помощью ключевого слова “inter”, а ключевые слова “rise” и “fall” могут быть использованы для определения количества успешных или неудачных проверок работоспособности, необходимых для обозначения сервера как доступного или недоступного.
Опциональные проверки работоспособности на уровне приложения могут быть настроены с помощью “option httpchk”, “option mysql-check” “option smtpchk”, “option pgsql-check”, “option ldap-check”, или “option redis-check”.
Пример:
check-reuse-pool
Допустимые контексты: tcp, http
Этот параметр позволяет проверкам использовать свободные соединения, если они доступны, вместо открытия отдельного соединения. Соединение возвращается в пул после завершения проверки. Основная цель — ограничить количество открытия и закрытия соединений на конкретном сервере. Эта функция совместима только с http-check правилами. Для других типов проверок она игнорируется без уведомления. Кроме того, политика повторного использования должна быть установлена на агрессивную на бэкенде, поскольку каждая попытка проверки выполняется через отдельную сессию.
Для упрощения конфигурации этот параметр игнорируется без уведомления, если определён какой-либо конкретный параметр подключения проверки, либо на строке сервера, либо через пользовательскую tcp-check правило подключения.
Этот параметр автоматически включается для серверов, работающих в качестве пассивного обратного HTTP гейтвей, поскольку для таких серверов подключение поддерживается только через переиспользование.
См. также: “check-pool-conn-name”
check-send-proxy
Допустимые контексты: tcp, http
Этот параметр заставляет генерировать строку протокола PROXY при исходных проверках работоспособности, независимо от того, использует ли сервер send-proxy для обычного трафика. По умолчанию, протокол PROXY включается для проверок работоспособности, если он уже включен для обычного трафика, и если отсутствуют директивы “port” и “addr”. Однако, если такие директивы присутствуют, для принудительного использования протокола необходимо использовать параметр “check-send-proxy”. Дополнительную информацию см. в отношении параметра “send-proxy”.
check-alpn <protocols>
Допустимые контексты: tcp, http
Определяет, какие протоколы следует рекламировать с помощью ALPN. Список протоколов состоит из запятой-разделённого списка названий протоколов, например: “http/1.1,http/1.0” (без кавычек). Если этот параметр не задан, используется сервер ALPN.
check-pool-conn-name <name>
Допустимые контексты: tcp, http
При использовании переработки соединений для проверок, применяется <name> как идентификатор соединения для соответствующего соединения в пуле. Это служит эквивалентом ключевого слова “pool-conn-name” сервер. “check-sni” также будет использоваться как резервный вариант, если текущий параметр не применяется.
См. также: “check-reuse-pool”
check-proto <name>
Допустимые контексты: tcp, http
Обязательно требует, чтобы мультиплексер использовал определённый протокол для соединений проверки работоспособности сервера. Он должен быть совместим с типом проверки работоспособности (TCP или HTTP). Он также должен быть применим на стороне бэкенда. Список доступных протоколов приведён в haproxy -vv. Свойства протоколов приведены: режим (TCP/HTTP), сторона (FE/BE), имя мультиплексера и его флаги.
Некоторые протоколы подвержены блокировке на уровне головы потока на стороне сервера (флаг=HOL_RISK). В конечном итоге некоторые протоколы не поддерживают обновления (флаг=NO_UPG). Также отображается совместимость HTX (флаг=HTX).
Здесь приведены протоколы, которые могут быть использованы в качестве аргумента директивы “check-proto” на строке сервера:
Понятие за счёт этого параметра — обойти выбор оптимального протокола мультиплексера для соединений проверки работоспособности, установленных к этому серверу. Если не задано, используется протокол сервера, если задан.
Если настроены параметры ALPN или NPN, указанные протоколы должны быть совместимы с протоколом мультиплексера, чтобы избежать проблем. Например, если задан “proto h1”, то ALPN не должен быть установлен в значение “h2”.
Настройка проверки работоспособности QUIC пока не полностью реализована. Во-первых, проверки QUIC могут выполняться только для серверов QUIC. Во-вторых, если указаны специфические параметры соединения для проверки на сервере QUIC, протокол проверки перейдёт к использованию TCP.
check-sni-auto
Допустимые контексты: tcp, http, log
Этот параметр включает автоматический выбор SNI при проверке работоспособности серверов через SSL, если значение не было задано ранее. Параметр включён по умолчанию, но может быть использован как “server” для сброса любого значения “no-check-sni-auto”, наследуемого из директивы “default-server” как значение по умолчанию. Он также может быть использован как “default-server” для сброса любого предыдущего значения “default-server” “no-check-sni-auto”.
Для HTTPS соединений, заголовок SNI автоматически выбирается, но только в случае отсутствия правила “http-check connect”. В этом случае, выбранный заголовок SNI определяется на основе значения заголовка хоста, указанного через директиву “option httpchk” или правило “http-check send”. Автоматическое выбора для правил “http-check connect” нет. Для других протоколов опция игнорируется.
Если используется автоматическое определение SNI для проверки работоспособности, то значение присваивается имени соединения, если установлено настройка “check-reuse-pool”, за исключением случая, когда оно перекрывается ключевым словом сервера “check-pool-conn-name”.
См. опцию “sni-auto” для включения автоматического выбора SNI для прокси-трафика.
check-sni <sni>
Допустимые контексты: tcp, http, log
Этот параметр позволяет указать SNI, используемый при проверке работоспособности через SSL. Возможна только строка для задания <sni>. Если необходимо задать SNI для проксированных потоков, см. “sni”.
check-ssl
Допустимые контексты: tcp, http, log
Этот параметр обеспечивает шифрование всех проверок работоспособности через SSL, независимо от того, использует ли сервер SSL для обычного трафика. Обычно этот параметр применяется тогда, когда указано явное “port” или “addr”, а проверки работоспособности через SSL не наследуются. Важно понимать, что данный параметр вставляет слой SSL на транспортном уровне ниже проверок, таким образом, простая проверка TCP соединения превращается в проверку SSL соединения, которая заменяет старую проверку ssl-hello-chk. Наиболее распространённый случай — отправка проверок HTTPS путём объединения проверок “httpchk” и SSL. Все настройки SSL распространяются на проверки работоспособности и трафик (например, шифры). См. параметр “ssl” для дополнительной информации и “no-check-ssl” для отключения этого параметра.
check-via-socks4
Допустимые контексты: tcp, http, log
Этот параметр включает исходящие проверки работоспособности с использованием прокси upstream socks4. По умолчанию проверки работоспособности не проходят через туннель socks, даже если такой туннель включен для обычного трафика.
ciphers <ciphers>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Этот параметр задаёт строку, описывающую список алгоритмов шифрования, устанавливаемых во время SSL/TLS-обмена с сервером. Формат строки определён в документации “man 1 ciphers” от OpenSSL. Для дополнительной информации и рекомендаций см. например,
(https://wiki.mozilla.org/Security/Server_Side_TLS
) и
(https://mozilla.github.io/server-side-tls/ssl-config-generator/
). Для настройки шифрования TLSv1.3 см. параметр “ciphersuites”.
ciphersuites <ciphersuites>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только при сборке с поддержкой OpenSSL и использовании OpenSSL 1.1.1 или более поздней версии для сборки HAProxy. Этот параметр задаёт строку, описывающую список алгоритмов шифрования, согласуемых во время TLS 1.3 рукопожатия с сервером. Формат строки определён в разделе “ciphersuites” документации OpenSSL, доступной по команде “man 1 ciphers”. Для настройки шифров TLSv1.2 и ранее обратитесь к ключевому слову “ciphers”.
client-sigalgs <sigalgs>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Устанавливает строку, описывающую список алгоритмов подписи, связанных с аутентификацией клиента, которые согласовываются. Формат строки определён в “man 3 SSL_CTX_set1_client_sigalgs” из страниц справки OpenSSL. Не рекомендуется использовать этот параметр, если не определён конкретный сценарий использования.
cookie <value>
Допустимые контексты: http
Параметр “cookie” устанавливает значение куки, присваиваемое серверу, в <value>. Это значение будет проверяться в входящих запросах, и первый рабочий сервер, обладающий таким же значением, будет выбран. В ответ, в режимах вставки или переписывания куки, это значение будет присваиваться куки, отправляемой клиенту. Нет ничего неправильного в том, чтобы несколько серверов делили одно и то же значение куки, и это, в действительности, довольно распространено между обычными и резервными серверами. См. также ключевое слово “cookie” в секции бэкенда.
crl-file <crlfile>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Он обозначает файл PEM из которого загружается список отозванных сертификатов, используемый для проверки сертификата сервера.
crt <cert>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Он указывает на файл PEM из которого необходимо загружать как сертификат, так и соответствующий приватный ключ. Такой файл может быть создан путем конкатенации двух файлов PEM. Данный сертификат будет отправлен, если сервер запрашивает сертификат клиента.
Если файл не содержит приватного ключа, HAProxy попытается загрузить ключ по тому же пути, но с суффиксом “.key” (при условии, что опция “ssl-load-extra-files” установлена соответствующим образом).
curves <curves>
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Устанавливает строку, описывающую список алгоритмов эллиптических кривых (“набор кривых”), которые устанавливаются во время SSL/TLS handshake с ECDHE. Формат строки — это список названий кривых, разделённых двоеточием. Пример: “X25519:P-256” (без кавычек)
disabled
Допустимые контексты: tcp, http, log
Ключевое слово “disabled” запускает сервер в состоянии “disabled”. Это означает, что сервер отмечен как выключенный в режиме технического обслуживания, и никакое соединение, кроме тех, которые разрешены режимом persist, не достигнет его. Оно очень хорошо подходит для настройки новых серверов, поскольку обычный трафик никогда не достигнет их, при этом возможно тестирование сервиса с использованием механизма force-persist. См. также настройку “enabled”.
enabled
Допустимые контексты: tcp, http, log
Этот параметр может быть использован как ‘server’ настройка для сброса любой ‘disabled’ настройки, которая была наследована из ‘default-server’ директивы как значение по умолчанию. Он также может быть использован как ‘default-server’ настройка для сброса любой предыдущей ‘default-server’ ‘disabled’ настройки.
error-limit <count>
Допустимые контексты: tcp, http, log
Если включена проверка состояния здоровья, параметр “error-limit” указывает количество последовательных ошибок, которое инициирует событие, выбранное опцией “on-error”. По умолчанию он установлен на 10 последовательных ошибок.
См. также “check”, “error-limit” и “on-error”.
fall <count>
Допустимые контексты: tcp, http, log
Параметр “fall” устанавливает, что сервер считается неисправным после <count> последовательных неудачных проверок работоспособности. Значение по умолчанию для этого параметра равно 3, если параметр не указан. См. также параметры “check”, “inter” и “rise”.
force-sslv3
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр обеспечивает использование только SSLv3 при SSL для связи с сервером. SSLv3 в целом менее затратен, чем соответствующие TLS при высокой интенсивности соединений. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.
force-tlsv10
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр обеспечивает использование TLSv1.0 только при использовании SSL для связи с сервером. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.
force-tlsv11
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр обеспечивает использование TLSv1.1 только при использовании SSL для связи с сервером. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.
force-tlsv12
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр обеспечивает использование TLSv1.2 только при использовании SSL для связи с сервером. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.
force-tlsv13
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр обеспечивает использование TLSv1.3 только при использовании SSL для связи с сервером. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.
guid <string>
Допустимые контексты: tcp, http, log
Укажите регистрозависимый уникальный идентификатор для этого сервера. Этот идентификатор должен быть уникальным во всей конфигурации HAProxy на всех типах объектов. См. описание ключевого слова “guid” прокси для получения дополнительной информации о его формате. См. также “shm-stats-file”.
hash-key <key>
Допустимые контексты: tcp, http, log
Укажите, как вычисляются ключи узла “hash-type consistent”
Аргументы:
Опции “addr” и “addr-port” могут быть полезны в сценариях, когда несколько процессов HAProxy распределяют трафик между одним и тем же набором серверов. Если порядок серверов в каждом процессе отличается (например, из-за того, что DNS записи были разрешены в различных порядках), то это позволит независимым процессам HAProxy согласовывать решения по маршрутизации. Примечание: “balance random” также использует “hash-type consistent”, и качество распределения будет зависеть от качества ключей.
healthcheck <name>
Допустимые контексты: tcp, http
Укажите секцию проверки работоспособности для проверки сервера.
Аргумент:
Благодаря этому параметру возможно использовать конфигурацию предварительной проверки работоспособности сервера вместо использования конфигурации прокси. См. также “секция проверки работоспособности”.
id <value>
Допустимые контексты: tcp, http, log
Установите постоянный идентификатор для сервера. Этот идентификатор должен быть положительным числом из 32 бит и уникальным для прокси. Если идентификатор не задан, будет автоматически назначено свободное значение. Первое назначаемое значение будет 1. Этот идентификатор в настоящее время возвращается только в статистике и используется для размещения узлов балансировки нагрузки при использовании алгоритмов консистентного хэша, когда “hash-key” установлен в “id” (по умолчанию). В этом случае используются только 28 наименьших бит значений (то есть (id % 268435356)), поэтому лучше использовать значения, включенные в диапазон от 1 до этого значения, чтобы избежать пересечения.
idle-ping <delay>
Допустимые контексты: tcp, http, log
Определите интервал для периодической проверки живучести на пассивных соединениях бэкенда. Если одноранговый узел не может ответить до следующего запланированного теста, соединение закрывается. Данное ключевое слово относится к бэкенду, поэтому оно полезно для проверки того, что пассивные соединения остаются работоспособными. Примечание: это не предотвратит разрушение соединения при очистке пула пассивных соединений.
Эта функция зависит от поддержки определённого базового протокола. На данный момент реализована только для H2 mux.
Проверка на пустоту игнорируется другими протоколами.
Этот параметр особенно полезен при использовании обратного HTTP. Установка его на строке сервера полезна для однорангового узла, который ожидает входящие соединения и присоединяет их к соответствующему серверу, чтобы позже использовать для пересылки трафика.
init-addr {last | libc | none | <ip>},[...]*
Допустимые контексты: tcp, http, log
Укажите порядок разрешения адреса сервера при запуске, если он использует FQDN.
При попытке разрешения адреса применяются по очереди все методы, перечисленные в списке, разделённом запятыми. Первый метод, который успешно работает, используется. Если конец списка достигнут без нахождения рабочего метода, генерируется ошибка. Метод “last” означает выбор адреса, присутствующего в файле состояния (см. “server-state-file”). Метод “libc” использует внутренний разрешитель libc (gethostbyname() или getaddrinfo() в зависимости от операционной системы и опций сборки). Метод “none” явно указывает на то, что сервер должен запускаться без действительного IP-адреса в состоянии down. Это может быть полезно для игнорирования некоторых DNS проблем при запуске, ожидая, пока ситуация будет исправлена позже. Наконец, может быть указан IP-адрес (IPv4 или IPv6). Он может быть текущим известным адресом сервера (например, заполненным конфигурационным генератором) или адресом виртуального сервера, используемого для перехвата старых сессий и предоставления при этом уместного сообщения об ошибке. При использовании алгоритма балансировки нагрузки “first” такой IP-адрес может указывать на фейковый сервер, используемый для запуска новых экземпляров на лету. Эта опция по умолчанию равна “last,libc”, что означает, что сначала используется предыдущий адрес из файла состояния (если он есть), иначе используется разрешитель libc. Это обеспечивает совместимость с историческим поведением. При использовании внутренних разрешителей рекомендуется либо отключать разрешение на основе libc, либо делать это явно (см. секцию 5.3
для дополнительной информации).
Пример 1:
Пример 2:
inter <delay>
Допустимые контексты: tcp, http, log
Параметр “inter” устанавливает интервал между двумя последовательными проверками работоспособности в <delay> миллисекунд. Если не указан, задержка по умолчанию равна 2000 ms. Также возможно использовать «fastinter» и «downinter» для оптимизации задержек между проверками в зависимости от состояния сервера:
Так же, как и для всех других параметров, зависящих от времени, они могут быть указаны в любой из явных единиц: { us, ms, s, m, h, d }. Параметр “inter” также служит тайм-аутом для проверок работоспособности, отправляемых серверам, если “timeout check” не задан. Чтобы снизить эффект “резонанса” при размещении нескольких серверов на одном оборудовании, запуск агента и проверок работоспособности всех серверов производится с небольшим временным смещением между ними. Также возможно добавить некоторое случайное отклонение в интервалы агента и проверок работоспособности с помощью глобального параметра “spread-checks”. Это имеет смысл, например, когда большое количество бэкендов использует одни и те же серверы. Глобальный параметр “tune.max-checks-per-thread”, если задан с ненулевым значением, ограничивает количество одновременно выполняемых проверок на любом из потоков. Для достижения этого HAProxy помещает в очередь проверки, которые планировались начать на потоке, достигшем этого предела, до тех пор, пока не завершится другая проверка. Это приведёт к увеличению эффективного интервала проверок. В таком случае сокращение параметра “inter” будет иметь очень ограниченное влияние, поскольку не сможет сократить время, затрачиваемое на ожидание в очереди.
init-state { fully-up | up | down | fully-down | none }
Допустимые контексты: tcp, http
Допустимые секции: defaults | frontend | listen | backend нет | нет | да | да
Опция “init-state” устанавливает начальное состояние сервера: - при значении ‘fully-up’ сервер считается немедленно доступным и, если включены проверки работоспособности для этого сервера, он будет переключен в состояние DOWN при неудаче всех проверок работоспособности. - при значении ‘up’ сервер считается немедленно доступным и, если включены проверки работоспособности для этого сервера, он будет немедленно переключен в состояние DOWN при неудаче следующей проверки работоспособности. - при значении ‘down’ сервер считается изначально недоступным и, если включены проверки работоспособности для этого сервера, он может быть переключен в состояние UP при успешной следующей проверке работоспособности. - при значении ‘fully-down’ сервер считается изначально недоступным и, если включены проверки работоспособности для этого сервера, он будет переключен в состояние UP при успешности всех проверок работоспособности. - при значении ’none’ (по умолчанию), управление init-state отключено. Оно может использоваться для восстановления стандартного поведения, когда этот параметр наследовался от директивы ‘default-server’.
Когда HAProxy-экземпляр запускается (перезапускается), обнаруживается новый сервер (например, через открытие сервиса / DNS), динамический сервер включается, сервер выходит из режима технического обслуживания и т.д., используется директива сервера init-state. Эта директива не может использоваться, когда сервер отслеживает другой сервер.
Примеры:
См. также: “option tcp-check”, “option httpchk”
ktls <on|off> [ EXPERIMENTAL ]
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Включает или отключает ktls для этих сокетов. При включении kTLS будет использоваться, если ядро поддерживает это и шифрование совместимо. Доступно только на Linux 4.17 и выше. Примечание: некоторые сетевые драйверы и/или TLS стеки могут ограничивать использование kTLS только для TLS v1.2. См. также “force-tlsv12”.
log-bufsize <bufsize>
Может быть использован в следующих контекстах: журнал
Ключ “log-bufsize” указывает на кольцо bufsize, которое будет использоваться для скрытого кольца, связанного с сервером журнала в бэкенде журнала. При отсутствии указания значение по умолчанию равно BUFSIZE. Использование большего значения приведёт к увеличению потребления памяти, но может помочь предотвратить потерю сообщений журнала при медленных серверах, поскольку буфер сможет вместить больше ожидающих сообщений. Данный ключ может использоваться только в секциях бэкенда журнала (с “mode log”)
log-proto <logproto>
Может использоваться в следующих контекстах: журнал, кольцо
“log-proto” указывает на протокол, используемый для передачи сообщений об событиях на сервер, настроенный в секции журнала или кольца. Возможные значения — “legacy” и “octet-count”, соответствующие соответственно “Non-transparent-framing” и “Octet counting” в rfc6587. “legacy” является по умолчанию.
maxconn <maxconn>
Допустимые контексты: tcp, http
Параметр “maxconn” указывает на максимальное количество одновременных соединений, которые будут отправлены на этот сервер. Если количество входящих одновременных соединений превышает указанное значение, они будут помещены в очередь и ожидать освобождения слота. Этот параметр очень важен, поскольку может предотвратить выход слабых серверов из строя под экстремальными нагрузками. Если указан параметр “minconn”, ограничение становится динамическим. Значение по умолчанию — “0”, что означает неограниченное количество. См. также параметры “minconn” и “maxqueue”, а также ключевое слово “fullconn” бэкенда.
В режиме HTTP этот параметр ограничивает количество одновременных запросов, а не количество соединений. Множественные запросы могут быть мультиплексированы через одно соединение TCP к серверу. Например, если вы укажете значение maxconn в виде 50, вы можете наблюдать от 1 до 50 фактических соединений с сервером, но не более чем 50 одновременных запросов.
maxqueue <maxqueue>
Допустимые контексты: tcp, http
Параметр “maxqueue” задаёт максимальное количество соединений, которые будут ждать в очереди для этого сервера. Если это ограничение достигнуто, последующие запросы будут перенаправлены на другие серверы вместо бесконечного ожидания обслуживания. Это нарушит сохранение сессии, но может позволить пользователям быстро повторно войти, если сервер, к которому они пытаются подключиться, выходит из строя. Некоторые алгоритмы балансировки нагрузки, такие как leastconn, учитывают это и допускают добавление запросов в очередь сервера до указанного значения, если оно явно установлено в значение, превышающее ноль, что часто позволяет лучше сгладить нагрузку при работе с однозначными значениями maxconn. Значение по умолчанию — “0”, что означает отсутствие ограничения на очередь. См. также параметры “maxconn” и “minconn” и “balance leastconn”.
max-reuse <count>
Может использоваться в следующих контекстах: http, ring
При использовании в контексте http:
Аргумент “max-reuse” указывает процессорам соединений HTTP, что они не должны повторно использовать соединение с сервером более чем указанное количество раз для отправки новых запросов. Разрешённые значения — -1 (по умолчанию), что отключает это ограничение, или любое положительное значение. Значение ноль будет эффективно отключать постоянное соединение. Это используется только для устранения определённых багов на серверах, приводящих к утечке ресурсов со временем. Аргумент не гарантируется нижележащими слоями, так как могут быть технические ограничения, препятствующие его соблюдению. По крайней мере HTTP/2 соединений с серверами будет учитывать это ограничение.
При использовании в контексте ring:
Аргумент “max-reuse” указывает на то, что обработчики соединений TCP должны не использовать соединение с сервером более чем указанное количество раз для отправки сообщений. Это означает, что соединение с сервером будет принудительно разрушено после обработки хотя бы “max-reuse + 1” сообщений на том же соединении. Затем соединение с сервером будет автоматически пересоздано. При работе с большим объёмом сообщений в многопоточной среде это может помочь более равномерно распределять нагрузку по нескольким потокам. Действительно, каждое соединение привязано к одному и тому же потоку CPU на протяжении всего своего срока существования: в отличие от HTTP, нет понятия транзакции syslog, поэтому соединение с сервером может существовать бесконечно, пока сервер не закроет соединение или не произойдёт сеть ошибки. Регулярное разрушение соединений даёт возможность другим потокам обрабатывать сообщения по очереди. Это также может помочь в плавной перезагрузке серверов логов в контекстах, где между HAProxy и серверами логов существует дополнительный слой балансировки нагрузки. Однако следует помнить, что при каждом перезапуске соединения остаётся исходный порт в состоянии TIME_WAIT, который не может быть повторно использован примерно на одну минуту на современных операционных системах, и поэтому необходимо быть осторожными при использовании слишком малых значений, чтобы избежать быстрого истощения исходных портов. Как правило, следует гарантировать, что соединения не разрушаются чаще чем несколько раз в секунду, и, предпочтительно, гораздо реже. Разрешённые значения — -1 (по умолчанию), что отключает это ограничение, или любое положительное значение. В отличие от контекста HTTP, при использовании с серверами-приёмниками “max-reuse” является попыткой: сообщения в кольце группируются, поэтому ограничение проверяется между каждым блоком.
minconn <minconn>
Допустимые контексты: tcp, http
Когда параметр “minconn” установлен, ограничение maxconn становится динамическим и зависит от нагрузки бэкенда. Сервер всегда принимает не менее <minconn> соединений, не более <maxconn>, и ограничение будет находиться в диапазоне между этими значениями при наличии менее чем <fullconn> одновременных соединений. Это позволяет ограничивать нагрузку на сервер во время обычной работы, но увеличивать её при важных нагрузках, не перегружая сервер во время экстремальных нагрузок. См. также параметры “maxconn” и “maxqueue”, а также ключевое слово “fullconn” бэкенда.
namespace <name>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
В Linux возможно указать, к какому сетевому пространству принадлежит сокет. Эта директива позволяет явно привязать сервер к пространству имен, отличному от стандартного. Для получения дополнительной информации о сетевых пространствах см. документацию операционной системы.
no-agent-check
Допустимые контексты: tcp, http, log
Этот параметр может быть использован как “server” настройка для сброса любой “agent-check” настройки, которая была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “agent-check” настройки.
no-backup
Допустимые контексты: tcp, http, log
Этот параметр может быть использован как “server” настройка для сброса любой “backup” настройки, которая бы была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “backup” настройки.
no-check
Допустимые контексты: tcp, http, log
Этот параметр может быть использован как “server” настройка для сброса любой “check” настройки, которая бы была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “check” настройки.
no-check-reuse-pool
Допустимые контексты: tcp, http
Этот параметр отменяет любые предыдущие “check-reuse-pool”, возможно наследуемые от “default-server”. Любые проверки будут проводиться на его отдельном соединении.
no-check-sni-auto
Допустимые контексты: tcp, http, log
Этот параметр может быть использован как “server” настройка для отключения автоматического выбора SNI для проверок здоровья SSL серверов, которые включены по умолчанию.
См. опцию “no-sni-auto” для отключения автоматического выбора SNI для прокси-трафика.
no-check-ssl
Допустимые контексты: tcp, http, log
Этот параметр может быть использован как “server” настройка для сброса любой “check-ssl” настройки, которая была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “check-ssl” настройки.
no-renegotiate
Допустимые контексты: tcp, http, log
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает механизмы переговоров, будь то устаревший небезопасный механизм или более современный механизм «безопасных переговоров» (RFC 5746 TLS Расширение указания переговоров), для указанного SSL бэкенда. Данный параметр также доступен в глобальном утверждении “ssl-default-server-options”. Переговоры больше не возможны в TLS 1.3. Если ни “renegotiate”, ни “no-renegotiate” не указаны, сохраняется стандартное поведение библиотеки SSL. Примечание: например, библиотека OpenSSL включает безопасные переговоры по умолчанию, в то время как AWS-LC отключает их. См. также “renegotiate”.
no-send-proxy
Допустимые контексты: tcp, http
Этот параметр может быть использован как “server” настройка для сброса любой “send-proxy” настройки, которая бы была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “send-proxy” настройки.
no-send-proxy-v2
Допустимые контексты: tcp, http
Этот параметр может быть использован как “server” настройка для сброса любой “send-proxy-v2” настройки, которая бы была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “send-proxy-v2” настройки.
no-send-proxy-v2-ssl
Допустимые контексты: tcp, http
Этот параметр может быть использован как “server” настройка для сброса любой “send-proxy-v2-ssl” настройки, которая бы была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “send-proxy-v2-ssl” настройки.
no-send-proxy-v2-ssl-cn
Допустимые контексты: tcp, http
Этот параметр может быть использован как “server” настройка для сброса любой “send-proxy-v2-ssl-cn” настройки, которая бы была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “send-proxy-v2-ssl-cn” настройки.
no-sni-auto
Может быть использован в следующих контекстах: tcp, http, log, peers, ring
Этот параметр может быть использован как “server” настройка для отключения автоматического выбора SNI, включенного по умолчанию.
См. параметр “no-check-sni-auto” для отключения автоматического выбора SNI для проверки работоспособности SSL.
no-ssl
Может быть использован в следующих контекстах: tcp, http, log, peers, ring
Этот параметр может быть использован как “server” настройка для сброса любой “ssl” настройки, которая была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “ssl” настройки.
Примечание: использование default-server ssl настройки и no-ssl на сервере инициализирует SSL соединение, поэтому его можно включить позже через runtime API: см. команды set server в документации по управлению.
no-ssl-reuse
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр отключает SSL повторное использование сессий при использовании SSL для связи с сервером. Он будет вынуждать сервер выполнять полную аутентификацию для каждого нового соединения. Вероятно, полезен только для бенчмаркинга, устранения неполадок и для пользователей с повышенной осторожностью.
no-sslv3
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр отключает поддержку SSLv3 при использовании SSL для связи с сервером. Примечание, что
SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. Используйте
“ssl-min-ver” и “ssl-max-ver” вместо этого.
Доступен в default-server: Нет
no-tls-tickets
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Отключает состояние-независимое восстановление сессии (RFC 5077 TLS Ticket extension) и вынуждает использовать состояние-зависимое восстановление сессии. Состояние-независимое восстановление сессии более затратно в CPU использовании на серверах. Этот параметр также доступен в глобальном утверждении “ssl-default-server-options”. Механизм TLS ticket используется только до TLS 1.2. Применение TLS тикетов нарушает безопасность передачи ключей, если ключи тикетов не периодически пересылаются (через перезагрузку или с помощью “tls-ticket-keys”). См. также “tls-tickets”.
no-tlsv10
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр отключает поддержку TLSv1.0 при использовании SSL для связи с сервером. Примечание, что
SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. TLSv1 дороже, чем SSLv3, поэтому часто имеет смысл отключать его при связи с локальными серверами. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
Доступен в default-server: Нет
no-tlsv11
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр отключает поддержку TLSv1.1 при использовании SSL для связи с сервером. Примечание, что
SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. TLSv1 дороже, чем SSLv3, поэтому часто имеет смысл отключать его при связи с локальными серверами. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
Доступен в default-server: Нет
no-tlsv12
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр отключает поддержку TLSv1.2 при использовании SSL для связи с сервером. Примечание, что
SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. TLSv1 дороже, чем SSLv3, поэтому часто имеет смысл отключать его при связи с локальными серверами. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
Доступен в default-server: Нет
no-tlsv13
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр отключает поддержку TLSv1.3 при использовании SSL для связи с сервером. Примечание, что
SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. TLSv1 дороже, чем SSLv3, поэтому часто имеет смысл отключать его при связи с локальными серверами. Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.
Доступен в default-server: Нет
no-verifyhost
Может быть использован в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр может быть использован как “server” настройка для сброса любой “verifyhost” настройки, которая была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “verifyhost” настройки.
no-tfo
Может быть использован в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Эта опция может быть использована как “server” настройка для сброса любой “tfo” настройки, которая была наследована из “default-server” директивы как значение по умолчанию. Она также может быть использована как “default-server” настройка для сброса любой предыдущей “default-server” “tfo” настройки.
non-stick
Допустимые контексты: tcp, http
Никогда не добавляйте соединения, присвоенные этому серверу, в stick-table. Это может быть использовано в сочетании с резервной копией для обеспечения отключения сохранения состояния для резервных серверов. stick-table
npn <protocols>
Допустимые контексты: tcp, http
Это включает расширение NPN TLS и объявляет указанный список протоколов как поддерживаемый в дополнение к NPN. Список протоколов состоит из запятой-разделённого списка названий протоколов, например:
“http/1.1,http/1.0” (без кавычек). Требуется, чтобы библиотека SSL была собрана с включённой поддержкой расширений TLS (проверьте с помощью haproxy -vv). Примечание, что расширение NPN было заменено расширением ALPN (см. ключевое слово “alpn”), хотя это расширение доступно только начиная с OpenSSL 1.0.2.
observe <mode>
Допустимые контексты: tcp, http
Этот параметр включает настройку проверки работоспособности на основе наблюдения за коммуникацией с сервером. По умолчанию данная функция отключена и для её включения необходимо также включить проверку работоспособности. Поддерживаются два режима: “layer4” и “layer7”. В режиме “layer4” значимы только успешные и неуспешные TCP-соединения. В режиме “layer7”, который допускается только для HTTP-прокси, проверяются ответы, получаемые от сервера, например, корректные/ошибочные HTTP-коды, непарсимые заголовки, тайм-аут и т.д. Корректные коды состояний включают 100 до 499, 501 и 505.
См. также “check”, “on-error” и “error-limit”.
on-error <mode>
Допустимые контексты: tcp, http, log
Выберите, что должно произойти при обнаружении достаточного количества последовательных ошибок. В настоящее время доступны четыре режима:
- fastinter: принудительно включить fastinter
- fail-check: имитировать неудачную проверку работоспособности, также принудительно включает fastinter (по умолчанию)
- sudden-death: имитировать неудачную проверку работоспособности перед критическим сбоем, один дополнительный неудачный результат проверки помечает сервер как выключенный, принудительно включает fastinter
- mark-down: немедленно помечает сервер как выключенный и принудительно включает fastinter
См. также “check”, “observe” и “error-limit”.
on-marked-down <action>
Допустимые контексты: tcp, http, log
Изменяйте то, что происходит при отмечении сервера как недоступного. В настоящее время доступно одно действие:
- shutdown-sessions: Завершение потоков однорангового узла. При включении этого параметра все соединения с сервером немедленно прекращаются при выходе сервера из строя. Этот параметр может быть использован, если проверка работоспособности выявляет более сложные случаи, чем простое состояние соединения, и длительные тайм-ауты приводят к тому, что сервис остаётся неотвечаемым слишком долго. Например, проверка работоспособности может обнаружить, что база данных застряла, и уже невозможно использовать существующие соединения. Соединения, завершённые таким образом, логируются с кодом завершения ‘D’ (для “Down”).
Действия отключены по умолчанию
on-marked-up <action>
Допустимые контексты: tcp, http, log
Изменяйте то, что происходит при отметке сервера как недоступного. В настоящее время доступно одно действие:
- shutdown-backup-sessions: Завершение потоков на всех серверах резервной копии. Это выполняется только если сервер не находится в состоянии резервной копии и не отключён (его эффективный вес > 0). Такое действие может быть использовано в некоторых случаях для принудительного возврата всех потоков на активный сервер после восстановления при работе с длительными сессиями (например, LDAP, SQL, …). Использование этой функции может привести к большему количеству проблем, чем оно решает (например, незавершённые транзакции), поэтому эта функция должна использоваться с крайней осторожностью. Потоки, завершённые из-за запуска сервера, логируются с кодом завершения ‘U’ (для “Up”).
Действия отключены по умолчанию
pool-conn-name <expr>
Допустимые контексты: http
При установке соединения с бэкендом оценивается это выражение для генерации имени соединения. Это имя является одним из ключевых свойств соединения в пуле пассивных серверов. См. ключевое слово “http-reuse”. При запросе на поиск существующего пассивного соединения оценивается это выражение для соответствия идентичному соединению.
В контексте, где SSL SNI используется для соединения с бэкендом, имя соединения автоматически присваивается результату выражения “sni”. Это соответствует наиболее распространённому использованию. Для более сложных настроек “pool-conn-name” может быть использован для перекрытия этого поведения.
См. также: “http-reuse”, “sni”
pool-low-conn <max>
Допустимые контексты: http
Установите низкий порог количества дежурных соединений для сервера, ниже которого поток не будет пытаться украдывать соединение у другого потока. Это может быть полезно для улучшения CPU в сценариях, включающих много очень быстрых серверов, чтобы обеспечить, чтобы все потоки всегда сохраняли несколько дежурных соединений, а не позволяли им накапливаться в одном потоке и мигрировать между потоками. Типичные значения — двойное количество потоков — показывают очень хорошую производительность уже при ответах в подмиллисекундах. По умолчанию значение ноль, что означает, что любое дежурное соединение может быть использовано в любое время. Это рекомендуемое значение для обычного использования. Это касается только соединений, которые могут быть совмещены по тем же принципам, что и те, которые применяются к “http-reuse”. В случае отключения совместного использования соединений между потоками через “tune.idle-pool.shared”, это настройка может стать очень важной для обеспечения того, чтобы каждый поток всегда имел несколько соединений, иначе коэффициент повторного использования соединений будет снижаться с увеличением количества потоков.
pool-max-conn <max>
Допустимые контексты: http
Установите максимальное количество дежурных соединений для сервера. -1 означает неограниченное количество соединений, 0 означает отсутствие дежурных соединений. По умолчанию — -1. При включении дежурных соединений, орфанные дежурные соединения, которые больше не принадлежат никакой сессии клиента, перемещаются в отдельный пул, чтобы оставаться доступными для будущих клиентов. Это касается только соединений, которые могут быть совместно использованы в соответствии с теми же принципами, что и для “http-reuse”.
pool-purge-delay <delay>
Допустимые контексты: http
Устанавливает задержку начала удаления пассивных соединений. Каждые <delay> интервал, половина пассивных соединений закрывается. 0 означает, что никакие пассивные соединения не сохраняются. По умолчанию — 5s.
port <port>
Допустимые контексты: tcp, http, log
Используя параметр “port”, становится возможным отправлять проверки работоспособности через другой порт или проводить пробы на agent-check. На некоторых серверах может быть желательно выделить порт для конкретного компонента, способного выполнять сложные тесты, более подходящие для проверок работоспособности, чем приложение. Обычно для этого запускают простой скрипт в inetd. Параметр игнорируется, если не задан параметр “check”. См. также параметр “addr”.
proto <name>
Допустимые контексты: tcp, http
Принудительно задаёт протокол мультиплексора, используемый для исходящих соединений с этим сервером. Он должен быть совместим с режимом бэкенда (TCP или HTTP). Должен также быть применим на стороне бэкенда. Список доступных протоколов приведён в свойствах протоколов haproxy -vv.The — указываются режим (TCP/HTTP), сторона (FE/BE), имя мультиплексора и его флаги.
Некоторые протоколы подвержены блокировке на уровне головы потока на стороне сервера (флаг=HOL_RISK). В конечном итоге некоторые протоколы не поддерживают обновления (флаг=NO_UPG). Также отображается совместимость HTX (флаг=HTX).
Здесь приведены протоколы, которые могут быть использованы в качестве аргумента директивы “proto” на строке сервера:
Понятие за счёт этого параметра — обойти выбор наилучшего протокола мультиплексера для всех
соединений, установленных к этому серверу.
Если настроены параметры ALPN или NPN, указанные протоколы должны быть совместимы с
протоколом мультиплексера, чтобы избежать каких-либо проблем. Например, если установлено “proto h1”, то ALPN
не должен быть установлен в значение “h2”.
См. также “ws” для использования альтернативного протокола для потоков WebSocket.
QMux — это подмножество QUIC, работающее над TCP. Оно соответствует следующему черновому протоколу https://www.ietf.org/archive/id/draft-ietf-quic-qmux-01.html . На данный момент считается экспериментальным в HAProxy.
quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]
Это QUIC специфичное настройка для выбора алгоритма управления перегрузкой для любого соединения, направленного на этот сервер. Они аналогичны тем, что используются в TCP. См. опцию bind с аналогичным названием для полного описания всех вариантов настройки.
Значение по умолчанию: cubic
См. также: “tune.quic.be.tx.pacing” и “tune.quic.be.cc.max-win-size”
redir <prefix>
Допустимые контексты: http
Параметр “redir” включает режим перенаправления для всех запросов GET и HEAD, адресующих данный сервер. Это означает, что вместо того чтобы передавать запрос серверу, HAProxy отправляет ответ «HTTP 302» с заголовком «Location», состоящим из этого префикса, сразу за которым следует запрошенный URI начиная с ведущего ‘/’ компонента пути. Это означает, что после <prefix> не должен использоваться завершающий слэш. Все невалидные запросы будут отклонены, а все не-GET или HEAD запросы будут нормально обрабатываться сервером. Примечание: поскольку ответ полностью синтезирован, в ответе невозможно изменять заголовки или вставлять куки. Однако куки в запросах всё ещё анализируются, что делает это решение полностью применимым для направления пользователей к удалённому месту в случае локальной катастрофы. Основное применение заключается в увеличении пропускной способности статических серверов за счёт прямого подключения клиентов к ним. Примечание: никогда не используйте относительный путь здесь, иначе возникнет цикл между клиентом и HAProxy!
Пример: сервер srv1 192.168.1.1:80 переадресация http://image1.mydomain.com проверка
renegotiate
Допустимые контексты: tcp, http, log
Этот параметр включает механизм безопасного повторного согласования (RFC 5746 TLS Расширение указания повторного согласования) для заданного бэкенда SSL. Это не означает, что клиент SSL будет отправлять запросы на повторное согласование, он лишь разрешает бэкендам проводить повторное согласование при запросе серверов. Требуется, чтобы лежащая в основе библиотека SSL фактически поддерживала повторное согласование. Этот параметр также доступен на глобальном уровне в операторе “ssl-default-server-options”. Повторное согласование больше невозможно в TLS 1.3. Если ни “renegotiate”, ни “no-renegotiate” не указаны, сохраняется поведение по умолчанию библиотеки SSL. Обратите внимание, что, например, библиотека OpenSSL включает безопасное повторное согласование по умолчанию, в то время как AWS-LC отключает его.
rise <count>
Допустимые контексты: tcp, http, log
Параметр “rise” указывает, что сервер будет считаться работоспособным после <count>
успешных последовательных проверок работоспособности. Значение по умолчанию равно 2, если параметр не указан. См. также параметры “check”, “inter” и “fall”.
resolve-opts <option>,<option>,… Может быть использован в следующих контекстах: tcp, http, log
Запятая-separated список опций, которые должны быть применены к DNS разрешению, связанному с этим сервером.
Доступные варианты:
allow-dup-ip По умолчанию HAProxy запрещает дублирование адресов IP в бэкенде при выполнении разрешения DNS в режиме работы. Однако в некоторых случаях оправдано, чтобы два сервера (в одном бэкенде, разрешаемые одним FQDN) имели один и тот же адрес IP. В таком случае включите эту опцию. Это противоположность prevent-dup-ip.
ignore-weight Игнорировать любое значение веса, установленное в записи SRV. Это полезно тогда, когда вы хотите управлять весами с помощью альтернативного метода, например, с помощью “agent-check” или через API времени выполнения.
prevent-dup-ip Обеспечить соблюдение стандартного поведения HAProxy на сервере: предотвратить повторное использование адреса IP, уже присвоенного серверу в одном бэкенде и имеющего одинаковое полное имя домена. Это противоположность allow-dup-ip.
Пример:
С опцией allow-dup-ip:
- если сервер именования возвращает один IP-адрес, тогда оба сервера будут использовать его
- Если сервер именования возвращает 2 IP-адресов, тогда каждый сервер будет использовать разный адрес
По умолчанию: не задано
resolve-prefer <family>
Допустимые контексты: tcp, http, log
Когда включена разрешение DNS для сервера и возвращаются несколько адресов IP из разных семейств, HAProxy будет предпочтительно использовать адрес из семейства, указанного в параметре “resolve-prefer”. См. также глобальный параметр “dns-accept-family” для принудительного использования конкретного семейства. Доступные семейства: “ipv4” и “ipv6”.
Значение по умолчанию: ipv6
Пример:
resolve-net <network>[,<network[,...]]
Допустимые контексты: tcp, http, log
Этот параметр приоритизирует выбор адреса IP, соответствующего сети. Это полезно в облаках для предпочтения локального IP. В некоторых случаях сервис высокой доступности в облаке может быть объявлен с множеством адресов в разных центрах обработки данных. Задержка между центрами обработки данных не является незначительной, поэтому данный параметр позволяет предпочтать локальный центр обработки данных. Если адрес не соответствует настроенной сети, выбирается другой адрес.
Пример:
resolvers <id>
Допустимые контексты: tcp, http, log
Указывает на существующую секцию “resolvers” для разрешения имени хоста текущего сервера. Часто рекомендуется отключать разрешение на основе libc при использовании разрешителей, хотя существуют исключения (см. секцию 5.3.1 ). В любом случае рекомендуется явно указывать “init-addr” при использовании разрешителей, чтобы не упустить этот элемент.
Пример:
См. также секцию 5.3 для деталей реализации и ловушек, на которые следует обратить внимание.
send-proxy
Допустимые контексты: tcp, http
Параметр “send-proxy” обеспечивает использование протокола PROXY при любом соединении, установленном с этим сервером. Протокол PROXY сообщает другой стороне о слоях 3/4 адресов входящего соединения, чтобы она могла узнать адрес клиента или публичный адрес, к которому он подключился, независимо от протокола верхнего уровня. Для соединений, принятых слушателем “accept-proxy” или “accept-netscaler-cip”, будет использоваться объявленный адрес. Поддерживаются только семейства адресов TCPv4 и TCPv6. Другие семейства, такие как Unix-сокеты, будут отображать семейство UNKNOWN. Серверы, использующие этот параметр, могут полностью быть связаны с другим экземпляром HAProxy, настроенным с параметром “accept-proxy”. Этот параметр не должен использоваться, если сервер не осведомлен о протоколе. При отправке проверок работоспособности на сервер, при наличии этого параметра, автоматически используется протокол PROXY, за исключением явного указания директивы “port” или “addr”, в случае чего потребуется также явная директива “check-send-proxy” для использования протокола PROXY. См. также параметр “no-send-proxy” данной секции и параметры “accept-proxy” и “accept-netscaler-cip” ключевого слова “bind”.
send-proxy-v2
Допустимые контексты: tcp, http
Параметр “send-proxy-v2” обеспечивает использование версии протокола PROXY 2 при любом соединении, установленном с этим сервером. Протокол PROXY сообщает другой стороне о слоях 3/4 адресов входящего соединения, чтобы он мог узнать адрес клиента или публичный адрес, к которому он подключился, независимо от протокола верхнего слоя. Он также передаёт ALPN информацию, если был достигнут соглашение по ALPN. Этот параметр не должен использоваться, если сервер не осведомлён об этой версии протокола. См. также опцию “no-send-proxy-v2” этой секции и опцию send-proxy ключевого слова “bind”.
set-proxy-v2-tlv-fmt(<id>) <fmt>
Допустимые контексты: tcp, http
Параметр “set-proxy-v2-tlv-fmt” используется для отправки произвольных TLV-блоков версии протокола PROXY 2. Для типа (<id>) диапазона определённого типа TLV см. секцию 2.2.8 в спецификации протокола прокси. Однако, значение может быть выбрано произвольно, при условии, что оно не превышает максимальную длину 65,535 байт. Его также можно использовать для передачи TLV-блоков, применяя команду fetch “fc_pp_tlv” для извлечения полученного TLV с фронтенда. Его можно использовать как опцию сервера или как опцию прокси default-server. Он должен использоваться в сочетании с send-proxy-v2 таким образом, чтобы на самом деле отправлялись TLV-блоки версии PPv2.
Пример: сервер srv1 192.168.1.1:80 send-proxy-v2 set-proxy-v2-tlv-fmt(0x20) %[fc_pp_tlv(0x20)]
В этом случае мы получаем TLV с типом 0x20 как строку и устанавливаем его в значение нового TLV, который также имеет тип 0x20.
proxy-v2-options <option>[,<option>]*
Допустимые контексты: tcp, http
Параметр “proxy-v2-options” добавляет опции отправки в версии протокола PROXY 2 при использовании “send-proxy-v2”. Доступные опции:
- ssl : См. также “send-proxy-v2-ssl”.
- cert-cn : См. также “send-proxy-v2-ssl-cn”.
- ssl-cipher: Название используемого шифра.
- cert-sig : Алгоритм подписи используемого сертификата.
- cert-key : Алгоритм ключа используемого сертификата
- authority: Значение имени хоста, переданное клиентом (поддерживаются только SNI из соединения TLS).
- crc32c : Хэш-сумма заголовка PROXYv2.
- unique-id: Передача уникального идентификатора, сгенерированного на основе фронтенда “unique-id-format” в заголовке PROXYv2. Уникальный идентификатор в первую очередь предназначен для “mode tcp”. Он может привести к непредвиденным результатам в “mode http”, поскольку сгенерированный уникальный идентификатор также используется для первого запроса HTTP в соединении постоянного соединения.
send-proxy-v2-ssl
Допустимые контексты: tcp, http
Параметр “send-proxy-v2-ssl” обеспечивает использование версии протокола PROXY 2 при любом соединении, установленном с этим сервером. Протокол PROXY сообщает другой стороне о слоях 3/4 адресов входящего соединения, чтобы он мог узнать адрес клиента или публичный адрес, к которому он подключился, независимо от протокола верхнего слоя. Кроме того, в заголовок протокола PROXY добавляется расширение информации SSL протокола PROXY. Данное настройка не должна использоваться, если сервер не осведомлён об этой версии протокола. См. также опцию “no-send-proxy-v2-ssl” этой секции и опцию “send-proxy-v2” ключевого слова “bind”.
send-proxy-v2-ssl-cn
Допустимые контексты: tcp, http
Параметр “send-proxy-v2-ssl” обеспечивает использование версии протокола PROXY 2 при любом соединении, установленном с этим сервером. Протокол PROXY сообщает другой стороне о слоях 3/4 адресов входящего соединения, чтобы он мог узнать адрес клиента или публичный адрес, к которому он обращался, независимо от протокола верхнего слоя. Кроме того, расширение информации SSL протокола PROXY, а также имя общего субъекта из сертификата клиента (если имеется), добавляется в заголовок протокола PROXY. Данное настройка не должна использоваться, если сервер не осведомлён об этой версии протокола. См. также опцию “no-send-proxy-v2-ssl-cn” этой секции и опцию “send-proxy-v2” ключевого слова “bind”.
shard <shard>
Может использоваться в следующих контекстах: одноранговые узлы
Параметр используется только в контексте синхронизации таблиц привязок с одноранговыми узлами. Параметр “shard” идентифицирует одноранговые узлы, которые получают все обновления stick-table по ключам с этим шардом в распределённой хеш-функции. Допустимыми значениями являются значения от 0 до значения параметра “shards”, указанного в секции “peers”. Значение 0 является значением по умолчанию, означающим, что узел получает все обновления по ключам. Значения, превышающие “shards”, будут игнорироваться. Это также относится к любому значению, заданному для локального узла.
Пример:
peers mypeers shards 3 peer A 127.0.0.1:40001 # local peer without shard value (0 internally) peer B 127.0.0.1:40002 shard 1 peer C 127.0.0.1:40003 shard 2 peer D 127.0.0.1:40004 shard 3
sigalgs <sigalgs>
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Устанавливает строку, описывающую список алгоритмов подписи, согласовываемых во время рукопожатия TLSv1.2 и TLSv1.3. Формат строки определён в “man 3 SSL_CTX_set1_sigalgs” из справочной документации OpenSSL. Не рекомендуется использовать этот параметр, если не требуется совместимость с промежуточным устройством.
slowstart <start_time_in_ms>
Допустимые контексты: tcp, http
Параметр “slowstart” для сервера принимает значение в миллисекундах, указывающее, через какое время сервер, только что вернувшийся в работу, начнёт функционировать на полной скорости. Как и для любого другого параметра, зависящего от времени, его можно указать в любой другой явной единице измерения: { us, ms, s, m, h, d }. Скорость увеличивается линейно от 0 до 100% в течение этого времени. Ограничение применяется к двум параметрам:
maxconn: количество принятых сервером соединений будет расти от 1 до 100% обычного
динамического предела, определенного выражением (minconn,maxconn,fullconn).weight: при использовании бэкендом динамического алгоритма с весом, вес растёт линейно от 1 до
100%. В этом случае вес обновляется при каждом проверке работоспособности. Поэтому важно, чтобы параметр “inter” был меньше чем “slowstart”, чтобы максимизировать количество шагов.
При запуске HAProxy механизм slowstart не применяется, иначе это привело бы к проблемам для работающих серверов. Он применяется только тогда, когда сервер ранее был обнаружен как неисправный.
sni <expression>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Параметр “sni” оценивает выражение извлечения образца, преобразует его в строку и использует результат как имя хоста, отправляемое в расширение SNI TLS серверу. Типичный сценарий — передача SNI, полученного от клиента, в сценарии моста TCP/SSL, используя выражение “ssl_fc_sni” для извлечения образца. ЭТО ДОЛЖНО НЕ ИСПОЛЬЗОВАТЬСЯ В СЛУЧАЯХ HTTPS, где следует использовать req.hdr(host), поскольку SNI в HTTPS всегда должна соответствовать полю Host, и клиенты допускают использование разных имен хостов в рамках одного соединения. Если установлено “verify required” (что является рекомендуемым настройкой), то получаемое имя также проверяется на соответствие именам в сертификате сервера. Дополнительные сведения см. в директиве “verify”. Если требуется задать SNI для проверки работоспособности, см. директиву “check-sni”.
По умолчанию, SNI присваивается имени соединения для “http-reuse”, если не переопределено директивой “pool-conn-name” сервера.
sni-auto
Может использоваться в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Параметр “sni-auto” включает автоматический выбор SNI, если значение ранее не было задано. Он устанавливает выражение “sni” в значение “req.hdr(host),field(1,:)”, что означает, что SNI будет содержать имя хоста запроса, отправляемого на сервер, с удалением номера порта. По умолчанию включено, однако данный параметр может использоваться как “server”-настройка для сброса любого “no-sni-auto”-настройки, которая могла быть унаследована от директивы “default-server” как значения по умолчанию. Он также может использоваться как “default-server”-настройка для сброса любой предыдущей “default-server” “no-sni-auto”-настройки.
Для HTTPS соединений выбранный SNI определяется на основе значения заголовка хост запроса, если он присутствует.
В противном случае он остаётся неустановленным. Для других протоколов опция игнорируется.
Если используется автоматическое определение SNI, то значение присваивается имени соединения для “http-reuse”, за исключением случая, когда это перекрывается ключевым словом “pool-conn-name” сервера.
См. опцию “check-sni-auto” для включения автоматического выбора SNI при проверке работоспособности для SSL.
source <addr>[:<pl>[-<ph>]] [usesrc { <addr2>[:<port2>] | client | clientip } ]
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Параметр “source” устанавливает исходный адрес, который будет использоваться при подключении к серверу. Он следует идентичным параметрам и принципам ключа бэкенда “source”, за исключением того, что он применяется только к серверу, который его ссылается. Для подробной информации см. ключ “source”.
Кроме того, утверждение “source” на строке сервера позволяет указать диапазон исходных портов, задавая нижнюю и верхнюю границы, разделённые дефисом (’-’). Некоторые операционные системы могут требовать действительный IP-адрес при указании диапазона исходных портов. Разрешено указывать один и тот же IP/диапазон для нескольких серверов. Это позволяет обойти ограничение в 64 тыс. одновременных соединений. Ограничение в этом случае достигнет 64 тыс. соединений на каждый сервер.
Поскольку в Linux 4.2/libc 2.23 IP_BIND_ADDRESS_NO_PORT установлено для соединений, указывающих исходный адрес без портов.
ssl
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Эта опция включает SSL шифрование на исходящих соединениях к серверу. Критически важно проверять сертификаты сервера с помощью “verify” при использовании SSL для подключения к серверам, иначе коммуникация подвергается простым атакам «человека в середине», что делает SSL бесполезной. При использовании этой опции проверки работоспособности автоматически отправляются в SSL, если нет директивы “port” или “addr”, указывающей на то, что проверка должна быть направлена в другое место. См. “no-ssl” для отключения опции “ssl” и опцию “check-ssl” для принудительной отправки проверок работоспособности в SSL.
ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр обеспечивает использование <version> или ниже при использовании SSL для связи с сервером.
Этот параметр также доступен на глобальном утверждении “ssl-default-server-options”. См. также
“ssl-min-ver”.
ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр обеспечивает использование <version> или верхнего уровня при использовании SSL для связи с сервером.
Этот параметр также доступен в глобальном утверждении “ssl-default-server-options”. См. также
“ssl-max-ver”.
ssl-reuse
Может быть использован в следующих контекстах: tcp, http, log, одноранговые узлы, ring
Этот параметр может быть использован как “server” настройка для сброса любой “no-ssl-reuse” настройки, которая бы была наследована из директивы “default-server” как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “no-ssl-reuse” настройки.
stick
Допустимые контексты: tcp, http
Этот параметр может быть использован как “server” настройка для сброса любой “non-stick” настройки, которая бы была наследована из “default-server” директивы как значение по умолчанию. Он также может быть использован как “default-server” настройка для сброса любой предыдущей “default-server” “non-stick” настройки.
strict-maxconn
Допустимые контексты: tcp, http
maxconn к серверам — это немного неточное выражение, на самом деле оно настраивает максимальное количество запросов, которые мы отправляем на сервер, но при наличии пассивных соединений у нас может быть больше общего количества соединений к серверу. Если требуется строгий лимит соединений с сервера, то можно использовать строгий maxconn. В этом случае мы никогда не устанавливаем больше соединений с сервером, чем maxconn, и пытаемся переиспользовать или уничтожить соединения при необходимости. Обратите внимание, однако, что это может привести к сбоям запросов в случае, если не удаётся установить новое соединение и нет доступного пассивного соединения. Это может происходить при установлении «приватных» соединений, соединений, связанных только с сессией, поскольку произошла аутентификация.
socks4 <addr>:<port>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр включает туннели socks4 для исходящих соединений с сервером. Использование данного параметра не будет по умолчанию заставлять проверку работоспособности проходить через socks4. Для включения функции необходимо использовать ключевое слово “check-via-socks4”.
tcp-md5sig <password>
Может быть использован в следующих контекстах: tcp, http, log, peers, ring
Включает подпись TCP MD5 (RFC 2385 Защита BGP Сессий через опцию подписи TCP MD5)
для всех исходящих соединений с этого сервера. Эта опция доступна только на Linux. При включении, строка <password> используется для подписи каждого TCP сегмента с помощью 16-байтового MD5 хэша. Это обеспечивает защиту TCP соединения от фальшивизации. Основное применение этой опции — защита BGP от введения фальшивых TCP сегментов в поток соединения. Однако она может быть полезна для любых очень длительных TCP соединений.
tcp-ut <delay>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Устанавливает тайм-аут пользователя TCP для всех исходящих соединений с этим сервером. Данное опция доступно на Linux с версии 2.6.37. Оно позволяет HAProxy настроить тайм-аут для сокетов, содержащих данные, не получающие подтверждения в течение заданного промежутка времени. Это особенно полезно для долговременных соединений с длительными периодами бездействия, таких как удалённые терминалы или пулы соединений с базами данных, где тайм-ауты клиента и сервера должны быть высокими для обеспечения длительного периода бездействия, но при этом важно обнаруживать исчезновение сервера с целью освобождения всех ресурсов, связанных с его соединением (и сессией клиента). Один из типичных сценариев использования — принудительное завершение неактивных соединений сервера при слишком медленных проверках работоспособности или во время мягкого перезагрузки, поскольку при этом проверки работоспособности отключаются. Аргумент — задержка, выраженная в миллисекундах по умолчанию. Работает только для обычных TCP соединений и игнорируется для других протоколов.
tfo
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр включает использование TCP fast open при подключении к серверам на системах, поддерживающих его (настоящим образом — только ядро Linux >= 4.11). Дополнительную информацию о TCP fast open см. в опции “tfo” bind. Обратите внимание, что при использовании tfo необходимо также использовать ключевые слова “conn-failure”, “empty-response” и “response-timeout” для “retry-on”, иначе HAProxy не сможет повторно подключаться при сбое. См. также “no-tfo”.
track [<backend>/]<server>
Допустимые контексты: tcp, http, log
Этот параметр позволяет устанавливать текущее состояние сервера путём отслеживания другого сервера. Возможна отслеживание сервера, который сам отслеживает другой сервер, при условии, что в конце цепочки сервер имеет включённые проверки работоспособности. Если <backend> не указан, используется текущий сервер. Если используется disable-on-404, то этот параметр должен быть включён на обоих прокси.
Пример:
tls-tickets
Может быть использован в следующих контекстах: tcp, http, log, peers, ring
Эта опция может быть использована как “server” настройка для сброса любой “no-tls-tickets” настройки, которая бы была наследована из “default-server” директивы как значение по умолчанию. Механизм билетов TLS используется только до TLS 1.2. Противоречие безопасности при передаче ключей обеспечивается при использовании TLS билетов, если ключи билетов периодически пересылаются (через перезагрузку или с помощью “tls-ticket-keys”). Она также может быть использована как “default-server” настройка для сброса любой предыдущей “default-server” “no-tls-tickets” настройки.
verify [none|required]
Может быть использован в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL. Если установлено значение ’none’, сертификат сервера не проверяется. В остальных случаях сертификат, предоставляемый сервером, проверяется с помощью ЦА из ‘ca-file’ и опциональных CRL из ‘crl-file’ после проверки того, чтобы имена, указанные в атрибутах subject и subjectAlternateNames сертификата, совпадали с именем, переданным с помощью директивы “sni”, или в случае отсутствия такого имени — с статическим именем хоста, переданным с помощью директивы “verifyhost”. При отсутствии совпадающего имени имена в сертификате игнорируются. Поэтому, в отсутствие SNI, важно использовать “verifyhost”. При неудаче проверки рукопожатия процесс прерывается. Критически важно проверять сертификаты серверов при подключении к серверам с помощью SSL, иначе коммуникация подвержена атакам типа «человек в середине», что делает SSL полностью бесполезным. Если в секции global отсутствует “ssl_server_verify”, по умолчанию “verify” установлено на “required”.
verifyhost <hostname>
Может использоваться в следующих контекстах: tcp, http, log, peers, ring
Этот параметр доступен только тогда, когда встроенная поддержка OpenSSL, и действует только при наличии ‘verify required’. Данный директивы устанавливает статический именной хост, по которому проверяется сертификат сервера, если при подключении к серверу не использован SNI. Если не используется SNI, это является единственным способом включения проверки имени хоста. Указанное статическое имя хоста также применяется при проверке работоспособности (при проверке работоспособности не предоставляется значение SNI). Если ни одно из имен хостов в сертификате сервера не совпадает с указанным именем, подключение прерывается. Имена хостов в сертификате сервера могут включать шаблоны. См. также опции “verify”, “sni” и “no-verifyhost”.
weight <weight>
Допустимые контексты: tcp, http
Параметр “weight” используется для настройки веса сервера по сравнению с другими серверами. Все серверы получают нагрузку пропорционально их весу относительно суммы всех весов, поэтому чем выше вес, тем выше нагрузка. По умолчанию вес равен 1, а максимальное значение — 256. Значение 0 означает, что сервер не участвует в балансировке нагрузки, но всё же принимает постоянные соединения. Если этот параметр используется для распределения нагрузки в соответствии с возможностями сервера, рекомендуется начинать с значений, которые могут как увеличиваться, так и уменьшаться, например, в диапазоне от 10 до 100, чтобы оставить достаточный запас как сверху, так и снизу для последующих корректировок.
ws { auto | h1 | h2 }
Допустимые контексты: http
Этот параметр позволяет настроить протокол, используемый при пересылке потоков WebSocket. Это особенно полезно при использовании бэкенда HTTP/2 без поддержки WebSocket H2 через RFC8441.
По умолчанию используется режим “auto”. Он будет использовать тот же протокол, что и основной. Единственное отличие — при использовании ALPN. В этом случае может попытаться понизить версию ALPN до «http/1.1» только для потоков WebSocket, если настроенный сервер ALPN содержит такую версию.
Значение “h1” используется для принудительного задания HTTP/1.1 для потоков WebSocket, через ALPN если SSL ALPN включено для сервера. Аналогично, “h2” может быть использован для принудительного задания HTTP/2.0 WebSocket. Используйте это значение с осторожностью: сервер должен поддерживать RFC8441 или при пересылке WebSocket HAProxy выдаст ошибку.
Примечание, что NPN не учитывается, так как его использование было отменено в пользу расширения ALPN
См. также “alpn” и “proto”.
5.3. Определение IP-адреса сервера через DNS
HAProxy позволяет использовать имя хоста в строке сервера для получения его IP-адреса с помощью серверов имен.
По умолчанию HAProxy разрешает имя при парсинге конфигурации, при запуске и кэширует результат на протяжении жизни процесса. В некоторых случаях это недостаточно, например, в Amazon, где IP-адрес сервера может измениться после перезагрузки или ELB виртуальный IP может изменяться в зависимости от текущей нагрузки.
В этом разделе описывается, как можно настроить HAProxy для выполнения разрешения имени сервера в режиме работы.
Независимо от того, включена ли разрешение имени сервера в режиме работы, по умолчанию HAProxy выполняет первое разрешение при запуске во время парсинга конфигурации через libc, если не отключено параметром “init-addr”.
5.3.1. Общий обзор
Как мы видели в введении, разрешение имени в HAProxy происходит на двух разных этапах жизненного цикла процесса:
Несколько других событий могут инициировать разрешение имени в режиме работы:
- при завершении проверки работоспособности сервера с тайм-аутом соединения: это может быть связано с тем, что сервер получил
новый IP-адрес. Следовательно, необходимо инициировать разрешение имени, чтобы узнать новый IP.
При использовании резолверов имя сервера может быть либо именем хоста, либо меткой SRV. HAProxy считает всё, что начинается с подчёркивания, меткой SRV. Если указана метка SRV, то соответствующие записи SRV будут получены с сервера DNS, а указанные имена хостов будут использоваться. Метка SRV будет проверяться периодически, и при добавлении или удалении серверов HAProxy автоматически выполнит аналогичные действия.
Несколько важных моментов, на которые следует обратить внимание:
все серверы именований запросываются в это же время. HAProxy обрабатывает первый валидный ответ.
Решение считается недействительным (NX, тайм-аут, отклонено), когда все серверы возвращают ошибку.
Клиент DNS, реализованный в HAProxy, является очень простым и не сможет понять большое количество опций и сложных настроек, которые может обрабатывать резолвер операционной системы. Следовательно, за исключением действительно простых конфигураций, в которых сервер, известный только по своему FQDN, имеет ровно один IP-адрес в любой момент времени и может периодически обновлять его (например, после перезагрузки), настоятельно рекомендуется избегать смешивания разрешения имён на этапе инициализации, основанного на библиотеке libc, с разрешением во время выполнения, основанным на DNS. Такие конфигурации известны своей склонностью к сбоям при обновлении адресов. В заключение, если вы не уверены в том, что делаете, всегда следует исключать “libc” из “init-addr” при использовании “resolvers” в строке сервера.
5.3.2. Секция resolvers
Эта секция посвящена информации о хостах, связанной с разрешением имен в HAProxy. Могут быть столько секций resolvers, сколько необходимо. Каждая секция может содержать множество серверов разрешения имен.
При запуске HAProxy пытается сгенерировать секцию resolvers, названную “default”, если в конфигурации нет секции с таким названием. Эта секция по умолчанию используется httpclient и использует ключевое слово parse-resolv-conf. Если HAProxy не может автоматически сгенерировать эту секцию, не выдается ни ошибки, ни предупреждения.
Когда в секции resolvers настроено несколько серверов разрешения имен, HAProxy использует первый валидный ответ. В случае невалидных ответов, только последний считается валидным. Цель — обеспечить возможность медленному серверу передать корректный ответ после того, как быстрый, неисправный или устаревший сервер вернул невалидный ответ.
Когда каждый сервер возвращает разный тип ошибки, HAProxy использует только последнюю ошибку. На этой ошибке применяется следующая обработка:
Например, при настройке 2 серверов в секции resolvers, возможны следующие сценарии:
Первый ответ является действительным и применяется немедленно, второй ответ игнорируется
Первый ответ является недействительным, второй — действительным, затем применяется второй ответ
Первый ответ — NX домен, второй — обрезанный ответ, затем HAProxy повторяет запрос с новым типом
Первый ответ — NX домен, второй — тайм-аут, затем HAProxy повторяет запрос с новым типом
Запрос истек по тайм-ауту для обоих серверов, затем HAProxy повторяет запрос с тем же типом запроса
Поскольку DNS сервер может не отвечать на все IP в одном DNS запросе, HAProxy хранит кэш предыдущих ответов, ответ считается устаревшим после <hold obsolete> секунд без возврата IP.
resolvers <resolvers id>
Создаёт новый список серверов имени, помеченный <resolvers id>. Как указано выше, специальный сервер имени “default” всегда существует и будет автоматически создан, если не объявлен явно; это будет тот, на который зависят внутренние службы, такие как httpclient. Объявление записи “default” повлияет на то, как такие службы выполняют разрешение имен.
Секция resolvers принимает следующие параметры:
accepted_payload_size <nb>
Определяет максимальный размер полезной нагрузки, который принимается HAProxy и объявляется всем серверам имен, настроенным в этой секции разрешителей. <nb> измеряется в байтах. Если не задано, HAProxy объявляет 512. (минимальное значение, определённое RFC 6891)
Примечание: максимально допустимое значение — 65535. Рекомендуемое значение для UDP — 4096, и не рекомендуется превышать 8192, за исключением случаев, когда вы уверены, что ваша система и сеть способны справиться с этим (значение, превышающее 65507, не имеет смысла, поскольку это максимальный размер полезной нагрузки UDP). Если вы используете только TCP серверы имен для обработки больших DNS ответов, следует установить это значение на максимум: 65535.
nameserver <name> <address>[:port] [param*]
Используется для настройки сервера имён. <name> сервера имён должен быть уникальным. По умолчанию <address> считается типом датаграммы. Это означает, что при настройке IPv4 или IPv6 без специальных префиксов адресов (параграф 11) будет использоваться протокол UDP. Если используется префикс адреса потокового протокола, сервер имён будет считаться потоковым сервером (TCP, например), и параметры “server”, указанные в параграфе 5.2, которые относятся к разрешению DNS, будут учитываться.
Примечание: в настоящее время в режиме TCP запросы 4 пайплайнятся по одному соединению. Каждые 5 секунд удаляются пакеты неактивных соединений. Параметр “maxconn” можно настроить для ограничения количества одновременных соединений, а параметр TLS также должен быть доступен, если сервер его поддерживает.
parse-resolv-conf
Добавляет все именные серверы, найденные в /etc/resolv.conf, в список именных серверов этого резолвера. Упорядочиваются как если бы каждый именной сервер из /etc/resolv.conf был индивидуально помещён в секцию резолвера на место этой директивы.
hold <status> <period>
При получении ответа DNS <status> определяется, следует ли изменить состояние сервера с UP на DOWN. Для этого проверяется, был ли получен любой действительный статус в течение последних <period>, чтобы противодействовать недавно полученному невалидному статусу.
`<status>`: последний статус разрешения имени.
nx После получения статуса NXDOMAIN проверяется наличие любого действительного статуса в периоде завершения.
refused После получения статуса REFUSED проверяется наличие любого действительного статуса в периоде завершения.
timeout После истечения "timeout retry" проверяется наличие любого действительного статуса в периоде завершения.
other После получения любого другого невалидного статуса проверяется наличие любого действительного статуса в периоде завершения.
valid Применяется только к действиям "http-request do-resolve" и "tcp-request content do-resolve". Определяет период, в течение которого сервер будет сохранять действительный ответ перед запуском нового разрешения. Не влияет на динамическое разрешение серверов.
obsolete Определяет период ожидания до удаления устаревших записей DNS после получения обновлённой записи ответа. Применяется к записям SRV.
`<period>`: количество времени в прошлом, в течение которого должен быть получен действительный ответ. Следует формату времени HAProxy и по умолчанию измеряется в миллисекундах.
Для сервера, который зависит от динамической разрешения DNS для определения своего IP-адреса, получение недопустимого ответа DNS, например, NXDOMAIN, приведёт к изменению состояния сервера с UP на DOWN. Параметры hold определяют, насколько далеко в прошлое искать допустимый ответ. Если допустимый ответ был получен в течение <period>, недавний недопустимый статус будет проигнорирован.
Если в период завершения не был получен допустимый ответ, сервер будет помечен как DOWN. Например, если “hold nx 30s” установлен и последний полученный ответ DNS был NXDOMAIN, сервер будет помечен как DOWN, если в последних 30 секундах не был получен допустимый ответ.
Сервер в состоянии DOWN будет немедленно помечен как UP при получении допустимого статуса от сервера DNS.
Существует отдельное поведение для “hold valid” и “hold obsolete”.
По умолчанию значение для «допустимого» — 10s, для «устаревшего» — 0s и для остальных — 30s.
resolve_retries <nb>
Определяет количество <nb> запросов, которые необходимо отправить для разрешения имени сервера, прежде чем отказаться. Значение по умолчанию: 3
Повторный запрос происходит при тайм-ауте наименования сервера или при завершении полной последовательности переключения при отказе DNS и необходимости перезапуска с типом запроса ANY.
timeout <event> <time>
Определяет тайм-ауты, связанные с разрешением имен <event>: событие, на котором применяется период тайм-аута <time>. Доступные события: - resolve: время, при котором запускается разрешение имен, если не применяется другое время. Значение по умолчанию: 1s - retry : время между двумя DNS запросами, если не получены действительные ответы. Значение по умолчанию: 1s <time>: время, связанное с событием. Оно следует формату времени HAProxy. <time> выражено в миллисекундах.
Пример:
13 - 6. Кеш
HAProxy предоставляет кеш, предназначенный для небольших объектов (favicon, css и т. п.). Это минималистичный кеш в оперативной памяти, не требующий сложного обслуживания.
Кеш использует общую для всех потоков область памяти, разделённую на блоки по 1kB.
Если объект больше не используется, его можно удалить, чтобы сохранить новый объект, независимо от срока его действия. При выделении места для нового объекта сначала удаляются самые старые объекты.
В качестве ключа кеш использует хеш заголовка host и URI.
Состояние кеша можно просмотреть командой сокета Unix «show cache»; дополнительные сведения приведены в разделе 9.3 «Команды сокета Unix» руководства по управлению.
Когда объект выдаётся из кеша, имя сервера в журнале заменяется на «<CACHE>».
6.1. Ограничения
Кеш не сохраняет и не выдаёт объекты в следующих случаях:
Если код ответа отличается от 200.
Если ответ содержит заголовок Vary, а параметр process-vary отключён либо значение Vary содержит заголовок, который пока не поддерживается (сейчас поддерживаются только accept-encoding, referer и origin).
Если Content-Length + размер заголовков превышает «max-object-size».
Если ответ нельзя кешировать.
Если у ответа нет явно заданного срока действия (директивы s-maxage или max-age в Cache-Control либо заголовка Expires) или валидатора (заголовков ETag или Last-Modified).
Если параметр process-vary включён и уже существует max-secondary-entries записей с тем же первичным ключом, что и у текущего ответа.
Если параметр process-vary включён, ответ зависит от клиентского заголовка accept-encoding и использует неизвестную кодировку (не указанную в https://www.iana.org/assignments/http-parameters/http-parameters.xhtml ).
Если метод запроса отличается от GET.
Если версия HTTP в запросе ниже 1.1.
Если запрос содержит заголовок Authorization.
6.2. Настройка
Для настройки кеша необходимо определить секцию cache и использовать её в прокси с соответствующими действиями http-request и http-response.
6.2.1. Секция cache
cache <name>
Объявляет секцию кеша и выделяет общую память кеша с именем <name>. Размер кеша обязателен (см. директиву «total-max-size» ниже).
max-age <seconds>
Задаёт максимальный срок действия. Срок действия равен меньшему из этого значения и значения директивы s-maxage или max-age (в таком порядке приоритета) в заголовке ответа Cache-Control. Значение по умолчанию — 60 секунд, то есть по умолчанию объект нельзя кешировать дольше 60 секунд.
max-object-size <bytes>
Задаёт максимальный размер кешируемого объекта. Он не должен превышать половину «total-max-size». Если не задан, равен 256-й доле размера кеша. Объекты размером больше «max-object-size» не кешируются.
max-secondary-entries <number>
Задаёт максимальное число одновременно существующих вторичных записей с одинаковым первичным ключом в кеше. Для этого должна быть включена поддержка vary. Значение по умолчанию — 10; следует указывать строго положительное целое число.
process-vary <on/off>
Включает или отключает обработку заголовка Vary. Если она отключена, ответы с таким заголовком никогда не кешируются. Если включена, для части заголовков всех входящих запросов требуется предварительно вычислять хеш (что может потребовать дополнительных ресурсов CPU); он используется для формирования вторичного ключа запроса (см. RFC 7234#4.1). Сейчас вторичный ключ формируется из содержимого заголовков ‘accept-encoding’, ‘referer’ и ‘origin’. Обратите внимание: согласно RFC заголовки ‘origin’ и ‘referer’ имеют по одному значению, поэтому запрос с несколькими вхождениями любого из них следует считать некорректным. Для таких запросов вторичный ключ не формируется и ответ никогда не выдаётся из кеша, чтобы сервер мог сам решить, как обработать ситуацию. Значение по умолчанию — off (отключено).
total-max-size <megabytes>
Задаёт размер кеша в оперативной памяти в мегабайтах. Эта память разделяется на блоки по 1kB, используемые записями кеша. Максимальное значение — 4095.
6.2.2. Секция прокси
Секция прокси, использующая кеш, должна включать действие «cache-use» в набор правил «http-request» для поиска запрошенного объекта в кеше и действие «cache-store» в набор правил «http-response» для сохранения или обновления полученного объекта. Оба действия могут дополнительно содержать условия. Например, можно пропускать «cache-use» для определённого подкаталога, содержимое которого заведомо не кешируется, либо пропускать «cache-store» для типов содержимого, кеширование которых заведомо бесполезно. Учтите, что ключ индексации кеша вычисляется при выполнении «cache-use»: если это действие пропущено, на этапе обработки ответа попытка обновления кеша в любом случае не выполняется.
Пример:
14 - 9. Поддерживаемые фильтры
Ниже перечислены официально поддерживаемые фильтры и принимаемые ими параметры. В зависимости от параметров сборки некоторые фильтры могут быть недоступны. Список доступных фильтров выводится командой haproxy -vv.
См. также: «filter».
9.1. Трассировка
filter trace [name <name>] [random-forwarding] [max-fwd <max>] [hexdump]
Аргументы:
Этот фильтр можно использовать как основу для разработки новых фильтров. Он определяет все обратные вызовы и для каждого из них выводит в стандартный поток ошибок (stderr) сообщение с полезными сведениями. Это может пригодиться для отладки работы других фильтров или самого HAProxy.
Параметры <random-parsing> и/или <random-forwarding> удобны для проверки поведения фильтра, разбирающего данные, которыми обмениваются клиент и сервер: они добавляют задержки при обработке.
9.2. Сжатие HTTP
filter comp-req
Включает фильтр, явно пытающийся сжимать запросы HTTP в соответствии с настройками «compression». Неявно задаёт «compression direction request».
filter comp-res
Включает фильтр, явно пытающийся сжимать ответы HTTP в соответствии с настройками «compression». Неявно задаёт «compression direction response».
filter compression (устарел)
Псевдоним для обратной совместимости, функционально эквивалентный одновременному включению фильтров «comp-req» и «comp-res». Для настройки нужного поведения необходимо использовать директиву «compression»:
В HAProxy 1.7 сжатие HTTP было перенесено в фильтр. Директива «compression» по-прежнему используется для включения и настройки сжатия HTTP. Если другие фильтры не используются, этого достаточно. Этого также достаточно при включённом кеше или fcgi-app. В таком случае сжатие всегда выполняется после сохранения ответа в кеше. Но если для того же слушателя/фронтенда/бэкенда используется хотя бы один фильтр, отличный от кеша или fcgi-app, для включения сжатия HTTP обязательно нужно явно добавить строку filter. Это необходимо для определения порядка выполнения фильтров.
См. также: «compression», раздел 9.4 о фильтре кеша и раздел 9.5 о фильтре fcgi-app.
9.3. Механизм вынесения обработки потоков (SPOE)
filter spoe [engine <name>] config <file>
Аргументы:
Stream Processing Offload Engine (SPOE) — фильтр, взаимодействующий с внешними компонентами. Он позволяет выносить отдельные виды обработки потоков во внешние уровни приложения. Эти внешние компоненты и сведения, которыми они обмениваются с HAProxy, в основном настраиваются в отдельных файлах. Также требуются выделенные бэкенды, определённые в конфигурации HAProxy.
SPOE взаимодействует с внешними компонентами по собственному двоичному протоколу Stream Processing Offload Protocol (SPOP).
Когда SPOE используется для потока, создаётся отдельный поток для взаимодействия с внешним компонентом. Основной поток является родительским для этого потока «SPOE». Это означает, что из потока «SPOE» можно получать переменные основного потока. Дополнительные сведения приведены в разделе 2.8 о переменных.
Полные сведения о настройке SPOE и спецификации SPOP приведены в «doc/SPOE.txt».
9.4. Кеш
filter cache <name>
Аргументы:
Кеш использует фильтр для сохранения кешируемых ответов. Чтобы определить, как и когда использовать кеш, необходимо применять правила HTTP «cache-store» и «cache-use». По умолчанию соответствующий фильтр определяется неявно. Если не используются другие фильтры, кроме fcgi-app или сжатия, этого достаточно. В таком случае фильтр сжатия всегда выполняется после фильтра кеша. Но если для того же слушателя/фронтенда/бэкенда используется хотя бы один фильтр, отличный от сжатия или fcgi-app, для использования кеша обязательно нужно явно добавить строку filter. Это необходимо для определения порядка выполнения фильтров.
См. также: раздел 9.2 о фильтре сжатия, раздел 9.5 о фильтре fcgi-app и раздел 6 о кеше.
9.5. Fcgi-app
filter fcgi-app <name>
Аргументы:
Приложение FastCGI использует фильтр для вычисления всех пользовательских параметров при обработке запроса и для обработки заголовков ответа. <name> должен ссылаться на существующую секцию fcgi-app. Для указания используемого приложения следует применять директиву «use-fcgi-app». По умолчанию соответствующий фильтр определяется неявно. Если не используются другие фильтры, кроме кеша или сжатия, этого достаточно. Но если для того же бэкенда используется хотя бы один фильтр, отличный от сжатия или кеша, для fcgi-app обязательно нужно явно добавить строку filter. Это необходимо для определения порядка выполнения фильтров.
См. также: «use-fcgi-app», раздел 9.2 о фильтре сжатия, раздел 9.4 о фильтре кеша и раздел 10 о приложениях FastCGI.
9.6. OpenTracing
Фильтр OpenTracing добавляет в HAProxy встроенную поддержку распределённой трассировки. Для этого запрос, соответствующий OpenTracing, отправляется одному из поддерживаемых трассировщиков: Datadog, Jaeger, Lightstep или Zipkin. Обратите внимание: трассировщики перечислены в алфавитном порядке, а не в порядке предпочтения.
Эта возможность доступна только при сборке HAProxy с USE_OT=1.
Фильтр OpenTracing включается явным указанием в конфигурации HAProxy. Если этого не сделать, фильтр OpenTracing никак не участвует в работе HAProxy.
filter opentracing [id <id>] config <file>
Аргументы:
Более подробная документация по работе, настройке и использованию фильтра находится в каталоге addons/ot.
Примечание: фильтр OpenTracing не следует использовать в новых проектах, поскольку сами авторы OpenTracing больше его не развивают и не поддерживают. Поэтому OpenTracing будет объявлен устаревшим в 3.3 и удалён в 3.5. Заменяющий его фильтр на основе OpenTelemetry доступен с 3.4; полные инструкции по сборке сейчас находятся по адресу:
9.7. Ограничение пропускной способности
filter bwlim-in <name> default-limit <size> default-period <time> [min-size <sz>] filter
bwlim-out <name> default-limit <size> default-period <time> [min-size <sz>] filter
bwlim-in <name> limit <size> key <pattern> [table <table>] [min-size <sz>] filter
bwlim-out <name> limit <size> key <pattern> [table <table>] [min-size <sz>]
Аргументы:
Фильтры ограничения пропускной способности следует использовать для ограничения скорости пересылки данных на уровне потока. Тем самым они ограничивают сетевую пропускную способность, потребляемую ресурсом. Можно использовать несколько таких фильтров. Например, один предел можно задать для каждого исходного адреса, чтобы клиент никогда не занимал всю пропускную способность сети в ущерб остальным, а другой — для каждого потока, чтобы справедливо обслуживать несколько соединений одного клиента.
Порядок определения этих фильтров важен. Если для потока включено несколько фильтров пропускной способности, они применяются в порядке определения. Важно понимать, что влияет и порядок определения остальных фильтров. Например, в зависимости от того, определён ли фильтр сжатия HTTP до или после фильтра ограничения пропускной способности, ограничение применяется к сжатой полезной нагрузке или к несжатой. То же верно для фильтра кеша.
Существуют два типа фильтров ограничения пропускной способности. Первый применяет ограничение по умолчанию отдельно к каждому потоку. Второй использует таблицу привязок для ограничения, поровну распределяемого между всеми потоками, использующими одну запись таблицы.
Кроме того, в зависимости от использованного ключевого слова фильтра ограничение может применяться к входящим данным, получаемым от клиента и пересылаемым серверу, либо к исходящим данным, получаемым от сервера и отправляемым клиенту. Для ограничения входящих данных необходимо использовать «bwlim-in», для исходящих — «bwlim-out». В обоих случаях ограничивается пересылка данных на уровне потока.
Ограничение пропускной способности действует на уровне потока, а не соединения. Для протоколов с мультиплексированием (H2, H3 и FastCGI) потоки одного соединения могут иметь разные ограничения.
Для фильтра, ограничивающего отдельные потоки, необходимо определить период и предел по умолчанию. Как следует из названий, это значения по умолчанию для настройки скорости потока. Однако для этого типа фильтра, и только для него, эти значения можно переопределить с помощью выражений образцов при включении фильтра действием TCP/HTTP «set-bandwidth-limit».
Для фильтра с общим ограничением таблица привязок должна хранить сведения о соответствующей скорости передачи байтов в зависимости от того, ограничиваются входящие или исходящие данные. Для ограничения входящих данных необходимо хранить счётчик «bytes_in_rate(<period>)», для исходящих — использовать «bytes_out_rate(<period>)».
Наконец, можно задать минимальное число байтов, которое фильтр ограничения пропускной способности может переслать за один раз для данного потока. Эту настройку следует использовать, чтобы не пересылать слишком маленькие порции данных и уменьшить потребление CPU. Значение нужно выбирать внимательно. Слишком маленькое значение может увеличить потребление CPU, а слишком большое — задержку. Оно также тесно связано с заданным пределом пропускной способности. Если значение слишком близко к этому пределу, могут возникать паузы, необходимые для соблюдения ограничения, поскольку за один раз передаётся слишком много байтов. Результат сильно зависит от конфигурации фильтра. Хорошая отправная точка — около 2 TCP MSS, обычно 2896 байтов, с последующей настройкой по результатам экспериментов.
Пример:
См. также: «tcp-request content set-bandwidth-limit», «tcp-response content set-bandwidth-limit», «http-request set-bandwidth-limit» и «http-response set-bandwidth-limit».
15 - 10. Приложения FastCGI
HAProxy может отправлять запросы HTTP приложениям FastCGI с ролью Responder. Эта возможность добавлена в HAProxy 2.1. Для её использования серверы необходимо настроить на протокол FastCGI (с помощью «proto fcgi» в строке server), а в управляющем ими бэкенде нужно настроить и подключить приложение FastCGI (с помощью «use-fcgi-app» в секции прокси). Можно определить несколько приложений FastCGI, но бэкенд одновременно может использовать только одно из них.
HAProxy реализует все возможности спецификации FastCGI для приложений Responder. В частности, он может мультиплексировать несколько запросов в одном соединении.
10.1. Настройка
10.1.1. Секция fcgi-app
fcgi-app <name>
Объявляет приложение FastCGI с именем <name>. Для корректной конфигурации необходимо определить как минимум корневой каталог документов.
acl <aclname> <criterion> [flags] [operator] <value> ...
Объявляет или дополняет список контроля доступа.
Подробности см. в описании директивы «acl» в разделе 4.2 и в разделе 7 об использовании ACL. Списки ACL, определённые для приложения FastCGI, доступны только ему. Их нельзя использовать в другом приложении или прокси. Аналогично приложение FastCGI не может использовать списки ACL, определённые в других секциях. Однако предопределённые ACL доступны.
docroot <path>
Задаёт корневой каталог документов на удалённом узле. <path> используется для формирования значений по умолчанию параметров FastCGI SCRIPT_FILENAME и PATH_TRANSLATED. Это обязательная настройка.
index <script-name>
Задаёт имя скрипта, добавляемое к URI, оканчивающемуся косой чертой («/»), чтобы получить значение по умолчанию параметра FastCGI SCRIPT_NAME. Это необязательная настройка.
Пример:
log-stderr global
Включает запись в журнал сообщений STDERR, выдаваемых приложением FastCGI.
Подробности см. в описании директивы «log» в разделе 4.2 . Это необязательная настройка. По умолчанию сообщения STDERR игнорируются.
pass-header <name> [ { if | unless } <condition> ]
Задаёт имя заголовка запроса, передаваемого приложению FastCGI. После него можно указать условие на основе ACL; тогда директива обрабатывается только при истинном условии.
Большинство заголовков запроса уже доступны приложению FastCGI с префиксом «HTTP_». Поэтому эта директива нужна только для передачи заголовков, которые намеренно исключаются. Сейчас исключаются заголовки «Authorization», «Proxy-Authorization» и заголовки, действующие только на одном участке соединения (hop-by-hop).
Обратите внимание: заголовки «Content-type» и «Content-length» никогда не передаются приложению FastCGI, поскольку уже преобразованы в параметры.
path-info <regex>
Задаёт регулярное выражение для извлечения script-name и path-info из пути после декодирования URL. <regex> может содержать две группы захвата: первая извлекает имя скрипта, вторая — path-info. Первая обязательна, вторая необязательна. Таким образом можно извлечь script-name из пути, игнорируя path-info. Это необязательная настройка. Если она не задана, сопоставление пути не выполняется, а параметры FastCGI PATH_INFO и PATH_TRANSLATED не заполняются.
Из соображений безопасности при заданном регулярном выражении в пути после декодирования URL запрещены символы перевода строки и нулевые символы. Ограничение связано с тем, что иначе сопоставление всегда завершается неудачей (из-за особенностей выполнения регулярных выражений в HAProxy). Поэтому, если после декодирования URL в пути обнаружен любой из этих двух символов, клиенту возвращается ошибка. Здесь применяется принцип наименьшего удивления.
Пример:
option get-values
Включает или отключает получение переменных управления соединениями.
При установке соединения HAProxy может отправить запись FCGI_GET_VALUES, чтобы получить значения следующих переменных:
* FCGI_MAX_REQS The maximum number of concurrent requests this
application will accept.
* FCGI_MPXS_CONNS "0" if this application does not multiplex connections,
"1" otherwise.
Некоторые приложения FastCGI не поддерживают эту возможность. Другие закрывают соединение сразу после отправки ответа. Поэтому по умолчанию этот параметр отключён.
Обратите внимание: максимальное число одновременных запросов, принимаемых приложением FastCGI, является переменной соединения. Оно ограничивает только число потоков на соединение. Если требуется ограничить общую нагрузку на приложение, необходимо задать параметры сервера «maxconn» и «pool-max-conn». Кроме того, если приложение не поддерживает мультиплексирование соединений, максимальное число одновременных запросов автоматически устанавливается в 1.
option keep-conn
Указывает приложению FastCGI, следует ли оставлять соединение открытым после отправки ответа.
Если параметр отключён, приложение FastCGI закрывает соединение после ответа на этот запрос. По умолчанию параметр включён.
option max-reqs <reqs>
Задаёт максимальное число одновременных запросов, которые принимает приложение.
Значение может быть переопределено, если при установке соединения получена переменная FCGI_MAX_REQS. Кроме того, если приложение не поддерживает мультиплексирование соединений, параметр игнорируется. Значение по умолчанию — 1.
option mpxs-conns
Включает или отключает поддержку мультиплексирования соединений.
Значение может быть переопределено, если при установке соединения получена переменная FCGI_MPXS_CONNS. По умолчанию параметр отключён.
set-param <name> <fmt> [ { if | unless } <condition> ]
Задаёт параметр FastCGI, который следует передать приложению. Его значение, определённое через <fmt>, должно соответствовать правилам пользовательского формата журнала (см. раздел 8.2.6
«Пользовательский формат журнала»). После него можно указать условие на основе ACL; тогда директива обрабатывается только при истинном условии.
Эта директива позволяет переопределять значения стандартных параметров FastCGI. Если вычисленное значение является пустой строкой, правило игнорируется. Директивы выполняются в порядке объявления.
Пример:
10.1.2. Секция прокси
use-fcgi-app <name> Задаёт приложение FastCGI, используемое бэкендом.
Аргументы:
Эта директива доступна только для прокси HTTP с возможностями бэкенда и хотя бы одним сервером FastCGI. При этом серверы FastCGI можно смешивать с серверами HTTP. Однако без веской причины делать это не рекомендуется (подробности см. в разделе 10.3 об ограничениях). Для каждого бэкенда одновременно можно определить только одно приложение.
Учтите: после привязки приложения FastCGI к бэкенду, в зависимости от конфигурации, часть обработки может выполняться даже для запросов, которые не отправляются на сервер FastCGI. Правила установки параметров и передачи заголовков приложению всё равно вычисляются.
10.1.3. Пример
frontend front-http mode http bind *:80 bind *:
use_backend back-dynamic if { path_reg ^/.+\.php(/.*)?$ }
default_backend back-static
backend back-static mode http server www A.B.C.D:80
backend back-dynamic mode http use-fcgi-app php-fpm server php-fpm A.B.C.D:9000 proto fcgi
fcgi-app php-fpm log-stderr global option keep-conn
docroot /var/www/my-app
index index.php
path-info ^(/.+\.php)(/.*)?$
10.2. Параметры по умолчанию
Приложение FastCGI с ролью Responder выполняет ту же задачу, что и программа CGI/1.1. Согласно спецификации CGI/1.1 (RFC3875), скрипту необходимо передавать несколько переменных. HAProxy задаёт их, а также некоторые другие переменные, часто используемые приложениями FastCGI. Все эти переменные можно переопределить, но делать это следует осторожно.
10.3. Ограничения
В текущей реализации есть ряд ограничений. Первое связано с тем, как некоторые заголовки запроса скрываются от приложений FastCGI. Это происходит при анализе заголовков на стороне бэкенда, до установки соединения. На этом этапе HAProxy знает, что бэкенд использует приложение FastCGI, но ещё не знает, будет ли запрос направлен на сервер FastCGI. Чтобы скрыть заголовки запроса, он просто удаляет их из сообщения HTX. Поэтому, если в итоге запрос направляется на сервер HTTP, тот никогда не увидит эти заголовки. По этой причине не рекомендуется смешивать серверы FastCGI и HTTP в одном бэкенде.
Аналогично правила «set-param» и «pass-header» вычисляются при анализе заголовков запроса. То есть они выполняются всегда, даже если запрос в итоге пересылается на сервер HTTP.
При применении правила «set-param» в сообщение HTX добавляется псевдозаголовок. Поэтому, как и при переписывании заголовков HTTP, операция может завершиться неудачей при заполненном буфере. Правила «set-param» конкурируют за место с правилами «http-request».
Наконец, все параметры FastCGI и заголовки HTTP отправляются в одной записи FCGI_PARAM. Эту запись необходимо закодировать за один проход, иначе возвращается ошибка обработки. Это означает, что размер закодированной записи FCGI_PARAM не должен превышать размер буфера. Однако соблюдать резерв свободного места здесь не требуется.
16 - 11. Таблицы привязок и одноранговые узлы
Таблицы привязок в HAProxy — это механизм, позволяющий ассоциировать определённое количество информации и метрик с ключом определённого типа на определённый срок после последнего обновления. Это можно рассматривать как строку в таблице с несколькими столбцами, где номер строки определяется значением ключа, а столбцы представляют отдельные критерии.
Таблицы привязок изначально были спроектированы для хранения информации о привязке сеанса между клиентом и сервером с целью поддержания постоянных сессий между этими сущностями. Клиент подключается или отправляет запрос, клиент идентифицируется с помощью дискриминатора (источний адрес, кука, URL параметр), и выбранный сервер сохраняется в ассоциации с этим дискриминатором в таблице привязок на заданное время, чтобы последующие запросы от того же клиента автоматически направлялись на тот же сервер, где клиент создавал свою сессию приложения.
Сегодня таблицы привязок могут хранить больше информации, чем просто номер сервера; могут храниться элементы, связанные с активностью конкретного клиента (счётчики/скорости запросов, соединений, байт и т.д.), а также некоторые произвольные счётчики (“gpc” — “General Purpose Counters”) и некоторые метки для обозначения определённых характеристик клиента (“gpt” — “General Purpose Tag”).
На таблицы привязок могут ссылаться директивы “stick”, обеспечивающие привязку клиента к серверу, правила “track-sc”, определяющие, какой ключ отслеживать в какой таблице для сбора метрик, а также функции извлечения образцов и преобразователи, которые могут немедленно найти заданный ключ и получить определённую метрику или данные. Общий принцип таков: обновление таблиц (gpt/gpc/metrics) и поиск сведений о привязке обновляют время доступа к записи и отодвигают срок её истечения. Простой поиск через функции извлечения образцов и преобразователи лишь получает данные, не отодвигая срок истечения записи.
Чтобы механизм масштабировался и сохранял работоспособность при перезагрузках HAProxy и переключении при отказе, обновлениями таблиц привязок можно обмениваться с другими узлами, называемыми “peers”, через механизм “Peers”, описанный в разделе 11.2 . Для точной настройки обмена можно также задать, что некоторые таблицы только получают сведения от одноранговых узлов либо что полученные от них обновления следует пересылать в другую таблицу.
Таблицы привязок можно объявлять в секциях прокси (фронтендах и бэкендах) директивой “stick-table”: в секции допускается лишь одна таблица, получающая имя секции. Либо их можно объявлять в секциях peers директивой “table”, за которой следует имя таблицы: так в одной секции “peers” можно определить несколько таблиц. Если нужно несколько таблиц привязок, обычно рекомендуется объявлять их в секции peers, когда предполагается обмен ими, либо создавать дополнительные секции бэкендов, содержащие только определение “stick-table”.
11.1. Объявление stick-table
Определение stick-table в секции прокси (“frontend”, “backend”, “listen”) и в секциях “peers” очень схоже, с тем, что вариант в секции пирсов требует обязательного имени и не принимает опции “peers”.
В секции “frontend”, “backend” или “listen”:
stick-table type <type> size <size> [expire <expire>] [nopurge] [recv-only] [write-to
<wtable>] [srvkey <srvkey>] [store <data_type>]* [brates-factor <factor>] [peers
<peersect>]
В секции “peers”:
table <name> type <type> size <size> [expire <expire>] [nopurge] [recv-only]
[write-to <wtable>] [srvkey <srvkey>] [store <data_type>]* [brates-factor <factor>]
Аргументы: (обязательные сначала, затем в алфавитном порядке):
тип
<type>Этот обязательный аргумент устанавливает тип ключа в<type>, который обычно представляет собой одно слово, но может также иметь собственные аргументы:ip Этот тип следует избегать в пользу более явного, например, “ipv4” или “ipv6”. До версии 3.2 он был единственным способом настройки IPv4. В 3.2 “ip” является алиасом для “ipv4”, а “ipv4” предпочтителен. В будущей версии “ip” будет соответствовать “ipv6”. Он предназначен только для упрощения перехода из пред-3.2 к пост-3.2.
ipv4 Таблица, объявленная с этим типом, будет хранить только адреса IPv4. Эта форма очень компактна (около 50 байт на запись) и обеспечивает очень быстрый поиск записей, при этом занимает почти никакой дополнительной памяти. Основное применение — хранение исходных IP-адресов клиентов.
ipv6 Таблица, объявленная с “type ipv6”, будет хранить только адреса IPv6. Эта форма очень компактна (около 60 байт на запись) и обеспечивает очень быстрый поиск записей, при этом занимает почти никакой дополнительной памяти. Основное применение — хранение исходных IP-адресов клиентов.
integer Таблица, объявленная с “type integer”, будет хранить 32-битные целые числа, которые могут представлять идентификатор клиента, найденный в запросе, например.
string [длина
<len>] Таблица, объявленная с “type string”, будет хранить подстроки длиной до<len>символов. Если строка, предоставленная паттерн-экстрактором, превышает<len>символов, она будет обрезана до хранения. При сравнении происходит сравнение не более чем<len>символов между строкой в таблице и извлечённым паттерном. Если длина не указана, строка автоматически ограничивается 32 символами. Увеличение длины может привести к значительному росту потребления памяти.binary [len
<len>] Таблица, объявленная с помощью “type binary”, будет хранить двоичные блоки из<len>байт. Если блок, предоставленный паттерн-экстрактором, превышает<len>, он будет обрезан до хранения. Если блок, предоставленный образцом выражения, короче<len>, он будет дополнен 0. При отсутствии указания блок автоматически ограничивается 32 байтами. Увеличение длины может привести к значительному росту потребления памяти.
size
<size>Этот обязательный аргумент устанавливает максимальное количество записей, которые могут быть размещены в таблице и составляют<size>. Значение напрямую влияет на использование памяти. Оцените примерно 50 байт на запись, дополнительно к размеру ключа выше, и, при необходимости, метрик, хранящихся в таблице, а также размер строки, если она есть. Размер поддерживает суффиксы “k”, “m”, “g” для 2^10, 2^20 и 2^30.expire
<delay>Определяет максимальное время существования записи в таблице с момента её создания, обновления с помощью ’track-sc’ или соответствующего соответствия с помощью ‘stick match’ или ‘stick on’ правила. Задержка истечения<delay>задаётся в стандартном формате времени, как и различные тайм-ауты, по умолчанию в миллисекундах. Максимальная продолжительность составляет чуть более 24 дней. См. секцию 2.5 для дополнительной информации. Если задержка истечения не указана, сессии не будут автоматически истекать, но при достижении полного объёма старейшие записи будут удаляться. Убедитесь, что не используется параметр “nopurge”, если задержка истечения не указана. Примечание: преобразователи ’table_*’ выполняют поиск, но не обновляют тайм-аут истечения, поскольку они не требуют ’track-sc’.brates-factor
<factor>Указывает множитель, применяемый к скорости входящих/исходящих байтов. Вместо подсчёта каждого байта, подсчитываются блоки байтов. Внутри, скорости определяются на 32-битных счётниках, ограничиваются примерно 4 миллиардами в период. Использование этого параметра позволяет иметь скорости, превышающие этот 4Г ограничение в течение заданного периода. Множитель должен быть больше 0 и меньше или равен 1024.nopurge означает, что мы отказываемся удалять старые записи при полном списке. При отсутствии этого параметра и при полном списке, когда HAProxy хочет сохранить запись, он удаляет несколько старых записей, чтобы освободить место под новые. Это чаще всего желаемое поведение. В некоторых специфических случаях может быть желательно отказаться от новых записей, вместо удаления старых. Это может быть актуально, когда объём данных для хранения значительно превышает аппаратные ограничения, и мы предпочитаем не предоставлять доступ новым клиентам, чем отклонять уже подключённых. При использовании этого параметра необходимо правильно настроить параметр “expire” (см. выше).
recv-only означает, что мы не планируем использовать список для выполнения обновлений, а только для получения данных от удалённого узла, на который мы ориентированы. Действительно, использование этого слова позволяет получать локальные значения, такие как “conn_cur”, которые по умолчанию не усваиваются, так как они конфликтуют с локальными обновлениями, выполняемыми на списке локальным узлом. Использование этого параметра актуально только для списков, не участвующих в отслеживании правил или методов, выполняющих обновления на списке, или, проще говоря, для удалённых списков, используемых только для получения информации.
peers
<peersect>Записи, создаваемые, обновляемые или обновляющиеся, будут отправлены в узлы секции<peersect>для синхронизации, а ключи, полученные от узлов в этой секции, также будут вставлены или обновлены в таблице. Кроме того, при запуске может быть выполнена попытка получения записей из более ранней версии процесса, обозначенной как «локальный узел» через эту секцию.srvkey
<srvkey>Указывает, как каждый сервер идентифицируется с целью привязки сеанса. Допустимые значения — “name” и “addr”. Если указано “name”, то используется аргумент<name>для сервера (может быть сгенерирован шаблоном). Если указано “addr”, то сервер идентифицируется по его текущему сетевому адресу, включая порт. “addr” особенно полезен, если вы используете открытие сервисов для генерации адресов серверов с привязкой сеанса и хотите использовать один и тот же хост на всех узлах для токена привязки сеанса.store
<data_type>Используется для хранения дополнительной информации в stick-table. Может быть использован в ACL для контроля различных критериев, связанных с активностью клиента, соответствующего stick-table. Для каждого указанного здесь элемента размер каждой записи будет увеличен, чтобы дополнительные данные могли поместиться. Множество типов данных может быть сохранено в записи. Множество типов данных может быть указано после ключевого слова “store”, как запятая-разделённый список. Альтернативно, возможно повторение ключевого слова “store” с одним или несколькими типами данных. Вместо типа “server_id”, который автоматически обнаруживается и включается, все типы данных должны быть явно объявлены для хранения. Если ACL ссылается на тип данных, который не хранится, то ACL просто не будет соответствовать. Некоторые типы данных требуют аргумента, который должен быть передан сразу после типа в скобках. См. ниже для поддерживаемых типов данных и их аргументов.write-to
<wtable>Указывает имя другой таблицы привязок, в которую будут записываться обновления узлов дополнительно к исходной таблице.<wtable>должен иметь тот же тип, что и таблица, определяемая в данном контексте, и должен иметь ту же длину ключа; исходная таблица не может быть использована в качестве целевой таблицы. При каждом получении обновления в исходной таблице через узел HAProxy пытается обновить соответствующую<wtable>запись. Если запись ещё не существует, она будет создана, в противном случае её значения будут обновлены, а также обновлена её таймер. Обратите внимание, что только типы, не участвующие в арифметических операциях, такие как server_id, server_key и gpt, будут записываться в<wtable>, чтобы предотвратить нарушение арифметических операций, выполняемых на локальной целевой таблице (например: предотвратить бесконечное увеличение общего счётчика). Один из распространённых случаев использования этой опции — возможность использования правил привязки (для сохранения соединений с серверами) в конфигурации кластера узлов, поскольку ключи для соответствия будут извлекаться из удалённых таблиц.
Типы данных, которые могут быть привязаны к записям с помощью директивы “store”, перечислены ниже. Важно учитывать, что памятные требования могут оказаться значительными при хранении большого количества типов данных. Действительно, хранение всех указанных ниже показателей одновременно в каждой записи может потребовать сотен байт на запись, или сотен мегабайт для таблицы из 1-миллион записей. По этой причине указано приблизительное значение объёма хранения для каждого типа в скобках после аргумента.
Аргументы:
bytes_in_cnt [4 байт] Это количество байт от клиента к серверу. Это положительное 64-битное целое число, которое подсчитывает суммарное количество байт, полученных от клиентов, соответствующих этому элементу. Заголовки включаются в подсчёт. Это может быть использовано для ограничения злоупотреблений в функциях загрузки на серверах фото или видео. Примечание: значения измеряются при входе данных в HAProxy, поэтому подсчёты не зависят от сжатия.
bytes_in_rate(
<period>) [12 байт] Это счётчик скорости передачи байт от клиента к серверу. Он принимает целочисленный параметр<period>, указывающий в миллисекундах длительность периода, в течение которого измеряется средняя скорость. Он отображает среднюю скорость входящей передачи байт за этот период, в байтах в период. Может использоваться для обнаружения пользователей, загружающих слишком много и слишком быстро. Предупреждение: при больших загрузках возможно, что объём переданных данных будет учтён один раз при завершении сессии, что приведёт к резким скачкам средней скорости передачи, вместо плавного изменения. Это может частично быть устранено с помощью “option contstats”, хотя это не является идеальным решением. Рекомендуется использовать byte_in_cnt для лучшего распределения нагрузки.bytes_out_cnt [4 байт] Это счётчик байт от сервера к клиенту. Это положительное 64-битное целое число, которое подсчитывает накопленное количество байт, отправленных клиентам, соответствующим этому вхождению. В счёт включаются заголовки. Может использоваться для ограничения злоупотреблений ботами, забирающими весь сайт. Примечание: значения измеряются при входе данных в HAProxy, поэтому счётчики не подвержены сжатию.
bytes_out_rate(
<period>) [12 байт] Это счётчик скорости передачи байт от сервера к клиенту. Он принимает целочисленный параметр<period>, указывающий в миллисекундах длительность периода, в течение которого измеряется средняя скорость. Он отображает среднюю скорость исходящей передачи байт за этот период, в байтах в период. Может использоваться для обнаружения пользователей, скачивающих слишком много и слишком быстро. Предупреждение: при больших передачах возможно, что объём переданных данных будет учтён один раз при завершении сессии, что приведёт к резким скачкам средней скорости передачи, вместо плавного изменения. Это может частично быть устранено с помощью “option contstats”, хотя это не является идеальным решением. Рекомендуется использовать byte_out_cnt для лучшего распределения нагрузки.conn_cnt [4 байт] Это количество соединений. Это положительное 32-битное целое число, которое подсчитывает абсолютное количество соединений, полученных от клиентов, соответствующих этому элементу. Оно не означает, что соединения были приняты, просто что они были получены.
conn_cur [4 байт] Это количество текущих соединений. Это положительное 32-битное целое число, которое хранит количество одновременных соединений для элемента. Оно увеличивается при получении входящего соединения, соответствующего элементу, и уменьшается при выходе соединения. Таким образом, можно определить в любое время точное количество одновременных соединений для элемента. Этот тип по умолчанию не учитывается с другими узлами, поскольку он не отражает никакой информации, так как игнорирует локальное значение. Однако в сочетании с recv-only он может использоваться для определения количества одновременных соединений, наблюдаемых у узлов.
conn_rate(
<period>) [12 байт] Это счётчик частоты соединений. Он принимает целочисленный параметр<period>, указывающий в миллисекундах длительность периода, в течение которого измеряется среднее значение. Он отображает среднюю интенсивность соединений за этот период, в соединениях на период. Результат — целое число, которое может быть использовано в ACL. Прием или отклонение соединений не влияет на их измерение.glitch_cnt [4 байт] Это счётчик сбоев на передающей стороне. Это положительное 32-битное целое число, которое подсчитывает накопленное количество сбоев, отмеченных на передающем соединении. Сбои соответствуют необычным или непредвиденным действиям (по протоколу) со стороны клиента, которые могут указывать на неисправный клиент или, возможно, на атакующего. Таким образом, этот счётчик может помочь принять решение о том, как действовать в таких случаях.
glitch_rate(
<period>) [12 байт] Счётчик частоты протокольных аномалий. Принимает целочисленный параметр<period>, задающий в миллисекундах длительность периода усреднения. Возвращает среднюю частоту аномалий на фронтенде за этот период. Может использоваться для обнаружения неисправных клиентов или потенциальных атакующих, выполняющих необычные или неожиданные с точки зрения протокола действия, если HAProxy отметил их как таковые.gpc(
<nb>) [4 *<nb>байт] Массив из<nb>элементов General Purpose Counter — счётчиков общего назначения. Это массив положительных 32-битных целых чисел, которыми можно считать что угодно. Чаще всего их используют как увеличиваемые счётчики в записях, например чтобы отметить достижение предела и запустить действия. Массив ограничен 100 элементами, от gpc0 до gpc99, чтобы сообщение обновления для однорангового узла помещалось в буфер. Пользователям следует учитывать, что большое число счётчиков увеличивает объём данных и трафик протокола peers, поскольку при изменении любого элемента передаются все данные и счётчики. Этот data_type исключает использование устаревших data_types ‘gpc0’ и ‘gpc1’ в той же таблице. При использовании массива ‘gpc’ в качестве data_type все функции извлечения образцов и действия для ‘gpc0’ и ‘gpc1’ применяются к первым двум элементам массива.gpc_rate(
<nb>,<period>) [12 *<nb>байт] Это массив скоростей увеличения общих целевых счётчиков за определённый период. Элементы этого массива — положительные 32-битные целые числа, которые могут использоваться для любых целей. Подобно<gpc>, счётчики событий, но вместо хранения накопленного значения, они сохраняют скорость увеличения счётчика. Чаще всего они используются для измерения частоты возникновения определённых событий (например, запросов к конкретному URL). Массив ограничен максимальным количеством 100 элементов: gpt(100), обеспечивающим хранение счётчиков gpc0 до gpc99, чтобы обеспечить вписывание сообщения о синхронизации узла в буфер. Массив не может содержать меньше 1 элементов: если требуется хранить только счётчик gpc0, используйте gpc(1). Пользователи должны учитывать, что большое количество счётчиков увеличивает объём данных и нагрузку на трафик при использовании протокола узлов, поскольку все данные/счётчики передаются при каждом обновлении. Это data_type исключает использование устаревшего data_types ‘gpc0_rate’ и ‘gpc1_rate’ в одной таблице. При использовании массива ‘gpc_rate’ data_type все операции по извлечению и обработке связанных с ‘gpc0’ и ‘gpc1’ счётчиков применяются к первым двум элементам этого массива.gpc0 [4 байт] Это первый общий счётчик. Это положительное 32-битное целое число, которое может использоваться для любых целей. Чаще всего оно используется для присвоения специальной метки определённым записям, например, чтобы отметить, что определённое поведение было обнаружено и должно быть известно для последующих совпадений.
gpc0_rate(
<period>) [12 байт] Это скорость увеличения первого общего счётчика за определённый период. Это положительное 32-битное целое число, которое может использоваться для любых целей. Подобно<gpc0>, оно подсчитывает события, но вместо хранения накопленного значения, оно сохраняет скорость увеличения счётчика. Чаще всего оно используется для измерения частоты возникновения определённых событий (например, запросов к конкретному URL).gpc1 [4 байт] Это второй общий счётчик. Это положительное целое число из 32 бит, которое может быть использовано для любых целей. Чаще всего оно применяется для присвоения специальной метки некоторым записям, например, чтобы отметить, что определённое поведение было обнаружено и должно быть известно для последующих совпадений.
gpc1_rate(
<period>) [12 байт] Это скорость увеличения второго общего счётчика за определённый период. Это положительное целое число из 32 бит, которое может быть использовано для любых целей. Подобно<gpc1>, оно подсчитывает события, но вместо хранения накопленного значения, оно сохраняет скорость увеличения счётчика. Чаще всего оно используется для измерения частоты появления определённых событий (например, запросов к конкретному URL).gpt(
<nb>) [4 *<nb>байт] Это массив из<nb>элементов общих меток. Это массив положительных целых чисел из 32 бит, которое может быть использовано для любых целей. Чаще всего они применяются для присвоения специальных меток некоторым записям, например, чтобы отметить, что определённое поведение было обнаружено и должно быть известно для последующих совпадений. Данный массив ограничен максимальным количеством 100 элементов: gpt(100) позволяет хранить метки gpt0 до gpt99, чтобы обеспечить вписывание сообщения о синхронизации в буфер. Массив не может содержать меньше 1 элементов: используйте gpt(1), если хотите хранить только метку gpt0. Пользователи должны учитывать, что большое количество счётчиков увеличит размер данных и нагрузку на трафик при использовании протокола пирсов, поскольку все данные/счётчики передаются при каждом обновлении. Данное data_type исключает использование устаревшего data_type ‘gpt0’ в той же таблице. При использовании массива ‘gpt’ data_type все запросы и действия, связанные с ‘gpt0’, будут применяться к первому элементу этого массива.gpt0 [4 байт] Это первый общий метка. Это положительное целое число с битом 32, которое может быть использовано для любых целей. Чаще всего оно применяется для постановки специальной метки на определённые записи, например, чтобы отметить обнаруженное конкретное поведение и обеспечить его знание для последующих совпадений.
http_req_cnt [4 байт] Это количество запросов HTTP. Это положительное целое число с битом 32, которое подсчитывает абсолютное количество запросов HTTP от клиентов, которые соответствовали этому элементу. Оно не учитывает, являются ли запросы действительными или нет. Примечание: это отличается от сессий при использовании постоянного соединения на стороне клиента.
http_req_rate(
<period>) [12 байт] Это счётчик частоты запросов. Он принимает целочисленный параметр<period>, указывающий в миллисекундах длительность периода, в течение которого вычисляется среднее значение. Он отображает среднюю интенсивность запросов HTTP в течение этого периода, в запросах за период. Результат — целое число, которое можно использовать в ACL. Не имеет значения, являются ли запросы действительными или нет. Примечание: это отличается от сессий при использовании постоянного соединения на клиентской стороне.http_err_cnt [4 байт] Это количество ошибок HTTP запросов. Это положительное целое число 32 бит, которое подсчитывает абсолютное количество ошибок HTTP запросов, вызванных клиентами, соответствующими данному входу. Ошибки учитываются для недопустимых и обрезанных запросов, а также для запрещённых или замедленных запросов, а также для неудачных попыток аутентификации. Если сервер отвечает кодом 4xx, запрос также считается ошибкой, поскольку ошибка была инициирована клиентом (например, сканирование уязвимостей).
http_err_rate(
<period>) [12 байт] Это счётчик частоты запросов HTTP. Он принимает целочисленный параметр<period>, указывающий в миллисекундах длительность периода, за который измеряется среднее значение. Счётчик возвращает среднюю частоту ошибок HTTP запросов за этот период, в запросах на период (см. http_err_cnt выше, что считается ошибкой). Результат — целое число, которое можно использовать в ACL.http_fail_cnt [4 байт] Это счётчик сбоев HTTP ответа. Это положительное целое число 32-бит, которое подсчитывает абсолютное количество сбоев HTTP ответов, вызванных серверами, соответствующими этому элементу. Ошибки учитываются при неверных и обрезанных ответах, а также при любых ответах 5xx, кроме 501 и 505. Предназначен для использования в сочетании с путём или URI для обнаружения сбоев сервиса.
http_fail_rate(
<period>) [12 байт] Это счётчик частоты сбоев HTTP ответа.
Он принимает целочисленный параметр<period>, указывающий в миллисекундах продолжительность периода,
за который измеряется среднее значение. Счётчик возвращает среднюю частоту сбоев HTTP ответа за этот
период, в запросах на период (см. http_fail_cnt выше, что считается сбоем). Результат — целое число,
которое можно использовать в ACL.server_id [4 байт] Это целое число, содержащее идентификатор сервера, к которому был присвоен запрос. Оно используется в правилах “stick match”, “stick store” и “stick on”. Оно включается автоматически при упоминании. Важно понимать, что привязка сеанса на основе учебной информации имеет некоторые ограничения, включая потерю всех изученных ассоциаций при перезапуске, если участники не настроены должным образом для передачи такой информации при перезапуске (рекомендуется). В целом привязка сеанса может быть хорошим дополнением к другим механизмам привязки сеанса, но не всегда может быть единственным механизмом.
sess_cnt [4 байт] Это количество сессий. Это положительное 32-битное целое число, которое подсчитывает абсолютное количество сессий, полученных от клиентов, соответствующих этому элементу. Сессия — это соединение, принятое слоем 4 правил (“tcp-request connection”).
sess_rate(
<period>) [12 байт] Это счётчик частоты сессий. Принимает целочисленный параметр<period>, указывающий в миллисекундах длительность периода, в течение которого вычисляется среднее значение. Отображает среднюю частоту входящих сессий за этот период, в сессиях за период. Результат — целое число, которое может использоваться в ACL.
Пример:
См. также: “stick match”, “stick on”, “stick store-request”, “track-sc”, секция 2.5 о формате времени, секция 11.2 о узлах, секция 9.7 о ограничениях пропускной способности и секция 7 о ACL.
11.2. Объявление одноранговых узлов
Записи любых типов данных в таблицах привязок можно распространять между несколькими экземплярами HAProxy по соединениям TCP в режиме с несколькими ведущими узлами. Каждый экземпляр отправляет свои локальные обновления и добавления удалённым одноранговым узлам. Переданные значения перезаписывают удалённые без агрегирования.
Исключение — тип данных “conn_cur”, который по умолчанию никогда не принимается от других узлов, поскольку должен отражать локальные значения. В старых версиях он синхронизировался по умолчанию, что приводило к отрицательным значениям в конфигурациях active-active и постоянному росту значений при перезагрузках или переключениях active-passive: локальное значение отражало больше соединений, чем имелось на самом деле. Однако иногда получать это значение от других узлов полезно, например для пассивной удалённой таблицы, используемой только для получения данных и мониторинга, без операций записи или обновления на её основе. Для этого в объявление таблицы добавляют “recv-only”. В любом случае сведения “conn_cur” всегда отправляются, чтобы системы мониторинга могли их наблюдать.
Прерванный обмен автоматически обнаруживается и возобновляется с последней известной точки. Кроме того, при мягком перезапуске старый процесс подключается к новому по такому соединению TCP и передаёт все свои записи до того, как новый процесс начнёт подключаться к другим одноранговым узлам. Это обеспечивает очень быструю репликацию при перезагрузке: обычно доли секунды даже для больших таблиц.
Учтите, что для удалённой идентификации серверов используются их ID. Поэтому важно, чтобы конфигурации были похожи или хотя бы чтобы для каждого сервера на всех участниках принудительно задавался один и тот же ID.
peers <peersect>
Создаёт новый список узлов с именем <peersect>. Это независимая секция, которая ссылается на одну или несколько таблиц привязок.
bind [<address>]:port [param*]
Определяет параметры привязки локального узла данной секции “peers”. Такие строки не поддерживаются в сочетании с строкой “peer” в той же секции “peers”.
disabled
Отключает секцию подруг. Отключает как прослушивание, так и любую синхронизацию, связанную с этой секцией. Данная возможность позволяет отключить синхронизацию таблиц привязок без необходимости закомментировать все “peers”.
default-bind [param*]
Определяет параметры привязки для локального узла, исключая его адрес.
default-server [param*]
Изменить стандартные параметры для сервера в секции “peers”.
Аргументы:
См. также: “server” и секция 5 о параметрах сервера
enabled
Это включает секцию «peers», которая ранее была отключена с помощью ключевого слова “disabled”.
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
“peers” секции поддерживают тот же “log” ключевое слово, что и для прокси в логировании информации о
“peers” слушателе. См. “log” опцию для прокси для дополнительных деталей.
peer <peername> [<address>]:port [param*]
Определяет узел внутри секции узлов. Если <peername> установлен в имя локального узла (по умолчанию имя хоста, или заданное с помощью команды “-L” или настройки “localpeer” в глобальной конфигурации), HAProxy будет ожидать входящее соединение от удалённого узла на указанном адресе. В противном случае адрес определяет место подключения для присоединения к удалённому узлу, а <peername> используется на уровне протокола для идентификации и проверки удалённого узла на стороне сервера.
При мягком перезапуске адрес локального узла используется старым экземпляром для подключения к новому и инициализации полного реплицирования (процесса обучения).
Рекомендуется иметь идентичную декларацию узлов на всех узлах и полагаться только на аргумент командной строки “-L” или настройку “localpeer” в глобальной конфигурации для изменения имени локального узла. Это упрощает поддержку единообразных конфигурационных файлов на всех узлах.
Можно использовать ссылки на переменные среды в параметре адреса, см. секцию 2.3 о переменных среды.
Примечание: ключевое слово “peer” может быть прозрачно заменено на ключевое слово “server” (см. объяснение ключевого слова “server” ниже).
server <peername> [<address>:<port>] [param*]
Как уже упоминалось, ключевое слово “peer” может быть заменено ключевым словом “server” с поддержкой всех
параметров “server”, приведённых в секции 5.2, относящихся к настройкам транспорта. Если удалённый узел локален, параметр адреса не должен присутствовать; он должен быть указан в строке “bind” (см. ключевое слово “bind” этой “peers” секции).
Некоторые параметры “server” неактуальны для секций “peers”. Узлы по своей природе не поддерживают динамическое разрешение имен хостов и проверку работоспособности, поэтому параметры, такие как “init_addr”, “resolvers”, “check”, “agent-check” или “track”, не поддерживаются. Аналогично, отсутствует балансировка нагрузки и привязка сеанса, поэтому параметры, такие как “weight” или “cookie”, не имеют эффекта.
Пример:
shards <shards>
В некоторых конфигурациях желательно распределять содержимое stick-table по некоторым узлам вместо отправки всего содержимого stick-table каждому узлу, указанному в секции “peers”. В таких случаях, “shards” указывает количество узлов, участвующих в распределении содержимого stick-table. См. также параметр сервера “shard”.
table <tablename> type {ip | integer | string [len <length>] | binary [len <length>]}
size `<size>` [expire `<expire>`] [write-to `<wtable>`] [nopurge] [store `<data_type>`]*
[recv-only]
Настройте таблицу привязки сеанса для текущей секции. Эта строка парсится точно так же, как и ключевое слово “stick-table” в других секциях, за исключением аргумента “peers”, который здесь необязателен и имеет дополнительный обязательный первый параметр для обозначения stick-table. В отличие от других секций, в секциях “peers” может быть несколько строк “table” (см. также полное определение ключевых слов “table” и “stick-table” в секции 11.1 выше).
Также следует учитывать, что секции “peers” имеют собственные пространства имен stick-table для предотвращения коллизий между именами stick-table, идентичными в разных секциях “peers”. Это внутренне реализуется путем присоединения к названию таблиц привязки сеансов имени секции “peers” и добавления символа ‘/’ после него. Если где-то ещё в конфигурационном файле необходимо ссылаться на такие таблици привязки, объявленные в секциях “peers”, то необходимо использовать префиксированное имя stick-table в следующем виде:
Это также версия с префиксом имени stick-table, которая должна использоваться для ссылки на таблицы привязок через CLI.
Для протокола “peers” такого различия не требуется, поскольку обмениваться данными могут только одноранговые узлы “peers”, принадлежащие одной секции. В нескольких секциях “peers” можно объявлять таблицы привязок с одинаковым именем. По сети передаётся сокращённое имя stick-table. Префикс состоит только из символа ‘/’, чтобы избежать конфликтов имён stick-table между таблицами, объявленными как бэкенды, и stick-table в секциях “peers”, как в следующей необычной, но поддерживаемой конфигурации:
Здесь таблица “t1” объявленная в секции “mypeers” имеет глобальное имя “mypeers/t1”. Таблица “t1” объявленная как бэкенд имеет глобальное имя “t1”. Однако на уровне протокола узла первая таблица называется “/t1”, вторая снова называется “t1”.
17 - 12. Другие секции
Секции, описанные ниже, реже используются и обычно поддерживают лишь несколько параметров. Между ними нет неявной связи. Они все начинаются с одного ключевого слова. Ни одна из них не допускается до секции “global”. Поддержка некоторых из них может зависеть от опций сборки (например, что касается SSL).
12.1. Трассировка
Для отладки можно включить трассировку подсистемы HAProxy. При этом выводятся отладочные сообщения об определённой подсистеме. Это мощное средство диагностики проблем. Трассировку можно динамически настраивать через CLI. Некоторые параметры также можно заранее задать в файле конфигурации, в отдельных секциях “traces”. Подробнее о трассировке см. руководство по управлению. Это инструмент разработчика для сложных сеансов отладки. Он выводит много сообщений и требует дополнительных ресурсов, поэтому используйте его осторожно. Поскольку это инструмент разработчика, обратная совместимость этой секции не гарантируется.
traces
Начинает новую секцию traces. Одна или несколько секций “traces” могут быть использованы. Все директивы оцениваются в порядке объявления, последующие перекрывают предыдущие.
trace <source> <args...>
Настраивает подсистему “trace”. Каждая из них может быть найдена в руководстве по управлению и соответствует идентичной синтаксису. Любое выведение, которое бы произвело команда “trace”, будет выведено во время этапа парсинга секции. Чаще всего это будут ошибки и предупреждения, но некоторые неполные команды могут перечислить допустимые варианты. Эта команда не предназначена для обычного использования, она будет рекомендована разработчикам только в ходе сложных сессий отладки. Важно помнить, что в зависимости от уровня трассировки и детализации, включение трассировок может серьёзно снизить глобальную производительность. См. руководство по управлению для синтаксиса команд.
Пример:
12.2. Списки пользователей
Возможно, контролировать доступ к frontend/backend/listen секциям или к статистике HTTP, разрешая только авторизованным и авторизованным пользователям. Для этого необходимо создать хотя бы один пользовательский список и определить пользователей.
userlist <listname>
Создаёт новый пользовательский список с именем <listname>. Множество независимых пользовательских списков может быть использовано для хранения данных аутентификации и авторизации для независимых клиентов.
group <groupname> [users <user>,<user>,(...)]
Добавляет группу <groupname> в текущий список пользователей. Возможность привязать пользователей к этой группе достигается с помощью перечисления имен, разделённых запятыми, предшествующих ключевому слову “users”.
user <username> [password|insecure-password <password>]
Добавляет пользователя <username> в текущий список пользователей. Можно использовать как зашифрованные (зашифрованные), так и незашифрованные (нешифрованные) пароли. Зашифрованные пароли оцениваются с помощью функции crypt(3), поэтому в зависимости от возможностей системы могут поддерживаться различные алгоритмы. Например, современные системы Linux на базе Glibc поддерживают MD5, SHA-256, SHA-512 и, конечно, классический метод шифрования паролей на основе DES.
Внимание: следует учитывать, что использование зашифрованных паролей может привести к значительному увеличению CPU,
в зависимости от количества запросов и алгоритма, используемого для их обработки. Для любых вариантов хеширования
пароль для каждого запроса должен быть обработан через выбранный алгоритм до того, как он будет сравниваться
с значением, указанном в конфигурационном файле. Большинство современных алгоритмов специально разработаны
для того, чтобы быть трудными в вычислении с целью сопротивления атакам подбором. Они не просто выполняют
хеширование ясного текста пароля один раз, а тысячи раз. Это может быстро привести к значительному увеличению
общего потребления HAProxy’а в виде CPU и даже вызвать сбои приложения!
Чтобы снизить высокое использование хэш-функций CPU, одним из подходов является уменьшение числа итераций хэш-функции (алгоритмы SHA) или сокращение «стоимости» функции, если это возможно.
Как примечание, реализации musl (например, Alpine Linux) известны тем, что при расчёте хэшей они медленнее, чем их аналоги на glibc, поэтому стоит также учитывать этот аспект.
Все пароли считаются обычными аргументами и, следовательно, подлежат стандартному секции 2.2
Ограничению и экранированию. Поэтому рекомендуется экранировать пароли с помощью одиночных кавычек.
Пример:
Примечание, что оба списка функционально идентичны.
12.3. Почтовые серверы
Возможно, отправлять электронные письма при изменении состояния серверов. Если настроены электронные уведомления, они отправляются каждому получателю, указанному в секции mailers. Электронные письма отправляются получателям через Lua (см. examples/lua/mailers.lua).
mailers <mailersect>
Создаёт новый список рассылки с именем <mailersect>. Это независимая секция, которая ссылается на один или более прокси.
mailer <mailername> <ip>:<port>
Определяет почтового отправителя внутри секции почтовых отправителей.
Пример:
timeout mail <time>
Определяет время, доступное для установления соединения и передачи письма на сервер. Если не определено, значение по умолчанию — 10 секунд. Для обеспечения передачи как минимум двух SYN-ACK пакетов в ходе инициализации TCP рукопожатия рекомендуется сохранять это значение выше 4 секунд.
Пример:
12.4. Ошибки HTTP
Возможно, глобально объявить несколько групп HTTP ошибок, которые затем импортируются в любую секцию прокси. Та же группа может быть ссылана в нескольких местах и может быть полностью или частично импортирована.
http-errors <name>
Создайте новую группу http-errors с именем <name>. Это независимая секция, которая может быть
использована одним или несколькими прокси с помощью её имени.
errorfile <code> <file>
Привязать содержимое файла к коду ошибки HTTP
Аргументы:
Пожалуйста, обратитесь к ключевому слову “errorfile” в секции 4 для подробностей.
Пример:
12.5. Кольцевые буферы
Возможно, глобально объявить кольцевые буферы, которые будут использоваться в качестве целей для лог-серверов или трейсов.
ring <ringname>
Создаёт новый кольцевой буфер с именем <ringname>.
backing-file <path>
Это заменяет обычное выделение памяти на файл, отображаемый через RAM, для хранения кольца. Это может быть полезно для сбора трассировок или логов для последующего анализа, без необходимости подключения медленного клиента к CLI. Новые записи автоматически заменяют старые, поэтому всегда доступны самые свежие данные. Записи в кольце станут видны в этом файле сразу после остановки процесса (обычно они станут видны очень быстро, но такого гарантии нет, поскольку записи не синхронизируются).
При использовании этой опции общая объём памяти уменьшается на размер структуры “struct ring”, начинающейся в начале области, необходимой для восстановления содержимого области. Файл будет создан с правами владельца пользователя, который его запустил, с режимом 0600 и размером, заданным директивой “size”. При парсинге директивы (включая проверку конфигурации) любой существующий не пустой файл будет сначала переименован с дополнительным суффиксом “.bak”, а любой ранее существовавший файл с суффиксом “.bak” будет удалён. Это обеспечивает, что мгновенная перезагрузка или перезапуск процесса не приведёт к потере важной информации для отладки, и даёт администратору время заметить новый файл “.bak” и архивировать его при необходимости. Таким образом, после сбоя файл, обозначенный <path>, будет содержать самую свежую информацию, а при перезапуске сервиса сам файл “<path>.bak” будет содержать эту информацию. Это означает, что общий объём памяти, необходимый для хранения, будет вдвое превышать размер кольца. Ошибки при перезаписи файла игнорируются, поэтому размещение файла в каталоге без прав на запись будет достаточным для избежания резервной копии, если это не требуется.
ПРЕДУПРЕЖДЕНИЕ: использование этой функции имеет последствия с точки зрения стабильности и безопасности. Во-первых, запись в кольцо на медленное устройство (например, физический жесткий диск) может привести к заметному замедлению при доступах, и в случае слишком большого количества потоков, конкурирующих за доступ, может даже вызвать сбой. Во-вторых, внешний процесс, изменяющий указанную область, может привести к сбою процесса HAProxy или к перезаписи его собственной памяти с отпечатками. В-третьих, если файловая система заполняется до того, как заполнится кольцо, записи в кольцо могут привести к сбою процесса.
Информация, содержащаяся в этом кольце, структурирована и НЕ может быть напрямую прочитана с помощью текстового редактора (хотя большая часть её выглядит почти непрочитаемой). Вывод этого файла предназначен только для разработчиков.
description <text>
Описание — это необязательная строка описания кольца. Оно будет отображаться на CLI. По умолчанию, <name> используется для заполнения этого поля.
format <format>
Формат, используемый для хранения событий в кольцевой буфер.
Аргументы:
maxlen <length>
Максимальная длина сообщения об событии, хранящегося в кольце, включая сформированный заголовок. Если длина сообщения об событии превышает <length>, оно будет обрезано до этой длины.
server <name> <address> [param*]
Настраивает сервер syslog по tcp для пересылки сообщений из кольцевого буфера. Поддерживаются все параметры “server” из пункта 5.2. Некоторые из них не имеют смысла для секций “ring”. Важный момент: добавлять в кольцевой буфер несколько серверов почти бессмысленно, поскольку каждый из них получает одну и ту же копию его содержимого, и буфер продвигается со скоростью самого медленного сервера. Если один сервер не отвечает, старые сообщения нельзя будет удалять, что может заблокировать добавление новых. Для отправки сообщений нескольким серверам следует использовать отдельный кольцевой буфер для каждого сервера журналирования, а не привязывать несколько серверов к одному буферу. Специальная директива сервера “log-proto” задаёт протокол отправки сообщений.
size <size>
Это опциональный размер кольцевой буферной памяти в байтах. Значение по умолчанию установлено на BUFSIZE.
timeout connect <timeout>
Установите максимальное время ожидания завершения попытки соединения с сервером.
Аргументы:
timeout server <timeout>
Установите максимальное время пребывания ожидающих данных в буфер вывода.
Аргументы:
Пример:
12.6. Пересылка журналов
Возможно, объявить одну или несколько секций пересылки журналов, HAProxy будет пересылать все полученные сообщения о логах на список серверов логов.
log-forward <name>
Создаёт новый прокси-пересылатель логов, идентифицированный как <name>.
backlog <conns>
Объявите подсказки системе о желаемом приблизительном размере ожидаемого количества соединений при принятии соединений.
bind <addr> [param*]
Используется для настройки слушателя потокового журнала для получения сообщений для пересылки. Поддерживаются параметры “bind”, описанные в разделе 5.1, включая параметры ssl, однако некоторые утверждения, такие как “alpn”, могут быть нерелевантны для протокола syslog через TCP. Такие слушатели поддерживают как режим «Подсчет октетов», так и режим «Непрозрачное формирование кадров», как определено в rfc-6587.
dgram-bind <addr> [param*]
Используется для настройки слушателя датаграмм логов, предназначенного для получения сообщений и их передачи. Адреса должны быть в формате IPv4 или IPv6, за которым следует порт. Поддерживается часть параметров “bind”, описанных в разделе 5.1, включая “interface”, “namespace” или “transparent”; остальные параметры игнорируются безусловно, так как не относятся к случаю UDP/syslog.
log global
Используется для настройки серверов логирования целей. См. подробности в документации по прокси. Если формат не указан, HAProxy пытается сохранить входной формат логов. Настроенный флаг игнорируется, если входное сообщение не содержит флага, но такой флаг обязателен на выходном формате. Если в входном формате отсутствует временная метка, но такое поле присутствует в выходном формате, HAProxy использует локальную дату.
Пример:
maxconn <conns>
Исправьте максимальное количество одновременных соединений на лог-форвардере. 10 — значение по умолчанию.
timeout client <timeout>
Установите максимальное время неактивности с клиента.
option assume-rfc6587-ntf
Приказывает HAProxy рассматривать поступающие TCP потоки логов всегда как использующие непрозрачную оболочку. Этот параметр упрощает логику оболочки и обеспечивает единообразное обработку сообщений, особенно при работе с некорректно сформированными начальными символами.
option dont-parse-log
Позволяет HAProxy передавать сообщения syslog без попытки их парсить и переформатировать, полезно
для пересылки сообщений, которые могут не соответствовать традиционным форматам. Этот параметр следует использовать вместе
с настройкой format raw на целевые лог-цели, чтобы сохранить исходное содержимое сообщения.
option host { replace | fill | keep | append }
Задаёт стратегию обработки поля hostname в секции log-forward для исходящих сообщений syslog в форматах rfc3164 или rfc5424.
replace If input message already contains a value for the hostname field,
we replace it by the source IP address from the sender.
If input message doesn't contain a value for the hostname field
(ie: '-' as input rfc5424 message or non compliant rfc3164 or
rfc5424 message), we use the source IP address from the sender as
hostname field.
fill If input message already contains a value for the hostname field,
we keep it.
If input message doesn't contain a value for the hostname field
(ie: '-' as input rfc5424 message or non compliant rfc3164 or
rfc5424 message), we use the source IP address from the sender as
hostname field.
(This is the default)
keep Если входное сообщение уже содержит значение поля hostname,
мы сохраняем его.
Если входное сообщение не содержит значения поля hostname,
мы устанавливаем его в 'localhost' (rfc3164) или '-' (rfc5424).
append Если входное сообщение уже содержит значение поля hostname,
мы добавляем запятую, за которой следует IP-адрес отправителя.
Если входное сообщение не содержит значения поля hostname,
мы используем IP-адрес отправителя.
Для всех перечисленных опций, если адрес исходного IP-адреса от отправителя недоступен (то есть: UNIX/ABNS socket), то получаемая стратегия будет “keep”.
Примечание: данное опция актуально только для формата логов rfc3164 или rfc5424. В противном случае настройка не окажет видимого эффекта.
12.7. Хранилище сертификатов
HAProxy использует внутренний механизм хранения для загрузки и хранения сертификатов, используемых в конфигурации.
Этот механизм хранения может быть настроен с помощью секции “crt-store”. Она позволяет настроить определения сертификатов и указать, какие файлы должны быть загружены в неё. Определение сертификата должно быть записано до его использования в других частях конфигурации.
crt-store [<name>]
Секция “crt-store” может принимать необязательное имя в качестве аргумента. Если имя указано, каждый сертификат этого хранилища должен ссылаться с помощью “@<name>/<crt>” или “@<name>/<alias>”.
Файлы в хранилище сертификатов также могут обновляться динамически с помощью CLI. См. “set ssl cert” в секции в руководстве по управлению 9.3 .
В секции “crt-store” поддерживаются следующие ключевые слова:
- crt-base
- key-base
- load
crt-base <dir>
Присваивает стандартную директорию для получения сертификатов SSL при использовании относительного пути с директивами “crt”. Абсолютные пути, указанные явно, имеют приоритет и игнорируют “crt-base”. При использовании в хранилище сертификатов игнорируется crt-base секции глобальной конфигурации.
key-base <dir>
Присваивает стандартную директорию для получения приватных ключей SSL при использовании относительного пути с директивами “key”. Абсолютные пути, указанные явно, имеют приоритет и игнорируют “key-base”. При использовании в crt-store игнорируется key-base секции глобального раздела.
load [crt <filename>] [param*]
Загружайте файлы SSL в хранилище сертификатов. Для списка параметров см. секцию “12.7.1. Опции загрузки”
Пример:
12.7.1. Параметры загрузки
Загрузите файлы SSL в хранилище сертификатов. Слово load может принимать несколько параметров, перечисленных ниже. Эти ключевые слова также могут использоваться в crt-list.
crt <filename>
Этот аргумент является обязательным, он загружает PEM, в котором должно быть указано публичное сертификат, но может также содержать сертификаты промежуточного уровня и приватный ключ. Если в этом файле не указан приватный ключ, ключ может быть указан с помощью ключевого слова “key”.
acme <string>
Этот параметр позволяет настроить протокол ACME для заданного сертификата. Это экспериментальная функция, требующая ключевого слова “expose-experimental-directives” в секции глобального уровня.
При использовании ключевого слова “acme” в crt-store возможно запускать без существующего сертификата на диске. Вместо этого будет использоваться временная пара ключей до генерации сертификата ACME. Это поведение является исключительным для crt-stores, ни строка crt-list, ни строка ssl-f-use не могут достичь такого результата без предварительного объявления crt-store.
См. также секцию 12.8 (“ACME”) и “domains” в этой секции.
alias <string>
Вариантный аргумент. Позволяет присвоить сертификату имя, чтобы он мог быть ссылаться на него в конфигурации. Имя должно предваряться символом ‘@/’ при использовании в других частях конфигурации.
domains <string>
Настройте список доменов, которые будут использоваться для ACME сертификатов. Первый домен в списке используется как CN. Домены разделяются запятыми в списке.
См. также секцию 12.8 (“ACME”) и “acme” в этой секции.
Пример:
ips <string>
Настройте список IP-адресов, которые будут включены как IP SAN в сертификате ACME. IP-адреса в списке разделяются запятыми.
Создание сертификата с IP-адресами может потребовать использования профиля “shortlived”.
См. также секцию 12.8 (“ACME”), “acme” и “domains” в этой секции.
Пример:
key <filename>
Этот аргумент является необязательным. Загрузите приватный ключ в формате PEM. Если приватный ключ уже был определён в “crt”, он заменит его.
ocsp <filename>
Этот аргумент является необязательным, он загружает ответ в формате OCSP в DER. Он может быть обновлён с помощью CLI.
issuer <filename>
Этот аргумент является необязательным. Загрузите издателя OCSP в формате PEM. Для идентификации того, к какому сертификату относится ответ OCSP, необходим сертификат издателя. Если сертификат издателя не найден в файле “crt”, его можно загрузить из файла с помощью этого аргумента.
sctl <filename>
Этот аргумент является необязательным. Поддержка расширения Certificate Transparency (RFC6962) TLS включена.
Файл должен содержать действительный список подписанного времени сертификации, как описано в RFC. Файл анализируется для проверки базовой синтаксической корректности, но подписи не проверяются.
ocsp-update [ off | on ]
Включите автоматическое обновление ответа OCSP при значении ‘on’, отключите в противном случае. Значение по умолчанию — ‘off’. Чтобы включить автоматическое обновление OCSP на строке bind, можно использовать этот параметр в crt-store или global-опцию “tune.ocsp-update.mode”. Если сертификат используется в нескольких crt-lists с разными значениями параметра ‘ocsp-update’, будет выдана ошибка. Аналогично, если сертификат наследует global-опцию на строке bind и имеет несовместимо заданный явный параметр ‘ocsp-update’ в crt-list, будет выдана та же ошибка.
Примеры:
Вот пример конфигурации, включающей его с помощью crt-list:
haproxy.cfg:
haproxy.list:
Вот пример конфигурации, включающей его с использованием crt-store:
haproxy.cfg:
Когда опция устанавливается в ‘on’, мы попытаемся получить ответ OCSP каждый раз, когда в сертификате фронтенда найден URI OCSP. Единственным ограничением этого режима является необходимость того, чтобы издатель сертификата был известен для построения идентификатора сертификата OCSP. Каждый ответ OCSP будет обновляться как минимум раз в час, и ещё чаще, если срок действия конкретного ответа OCSP истекает раньше этого часового лимита. Останется минимальный интервал обновления в 5 минут, чтобы избежать слишком частых обновлений ответов, срок действия которых очень короток или вообще отсутствует. Из-за этого жёсткого ограничения, следует отметить, что при включении автоматического обновления в ‘on’, любые ответы OCSP, загруженные при инициализации, не будут обновляться до тех пор, пока не пройдёт как минимум 5 минут, даже если их срок действия истекает до текущего времени плюс 5 минут. Это не должно быть слишком большим препятствием, поскольку ответ OCSP должен быть действительным при загрузке во время инициализации (срок действия должен быть в будущем), и, следовательно, маловероятно, что такой ответ истечёт так быстро после инициализации. С другой стороны, если сертификат имеет указанную URI OCSP и отсутствует ответ OCSP, установка этой опции в ‘on’ для данного сертификата обеспечит автоматическое получение ответа OCSP сразу после инициализации. Значения минимального и максимального задержек (5 минут и 1 часа соответственно) могут быть настроены с помощью глобальных опций “ocsp-update.maxdelay” и “ocsp-update.mindelay”.
Каждый раз, когда обновляется ответ OCSP автоматической задачей обновления или в результате вызова команды “update ssl
ocsp-response” CLI, генерируется отдельная строка лога. Она следует специфическому формату, содержащему следующий заголовок “<OCSP-UPDATE>” и последующую информацию, связанную с OCSP: — путь к соответствующему сертификату фронтенда — числовое состояние обновления — текстовое состояние обновления — количество сбоев обновления для данного ответа — количество успешных обновлений для данного ответа. См. команду “show ssl ocsp-updates” CLI для полного списка кодов ошибок и сообщений об ошибках. Эта строка генерируется независимо от успешности или неуспешности обновления ответа OCSP. Запрос/ответ OCSP передаётся и получается через экземпляр http_client, у которого установлено опция dontlog-normal и который использует стандартный формат лога HTTP в случае ошибки (например, недоступный ответчик OCSP). Если возникает такая ошибка, дополнительно генерируется строка лога, содержащая информацию, связанную с HTTP, и одновременно с «обычной» строкой OCSP (в которой, скорее всего, будет указано «ошибка HTTP»). Однако, если возникает чистая ошибка HTTP (например, недоступный ответчик OCSP), дополнительно генерируется строка лога, следующая за стандартным форматом HTTP log-format. Ниже приведены два примера таких строк лога: сначала пример строки лога успешного обновления OCSP, затем пример ошибки HTTP с двумя разными строками (строки были выведены, а URL было сокращено для удобства чтения):
Устранение неполадок: Частой ошибкой, которая может возникнуть при использовании сертификатов Let’s Encrypt, является то, что разрешение DNS предоставляет адрес IPv6, а в вашей системе отсутствует действительный исходящий маршрут IPv6. В таком случае вы можете либо создать соответствующий маршрут, либо установить опцию “httpclient.resolvers.prefer ipv4” в секции глобального настройки. В случае ошибки “проверка ответа OCSP неудачна” рекомендуется проверить, является ли предоставленный сертификат издателя действительным. Более точное сообщение об ошибке может быть отображено в скобках после общего сообщения об ошибке. Ошибка может возникать при “проверка ответа OCSP неудачна” или при ошибке “ошибка при вставке”.
jwt [ off | on ]
Разрешить использование этого сертификата для проверки JWT или дешифровки через преобразователь “jwt_verify_cert”, “jwt_decrypt_cert” или “jwt_decrypt” при установке значения ‘on’. Значение по умолчанию — ‘off’.
При установке значения ‘on’ для заданного сертификата команда CLI “del ssl cert” не будет работать. Для удаления сертификата он должен не использоваться ни для проверки SSL, ни для проверки JWT.
Эту опцию можно изменить в режиме работы с помощью команд “add ssl jwt” и “del ssl jwt” CLI. См. также команду “show ssl jwt” CLI.
generate-dummy [ off | on ]
Разрешает генерацию приватного ключа и его самоподписанных сертификата в момент парсинга при установке в
‘on’. Это может быть полезно, если в ходе тестирования нет доступного сертификата, например. В этом случае, “keytype”, “bits” и “curves” могут быть использованы для настройки приватного ключа.
При отсутствии использования, значение по умолчанию — ‘off’. (см. также “keytype”, “bits” и “curves”).
keytype [ RSA | ECDSA ]
Разрешает выбор типа приватного ключа, используемого для генерации самоподписанных сертификатов при парсинге. В случае, если “generate-dummy” установлен в ‘on’ для этого сертификата, применяется такой режим. При отсутствии указания значение по умолчанию — ‘RSA’. (см. также “generate-dummy”).
bits <number>
Настройте количество бит, необходимое для генерации сертификата со знаком RSA при том, что “generate-dummy” установлен в ‘on’ для этого сертификата со знаком и “keytype” установлен в ‘RSA’. При отсутствии использования значение по умолчанию — 2048. (см. также “generate-dummy”).
curves <string>
Настройте кривые при том, что “generate-dummy” установлен в ‘on’ и “keytype” установлен в ‘ECDSA’ для этого самоподписного сертификата. По умолчанию — ‘P-384’.
12.8. ACME
acme <name>
Протокол ACME может быть настроен с помощью секции “acme”. Секция принимает аргумент “<name>”, который используется для привязки сертификата к секции.
Секция ACME позволяет настроить HAProxy как клиента ACMEv2. Эта функция является экспериментальной, что означает, что “expose-experimental-directives” должен быть указан в глобальной секции, чтобы можно было использовать эту функцию.
Руководство доступно на HAProxy wiki https://github.com/haproxy/wiki/wiki/ACME:--native-haproxy
- The feature is limited to the http-01, dns-01 or dns-persist-01 challenges
на данный момент. http-01 полностью обрабатывается HAProxy, но dns-01 и dns-persist-01 требуют либо API датаплэйна, либо другого 3 стороннего инструмента для взаимодействия с поставщиком DNS API. dns-persist-01 требует только установки записи TXT один раз, поэтому она может быть настроена вручную без использования инструмента.
- It is possible to start without an existing certificate on the disk. To do
таким образом, сертификат должен быть настроен в хранилище crt. При использовании ключевого слова “acme” в хранилище crt будет использован временный пароль ключей до генерации сертификата ACME.
- The current HAProxy architecture is a non-blocking model, access to the disk
не должен выполняться после загрузки конфигурации, поскольку это может заблокировать цикл событий, блокируя трафик на том же потоке. Означает, что сертификаты и ключи, сгенерированные в HAProxy, должны быть экспортированы снаружи HAProxy с помощью “dump ssl cert” на сокете статуса. Экспорт сертификатов можно автоматизировать с помощью API планировщика или скрипта HAProxy-dump-certs, предоставленного в директории admin/cli/.
Планировщик ACME запускается при старте HAProxy, он проходит по сертификатам и запускает задачу ACME обновления при прохождении времени notAfter + (notAfter - notBefore) / 12, или 7 дней, если notBefore не определён. Планировщик затем спит и пробуждается через 12 часов. Возможность ручного запуска задачи обновления осуществляется с помощью команды “acme renew”. См. также “acme status” в руководстве по управлению.
Следующие ключевые слова доступны в секции ACME:
account-key <filename>
Настройте путь к ключу учетной записи. Ключ должен быть сгенерирован до запуска HAProxy. Если не используется ключ учетной записи, секция acme попытается загрузить файл по имени секции “<name>.account.key”. Если файл не существует, HAProxy сгенерирует его, используя параметры из секции acme.
Также можно сгенерировать вручную ключ RSA приватного ключа с помощью OpenSSL:
Или ecdsa один:
acme-vars <string>
Передавайте произвольные переменные внешнему инструменту DNS для настройки (например, dataplaneAPI) через синтаксис “dpapi”. Семантика зависит от конкретного инструмента; см. документацию вашего инструмента DNS для настройки.
Этот ключ имеет смысл только в случае, когда тип вызова равен “dns-01” или “dns-persist-01”.
См. также: “challenge”, “provider-name”
bits <number>
Настройте количество бит, необходимое для генерации сертификата RSA. По умолчанию — 2048. Установка слишком высокого значения может вызвать предупреждение, если ваша машина не имеет достаточной производительности. (Это может быть настроено с помощью “warn-blocked-traffic-after”, однако блокировка трафика слишком долго может сработать с watchdog.)
challenge <string>
Принимает тип вызова в качестве параметра, этот параметр должен быть http-01, dns-01 или dns-persist-01. При отсутствии использования данного параметра по умолчанию выбирается http-01.
dns-persist-01 реализует draft-ietf-acme-dns-persist. В отличие от dns-01, он использует статическую запись TXT в “_validation-persist.<domain>”, которая устанавливается один раз и не изменяется между перезагрузками. Запись должна содержать идентификатор аккаунта URI и опциональную политику. Тип вызова dns-persist-DNS не требует прав на запись в провайдере API при каждом обновлении.
challenge-ready <value>[,<value>]*
Настройте условия, которые должны быть выполнены перед уведомлением сервера ACME о готовности днс-01 вызова для проверки. Допустимые значения:
Множественные значения могут быть объединены запятой. При указании нескольких условий HAProxy обрабатывает их в следующем порядке: сначала ожидает подтверждения CLI (“cli”), затем применяет начальный задержку (“delay”), затем выполняет DNS проверки (“dns”).
Этот параметр совместим только с типами вызова dns-01 и dns-persist-01.
Когда “challenge” установлен в “dns-01” и этот параметр не настроен, значение по умолчанию — “cli”.
Когда “challenge” установлен в “dns-persist-01” и этот параметр не настроен, значение по умолчанию равно
“dns,delay”.
Когда “challenge” установлен в “dns-persist-01”, всегда выполняется инициальный опциональный DNS проверка до оценки challenge-ready условий. Поскольку запись “_validation-persist.<domain>” TXT устанавливается один раз и не изменяется между перезагрузками, HAProxy проверяет в момент перезагрузки, присутствует ли запись. Если проверка успешно проходит для всех доменов, вызов проверки немедленно выполняется без прохождения challenge-ready этапов (cli, delay, dns). Если проверка не проходит, HAProxy переходит к обычному challenge-ready потоку.
Пример:
contact <string>
Электронная почта для связи, которая будет привязана к ключу учетной записи в CA.
curves <string>
При использовании типа ключа ECDSA настройте кривые. По умолчанию — P-384.
directory <string>
Этот ключ конфигурирует каталог URL для сертификатного агента, используемого в этой секции acme. Этот ключ является обязательным, поскольку отсутствует стандартный URL.
Пример:
dns-delay <time>
Настройте задержку, используемую условиями “challenge-ready” «delay» и «dns». Значение — время, выраженное в формате времени HAProxy (например, «5m», «300s»). По умолчанию — 30 секунд.
Её роль зависит от используемых условий “challenge-ready”:
Примечание: разрешение проходит через настроенный раздел “default” резолверов, а не через авторитетные серверы имен. Результаты могут поэтому все еще быть подвержены кэшированию DNS на уровне резолвера.
dns-timeout <time>
Когда “challenge-ready” содержит “dns”, настройте максимальное время, разрешающееся для успешного разрешения записи TXT перед отменой вызова. Значение — время, выраженное в формате времени HAProxy (например, “10m”, “600s”). По умолчанию — 600 секунд.
Таймер начинается с момента первого запуска попытки разрешения DNS (после первичного “dns-delay”). Если следующая попытка разрешения была бы запущена после истечения тайм-аута, вызов отменяется с ошибкой. Это предотвращает бесконечный цикл повторных попыток при сбое распространения DNS.
См. также: “dns-delay”
keytype <string>
Настройте тип ключа, который будет сгенерирован. Значение может быть либо “RSA”, либо “ECDSA”. Вы также можете настроить “curves” для ECDSA и количество “bits” для RSA. По умолчанию генерируются ключи EC384.
map <map>
Настройте карту, которая будет использоваться для хранения токена (ключ) и отпечатка (значение), что позволяет отвечать на вызов при использовании нескольких аккаунтов. Задача acme добавит записи до проверки вызова и удалит их в конце выполнения задачи.
profile <string>
Запросите конкретный профиль сертификата у Центра сертификации, включив поле “profile” в запрос нового заказа. Это реализует draft-ietf-acme-profiles.
Имена профилей — это краткие идентификаторы, специфичные для каждого CA (например, “classic”, “shortlived”). При задании профиля имя профиля передаётся без изменений в полезную нагрузку нового заказа JSON. CA может игнорировать запрос или возвращать ошибку, если профиль не поддерживается. При отсутствии задания профиля поле профиля не включается, и CA использует свою стандартную политику выдачи.
См. https://letsencrypt.org/docs/profiles/ для профилей Let’s Encrypt.
Пример:
provider-name <string>
Задайте имя провайдера DNS, передаваемое внешнему инструменту DNS управления (например, dataplaneAPI) через приемник “dpapi”. Допустимые значения зависят от инструмента; обратитесь к документации вашего инструмента управления DNS.
Этот ключ имеет смысл только в случае, когда тип вызова равен “dns-01” или “dns-persist-01”.
См. также: “challenge”, “acme-vars”
reuse-key { on | off }
Если установлено “on”, HAProxy не генерирует новый приватный ключ и сохраняет предыдущий. Ротация приватных ключей рекомендуется; при включении этой опции рекомендуется регулярно вручную пересоздавать ключи.
Этот параметр может быть полезен при использовании ключей RSA, больших чем 2048, которые могут занимать время на генерацию и могут замедлять одну нитку, выполняющую такую операцию.
Использование одного и того же ключа может быть полезным при работе с кэшем вашего ACME сервера, так как это поможет получить соответствующий действительный сертификат для текущего ключа.
Предварительное значение — “off”.
Пример:
eab-key-id <filename>
Укажите путь к файлу идентификатора ключа EAB. Средство аутентификации предоставляется Центром сертификации и должно быть размещено на указанном пути до запуска HAProxy. Оно используется только при создании аккаунта.
Файл должен содержать простую строку ASCII.
Средства аутентификации EAB требуются только при первоначальном создании аккаунта ACME и могут быть удалены в дальнейшем, либо из конфигурации, либо путем очистки файлов. Пустой файл игнорируется без сообщения. Пробелы не игнорируются, за исключением завершающей строки.
См. также: “eab-mac-key”, “eab-mac-alg”
eab-mac-key <filename>
Настройте путь к файлу ключа EAB MAC. Ключ предоставляется CA и должен быть размещён по указанному пути до запуска HAProxy. Используется только при создании учётной записи.
Файл должен содержать закодированный в формате base64url ключ MAC.
Ключи EAB требуются только при первоначальном создании учётной записи ACME и могут быть удалены впоследствии, либо из конфигурации, либо путём очистки файлов. Пустой файл игнорируется без сообщения. Пробелы не игнорируются, за исключением завершающей строки.
См. также: “eab-key-id”, “eab-mac-alg”
eab-mac-alg { HS256 | HS384 | HS512 }
Настройте алгоритм MAC, используемый для подписи EAB. По умолчанию — HS256. Ключ EAB MAC должен быть достаточно велик, чтобы поддерживать заданный алгоритм MAC. Не все Центры сертификации поддерживают алгоритмы, кроме HS256.
См. также: “eab-key-id”, “eab-mac-key”
12.9. Проверки работоспособности
Возможно, глобально объявить несколько проверок работоспособности, которые могут быть использованы серверами во всей конфигурации, заменяя локальную конфигурацию прокси.
healthcheck <name>
Создан новый проверка работоспособности с именем <name>. Это имя должно быть уникальным. Оно следует использовать в строке сервера для ссылки на конкретную секцию проверки работоспособности.
type <type>
Определяет тип проверки работоспособности. Этот параметр обязательный. Поддерживаются следующие типы проверки работоспособности:
* tcp-check
* httpchk
* ssl-hello-chk
* smtpchk
* pgsql-check
* redis-check
* mysql-check
* ldap-check
* spop-check
Каждый тип использует те же параметры, что и соответствующий опции прокси. Например, параметры метода, URI… могут быть указаны для типа “httpchk”:
Примеры:
См. также: “option tcp-check”, “option httpchk”, “option ssl-hello-chk”, “option smtpchk”, “option mysql-check”, “option pgsql-check”, “option redis-check”, “опция ldap-check” и “опция spop-check”
http-check comment <string>
Добавьте конкретное правило http-check для проверки здоровья “httpchk”. Используется та же синтаксис, что и в соответствующих директивы прокси. См. соответствующую документацию по прокси для подробностей.
tcp-check comment <string>
Добавьте конкретное правило tcp-check для проверки здоровья “tcp-check”. Используется та же синтаксис, что и в соответствующих директивы прокси. См. соответствующую документацию по прокси для подробностей.
18 - 1. Предварительные требования
В этом документе описаны запуск, остановка, управление HAProxy и устранение неполадок, а также некоторые известные
ограничения и подводные камни, которых следует избегать. Настройка HAProxy здесь не рассматривается (об этом читайте
в configuration.txt
).
Предполагается, что читатель обладает достаточными навыками администрирования UNIX-подобной операционной системы, ежедневно использует командную оболочку и знаком с утилитами устранения неполадок, такими как strace и tcpdump.
19 - 2. Архитектура HAProxy
HAProxy — многопоточный неблокирующий демон с событийной архитектурой. Это означает, что для планирования всех своих действий он использует мультиплексирование событий, вместо того чтобы полагаться на системный планировщик при переключении между ними. Чаще всего он работает как один процесс, поэтому вывод “ps aux” в системе показывает только один процесс “haproxy”, кроме случаев, когда идёт плавная перезагрузка конфигурации и старый процесс завершает работу параллельно с новым. Поэтому его работу всегда легко отслеживать с помощью утилиты strace. Чтобы масштабироваться с ростом числа доступных процессоров, по умолчанию haproxy запускает по одному рабочему потоку на каждый процессор, на котором ему разрешено выполняться. Если явно не задана иная конфигурация, входящий трафик распределяется между всеми этими потоками, каждый из которых выполняет один и тот же цикл событий. Особое внимание уделяется сведению зависимостей между потоками к строгому минимуму, чтобы добиться масштабируемости, близкой к линейной. Это имеет ряд следствий, в частности каждое соединение обслуживается одним потоком. Поэтому для использования всей доступной вычислительной мощности необходимо как минимум столько же соединений, сколько потоков, что почти всегда обеспечивается.
HAProxy спроектирован так, чтобы при запуске изолировать себя в окружении chroot, где он вообще не может обращаться к файловой системе. Это относится и к библиотекам, от которых он зависит (например, libc, libssl и т. д.). Непосредственное следствие: работающий процесс не может повторно загрузить файл конфигурации, чтобы применить изменения; вместо этого запускается новый процесс с обновлённым файлом конфигурации. Есть и менее очевидные последствия: некоторые файлы часовых поясов или настройки разрешения имён, к которым libc может попытаться обратиться во время выполнения, не будут найдены, хотя обычно этого происходить не должно, поскольку после запуска они не нужны. Полезное следствие этого принципа — процесс HAProxy совершенно не сохраняет состояние, и после его принудительного завершения не нужна очистка: любой действенный способ завершения приведёт к правильному результату.
HAProxy не записывает файлы журналов, а использует стандартный протокол syslog для отправки записей на удалённый сервер (который часто находится на той же системе).
Для соблюдения тайм-аутов HAProxy использует внутренние часы, которые основаны на системном времени, но корректируют неожиданные отклонения. Для этого ограничивается время ожидания события в poll() и измеряется фактическая длительность ожидания. На практике оно никогда не превышает одну секунду. Поэтому при запуске strace для полностью бездействующего процесса видны периодические вызовы poll() (или одного из его вариантов), заключённые между двумя вызовами gettimeofday(). Это нормально, совершенно безвредно и настолько дёшево, что создаваемая нагрузка совершенно незаметна в масштабе системы; ничего необычного здесь нет. Пример:
HAProxy — TCP-прокси, а не маршрутизатор. Он работает с установленными соединениями, проверенными ядром, а не с пакетами какого-либо вида или сокетами в других состояниях (например, не с SYN_RECV и не с TIME_WAIT), хотя их наличие может помешать привязке к порту. Приём входящих соединений и установление исходящих он поручает системе. Непосредственное следствие: пакеты, наблюдаемые с двух сторон пересылаемого соединения, не связаны друг с другом и могут различаться размером, количеством и даже семейством. Поскольку соединение можно принять только с сокета в состоянии LISTEN, все прослушиваемые сокеты обязательно видны при использовании утилиты “netstat” для отображения прослушивающих сокетов. Пример:
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1629/sshd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 2847/haproxy tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 2847/haproxy
20 - 3. Запуск HAProxy
HAProxy запускается путём вызова программы “haproxy” с передачей на командной строке нескольких аргументов. Фактический синтаксис следующий:
где [<options>]* — произвольное число параметров. Параметр всегда начинается с ‘-’, за которым следуют одна или несколько букв и, возможно, один или несколько дополнительных аргументов. Без параметров HAProxy показывает страницу справки с перечнем поддерживаемых параметров. Доступные параметры могут немного различаться в зависимости от операционной системы. Многие из них имеют аналоги в секции “global”. В таком случае командная строка всегда имеет приоритет над файлом конфигурации, что позволяет быстро принудительно задать настройки, не изменяя конфигурационные файлы. Текущий список параметров:
-- <cfgfile>*
все аргументы, следующие за “–”, являются путями к файлу/директории конфигурации, которые должны быть загружены и обработаны в порядке объявления. Это особенно полезно при использовании оболочки для загрузки большого количества файлов, упорядоченных по числовому значению. См. также “-f”. Разница между “–” и “-f” заключается в том, что перед каждым именем файла должно стоять одно “-f”, в то время как перед всеми именами файлов достаточно одного “–”. Оба варианта могут использоваться вместе, порядок аргументов командной строки остаётся действительным. При указании более чем одного файла каждый файл должен начинаться на границе секции, так что первое ключевое слово каждого файла должен быть одним из “global”, “defaults”, “peers”, “listen”, “frontend”, “backend”, и так далее. Файл не может содержать только список серверов, например.
-f <cfgfile|cfgdir>
добавляет <cfgfile> в список конфигурационных файлов для загрузки. Если <cfgdir> — директория, то все файлы (и только файлы), содержащиеся в ней, добавляются в лексикографическом порядке (используя LC_COLLATE=C), в список конфигурационных файлов для загрузки; добавляются только файлы с расширением “.cfg”, только не скрытые файлы (не начинающиеся с “.”). Конфигурационные файлы загружаются и обрабатываются в порядке их объявления. Данную опцию можно указывать несколько раз для загрузки нескольких файлов. См. также “–”. Разница между “–” и “-f” заключается в том, что перед каждым именем файла необходимо указывать один “-f”, в то время как перед всеми именами файлов достаточно одного “–”. Оба варианта могут использоваться вместе, порядок аргументов командной строки всё ещё применяется. При указании более чем одного файла каждый файл должен начинаться на границе секции, поэтому первое ключевое слово каждого файла должно быть одним из “global”, “defaults”, “peers”, “listen”, “frontend”, “backend” и так далее. Файл не может содержать только список серверов, например.
-C <dir>
переходит в каталог <dir> перед загрузкой файлов конфигурации. Это удобно при использовании относительных путей. Будьте осторожны с подстановочными знаками после “–”: оболочка раскрывает их ещё до запуска haproxy.
-D
запускать как демон. Процесс отсоединяется от текущего терминала после создания дочернего процесса, и ошибки больше не отображаются в терминале. Это эквивалентно ключу “daemon” в секции “global” конфигурации. Рекомендуется всегда включать его в любых скриптах инициализации, чтобы некорректная конфигурация не мешала загрузке системы.
-L <name>
изменяет имя локального однорангового узла на <name>; по умолчанию используется локальное имя хоста. Применяется только для репликации peers. Чтобы сослаться на имя узла в конфигурационном файле, можно использовать переменную $HAPROXY_LOCALPEER.
-N <limit>
задаёт для каждого прокси значение maxconn по умолчанию, равное <limit>, вместо встроенного значения (обычно 2000). Полезно только для отладки.
-V
включить режим подробного вывода (отключает режим тишины). Отменяет эффект “-q” или “quiet”.
-W
режим master-worker. Эквивалентен директиве “master-worker” в секции “global” конфигурации. В этом режиме запускается главный процесс (“master”), контролирующий рабочие процессы (“workers”). HAProxy можно перезагрузить напрямую, отправив главному процессу сигнал SIGUSR2. Режим master-worker совместим как с работой на переднем плане, так и с режимом демона. Рекомендуется использовать его при многопроцессном запуске и с systemd.
-Ws
Режим master-worker с поддержкой типа службы systemd notify.
-4
принудительно ограничивает DNS-резолверы запросами и приёмом только адресов IPv4 (записей “A”). Это может помочь при проблемах в средах без сквозной связности по обоим стекам. Параметр переопределяет глобальную директиву “dns-accept-family”, принудительно устанавливая её в “ipv4”.
-c
только проверяет файлы конфигурации и завершается, не пытаясь привязаться к портам. Код завершения равен нулю при успехе и ненулевому значению при ошибке. Если есть предупреждения, о них сообщается. По умолчанию сообщение об успехе не выводится. В сочетании с “-V” при успехе выводится сообщение “Configuration file is valid”.
Скрипты должны определять успешность команды по коду завершения.
-cc
вычисляет условие в том же формате, что используется в условных блоках конфигурации. Код завершения равен нулю, если условие истинно, 1 — если ложно, и 2 — при ошибке.
-d
включает режим отладки. Он отключает режим демона, заставляет процесс оставаться на переднем плане и показывать входящие и исходящие события. Его никогда нельзя использовать в сценарии инициализации.
-dA[file]
сразу после загрузки конфигурации сохраняет в указанном файле архив tar со всеми зависимостями, обнаруженными при запуске. Это эквивалентно “set-dumpable libs”, но библиотеки сохраняются в файл, а не удерживаются в памяти. Это можно использовать после получения дампа памяти процесса, чтобы передать разработчикам все библиотеки, необходимые для его анализа. Возможность доступна не во всех операционных системах. Настоятельно рекомендуется использовать её с обычными файлами конфигурации, а при ручном запуске — при необходимости с “-c”, чтобы haproxy завершился сразу после сохранения архива, не начиная работу. Пример:
-dC[key]
выводит файл конфигурации. Вывод формируется после разбиения строк на токены, поэтому комментарии удалены, а отступы приведены к единому виду. Если задан ненулевой ключ, строки обрезаются перед чувствительными или конфиденциальными полями, а идентификаторы и адреса хешируются этим ключом по тому же алгоритму, что используется в режиме анонимизации CLI. Поэтому вывод можно безопасно передать разработчику, которому нужно разобраться в дампе, анонимизированном тем же ключом. См. также команду CLI “set anon”.
-dD
включает диагностический режим. В нём выводятся дополнительные предупреждения о подозрительных конструкциях конфигурации. Они никогда не препятствуют запуску, даже в режиме “zero-warning”, и не меняют код завершения.
-dF
отключает ускоренную пересылку данных. Этот механизм оптимизирует пересылку, передавая данные напрямую между сторонами без пробуждения потока. Данная директива позволяет отключить оптимизацию. Учтите, что она также отключает механизм tcp splicing в ядре. Команда не предназначена для обычного использования: как правило, разработчики рекомендуют её лишь при сложной отладке.
-dG
отключает использование getaddrinfo() для разрешения имён хостов в адреса. Параметр можно применять при подозрении, что getaddrinfo() работает неправильно. Он появился из-за множества ошибочных реализаций getaddrinfo() в разных системах, вызывающих труднодиагностируемые аномалии.
-dI
разрешает небезопасный вызов fork. Эквивалентен “insecure-fork-wanted” в секции global. Может пригодиться при запуске всех reg-тестов с ASAN, которым нужно запускать addr2line через fork для разрешения адресов.
-dK<class[,class]*>
выводит список зарегистрированных ключевых слов каждого класса. Список классов доступен через “-dKhelp”. Для вывода всех классов используется “-dKall”, иначе можно указать выбранные классы из справки через запятую. Формат зависит от класса: например, “cfg” показывает известные ключевые слова конфигурации в формате, похожем на конфигурационный файл, а “smp” — функции извлечения образцов, предварённые матрицей совместимости с наборами правил. Такие данные редко используются человеком напрямую, но очень полезны внешним инструментам, выявляющим новые ключевые слова для автоматического обновления документации, файлов подсветки синтаксиса, парсеров конфигурации, API и т. п. Формат может со временем немного меняться, поэтому настоятельно рекомендуется использовать вывод главным образом для поиска отличий от предыдущих архивов. Учтите, что перечисляются не все ключевые слова: многие появились задолго до создания подсистем регистрации и в них не представлены. Однако новые ключевые слова добавляются только современными механизмами, поэтому вывод позволяет достаточно точно обнаруживать расширение языка. Вывод выполняется только после полного разбора конфигурации, чтобы учесть даже динамически созданные ключевые слова. Удобный способ вывести список и завершиться — выполнить тихую проверку существующей конфигурации:
Если файла конфигурации нет, “-f /dev/null” также позволяет вывести все ключевые слова по умолчанию. Однако код завершения будет ненулевым из-за отсутствия слушателя, и его придётся игнорировать.
-dL
выводит список динамических разделяемых библиотек, загруженных к окончанию обработки конфигурации. Обычно в него также входят косвенные зависимости, например загруженные кодом Lua, и сам исполняемый файл. Формат достаточно легко обработать для непосредственного создания архива tar со всеми зависимостями. Поскольку параметр не останавливает запуск программы, рекомендуется использовать его только совместно с “-c” и “-q”: тогда выводится лишь список загруженных объектов либо ничего при ошибке. Кроме того, передавая такой пакет для анализа файла дампа памяти процесса, учитывайте, что большинство библиотек на самом деле являются символическими ссылками, которые необходимо разыменовывать при создании архива:
При запуске в режиме подробного вывода (-V) также перечисляются диапазоны адресов разделяемых библиотек, если не включён тихий режим (-q).
-dM[<byte>[,]][help|options,...]
принудительно включает заполнение памяти контрольным байтом и/или меняет другие параметры отладки памяти. При таком заполнении каждая область, выделенная через malloc() или pool_alloc(), перед передачей вызывающей стороне заполняется значением <byte>. Если <byte> не задан, используется 0x50 (‘P’). Это немного замедляет работу, но помогает надёжно воспроизвести ошибки из-за пропущенной инициализации, вызывающие случайные аварийные завершения. Учтите: -dM0 фактически превращает любой malloc() в calloc(). Если применение параметра приводит к появлению или исчезновению проблемы, в haproxy есть ошибка, о которой следует сообщить. Другие параметры можно указывать отдельно либо после запятой, следующей за байтом. Специальный параметр “help” выводит список поддерживаемых параметров и их текущие значения. Каждый параметр отладки можно принудительно включить или отключить. Оптимальные значения обычно выбираются при сборке согласно операционной системе и не требуют изменения без рекомендации разработчика. Поддерживаются следующие параметры отладки (включение/отключение):
- fail / no-fail:
- без слияния / слияние:
- холодный первый / горячий первый:
- целостность / без целостности:
- резервная копия / no-backup:
- без глобального / глобальный:
- без кэширования / кэширование:
- caller / без-вызова:
- tag / без-метки:
- опасный / без-опасного:
-dR
отключает параметр сокета SO_REUSEPORT для прослушиваемых портов. Эквивалентен директиве “noreuseport” в секции “global”. Может применяться в многопоточных конфигурациях при проблемах распределения нагрузки между потоками haproxy, которые можно наблюдать через top.
-dS
отключает системный вызов splice(). Эквивалентен директиве “nosplice” в секции “global”. Может применяться при подозрении на неправильную работу splice() или связанные с ним проблемы производительности, а также при просмотре пересылаемых данных через strace: при использовании splice() эти данные не видны.
-dT
отключает ktls. Эквивалентен директиве “noktls” в секции “global”. В основном полезен при подозрении на ошибку, связанную с ktls.
-dV
отключает проверку SSL на стороне сервера. Эквивалентен “ssl-server-verify none” в секции “global”. Полезен для воспроизведения проблем рабочей среды за её пределами. Никогда не используйте его в сценарии инициализации: он снижает безопасность SSL-соединений с серверами.
-dW
Если параметр задан, haproxy откажется запускаться, если при обработке конфигурации было выдано хотя бы одно предупреждение. Это помогает обнаруживать неочевидные ошибки и сохранять конфигурацию аккуратной и переносимой между версиями. Рекомендуется задавать этот параметр в сценариях службы, когда конфигурациями управляют люди, но не рекомендуется применять его к автоматически создаваемым конфигурациям, которые обычно вызывают больше предупреждений. Его можно сочетать с “-c”, чтобы предупреждения приводили к неуспешному результату проверки конфигурации. Он эквивалентен глобальному параметру “zero-warning”.
-dZ
отключает пересылку данных в режиме “zero-copy”. Эквивалентен директиве “tune.disable-zero-copy-forwarding” в секции “global”. Может помочь при потере данных или нарушении их целостности, а также при просмотре пересылаемых данных через strace, поскольку отключает и механизм tcp splicing в ядре.
-db
отключает фоновый и многопроцессный режимы. Процесс остаётся на переднем плане. Параметр в основном используется при разработке или небольших тестах: для остановки достаточно Ctrl-C. Никогда не используйте его в сценарии инициализации.
-dc
включает отладку привязки к CPU. Перед запуском выводится список выбранных и исключённых CPU вместе с их топологией.
-de
отключает механизм опроса “epoll”. Эквивалентен директиве “noepoll” в секции “global”. В основном полезен при подозрении на ошибку этого механизма. В системах с поддержкой epoll вместо него обычно используется механизм “poll”.
-dk
отключает механизм опроса “kqueue”. Эквивалентен директиве “nokqueue” в секции “global”. В основном полезен при подозрении на ошибку этого механизма. В системах с поддержкой kqueue вместо него обычно используется механизм “poll”.
-dp
отключает механизм опроса “poll”. Эквивалентен директиве “nopoll” в секции “global”. В основном полезен при подозрении на ошибку этого механизма. В системах с поддержкой poll вместо него обычно используется “select”, который нельзя отключить и который ограничен 1024 файловыми дескрипторами.
-dr
игнорирует ошибки разрешения адресов серверов. При проверке конфигурации вне рабочей среды часто нет доступа к тем же резолверам, из-за чего разрешение адресов завершается ошибкой и мешает тестированию. Параметр просто добавляет метод “none” в список методов разрешения адресов всех серверов, чтобы даже при неудаче libc последовательность запуска не прерывалась.
-dt [<trace_desc>,...]
включает трассировку с выводом в stderr. Без аргумента включаются все источники трассировки на уровне ошибок. Это особенно полезно для обнаружения нарушений протокола клиентами или серверами. Необязательный аргумент задаёт список конфигураций трассировки, разделённых символом ‘,’. Каждый элемент включает один или все источники. Для каждого элемента можно дополнительно задать уровень и подробность вывода, отделив их от имени источника символом ‘:’. При неверном имени уровня или степени подробности выводится список допустимых ключевых слов. Например, удобно сначала указать ‘help’ в каждом поле, чтобы посмотреть список.
-dv
отключает механизм опроса “evports”. Эквивалентен директиве “noevports” в секции “global”. В основном полезен при подозрении на ошибку этого механизма. В системах с поддержкой портов событий (SunOS на основе Solaris 10 и новее) вместо него обычно используется механизм “poll”.
-m <limit>
ограничивает объём выделяемой памяти для данных процесса значением <limit> в мегабайтах. В зависимости от объёма памяти, необходимого для обычной работы, это может привести к отказам в приёме соединений или замедлению. Обычно параметр нужен, чтобы принудительно проверить работу haproxy при ограниченных ресурсах. Важно учитывать, что память не является общей для процессов haproxy, а дочерний процесс, созданный системным вызовом fork(), наследует ограничения ресурсов родителя. Поэтому в режиме master-worker этот предел применяется отдельно к главному процессу и созданному им рабочему процессу.
-n <limit>
ограничивает число соединений на процесс значением <limit>. Эквивалентен директиве “maxconn” секции global и имеет над ней приоритет. Позволяет быстро принудительно снизить предел, чтобы избежать недоступности службы в системах со слишком низкими ограничениями ресурсов.
-p <file>
при запуске записывает PID всех процессов в <file>. Эквивалентен директиве “pidfile” в секции “global”. Файл открывается до перехода в окружение chroot и после вызова chdir(), подразумеваемого параметром “-C”. Каждый PID записывается отдельной строкой.
-q
включает режим “quiet”, отключающий вывод сообщений. Можно сочетать с “-c”, чтобы только проверить корректность файла конфигурации.
-S <bind>[,bind_options...]
в режиме master-worker создаёт сокет CLI главного процесса, позволяющий обращаться ко всем процессам: работающим и завершающимся. Из соображений безопасности рекомендуется привязывать этот CLI к локальному сокету UNIX. Параметры привязки те же, что у директивы “bind” в конфигурации, но слова разделяются запятыми вместо пробелов.
Учтите, что через этот сокет нельзя получить прослушивающие сокеты старого процесса при плавной перезагрузке конфигурации.
-sf <pid>*
после завершения запуска отправляет старым процессам сигнал завершения “finish” (SIGUSR1), предлагая закончить текущую работу и выйти. <pid> — список PID получателей, по одному на аргумент. Список заканчивается при появлении любого параметра, начинающегося с “-”. Пустой список допустим, поэтому его удобно формировать на лету по результату команды вроде “pidof” или “pgrep”.
-st <pid>*
после завершения запуска отправляет старым процессам сигнал “terminate” (SIGTERM), немедленно завершая их без окончания текущей работы. <pid> — список PID получателей, по одному на аргумент. Список заканчивается при появлении любого параметра, начинающегося с “-”. Пустой список допустим, поэтому его удобно формировать на лету по результату команды вроде “pidof” или “pgrep”.
-v
отчёт по версии и дате сборки
-vv
показывает версию, параметры сборки, версии библиотек и доступные механизмы опроса. Этот вывод всегда запрашивают при сообщении об ошибке.
-x <unix_socket>
подключается к указанному сокету, пытается получить прослушивающие сокеты старого процесса и использует их вместо создания новых привязок. Это позволяет не терять новые соединения при перезагрузке конфигурации в Linux.
Без режима master-worker эту возможность необходимо включить на сокете статистики с помощью “expose-fd listeners” в конфигурации.
В режиме master-worker “expose-fd listeners” не требуется: при перезагрузке главный процесс автоматически использует эту возможность через синтаксис “sockpair@”, позволяющий напрямую подключиться к рабочему процессу без сокета статистики из конфигурации. Чтобы отключить это поведение, можно передать -x /dev/null.
Безопасный способ запуска HAProxy из файла инициализации — принудительно включить режим демона, сохранить существующие PID в файл и использовать его для уведомления старых процессов, что им следует завершить работу и выйти:
Когда конфигурация разделяется на несколько конкретных файлов (например: tcp по отношению к http), рекомендуется использовать опцию “-f”:
Если число файлов заранее неизвестно, например для отдельных файлов заказчиков, рекомендуется начинать их имена с порядкового номера фиксированной ширины и загружать их через “–”, при необходимости предварительно загрузив общие настройки:
Иногда может произойти сбой при запуске из-за каких-либо причин. В таком случае важно убедиться, что версия HAProxy, которую вы запускаете, соответствует ожидаемой версии и поддерживает требуемые функции (например: SSL, PCRE, сжатие, Lua и т.д.). Это можно проверить с помощью команды “haproxy -vv”. Там отображаются важные сведения, такие как определённые параметры сборки, целевая система и версии используемых библиотек. Именно это содержимое вы будете систематически запрашивать при подаче отчёта о баге:
HAProxy version 1.6-dev7-a088d3-4 2015/10/08 Copyright 2000-2015 Willy Tarreau willy@haproxy.org
Build options:
Default settings:
Encrypted password support via crypt(3): yes Built with zlib version: 1.2.6 Compression algorithms supported: identity(“identity”), deflate(“deflate”), \ raw-deflate(“deflate”), gzip(“gzip”) Built with OpenSSL version: OpenSSL 1.0.1o 12 Jun 2015 Running on OpenSSL version: OpenSSL 1.0.1o 12 Jun 2015 OpenSSL library supports TLS extensions: yes OpenSSL library supports SNI: yes OpenSSL library supports prefer-server-ciphers: yes Built with PCRE version: 8.12 2011-01-15 PCRE library supports JIT: no (USE_PCRE_JIT not set) Built with Lua version: Lua 5.3.1 Built with transparent proxy support using: IP_TRANSPARENT IP_FREEBIND
Available polling systems:
Total: 3 (3 usable), will use epoll.
Следующая информация, которую многие пользователи, не являющиеся разработчиками, могут здесь проверить:
- the version
В приведённой выше строке 1.6-dev7-a088d3-4 означает, что код соответствует коммиту “a088d3”, 4-му после официальной версии “1.6-dev7”. Сама версия 1.6-dev7 отображалась бы как “1.6-dev7-8c1ad7”. Существенная часть здесь — “1.6-dev7”: это 7-я версия разработки будущего выпуска 1.6. Версия разработки не подходит для рабочей среды, если только вы в точности не понимаете, что делаете. Стабильная версия имеет номер из 3 чисел, например “1.5.14-16f863”, обозначающий 14-й корректирующий выпуск версии 1.5. Такая версия готова к использованию в рабочей среде.
- the release date
2015/10/08. Дата представлена в универсальном формате year/month/day (год/месяц/день). Здесь это означает 8 августа 2015 года. Стабильные выпуски выходят раз в несколько месяцев: сначала через 1-2 месяца, а после достижения высокой стабильности — иногда через 6 месяцев. Поэтому старая дата, вероятно, означает наличие уже исправленных ошибок или уязвимостей; стоит проверить сведения на официальном сайте.
- build options
Они важны для тех, кто самостоятельно собирает пакеты, и помогают объяснить неожиданное поведение. Например, указанная выше версия разработки собрана для Linux 2.6.28 или новее с расчётом на универсальный CPU, без оптимизаций под конкретный CPU. Кроме того, оптимизация кода отключена (-O0), поэтому производительность будет низкой.
- libraries versions
Версия zlib выводится по сведениям самой библиотеки. В целом zlib считается очень стабильным продуктом, обновлять который почти никогда не требуется. Для OpenSSL выводятся две версии: использованная при сборке и используемая сейчас, найденная в системе. Они могут отличаться последней буквой, но никогда не числами. Также выводится дата сборки, поскольку большинство ошибок OpenSSL связано с безопасностью и требует серьёзного отношения: эту библиотеку обязательно нужно поддерживать в актуальном состоянии. Версия возрастом 4 месяца вызывает серьёзные подозрения и означает пропущенное обновление. PCRE обеспечивает очень быстрые регулярные выражения и настоятельно рекомендуется. Некоторые расширения, например JIT, есть не во всех версиях и ещё сравнительно молоды, поэтому часть пользователей предпочитает собирать без них; именно поэтому выводится и состояние их включения при сборке. Что касается языка скриптов Lua, HAProxy ожидает версию 5.3, выпущенную совсем недавно, незадолго до HAProxy 1.6. Важно проверять на сайте Lua наличие исправлений для этой ветки.
- Available polling systems will affect the process's scalability when
при обработке более чем примерно тысячи одновременных соединений. Они доступны только при правильном указании системы в переменной TARGET во время сборки. Для Linux настоятельно рекомендуется механизм “epoll”, для BSD — kqueue. При их отсутствии используется poll() или даже select(), что приводит к высокой нагрузке на CPU при большом числе соединений.
21 - 4. Остановка и перезапуск HAProxy
HAProxy поддерживает плавную и жёсткую остановку. Жёсткая остановка проста: при отправке процессу haproxy сигнала SIGTERM он немедленно завершается, а все установленные соединения закрываются. Плавная остановка запускается сигналом SIGUSR1, отправленным процессу haproxy. При этом процесс лишь освобождает прослушиваемые порты, продолжая обрабатывать существующие соединения до их закрытия. После закрытия последнего соединения процесс завершается.
Жёсткая остановка используется для действий «stop» и «restart» сценария управления службой. Плавная остановка применяется для действия «reload», которое пытается незаметно для клиентов загрузить новую конфигурацию в новом процессе.
Оба сигнала может отправлять сам новый процесс haproxy при перезагрузке конфигурации или перезапуске, чтобы это происходило как можно позже и только при крайней необходимости. Именно это делают параметры «-st» (жёсткая остановка) и «-sf» (плавная остановка) соответственно.
В режиме master-worker для перезагрузки конфигурации не требуется запускать новый процесс haproxy. Получив сигнал SIGUSR2, главный процесс повторно запускает себя с параметром -sf, за которым следуют PID рабочих процессов. Затем главный процесс разбирает файл конфигурации и создаёт новые рабочие процессы с помощью fork.
Чтобы лучше понять применение этих сигналов, важно разобраться во всём механизме перезапуска.
Изначально уже работает процесс haproxy. Администратор выполняет команду, принятую в данной системе, например «/etc/init.d/haproxy reload», чтобы применить новый файл конфигурации. Далее происходит следующее. Сначала сценарий службы (/etc/init.d/haproxy или его аналог) проверяет корректность разбора файла конфигурации командой «haproxy -c». Затем он пытается запустить haproxy с этим файлом конфигурации, используя «-st» или «-sf».
После этого HAProxy пытается привязаться ко всем прослушиваемым портам. При фатальной ошибке (например, если адрес отсутствует в системе или доступ запрещён) процесс завершается с ошибкой. Если привязка сокета не удалась из-за того, что порт уже занят, процесс сначала отправляет сигнал SIGTTOU всем PID из списка, заданного в «-st» или «-sf». Это так называемый сигнал приостановки: он предписывает всем существующим процессам haproxy временно прекратить прослушивание своих портов, чтобы новый процесс мог повторить попытку привязки. В это время старый процесс продолжает обрабатывать существующие соединения. Если привязка по-прежнему не удаётся (например, порт занят другим демоном), новый процесс отправляет старым процессам сигнал SIGTTIN, предписывая возобновить работу как ни в чём не бывало. Старые процессы снова начинают прослушивать порты и принимать соединения. Обратите внимание: этот механизм зависит от системы, и некоторые операционные системы могут не поддерживать его в многопроцессном режиме.
Если новому процессу удалось привязаться ко всем портам, он отправляет всем процессам либо SIGTERM (жёсткая остановка при «-st»), либо SIGUSR1 (плавная остановка при «-sf»), уведомляя их, что теперь он обслуживает трафик, а старые процессы должны завершиться — немедленно или после окончания своей работы.
Важно учитывать, что в этот промежуток есть два небольших окна длительностью по несколько миллисекунд, в течение которых при высокой нагрузке возможны единичные сбои соединений. Обычно наблюдается около 1 сбоя при перезагрузке конфигурации на каждые 10000 новых соединений в секунду. Это означает, что высоконагруженный сайт с 30000 новых соединений в секунду может получать примерно 3 неудачных соединения при каждой перезагрузке конфигурации. Такие сбои возникают в двух случаях:
Если новый процесс не может привязаться к порту из-за старого процесса, ему сначала приходится выполнить последовательность SIGTTOU+SIGTTIN. Для нескольких десятков фронтендов она обычно занимает около одной миллисекунды, в течение которой часть портов уже освобождена старым процессом, но ещё не занята новым. HAProxy обходит эту проблему в системах с поддержкой параметра сокета SO_REUSEPORT, который позволяет новому процессу привязаться к порту, не запрашивая предварительно его освобождение у старого. Большинство систем BSD поддерживают его практически всегда. Linux поддерживал его в версии 2.0, но примерно в версии 2.2 поддержка была удалена, хотя к тому времени существовали отдельные патчи. Она вернулась в ядре 3.9, поэтому, если частота сбоев соединений выше указанной, убедитесь, что используете ядро 3.9 или новее либо что соответствующие патчи перенесены в ваше ядро (что менее вероятно).
Когда старые процессы закрывают прослушиваемые порты, ядро не всегда перераспределяет ожидающие соединения, оставшиеся в очереди сокета. При высокой нагрузке пакет SYN может прийти непосредственно перед закрытием сокета, что приведёт к отправке клиенту пакета RST. В некоторых критически важных средах, где недопустима даже одна потеря, с этим иногда борются с помощью правил межсетевого экрана, блокирующих пакеты SYN на время перезагрузки конфигурации и вынуждающих клиента повторить передачу. Поведение целиком зависит от системы: некоторые системы могут просмотреть другие очереди прослушивания и избежать отправки RST. Второй случай касается клиентского ACK для локального сокета, который непосредственно перед закрытием находился в состоянии SYN_RECV. Этот ACK вызовет отправку RST, хотя процесс haproxy ещё ничего об этом не знает. Избавиться от такого случая сложнее, но упомянутые правила фильтрации межсетевого экрана хорошо сработают, если применить их примерно за секунду до перезапуска процесса.
У подавляющего большинства пользователей подобных потерь никогда не возникает, поскольку нагрузки недостаточно для возникновения гонок. А для большинства пользователей с большим объёмом трафика частота сбоев остаётся в пределах статистического шума, если их системы хотя бы корректно поддерживают SO_REUSEPORT.
22 - 5. Ограничения файловых дескрипторов
Чтобы обеспечить успешное обслуживание всех входящих соединений, HAProxy при загрузке вычисляет общее число файловых дескрипторов, которые потребуются за время жизни процесса. Обычному процессу Unix по умолчанию обычно предоставляется 1024 файловых дескриптора, а привилегированный процесс может самостоятельно увеличить этот лимит. Это одна из причин запускать HAProxy от имени root и позволять ему настроить лимит. Лимит по умолчанию в 1024 файловых дескриптора позволяет обслуживать примерно 500 одновременных соединений. Расчёт основан на глобальном параметре maxconn, ограничивающем общее число соединений на процесс, числе слушателей, числе серверов с включённой проверкой работоспособности, агентских проверках, одноранговых узлах, получателях журналов и, возможно, нескольких других технических потребностях. Для грубой оценки достаточно удвоить значение maxconn и добавить несколько десятков: получится приблизительное число необходимых файловых дескрипторов.
Изначально HAProxy не умел вычислять это значение, и его нужно было передавать через параметр “ulimit-n” в глобальной секции. Поэтому даже сегодня этот параметр встречается во множестве конфигураций. К сожалению, его часто рассчитывали неверно, что приводило к сбоям соединений при приближении к maxconn вместо ограничения приёма входящих соединений на время ожидания нужных ресурсов. Поэтому важно удалить все унаследованные параметры “ulimit-n”, которые могли остаться от очень старых версий.
Для работы даже с умеренной нагрузкой число файловых дескрипторов обязательно нужно увеличить, но это требует некоторых настроек, зависящих от ОС. Во-первых, механизм опроса select() ограничен 1024 файловыми дескрипторами. На самом деле в Linux он раньше мог обрабатывать и больше, однако некоторые ОС поставляются с излишне строгими политиками SELinux, запрещающими select() использовать более 1024 файловых дескрипторов. Поэтому теперь HAProxy в таком случае отказывается запускаться, чтобы избежать проблем во время выполнения. Во всех поддерживаемых операционных системах доступен poll(), который не имеет этого ограничения. Он выбирается автоматически, так что для получения рабочей конфигурации ничего делать не требуется. Однако poll() становится очень медленным с ростом числа файловых дескрипторов. Хотя HAProxy старается уменьшить влияние на производительность (например, используя внутренний кэш файловых дескрипторов и пакетную обработку), практическое правило таково: использование poll() при более чем тысяче одновременных соединений создаёт большую нагрузку на CPU.
В системах Linux с ядром 2.6 и выше используется системный вызов epoll(). Это гораздо более масштабируемый механизм на основе обратных вызовов в ядре, которые гарантируют постоянное время пробуждения независимо от числа зарегистрированных для наблюдения файловых дескрипторов. Он используется автоматически, если обнаружен, при условии, что HAProxy собран для одного из вариантов Linux. Его наличие и поддержку можно проверить с помощью “haproxy -vv”.
В системах BSD с соответствующей поддержкой доступна альтернатива — kqueue(). Он значительно быстрее poll() и даже немного быстрее epoll() благодаря пакетной обработке изменений. Его поддерживают как минимум FreeBSD и OpenBSD. Как и в случае с Linux epoll(), сведения о его поддержке и доступности выводятся командой “haproxy -vv”.
Наличие хорошего механизма опроса — лишь часть задачи: процесс обязательно должен иметь возможность достичь нужных лимитов. При запуске HAProxy сразу устанавливает новые лимиты файловых дескрипторов процесса и проверяет успешность операции. В случае неудачи он сообщает об этом до создания дочернего процесса, чтобы администратор увидел проблему. Если процесс запущен от имени root, оснований для отказа в этой настройке быть не должно. Однако она может завершиться неудачно, если процесс запускает непривилегированный пользователь. Если есть веская причина не запускать haproxy от имени root (например, его запускают конечные пользователи или учётная запись отдельного приложения), системный администратор может увеличить лимит файловых дескрипторов для конкретного пользователя. Действие настройки можно проверить командой “ulimit -n” в оболочке этого пользователя. Она должна показать новый лимит.
Предупреждение: при изменении лимитов в учётной записи непривилегированного пользователя часто оказывается, что новые значения учитываются только при входе пользователя в систему и совсем не применяются к некоторым сценариям, выполняемым при загрузке системы, или к заданиям crontab. Это полностью зависит от операционной системы, поэтому при таком способе запуска не забывайте проверять “ulimit -n” перед запуском haproxy. Общая рекомендация — никогда не запускать haproxy от имени непривилегированного пользователя в промышленной эксплуатации. Ещё одна веская причина в том, что такой запуск мешает haproxy включить некоторые защитные механизмы.
Когда установлено, что система разрешает процессу haproxy использовать запрошенное число файловых дескрипторов, могут встретиться ещё два системных ограничения. Первое — общесистемный лимит файловых дескрипторов, то есть общее число дескрипторов, открытых в системе всеми процессами. При достижении этого лимита accept() или socket() обычно возвращают ENFILE. Второе — жёсткий лимит числа файловых дескрипторов на процесс, который не позволяет установить через setrlimit() более высокое значение. Оба сильно зависят от операционной системы. В Linux системный лимит задаётся при загрузке в зависимости от объёма памяти. Его можно изменить параметром sysctl “fs.file-max”. Жёсткий лимит на процесс по умолчанию равен 1048576, но его можно изменить параметром sysctl “fs.nr_open”.
Если лимиты файловых дескрипторов слишком низкие, их действие можно наблюдать на работающем процессе. Утилита strace покажет, что accept() и socket() возвращают “-1 EMFILE”, когда достигнуты лимиты процесса. В этом случае достаточно увеличить значение “ulimit-n” (или удалить его), чтобы решить проблему. Если эти системные вызовы возвращают “-1 ENFILE”, это означает, что достигнуты лимиты ядра и нужно изменить общесистемный параметр. Такие проблемы обязательно необходимо устранить: они приводят к высокой загрузке CPU (при сбоях accept()) и неудачным соединениям, обычно заметным пользователю. Ещё один вариант решения — уменьшить глобальное значение maxconn, чтобы обеспечить последовательное обслуживание, и, возможно, отключить режим HTTP keep-alive, чтобы соединения освобождались и использовались повторно быстрее.
23 - 6. Управление памятью
HAProxy использует простое и быстрое управление памятью на основе пулов. Поскольку он работает с небольшим числом различных типов объектов, гораздо эффективнее брать новые объекты из пула, уже содержащего объекты подходящего размера, чем вызывать malloc() для каждого отдельного размера. Пулы организованы как стек, или LIFO: при выделении используются недавно освобождённые объекты, которые ещё находятся в кэшах CPU. Пулы близких размеров объединяются, чтобы ограничить фрагментацию памяти.
По умолчанию, поскольку приоритет отдаётся производительности, каждый освобождённый объект возвращается в свой исходный пул, а выделенная память под объекты никогда не освобождается, так как ожидается их скорое повторное использование.
В CLI можно проверить использование памяти пулами с помощью команды “show pools”:
Имя пула носит лишь справочный характер: это имя первого типа объектов, использовавшего данный пул. Размер в скобках — размер объектов в этом пуле. Размеры объектов всегда округляются вверх до ближайшего числа, кратного 16 байтам. Выводятся текущее число выделенных объектов и соответствующее количество байтов, что позволяет легко определить, какой пул потребляет больше всего памяти. Число объектов, используемых в данный момент, также приводится в поле “used”. Разница между “allocated” и “used” соответствует освобождённым объектам, доступным для немедленного использования. Адрес в конце строки — это адрес пула, а следующее за ним число — индекс пула, если он существует; если индекс не назначен, выводится -1.
Объём памяти, выделяемой на процесс, можно ограничить параметром командной строки “-m”, указав после него число мегабайт. Он охватывает всё адресуемое пространство процесса, включая память некоторых библиотек и стек, но обеспечивает надёжное ограничение при построении системы с ограниченными ресурсами. Он работает так же, как “ulimit -v” в системах, где эта команда доступна, или “ulimit -d” в остальных.
Если выделить память не удалось из-за достижения лимита или из-за нехватки памяти в системе, haproxy сначала освобождает все доступные объекты во всех пулах, а затем снова пытается выделить память. Этот механизм освобождения неиспользуемой памяти можно запустить, отправив процессу haproxy сигнал SIGQUIT.
При перезагрузке конфигурации процесс, перешедший в состояние плавной остановки, также автоматически очищает память после освобождения каждого соединения, чтобы высвободить как можно больше памяти для нового процесса.
24 - 7. Использование CPU
Обычно HAProxy проводит большую часть времени в системном режиме, а меньшую — в пользовательском пространстве. Тщательно настроенный CPU с частотой 3.5 GHz способен поддерживать около 80000 установок и закрытий сквозных соединений в секунду при загрузке CPU 100% на одном ядре. При полной загрузке одного ядра типичны следующие показатели:
- 95% в системном режиме, 5% в пользовательском — для длительных соединений TCP или больших объектов HTTP;
- 85% в системном режиме и 15% в пользовательском — для коротких соединений TCP или маленьких объектов HTTP в режиме закрытия соединений;
- 70% в системном режиме и 30% в пользовательском — для маленьких объектов HTTP в режиме постоянных соединений.
Обработка правил и регулярных выражений увеличивает долю пользовательского времени. Наличие правил межсетевого экрана, отслеживания соединений и сложных таблиц маршрутизации в системе, напротив, увеличивает долю системного времени.
В большинстве систем время CPU при передаче данных по сети можно разделить на 4 части:
Время обработки прерываний: вся обработка при поступлении ввода-вывода, ещё до того, как определён целевой процесс. Обычно приём пакетов Rx учитывается как обработка прерываний. В некоторых системах, например Linux, обработка прерываний может откладываться и передаваться выделенному потоку; тогда она может отображаться как softirq, а поток называется ksoftirqd/0 (для CPU 0). CPU, выполняющий эту работу, обычно определяется настройками оборудования, хотя для softirq часто можно переназначить обработку на другой CPU. Эту долю времени часто воспринимают как паразитную, поскольку она не связана ни с одним процессом, но в действительности это подготовительная работа для процесса.
Системное время: вся обработка кодом ядра, вызываемым из пользовательского пространства. Например, системные вызовы учитываются как системное время. Все синхронно отправляемые пакеты Tx также учитываются здесь. Если отправку некоторых пакетов приходится отложить из-за заполнения очередей, впоследствии они могут обрабатываться в контексте прерывания (например, при получении ACK, открывающего окно TCP).
Пользовательское время: выполнение исключительно кода приложения в пользовательском пространстве. HAProxy работает только в этой области, хотя активно использует системные вызовы. Обработка правил, регулярные выражения, сжатие и шифрование увеличивают пользовательскую долю потребления CPU.
Время простоя: то, что CPU делает, когда работы нет. Например, HAProxy ожидает входящего соединения или отправки данных, то есть система ждёт ACK от клиента, чтобы передать эти данные.
На практике для оценки работы HAProxy обычно достаточно разумно (хотя и совершенно неточно) считать, что прерывания и softirq вызваны обработкой Rx в драйверах ядра, пользовательское время — обработкой на уровне 7 в HAProxy, а системное время — сетевой обработкой на пути Tx.
Поскольку HAProxy построен вокруг цикла событий, он ожидает новых событий с помощью poll() (или аналога), максимально быстро обрабатывает их, а затем возвращается к poll() для ожидания следующих событий. Он измеряет время ожидания в poll() относительно времени обработки событий. Отношение времени опроса к общему времени называется временем простоя «idle»: это доля времени, затраченная на ожидание событий. Она отображается на странице статистики в строке «idle» или в CLI как «Idle_pct». Значение, близкое к 100%, означает крайне низкую нагрузку. Значение, близкое к 0%, означает постоянную активность. В перегруженной системе этот показатель не может быть очень точным, поскольку другие процессы могут вытеснять haproxy с CPU, однако он хорошо отражает, как HAProxy оценивает собственную работу. Если и нагрузка, и доля простоя низкие, это может означать, что HAProxy выполняет много работы, возможно, обрабатывает очень затратные правила. Напротив, если HAProxy показывает простой, близкий к 100%, но работа идёт медленно, он ничего не может сделать для ускорения: он уже ожидает входящих данных для обработки. В следующем примере haproxy полностью бездействует:
Когда доля простоя становится очень низкой, важно настроить систему и правильно распределить процессы и прерывания, чтобы сохранить как можно больше ресурсов CPU для всех задач. Если используется межсетевой экран, стоит попробовать отключить или настроить его, чтобы убедиться, что он не является основной причиной ограничения производительности. Учтите, что выгрузка межсетевого экрана с отслеживанием состояния обычно уменьшает и долю прерываний/softirq, и системное время, поскольку такие экраны работают на обоих путях — Rx и Tx. В Linux выгрузка модулей nf_conntrack и ip_conntrack покажет, можно ли получить выигрыш. Если да, значит модуль работает с настройками по умолчанию, и нужно выяснить, как настроить его для лучшей производительности. Обычно это сводится к значительному увеличению размера хеш-таблицы. Во FreeBSD команда «pfctl -d» одновременно отключает межсетевой экран «pf» и его механизм отслеживания состояния.
Если много времени уходит на прерывания/softirq, важно убедиться, что они не выполняются на том же CPU. Большинство систем старается закреплять задачи за тем CPU, на котором они получают сетевой трафик: при некоторых нагрузках это улучшает производительность. Но при сильно выраженной сетевой нагрузке эффект обратный, поскольку процесс haproxy вынужден конкурировать с соответствующей обработкой в ядре. Закрепление haproxy за одним ядром CPU, а прерываний — за другим ядром с общим кешем L3 обычно заметно повышает сетевую производительность. На практике объёмы работы haproxy и сетевого стека довольно близки, и каждый из них может почти полностью загрузить отдельный CPU. В Linux для этого используются taskset (для haproxy) или cpu-map (в конфигурации haproxy), а прерывания назначаются через /proc/irq. Многие сетевые интерфейсы поддерживают несколько очередей и прерываний. Обычно полезно распределить их по небольшому числу ядер CPU с общим кешем L3. Обязательно останавливайте irq_balance: при таких нагрузках он всегда действует наихудшим образом.
Для нагрузок, ограниченных CPU и связанных с большим объёмом трафика SSL или сжатия, может быть полезно выделить несколько процессов для определённых задач. Универсального правила здесь нет, поэтому придётся экспериментировать.
Для увеличения доступных ресурсов CPU можно запустить HAProxy в виде нескольких процессов с помощью директивы «nbproc» в секции global. Однако существуют ограничения:
- Проверки работоспособности выполняются каждым процессом, поэтому целевые серверы получают столько проверок, сколько процессов запущено.
- Значения maxconn и очереди относятся к отдельным процессам, поэтому необходимо правильно задать значение, чтобы не перегрузить серверы.
- В исходящих соединениях следует избегать использования диапазонов портов, чтобы не возникали конфликты.
- Таблицы stick-tables относятся к отдельным процессам и не являются общими для нескольких процессов.
- Каждая секция peers одновременно может работать только в одном процессе.
- Операции CLI одновременно действуют только на один процесс.
С учётом этих ограничений самый простой вариант часто состоит из первого уровня, работающего в нескольких процессах и выполняющего тяжёлую обработку, который передаёт трафик второму уровню, работающему в одном процессе. Этот механизм подходит для SSL и сжатия — двух наиболее затратных для CPU функций. Экземпляры легко объединить в цепочку через сокеты UNIX (они дешевле сокетов TCP и не расходуют порты) и протокол proxy, позволяющий передавать сведения о клиенте на следующий этап. При такой схеме обычно полезно закрепить все однопроцессные задачи за процессом номер 1, а дополнительные задачи — за следующими процессами: это упрощает генерацию похожих конфигураций для разных машин.
В Linux версии 3.9 и новее многопроцессный режим HAProxy гораздо эффективнее, если каждый процесс использует отдельный прослушивающий сокет на одной и той же паре IP:port. Тогда ядро равномерно распределяет нагрузку между процессами, вместо того чтобы пробуждать их все. Дополнительные сведения о параметре «process» в строках директивы «bind» приведены в руководстве по конфигурации.
25 - 8. Ведение журнала
Для ведения журнала HAProxy всегда использует сервер syslog, поскольку сам не обращается к файловой системе. Стандартный способ — отправлять журналы по UDP на сервер журналирования (по умолчанию на порт 514). Очень часто используется адрес 127.0.0.1, где работает локальный демон syslog, но также применяется передача по сети на центральный сервер. Центральный сервер даёт дополнительные преимущества, особенно в схемах active-active, где желательно объединять журналы в порядке поступления. HAProxy может отправлять журналы локальному демону syslog и через сокет UNIX, но это совершенно не рекомендуется: если сервер syslog перезапустить во время работы haproxy, сокет будет заменён, а новые записи журналов будут теряться. Поскольку HAProxy изолирован в окружении chroot, он не сможет повторно подключиться к новому сокету. На практике также наблюдалось, что буферы журналирования сокетов UNIX очень малы, из-за чего сообщения теряются даже при очень низкой нагрузке. Однако для тестирования такой вариант вполне допустим.
Чтобы HAProxy отправлял журналы локальному демону с категорией facility «local0», рекомендуется добавить в секцию «global» следующую директиву:
а затем добавить следующую директиву в каждую секцию «defaults» либо в каждую секцию фронтенда и бэкенда:
Таким образом, все журналы будут централизованно направляться на сервер, указанный в глобальном определении.
Некоторые демоны syslog по умолчанию не принимают трафик UDP, поэтому синтаксис включения этой возможности зависит от используемого демона:
Для sysklogd нужно передать аргумент «-r» в командной строке демона, чтобы он прослушивал сокет UDP для удалённых журналов. Учтите, что ограничить прослушивание адресом 127.0.0.1 невозможно, поэтому он будет принимать журналы и от удалённых систем.
Для rsyslogd в файл конфигурации необходимо добавить следующие строки:
- Для syslog-ng можно создать новый источник следующим образом, а затем добавить его как допустимый источник в одну из директив «log»:
Дополнительные сведения приведены в руководстве используемого демона syslog. Если в системных файлах журналов нет записей, выполните следующие проверки:
Перезапустите haproxy. Каждый фронтенд и бэкенд записывает строку о своём запуске. Если эти записи поступают, журналирование работает.
Выполните «strace -tt -s100 -etrace=sendmsg -p <haproxy’s pid>» и выполните действия, которые должны попасть в журнал. В выводе должны быть видны сообщения журнала, отправляемые через sendmsg(). Если их нет, перезапустите haproxy под strace. Если журналы по-прежнему отсутствуют, в конфигурации определённо есть ошибка.
Запустите tcpdump для наблюдения за портом 514, например на интерфейсе обратной петли, если трафик передаётся локально: «tcpdump -As0 -ni lo port 514». Если пакеты видны, это доказывает, что они отправляются, и нужно искать неисправность в демоне syslogd.
Хотя журналы трафика отправляют фронтенды, принимающие входящие соединения, бэкенды также должны иметь возможность отправлять записи, чтобы сообщать об изменении состояния сервера по результатам проверки работоспособности. Дополнительные сведения обо всех доступных настройках журналирования приведены в руководстве по конфигурации HAProxy.
Удобно выбрать категорию facility, которая не используется другими демонами. В примерах HAProxy часто предлагаются «local0» для журналов трафика и «local1» для административных журналов, поскольку на практике эти категории нигде не встречаются. Одной категории также было бы достаточно. Раздельные журналы удобны для анализа, но важно помнить, что в них иногда содержатся конфиденциальные сведения, поэтому их нельзя смешивать с другими журналами, которые могут случайно попасть к посторонним.
Для устранения неполадок в рабочей среде без существенного влияния на производительность сервера рекомендуется использовать утилиту «halog», поставляемую с HAProxy. Она похожа на grep и предназначена для очень быстрой обработки файлов журналов HAProxy. Типичная скорость составляет от 1 до 2 GB журналов в секунду. Она умеет извлекать только определённые записи (например, искать по классам кодов состояния HTTP, состояниям завершения соединений, диапазонам времени ответа или только ошибки), считать строки, ограничивать число выводимых строк и выполнять более сложную статистическую обработку: сортировать серверы по времени ответа или числу ошибок, URL по времени или числу обращений, адреса клиентов по числу обращений и так далее. Это очень удобно для быстрого выявления аномалий, например бота, бесконечно обходящего сайт, и их блокирования.
26 - 10. Упрощение управления конфигурацией
Очень часто два узла HAProxy, образующие кластер, используют совершенно одинаковую конфигурацию, за исключением нескольких адресов. Вместо того чтобы сопровождать отдельную копию конфигурации для каждого узла, которые неизбежно начнут различаться, можно включить в конфигурацию переменные окружения. Тогда несколько конфигураций смогут использовать один и тот же файл, различаясь лишь несколькими общесистемными переменными окружения. Эта возможность появилась в версии 1.5, где переменные окружения допускались только в адресах; версия 1.6 расширяет их поддержку на все параметры. Синтаксис такой же, как в оболочке UNIX: переменная начинается со знака доллара (’$’), за которым следуют открывающая фигурная скобка (’{’), имя переменной и закрывающая скобка (’}’). За исключением адресов, переменные окружения интерпретируются только в аргументах, заключённых в двойные кавычки (это ограничение было необходимо, чтобы не нарушить работу существующих конфигураций с регулярными выражениями, содержащими знак доллара).
Переменные окружения также удобны для конфигураций, которые должны работать на разных площадках и различаться только адресами. Кроме того, они позволяют убрать пароли из некоторых конфигурационных файлов. В приведённом ниже примере сценарий инициализации при запуске загружает файл «site1.env»:
27 - 11. Известные подводные камни, которых следует избегать
Время от времени кто-нибудь сообщает, что после перезагрузки системы служба haproxy не запустилась, но при ручном запуске работает. Чаще всего такие пользователи применяют механизм кластерного IP-адреса, например keepalived, чтобы назначать IP-адрес службы только главному узлу. Пока haproxy был привязан к адресу 0.0.0.0, всё работало, но после привязки к виртуальному IP-адресу запуск перестал удаваться. Причина в том, что при запуске службы виртуальный IP-адрес ещё не принадлежит локальному узлу, и, когда HAProxy пытается к нему привязаться, система отклоняет запрос, поскольку адрес не локальный. Решение состоит не в задержке запуска службы haproxy (это не помогло бы при перезапуске), а в правильной настройке системы, разрешающей привязку к нелокальным адресам. В Linux это легко сделать, установив параметр sysctl net.ipv4.ip_nonlocal_bind в 1. Это также необходимо для прозрачного перехвата IP-трафика, проходящего через HAProxy к определённому адресу назначения.
Многопроцессные конфигурации с диапазонами исходящих портов могут выглядеть работоспособными, но при высокой нагрузке вызывают случайные сбои: несколько процессов могут попытаться использовать один и тот же исходящий порт для подключения к одному серверу, что невозможно. Система сообщит об ошибке, после чего будет выполнена повторная попытка с выбором другого порта. Высокое значение параметра “retries” может в некоторой степени скрыть этот эффект, но также увеличивает загрузку CPU и время обработки. В журналах тоже будет отражено некоторое число повторных попыток. Поэтому в многопроцессных конфигурациях следует избегать диапазонов портов.
Поскольку HAProxy использует SO_REUSEPORT и поддерживает привязку нескольких независимых процессов к одному IP:port, при устранении неполадок может оказаться, что старый процесс не остановили перед запуском нового. Это приводит к абсурдным результатам проверок, создающим впечатление, что любые изменения конфигурации игнорируются. Причина в том, что, даже если новый процесс перезапущен с новой конфигурацией, старый тоже принимает часть входящих соединений и обрабатывает их, возвращая неожиданные результаты. При сомнениях просто остановите новый процесс и проверьте снова. Если всё ещё работает, скорее всего, старый процесс остался активен и его нужно остановить. Здесь хорошо помогает Linux-команда “netstat -lntp”.
При добавлении записей в ACL из командной строки (например, при внесении исходного адреса в чёрный список) важно помнить, что эти записи не синхронизируются с файлом и при перезагрузке конфигурации будут потеряны. Хотя часто это желаемый эффект (для чёрного списка), он может не соответствовать ожиданиям, если изменение было внесено для исправления проблемы. См. действие “add acl” интерфейса CLI.
28 - 12. Отладка и проблемы производительности
При запуске HAProxy с параметром «-d» процесс остаётся на переднем плане и выводит по строке на каждое событие — входящее соединение, завершение соединения, каждую встреченную строку заголовка запроса или ответа. Этот отладочный вывод формируется до обработки содержимого, поэтому локальные изменения в нём не учитываются. Основное назначение — показывать запросы и ответы без запуска анализатора сетевого трафика. При одновременной обработке нескольких соединений вывод читается хуже, но скрипты «debug2ansi» и «debug2html» из каталога examples/ заметно помогают, раскрашивая его.
Если HAProxy отклоняет запрос или ответ HTTP/1.x как некорректный, лучше всего подключиться к CLI и выполнить «show errors». Команда показывает последние сохранённые ошибочные запрос и ответ HTTP/1.x для каждого фронтенда и бэкенда, включая все сведения для точного определения первого отклонённого символа входного потока. Иногда это необходимо, чтобы доказать заказчикам или разработчикам наличие ошибки в их коде. В таком случае часто можно ослабить проверки, сохранив захват ошибок, с помощью «option accept-unsafe-violations-in-http-request» или аналогичного параметра для ответов сервера «option accept-unsafe-violations-in-http-response». Подробнее см. руководство по конфигурации.
Пример:
Вывод команды «show info» в CLI содержит полезные сведения о максимальной достигнутой интенсивности соединений, максимальной достигнутой скорости вычисления ключей SSL и в целом информацию, помогающую объяснить временные проблемы с использованием CPU или памяти. Пример:
Если в новой версии HAProxy проблема возникает как будто случайно (например, прерывается каждый второй запрос или изредка происходит аварийное завершение), стоит попробовать включить заполнение памяти контрольным значением: тогда сразу после каждого вызова malloc() выделенная область заполняется заданным байтом. По умолчанию используется байт 0x50 (ASCII-код ‘P’), но можно выбрать любой другой, в том числе нулевой (это даёт тот же эффект, что calloc(), и может скрыть проблему). Заполнение памяти включается параметром командной строки «-dM». Оно немного снижает производительность и не рекомендуется для рабочей среды. Если с ним проблема возникает всегда либо никогда не возникает при заполнении нулями, это явно указывает на ошибку, о которой обязательно следует сообщить. Если заметных изменений нет, проблема с этим не связана.
При отладке задержек важно использовать и strace, и tcpdump на локальной машине, а также ещё один tcpdump на удалённой системе. Задержки возникают на всех этапах обработки, и нужно установить, какой именно этап их вызывает, чтобы понять, где вмешаться. На практике локальный tcpdump показывает время поступления входящих данных. Strace показывает, когда haproxy получает эти данные через recv/recvfrom. Внимание: OpenSSL использует системные вызовы read()/write() вместо recv()/send(). Strace также показывает, когда haproxy отправляет данные, а tcpdump — когда система передаёт их интерфейсу. Затем внешний tcpdump показывает, когда отправленные данные действительно получены (локальный показывает только постановку пакетов в очередь). Преимущество захвата трафика в локальной системе состоит в том, что strace и tcpdump используют одни и те же часы. Strace следует запускать с «-tts200», чтобы получать полные временные метки и достаточно большие для чтения фрагменты данных. Tcpdump следует запускать с «-nvvttSs0», чтобы видеть полные пакеты, реальные номера последовательности и полные временные метки.
На практике поступившие данные почти всегда сразу получает haproxy, если только CPU машины не перегружен либо данные некорректны и потому не доставляются. Если данные получены, но не отправлены, причина обычно в заполнении выходного буфера: получатель недостаточно быстро читает данные. Это можно подтвердить, заметив, что механизм опроса некоторое время не сообщает о возможности записи в выходной файловый дескриптор. Часто проще найти в выводе strace момент, когда данные наконец отправлены, а затем просмотреть более ранние события и установить, когда поступило уведомление о готовности к записи. Обычно оно совпадает с получением ACK от адресата, видимым в tcpdump. После отправки данные могут некоторое время бездействовать внутри системы. И здесь окно перегрузки TCP может быть ограничено и не позволять отправить данные до получения ACK, открывающего окно. Если трафик отсутствует, а отправка данных задерживается на 40 ms или 200 ms, причина иная и фактически не является неисправностью: алгоритм Нейгла не позволяет немедленно отправлять пустые пакеты в надежде объединить их с последующими данными. HAProxy автоматически отключает алгоритм Нейгла в чистом режиме TCP и в туннелях. Однако при пересылке тела HTTP он остаётся включённым, повышая производительность за счёт уменьшения числа пакетов. Некоторые приложения, не соответствующие HTTP, могут быть чувствительны к задержке доставки неполных ответов HTTP. В таком случае нужно включить «option http-no-delay», чтобы отключить алгоритм Нейгла и обойти особенности их реализации. При этом следует помнить, что любой другой прокси в цепочке может столкнуться с тем же эффектом. Если tcpdump показывает немедленную отправку данных, но другая сторона получает их с задержкой, причиной может быть перегруженный канал WAN, перегруженная локальная сеть с включённым управлением потоком, препятствующим отправке, либо, что встречается чаще, работа HAProxy в виртуальной машине, гипервизор которой по какой-то причине решил отложить отправку данных. В виртуализированных средах задержки почти всегда вызваны слоем виртуализации, поэтому для экономии времени стоит сначала сравнить tcpdump внутри виртуальной машины и на внешних компонентах. Любую разницу следует относить к гипервизору и сопутствующим драйверам.
Если в трассировке tcpdump с параметром -vv видны сегменты TCP SACK, это всегда означает, что отправившая их сторона получила подтверждение потери пакета. Отсутствие SACK не доказывает отсутствие потерь, но их наличие определённо указывает на потери в сети. Потери в сети нормальны, однако их частота должна быть такой, чтобы SACK не бросались в глаза. Если они часто встречаются в трассировке, стоит точно выяснить, что происходит и где теряются пакеты. HTTP плохо переносит потери TCP, поскольку они вызывают огромные задержки.
Команда «netstat -i» выводит статистику по интерфейсам. Рост счётчика Rx-Ovr означает, что системе не хватает ресурсов для приёма всех входящих пакетов и они теряются ещё до обработки сетевым драйвером. Rx-Drp показывает потери уже полученных пакетов в сетевом стеке из-за того, что приложение недостаточно быстро их обрабатывает. Такое возможно и при некоторых атаках. Tx-Drp означает, что выходные очереди заполнены и пакеты пришлось отбросить. При использовании TCP это должно происходить очень редко, но может указывать на перегрузку исходящего канала.
29 - 13. Соображения безопасности
HAProxy рассчитан на работу с очень ограниченными привилегиями. Стандартный способ его использования — изолировать его в окружении chroot и сбросить привилегии до обычного пользователя, не имеющего никаких разрешений внутри этого окружения. Тогда, если в будущем обнаружится уязвимость, компрометация HAProxy не затронет остальную систему.
Чтобы выполнить chroot, процесс сначала нужно запустить от имени root. Создавать окружения chroot вручную и запускать процесс уже внутри них бессмысленно: их трудно создавать, их никогда не сопровождают должным образом, и ошибок в них всегда гораздо больше, чем в основной файловой системе. Кроме того, при компрометации злоумышленник сможет воспользоваться специально подготовленной файловой системой. К сожалению, многие администраторы путают «запустить от имени root» и «работать от имени root», из-за чего меняют UID ещё до запуска haproxy и тем самым ослабляют действующие ограничения безопасности.
HAProxy нужно запускать от имени root, чтобы:
- изменять ограничения на число файловых дескрипторов;
- привязываться к привилегированным портам;
- привязываться к определённому сетевому интерфейсу;
- прозрачно прослушивать чужой адрес;
- изолировать себя в окружении chroot;
- переходить на другой непривилегированный UID.
HAProxy может потребоваться работать от имени root, чтобы:
- привязываться к интерфейсу для исходящих соединений;
- привязываться к привилегированным исходным портам для исходящих соединений;
- прозрачно привязываться к чужому адресу для исходящих соединений.
Большинству пользователей никогда не понадобится «работать от имени root». Однако «запуск от имени root» охватывает большинство сценариев использования.
Безопасная конфигурация содержит:
- Директиву chroot, указывающую на пустой каталог без каких-либо прав доступа. Его можно подготовить следующей командой UNIX:
и указать следующим образом в секции global конфигурации HAProxy:
- Обе директивы uid/user и gid/group в секции global:
- Сокет stats, у которого mode, uid и gid соответствуют пользователю и/или группе, которым разрешён доступ к CLI, чтобы посторонние не могли получить к нему доступ:
13.1. Поддержка Linux capabilities
Начиная с версии v2.9 haproxy поддерживает Linux capabilities. Если исполняемый файл собран с USE_LINUX_CAP=1, он может сохранять возможности, указанные в директиве ‘setcap’, при переходе от пользователя root к обычному пользователю.
Начиная с версии v3.1 haproxy также проверяет, установил ли администратор возможности из директивы ‘setcap’ в наборе Permitted его исполняемого файла (системный вызов capget). Если это так, он переносит эти возможности в набор Effective своего процесса (системный вызов capset), работая от имени обычного пользователя.
Это сделано, чтобы исключить все возможные случаи, когда haproxy запускается и работает от имени root: режим прозрачного прокси и привязку к привилегированным портам.
Директива ‘setcap’ поддерживает следующие сетевые возможности:
- cap_net_admin: прозрачное проксирование, привязка сокета к определённому сетевому интерфейсу, использование действия set-mark;
- cap_net_raw (подмножество cap_net_admin): прозрачное проксирование;
- cap_net_bind_service: привязка сокета к определённому сетевому интерфейсу;
- cap_sys_admin: создание сокета в определённом сетевом пространстве имён.
HAProxy никогда не переносит эти возможности из своего набора Permitted в Effective, если они не перечислены в аргументе ‘setcap’. Дополнительные сведения о директиве ‘setcap’ и поддерживаемых возможностях приведены в главе 3.1 «Управление процессами и безопасность» руководства по конфигурации.
Администратор может добавить необходимые возможности в набор Permitted исполняемого файла haproxy следующей командой:
Пример:
Добавленные возможности будут видны в наборе Permitted процесса после его запуска. Если те же возможности указаны в аргументах директивы ‘setcap’, они также могут быть видны в наборе Effective процесса. Это можно проверить следующей командой:
Пример:
CapInh: 0000000000000000
CapPrm: 0000000000001400
CapEff: 0000000000001400
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000
Дополнительные сведения о setcap и наборах возможностей приведены в справочных страницах Linux (capabilities(7)).
В некоторых сценариях, например при прозрачном проксировании или создании сокета в определённом сетевом пространстве имён, парсер конфигурации определяет, что требуются cap_net_raw, cap_sys_admin или другие поддерживаемые возможности. Затем на этапе инициализации процесс haproxy проверяет, можно ли включить их в свой набор Effective. Если это невозможно из-за сбоя системного вызова capget или capset (например, из-за ограничений на системные вызовы, наложенных модулями безопасности SELinux, Seccomp и т. п.), процесс выводит диагностические предупреждения (при запуске с -dD).
Из-за поддержки множества платформ с разными системными настройками парсер не может определить по файлу конфигурации, будет ли выполняться привязка к привилегированным портам. Поэтому при недостаточных привилегиях (работа от имени обычного пользователя) процесс завершится только с сообщением об ошибке наподобие приведённого ниже. Пользователь должен самостоятельно перепроверить конфигурацию и набор возможностей исполняемого файла haproxy.
Пример: