Налаштування HAProxy: зворотний проксі, балансування, SSL

Точка входу — найуразливіше місце інфраструктури: на піку трафіку відмова балансувальника зупиняє весь сервіс. Ми налаштовуємо зворотний проксі та балансування під ключ: проєктуємо схему, втілюємо її в конфігураціях і передаємо в експлуатацію з регламентами. Простої під час відмови окремих вузлів зникають, а пропускна здатність під навантаженням зростає в рази.
Часті запитання

HAProxy зворотний проксі: де схема ламається під навантаженням

Зворотний проксі стоїть першим у схемі й першим приймає наслідки: поки трафік помірний, конфігурація з десятка рядків тримає навантаження непомітно.

Ламається вона там, де сплеск запитів або відмова вузла застосунку перетворюють проксі на точку відмови для всього сервісу — зникає вхід, а не окрема функція.

Переповнення з'єднань проявляється раніше за решту. Черга на фронтенді розрахована на спокійний потік: під час залпу вільні слоти закінчуються, частина клієнтів отримує обрив замість відповіді, а бекенд, здатний їх обробити, простоює.

Деградація під навантаженням іде нелінійно — час відповіді зростає стрибком, бо нові запити стають в одну чергу зі старими й чекають разом із ними.

Друге вузьке місце схеми — відсутність перевірок працездатності вузлів. Без періодичного опитування балансувальник продовжує слати трафік туди, де застосунок уже віддає помилки, і відмова вузла застосунку тягне за собою весь сервіс цілком.

Поруч ще одна типова причина: ручні правки конфігурації без відкату, коли перезавантаження йде без перевірки синтаксису й без збереженої попередньої версії, — і в момент аварії інженер залишається без шляху назад.

Усі три сценарії закриваються на рівні схеми й правил, а не героїчними діями під час збою.

Нижче розбираємо, як саме: ліміти й таймаути під реальний профіль трафіку, перевірки стану з виведенням вузла з ротації, безпечне застосування змін зі збереженням попередньої версії та швидким поверненням до неї.

Що дає керований балансувальник: стійкість і передбачуваність

Відмова вузла перестає бути подією для користувача. Балансувальник на HAProxy опитує сервери застосунків із заданим інтервалом і з порогами rise/fall виводить той, що відмовив, із пулу раніше, ніж клієнт отримає помилку, а резервний вузол приймає навантаження сам.

Час відновлення вимірюється секундами й більше не залежить від того, хто першим помітив проблему — черговий чи система моніторингу.

Пропускна здатність зростає на тому самому обладнанні.

Повторне використання з'єднань до серверів і балансування за кількістю активних запитів прибирають перекіс, коли один вузол тримає більше клієнтів, ніж решта; повторне використання захищених сесій скорочує накладні витрати на встановлення зв'язку.

Зникає цілий клас відмов, пов'язаних із ручним втручанням: викочування нової версії йде через плавне виведення вузла з ротації, а не через зупинку сервісу, а невдалі запити до повторюваних операцій переходять на живий вузол.

Правила закріплення сесії задаються явно, тому «плаваючі» помилки авторизації, які інакше шукають тижнями, не виникають узагалі.

З'являється прозорий журнал подій: єдиний формат запису фіксує час відгуку по кожному серверу, коди відповідей і те, який вузол обслужив запит.

За ним одразу видно, де деградація — у застосунку чи на шляху до нього, — а передбачуваність відгуку перестає бути предметом здогадів: 95-й процентиль тримається у вузькому коридорі й на піковому навантаженні.

Режими роботи проксі та балансування: що вибрати під задачу

Режим роботи проксі визначає, що взагалі доступно на точці входу: видно лише адресу й порт чи ще й заголовки, шлях, домен. Від цього залежать маршрутизація за вмістом, термінація шифрування та те, на якому рівні рахуються перевірки працездатності.

Чотири варіанти, між якими реально вибирають:

Варіант Коли підходить Обмеження
Прямий прохід на рівні з'єднань Нестандартні протоколи, бази даних, наскрізне шифрування до сервера Вміст запиту закрито: ні маршрутизації за шляхом, ні правки заголовків; перевірка — лише доступність порту
Термінація шифрування на точці входу Вебсервіси зі спільним доменом, єдиний сертифікат, повторне використання з'єднань Ключ лежить на проксі; внутрішня ділянка без повторного шифрування потребує довіреної мережі
Маршрутизація за вмістом Кілька сервісів за однією адресою, канареечні релізи, розведення за версіями Потрібен повний розбір запиту: вища затримка на точці входу, збій одного сервера помітніший
Зовнішній керований сервіс Немає власної відмовостійкої точки входу, потрібні готові сертифікати Менше контролю над алгоритмами й таймаутами, прив'язка до провайдера

Після вибору режиму залишається розподіл запитів і перевірки працездатності: для довгих з'єднань вигідніший лічильник активних сесій, для сервісів із прив'язкою до сесії — утримання клієнта на вузлі, а активні проби виводять сервер з ротації й повертають його лише після кількох успішних відгуків. Так зникає основна причина «плаваючих» п'ятисоток під навантаженням.

Порядок впровадження: від аудиту схеми до передачі в експлуатацію

Роботи йдуть послідовно: поки не з'ясовано поточну топологію та профіль трафіку, будь-яка правка конфігурації — це вгадування. Тому починаємо з аудиту схеми, а бойовий потік переводимо на нову конфігурацію лише після того, як вона відпрацювала на тестовому контурі. Нижче — етапи впровадження.

  1. Аудит схеми. Збираємо фактичну картину: де стоїть зворотний проксі, які frontend і backend оголошені, як розкладено правила маршрутизації, чим перевіряється доступність серверів. Звіряємо це з логами помилок і статистикою за кодами відповідей.
  2. Проєктування цільової схеми. Вирішуємо, що балансуємо — HTTP чи TCP, де термінується TLS, як утримуються сесії користувача і за якими ознаками вузол вважається неробочим і виводиться з ротації.
  3. Налаштування конфігурації. Описуємо frontend і backend, правила маршрутизації, таймаути, ліміти з'єднань і повтори запитів. Конфігурацію тримаємо в системі контролю версій — кожна зміна проходить рев'ю.
  4. Перевірка на тестовому контурі. Проганяємо відмови: падіння вузла, плавний перезапуск, зростання навантаження, закінчення терміну сертифіката. Критерій готовності — відмова однієї ноди непомітна для користувача.
  5. Кероване перенесення трафіку. Перемикаємо частками: спочатку частину запитів, потім весь потік. Відкат на попередню схему залишається доступним однією командою до кінця перенесення.
  6. Передача в експлуатацію. Віддаємо черговій зміні карту сервісів, регламент правок, набір метрик і алертів, порядок планового оновлення сертифікатів і дій під час деградації.

Що залишається в команди: конфігурації, схеми й регламенти

Усе, що ми налаштовуємо в HAProxy, залишається у вас у репозиторії з історією правок, а не в листуванні з інженером.

Нижче — перелік артефактів, які замовник отримує на руки під час здачі: за ними експлуатація й розвиток сервісу не залежать від того, хто саме налаштовував конфігурацію.

  • Робочі конфігурації — файли з коментарями по кожній секції: правила маршрутизації за доменом і шляхом, таймаути, ліміти одночасних з'єднань, режим балансування та параметри перевірок доступності серверів.
  • Схема зв'язків — карта потоку запитів: точки термінації шифрування, пули серверів за проксі, порядок відмовостійкості, поведінка під час випадіння вузла й логіка повернення трафіку після відновлення.
  • Політики доступу — правила обмеження за адресами й частотою запитів, розділення службових і публічних маршрутів, робота із заголовками клієнта та режим обслуговування під час релізу.
  • Регламент відкату — покроковий порядок повернення до попередньої версії конфігурації: де лежать резервні копії, як перевірити конфігурацію перед застосуванням, за який час виконується відкат.
  • Порядок оновлення сертифікатів — хто відповідає за випуск, як проходить автоматичне продовження, що робити в разі помилки перевірки й як переконатися, що новий сертифікат підхопився без розриву з'єднань.
  • Інструкції для чергової зміни — типові збої та ознаки їх появи в логах, що можна виправити на місці, а в яких випадках ескалувати задачу, із зазначенням порогів спрацювання моніторингу.
  • Перевірка змін — опис стенда, на якому правки обкатуються до продакшену, і набору перевірок, які мають пройти до застосування конфігурації на бойових вузлах.

Кейс: як точка входу пережила пікове навантаження без деградації

Клієнт — сервіс особистих кабінетів із добовою аудиторією в десятки тисяч людей. Точка входу була одна: весь трафік приймав єдиний вузол, він же тримав сертифікати й завершував захищені з'єднання. Поки навантаження зростало плавно, схема справлялася, але на промо-піку вперлася в межу.

Що було на піку

У години розпродажу одночасних підключень стало вдвічі більше за звичайне, і вузол почав упиратися в ліміт з'єднань. Частка запитів, що завершувалися помилкою, сягала 7%, а час відгуку в частини користувачів перевалював за 4 секунди — кошики не доживали до оплати.

Окремий біль: будь-який перезапуск означав до 9 хвилин повної недоступності, бо переключитися було ні на кого.

Що змінили

Зібрали відмовостійку пару вузлів HAProxy у двох різних зонах доступності, об'єднавши їх спільною віртуальною адресою.

Активний вузол приймає трафік, резервний постійно перевіряє його стан і перехоплює адресу в разі відмови — за частки секунди, без розриву вже встановлених з'єднань. Окремо перерахували черги й таймаути під реальний профіль запитів, щоб повільний клієнт не займав слоти здорових.

Що стало

Простій під час відмови вузла скоротився з 9 хвилин до менш ніж секунди — користувач не встигає помітити переключення. Частка помилок на піку впала з 7% до 0,2%, а час відгуку на тому самому обсязі трафіку — з 4,5 до 0,8 секунди.

Оновлення й обслуговування тепер ідуть по одному вузлу: другий тримає трафік, окреме вікно недоступності більше не потрібне.

Балансування з'єднань чи маршрутизація за вмістом?

Якщо трафік нерозбірний — з'єднання до бази, брокера черг, шифрований потік, який проксі не розшифровує, — достатньо балансування з'єднань: рішення ухвалюється один раз під час встановлення зв'язку, і далі всі пакети йдуть до одного вузла.

Щойно з'являються HTTP-запити з різними шляхами, хостами й заголовками, розподілу мало — потрібна маршрутизація за вмістом.

Балансування з'єднань дешевше: проксі не розбирає запит, а рахує з'єднання за вузлами — по колу, за кількістю активних, за адресою клієнта, коли сесію треба втримати на одному сервері.

Обмеження одне: всередині з'єднання не видно, де /api, а де статика, тому розвести навантаження за типами запитів не вийде.

Маршрутизація за вмістом працює на рівні HTTP: запит розбирається цілком, правила розкладають його за пулами за хостом, шляхом або заголовком. З'являються перевірки здоров'я за кодом відповіді, а не за відкритим портом, мітка сесії в cookie і проброс початкової адреси клієнта. Ціна — обчислення на кожен запит і спільний із застосунком набір заголовків.

Поєднання підходів — робоча схема: вузол приймає HTTP-трафік і розподіляє його за пулами, а частину пулів залишає з'єднання нерозібраними — для баз, черг або шифрованого потоку, ключі від якого залишаються у власника сервісу. Вибір режиму задає й те, які перевірки здоров'я будуть у пулів, і як ви будете діагностувати збій.

Варіант Коли підходить Обмеження
Балансування з'єднань Нерозбірний трафік: бази, черги, шифрування без розшифрування на проксі Шляхи й заголовки не видні, типи запитів не розділити
Маршрутизація за вмістом HTTP-сервіси, кілька застосунків, статика окремо від API Дорожче за обчисленнями, потрібні узгоджені заголовки й правила
Поєднання Змішаний контур: HTTP-маршрути назовні, нерозібрані потоки всередині Схема складніша, потрібна карта пулів і перевірок

Часті технічні сумніви перед зміною схеми

Під час перенесення схеми головне питання не «чи спрацює», а що станеться з уже відкритими з'єднаннями в момент переключення. Нижче — чотири сумніви, які найчастіше виринають до того, як ми щось чіпаємо в робочому контурі.

Поточні з'єднання обриваються під час переключення вузлів?

Для коротких запитів перехід непомітний: клієнт повторює звернення, а зворотний проксі надсилає його на живий вузол.

Довгі з'єднання — потокові, веб-сокети — виводяться через м'яке завершення: сервер знімається з ротації, але дочікується відповіді за вже відкритими сесіями, нові запити йдуть на ті, що залишилися.

Чи потрібно щось змінювати в застосунку?

У більшості випадків ні — застосунок отримує запити як раніше, змінюється лише точка входу. Правки потрібні там, де код сам обчислює адресу клієнта за заголовками: якщо початкова адреса не пробрасується, у логах і обмеженнях за IP з'являється адреса балансувальника. Це закривається налаштуванням, без випуску нової версії коду.

Як швидко вимикається збійний вузол?

Періодичність і поріг перевірок задаються явно. За вивірених значень неробочий вузол випадає з ротації за кілька секунд — стільки ж займає повернення після відновлення.

Надто часті перевірки дають хибні спрацювання на піку навантаження, надто рідкі розтягують деградацію, тому пороги підбираються за фактичним профілем трафіку, а не «на око».

Як оновлювати конфігурацію без простою?

Спочатку синтаксична перевірка файлу, потім плавне перезавантаження: новий процес піднімається й приймає трафік, старий допрацьовує активні сесії. Вікно недоступності нульове, сокети не перестворюються.

Відкат — повернення попередньої конфігурації й повтор тієї самої процедури, тому зміни вносимо невеликими кроками.

Обговоримо задачу й повернемося з планом впровадження

Щоб повернутися з планом впровадження, а не із загальними домовленостями, нам потрібен від вас набір вхідних даних. За ними ми робимо оцінку строків, вибираємо алгоритм балансування й порядок переключення — так роботи йдуть без зупинки сервісу.

  • Перелік сервісів, які підуть через зворотний проксі: адреси, порти, протоколи й де термінуються сертифікати — на балансувальнику чи на боці застосунків.
  • Поточна схема: що стоїть зараз (HAProxy чи інший балансувальник), як розподіляється трафік, які перевірки доступності вузлів налаштовані й як виконується відкат.
  • Очікуване навантаження: пікові запити за секунду, кількість одночасних з'єднань, частка довгих сесій — від цього залежать алгоритм балансування й ліміти.
  • Обмеження за вікнами робіт: допустима тривалість переключення, чи є резервний контур, чи можна змінювати записи в DNS і в який час.
  • Доступи: сервери, репозиторій конфігурацій, панель керування сертифікатами, права на зміну правил мережі.
  • Вимоги до сертифікатів: хто випускає, чи потрібна автоматична заміна й перевірка ланцюжка під час оновлення.
  • Критерії приймання: відмова вузла, сплеск трафіку, планова заміна сертифіката — і хто з боку замовника підтверджує результат.

Цього достатньо, щоб підготувати план впровадження з етапами, точками відкату й оцінкою строків. Опишіть задачу — повернемося з планом і складом робіт.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139