tls offload что это
Описание
Балансировка нагрузки с помощью FortiGate включает в себя все необходимые функции для распределения трафика между несколькими серверами в вашей инфраструктуре, развернутой в Selectel, включая как выделенные аппаратные серверы, так и виртуальные серверы в Облачной платформе Selectel.
FortiGate обеспечивает комплексную защиту вашей инфраструктуры и балансирует нагрузки серверов, распределяя потоки трафика по заданным правилам, что позволяет объединить в одном устройстве функции балансировщика нагрузки, Next Generation Firewall (NGFW) и защиту от угроз.
Балансировка нагрузки на основе решений FortiGate обеспечивает:
Балансировщик нагрузки поддерживает HTTP, HTTPS, IMAPS, POP3S, SMTPS, SSL или более низкоуровневые протоколы TCP/UDP или IP. Сохранение сеанса поддерживается на основе идентификатора сеанса SSL или на основе введенного файла cookie HTTP.
Перед началом работы
Прежде чем настраивать балансировку нагрузки в графическом интерфейсе, включите отображение специального раздела настроек:
В данном примере будут рассмотрены настройки Load Balancing для HTTP и HTTPS на аппаратном FortiGate-100E, первоначальную базовую настройку которого можно провести согласно инструкциям по настройке межсетевых экранов. В качестве серверов используются облачные серверы в Облачной платформе Selectel.
FortiGate и проект в Облачной платформе соединены приватной сетью, для подключения которой используется L3VPN между регионами и услугами, что позволяет устанавливать за межсетевым экраном также выделенные серверы и серверы в Облаке на базе VMware.
Термины и определения
Методы балансировки нагрузки
Трафик может распределяться между серверами на основе методов:
Health Check
Health Check — механизм проверки работоспособности серверов для предотвращения отправки трафика балансировки нагрузки на неработающие серверы. Для проверки используется ICMP ping или другое более сложное тестирование TCP-соединений. Health Check удаляет из кластера балансировки нагрузки неработающие реальные серверы. Удаление реальных серверов из кластеров основано на настройках:
Типы Health Check по протоколам: TCP, HTTP, PING.
Virtual Server
Virtual Server — виртуальный сервер, на чей внешний IP-адрес поступает трафик, который перенаправляется к балансировщику нагрузки.
Real Server
Real Server — действительный, реальный, сервер, на который поступают запросы после балансировки. За каждым виртуальным сервером может быть закреплено несколько реальных серверов. Конфигурация реального сервера включает IP-адрес и номер порта, на котором реальный сервер принимает сеансы. Устройство FortiGate отправляет сеансы на IP-адрес реального сервера, используя номер порта назначения в реальной конфигурации сервера. Конфигурация сервера включает его IP-адрес и номер порта, на котором принимает сеансы.
SSL Offloading
SSL Offloading — механизм ускорения SSL-соединения клиентов с сервером, при котором операции шифрования производятся на FortiGate вместо самих серверов с помощью отдельного специального процессора. Данный механизм можно применить, только если для балансировки нагрузки задан тип одного из протоколов SSL (HTTPS, IMAPS, POP3S, SMTPS, SSL). FortiGate предоставляет возможность выбрать, какие сегменты SSL-соединения будут получать разгрузку SSL, определив режим:
HTTP multiplexing
HTTP multiplexing — функция, которая позволяет веб-клиенту использовать одно соединение TCP для всех запросов к серверу. Данная особенность снижает нагрузку на веб-сервер за счет установки единого соединения, по которому параллельно отправляются запросы и ответы. Каждый фрагмент ассоциируются с помощью специальных встроенных мета-данных, что обеспечивает возможность корректной обработки множества несвязанных запросов HTTP или HTTPS в различном порядке в одном и том же соединении. Более того, ответы получаются по мере их готовности, следовательно, тяжелые запросы не будут блокировать обработку и выдачу более простых объектов.
Например, если веб-браузеры пользователей совместимы только с HTTP 1.0, в котором данная функция не реализована, то включение опции HTTP multiplexing может повысить производительность между веб-сервером и FortiGate.
Persistence
Persistence — параметр, который сохраняет и отслеживает данные сеанса, чтобы убедиться, что пользователь подключается к одному и тому же серверу каждый раз, когда он делает запрос, являющийся частью одного и того же сеанса или последующих сеансов. HTTP cookie persistence использует внедренные файлы cookie для обеспечения сохраняемости.
При настройке Persistence FortiGate балансирует нагрузку нового сеанса на реальный сервер в соответствии с методом балансировки нагрузки. Если у сеанса есть HTTP cookie или идентификатор сеанса SSL, устройство FortiGate отправляет все последующие сеансы с одним и тем же файлом cookie HTTP или идентификатором сеанса SSL на один и тот же реальный сервер.
Что такое TLS
Данный текст является вольным переводом вот этой главы замечательной книги «High Performance Browser Networking» авторства Ильи Григорика. Перевод выполнялся в рамках написания курсовой работы, потому очень вольный, но тем не менее будет полезен тем, кто слабо представляет что такое TLS, и с чем его едят.
Общие сведения о TLS
Протокол TLS (transport layer security) основан на протоколе SSL (Secure Sockets Layer), изначально разработанном в Netscape для повышения безопасности электронной коммерции в Интернете. Протокол SSL был реализован на application-уровне, непосредственно над TCP (Transmission Control Protocol), что позволяет более высокоуровневым протоколам (таким как HTTP или протоколу электронной почты) работать без изменений. Если SSL сконфигурирован корректно, то сторонний наблюдатель может узнать лишь параметры соединения (например, тип используемого шифрования), а также частоту пересылки и примерное количество данных, но не может читать и изменять их.
Конкретное место TLS (SSL) в стеке протоколов Интернета показано на схеме:
После того, как протокол SSL был стандартизирован IETF (Internet Engineering Task Force), он был переименован в TLS. Поэтому хотя имена SSL и TLS взаимозаменяемы, они всё-таки отличаются, так как каждое описывает другую версию протокола.
Первая выпущенная версия протокола имела название SSL 2.0, но была довольно быстра заменена на SSL 3.0 из-за обнаруженных уязвимостей. Как уже упоминалось, SSL был разработан компанией Netscape, так что в январе 1999 года IETF открыто стандартизирует его под именем TLS 1.0. Затем в апреле 2006 года была опубликована версия TLS 1.1, которая расширяла первоначальные возможности протокола и закрывала известные уязвимости. Актуальная версия протокола на данный момент – TLS 1.2, выпущенная в августе 2008 года.
Как уже говорилось, TLS был разработан для работы над TCP, однако для работы с протоколами дейтаграмм, такими как UDP (User Datagram Protocol), была разработана специальная версия TLS, получившая название DTLS (Datagram Transport Layer Security).
Шифрование, аутентификация и целостность
Также в рамках процедуры TLS Handshake имеется возможность установить подлинность личности и клиента, и сервера. Например, клиент может быть уверен, что сервер, которые предоставляет ему информацию о банковском счёте, действительно банковский сервер. И наоборот: сервер компании может быть уверен, что клиент, подключившийся к нему – именно сотрудник компании, а не стороннее лицо (данный механизм называется Chain of Trust и будет рассмотрен в соответствующем разделе).
Наконец, TLS обеспечивает отправку каждого сообщения с кодом MAC (Message Authentication Code), алгоритм создания которого – односторонняя криптографическая функция хеширования (фактически – контрольная сумма), ключи которой известны обоим участникам связи. Всякий раз при отправке сообщения, генерируется его MAC-значение, которое может сгенерировать и приёмник, это обеспечивает целостность информации и защиту от её подмены.
Таким образом, кратко рассмотрены все три механизма, лежащие в основе криптобезопасности протокола TLS.
TLS Handshake
Перед тем, как начать обмен данными через TLS, клиент и сервер должны согласовать параметры соединения, а именно: версия используемого протокола, способ шифрования данных, а также проверить сертификаты, если это необходимо. Схема начала соединения называется TLS Handshake и показана на рисунке:
Также имеется дополнительное расширение процедуры Handshake, которое имеет название TLS False Start. Это расширение позволяет клиенту и серверу начать обмен зашифрованными данными сразу после установления метода шифрования, что сокращает установление соединения на одну итерацию сообщений. Об этом подробнее рассказано в пункте “TLS False Start”.
Обмен ключами в протоколе TLS
По различным историческим и коммерческим причинам чаще всего в TLS используется обмен ключами по алгоритму RSA: клиент генерирует симметричный ключ, подписывает его с помощью открытого ключа сервера и отправляет его на сервер. В свою очередь, на сервере ключ клиента расшифровывается с помощью закрытого ключа. После этого обмен ключами объявляется завершённым. Данный алгоритм имеет один недостаток: эта же пара отрытого и закрытого ключей используется и для аутентификации сервера. Соответственно, если злоумышленник получает доступ к закрытому ключу сервера, он может расшифровать весь сеанс связи. Более того, злоумышленник может попросту записать весь сеанс связи в зашифрованном варианте и занять расшифровкой потом, когда удастся получить закрытый ключ сервера. В то же время, обмен ключами Диффи-Хеллмана представляется более защищённым, так как установленный симметричный ключ никогда не покидает клиента или сервера и, соответственно, не может быть перехвачен злоумышленником, даже если тот знает закрытый ключ сервера. На этом основана служба снижения риска компрометации прошлых сеансов связи: для каждого нового сеанса связи создаётся новый, так называемый «временный» симметричный ключ. Соответственно, даже в худшем случае (если злоумышленнику известен закрытый ключ сервера), злоумышленник может лишь получить ключи от будущих сессий, но не расшифровать ранее записанные.
На текущий момент, все браузеры при установке соединения TLS отдают предпочтение именно сочетанию алгоритма Диффи-Хеллмана и использованию временных ключей для повышения безопасности соединения.
Следует ещё раз отметить, что шифрование с открытым ключом используется только в процедуре TLS Handshake во время первоначальной настройки соединения. После настройки туннеля в дело вступает симметричная криптография, и общение в пределах текущей сессии зашифровано именно установленными симметричными ключами. Это необходимо для увеличения быстродействия, так как криптография с открытым ключом требует значительно больше вычислительной мощности.
Возобновление сессии TLS
Как уже отмечалось ранее, полная процедура TLS Handshake является довольно длительной и дорогой с точки зрения вычислительных затрат. Поэтому была разработана процедура, которая позволяет возобновить ранее прерванное соединение на основе уже сконфигурированных данных.
Начиная с первой публичной версии протокола (SSL 2.0) сервер в рамках TLS Handshake (а именно первоначального сообщения ServerHello) может сгенерировать и отправить 32-байтный идентификатор сессии. Естественно, в таком случае у сервера хранится кэш сгенерированных идентификаторов и параметров сеанса для каждого клиента. В свою очередь клиент хранит у себя присланный идентификатор и включает его (конечно, если он есть) в первоначальное сообщение ClientHello. Если и клиент, и сервер имеют идентичные идентификаторы сессии, то установка общего соединения происходит по упрощённому алгоритму, показанному на рисунке. Если нет, то требуется полная версия TLS Handshake.
Процедура возобновления сессии позволяет пропустить этап генерации симметричного ключа, что существенно повышает время установки соединения, но не влияет на его безопасность, так как используются ранее нескомпрометированные данные предыдущей сессии.
Однако здесь имеется практическое ограничение: так как сервер должен хранить данные обо всех открытых сессиях, это приводит к проблеме с популярными ресурсами, которые одновременно запрашиваются тысячами и миллионами клиентов.
Для обхода данной проблемы был разработан механизм «Session Ticket», который устраняет необходимость сохранять данные каждого клиента на сервере. Если клиент при первоначальной установке соединения указал, что он поддерживает эту технологию, то в сервер в ходе TLS Handshake отправляет клиенту так называемый Session Ticket – параметры сессии, зашифрованные закрытым ключом сервера. При следующем возобновлении сессии, клиент вместе с ClientHello отправляет имеющийся у него Session Ticket. Таким образом, сервер избавлен от необходимости хранить данные о каждом соединении, но соединение по-прежнему безопасно, так как Session Ticket зашифрован ключом, известным только на сервере.
TLS False Start
Технология возобновления сессии бесспорно повышает производительность протокола и снижает вычислительные затраты, однако она не применима в первоначальном соединении с сервером, или в случае, когда предыдущая сессия уже истекла.
Для получения ещё большего быстродействия была разработана технология TLS False Start, являющаяся опциональным расширением протокола и позволяющая отправлять данные, когда TLS Handshake завершён лишь частично. Подробная схема TLS False Start представлена на рисунке:
Важно отметить, что TLS False Start никак не изменяет процедуру TLS Handshake. Он основан на предположении, что в тот момент, когда клиент и сервер уже знают о параметрах соединения и симметричных ключах, данные приложений уже могут быть отправлены, а все необходимые проверки можно провести параллельно. В результате соединение готово к использованию на одну итерацию обмена сообщениями раньше.
TLS Chain of trust
Пусть теперь Алиса получает сообщение от Чарли, с которым она не знакома, но который утверждает, что дружит с Бобом. Чтобы это доказать, Чарли заранее попросил подписать собственный открытый ключ закрытым ключом Боба, и прикрепляет эту подпись к сообщению Алисе. Алиса же сначала проверяет подпись Боба на ключе Чарли (это она в состоянии сделать, ведь открытый ключ Боба ей уже известен), убеждается, что Чарли действительно друг Боба, принимает его сообщение и выполняет уже известную проверку целостности, убеждаясь, что сообщение действительно от Чарли:
Описанное в предыдущем абзаце и есть создание «цепочки доверия» (или «Chain of trust», если по-английски).
В протоколе TLS данные цепи доверия основаны на сертификатах подлинности, предоставляемых специальными органами, называемыми центрами сертификации (CA – certificate authorities). Центры сертификации производят проверки и, если выданный сертификат скомпрометирован, то данный сертификат отзывается.
Из выданных сертификатов складывается уже рассмотренная цепочка доверия. Корнем её является так называемый “Root CA certificate” – сертификат, подписанный крупным центром, доверие к которому неоспоримо. В общем виде цепочка доверия выглядит примерно таким образом:
Естественно, возникают случаи, когда уже выданный сертификат необходимо отозвать или аннулировать (например, был скомпрометирован закрытый ключ сертификата, или была скомпрометирована вся процедура сертификации). Для этого сертификаты подлинности содержат специальные инструкции о проверке их актуальности. Следовательно, при построении цепочки доверия, необходимо проверять актуальность каждого доверительного узла.
Механизм этой проверки прост и в его основе лежит т.н. «Список отозванных сертификатов» (CRL – «Certificate Revocation List»). У каждого из центров сертификации имеется данный список, представляющий простой перечень серийных номеров отозванных сертификатов. Соответственно любой, кто хочет проверить подлинность сертификата, попросту загружает данный список и ищет в нём номер проверяемого сертификата. Если номер обнаружится – это значит, что сертификат отозван.
Таким образом, в данной статье рассмотрены все ключевые средства, предоставляемые протоколом TLS для защиты информации. За некоторую отсебятину в статье прошу прощения, это издержки изначальной цели выполнения перевода.
SSL без ключей
Реверс малвари
CDN-провайдер Cloudflare объявил, что запускает для клиентов новую услугу Keyless SSL, то есть «SSL без ключей». Это означает, что Cloudflare может устанавливать защищённые соединения от имени своих клиентов, даже не имея на руках их секретных ключей.
Такой способ защиты реализован, чтобы одновременно обеспечить защищённую связь и оставить нетронутыми секретные SSL-ключи клиентов. Это действительно важная причина, ведь многие компании из финансового или государственного сектора не могут воспользоваться услугами CDN-провайдера, потому что не имеют права передавать свои секретные цифровые ключи. В то же время, их сайты обязаны работать по HTTPS. Теперь эта проблема решена. По крайней мере, так считает Cloudflare, хотя некоторые независимые эксперты не одобряют подобный подход.
Cloudflare предлагает слегка модифицировать традиционную схему рукопожатия при установке SSL-соединения, чтобы вместо секретного ключа использовался key-сервер. Он просто возвращает «секретное» значение, которое подписано секретным ключом. При этом key-сервер находится в локальной сети клиента, а Cloudflare не имеет к нему доступа.
Другими словами, процесс рукопожатия SSL разбивается географически. Основная часть происходит на серверах Cloudflare, но только одно секретное значение нужно получить с key-сервера клиента. Этот сервер может работать под Linux (Red Hat/CentOS, Debian, Ubuntu и др.), другими UNIX-системами (включая FreeBSD) и Microsoft Windows Server.
В этом случае схема SSL-рукопожатия выглядит следующим образом.
Cхема рукопожатия Keyless SSL без использования секретного ключа RSA
Cхема рукопожатия Keyless SSL без использования секретного ключа DH
Исходный код Keyless SSL прошёл независимый аудит в компаниях iSEC Partners и Matasano Security. Реализация подобной схемы потребует внесения изменений в библиотеку OpenSSL и сервер Nginx, говорит Cloudflare.
Keyless SSL точно не повышает безопасность SSL-рукопожатия. В то же время, независимые эксперты сомневаются в инновационности предложенной методики. Они говорят, что загрузку цифрового ключа со стороннего носителя (SSL offloading) можно реализовать в рамках существующих стандартов.
Сравнение решений по балансировке высоконагруженных систем
И вновь мы публикуем расшифровки выступлений с конференции HighLoad++, которая прошла в подмосковном Сколково 7—8 ноября 2016 года. Сегодня Евгений Пивень знакомит нас с решениями балансировки в облаках.
Меня зовут Женя, я работаю в компании IPONWEB. Сегодня мы поговорим про развитие наших решений в балансировке высоконагруженных систем.
Сначала я пробегусь по понятиям, которыми буду оперировать. Начнём с того чем мы занимается: RTB, Real Time Bidding — показ рекламы с аукционом в реальном времени. Очень упрощенная схема того, что происходит, когда вы заходите на сайт:
Для того, чтобы показать рекламу, идет запрос на RTB-сервер, который запрашивает у рекламных серверов их ставки и потом решает, какую рекламу вам показать.
Особенности IPONWEB
У нас вся инфраструктура в облаках. Мы очень активно пользуемся Amazon и GCE, у нас несколько тысяч серверов. Главная причина, по которой мы полностью живем в облаках, — это скалируемость, то есть у нас реально часто нужно добавлять/удалять инстансы, иногда очень много.
У нас есть миллионы запросов в секунду, все эти запросы HTTP. Это может быть не до конца применимо к остальным протоколам. У нас очень короткие ответы. Может быть, и не очень, я думаю, в среднем от одного до несколько килобайт ответы. Мы не оперируем какими-то большими объемами информации, просто очень большим их количеством.
Для нас не актуально кэширование. Мы не поддерживаем CDN. Если нашим клиентам нужны CDN, то они сами занимаются этими решениями. У нас есть очень сильные суточные и событийные колебания. Они проявляются во время праздников, спортивных событий, каких-то сезонных скидок и т. д. Суточные можно хорошо посмотреть на таком графике:
Красный график — обычный стандартный график в европейской стране, а синий график — это Япония. На этом графике мы видим, что каждый день примерно в двенадцать у нас есть резкий скачок, и примерно в час трафик резко падает. Связано это с тем, что люди уходят на обед, и как очень порядочные японские граждане они пользуются интернетом активно больше всего на обеде. Такое очень хорошо видно на этом графике.
У нас есть большой разброс пользователей по всему миру. Это — вторая большая причина, почему мы пользуемся облаками. Нам очень важно отдать ответ быстро, и если сервера находятся в каких-то других регионах от пользователей, то часто это неприемлемо для RTB-реалий.
И у нас есть чёткое разграничение серверного и пользовательского трафика. Вернёмся к той схеме, которую я показал на первом слайде. Для простоты всё то, что приходит от пользователя до первичного RTB-сервера — это пользовательский трафик, все то что происходит за ним — это серверный трафик.
Зачем балансировать?
Две главные причины — это масштабируемость и доступность сервисов.
Масштабируемость — это когда мы добавляем новые сервера, когда мы из одного сервера, который уже не может справиться, вырастаем как минимум до двух, и между ними надо как-то раскидывать запросы. Доступность — это когда мы боимся, что с этим одним сервером что-то случится. Опять же нужно добавить второй, чтобы между ними как-то всё это балансировать и распределять запросы только по тем серверам, которые могут на них ответить.
Что ещё часто требуется от балансировщиков? Эти функции, естественно, для целей каждого приложения могут быть разными. Для нас больше всего актуально SSL Offload. Как это работает, показано здесь.
От пользователя до балансировщика идёт трафик, который зашифрован. Балансировщик расшифровывает его, раскидывает по бэкендам уже расшифрованный HTTP-трафик. Потом балансировщик обратно зашифровывает его и отдает пользователю опять в зашифрованном виде.
Ещё нам очень важна такая штука, как Sticky-балансировка, которую часто называют session affinity.
Почему для нас это актуально? Когда мы видим несколько слотов для рекламы на странице, мы хотим, чтобы при открытии этой страницы все запросы пришли сразу на один бэкенд. Почему это важно? Есть такая особенность как roadblock. Она означает, что если мы показали в одном из слотов баннер, например, Pepsi, то в другом мы не можем показать баннер той же самой Pepsi или Coca-Cola, потому что это конфликтующие баннеры.
Нам нужно понимать, какие баннеры мы показываем в данный момент пользователю. При балансировке нам нужно удостовериться, что пользователь пришел на один бэкенд. На этом бэкенде у нас создается некое подобие сессии, и мы понимаем, какие именно рекламы можно показать этому пользователю.
Также у нас есть Fallback. На примере сверху виден баннер, на котором он не работает, а справа — баннер, на котором он работает.
Fallback — это ситуация, когда по каким-то причинам бэкенд не справляется, и дабы не сломать страницу пользователю, мы отдаем ему обычно совсем пустой пиксель. Здесь я его нарисовал большим зеленым прямоугольником для понимания, но на самом деле обычно это просто маленькая гифка, двухсотый HTTP Response и правильный набор header’ов, чтобы у нас не сломалось ничего в верстке.
Так у нас выглядит нормальная балансировка.
Синяя жирная линия — это сумма всех запросов. Эти маленькие линии, много-много, — это идут запросы на каждый инстанс. Как мы видим, тут балансировка достаточно хорошая: практически все они идут почти одинаково, сливаясь в одну линию.
Это — балансировка курильщика. Здесь что-то пошло не так.
Проблема — на стороне Amazon. Подобное, кстати, произошло совсем недавно, буквально две недели назад. С амазоновских балансеров трафик стал приходить в таком виде.
Стоит сказать, что метрики — это хорошо. Здесь Amazon до сих пор не верит нам, что у нас происходит что-то плохое. Они видят только вот этот общий график, в котором видно лишь сумму запросов, но не видно, сколько запросов приходит по инстансам. До сих пор с ними боремся, пытаемся им доказать, что что-то с их балансировщиком идет не так.
Балансировка DNS
Итак, про балансировку я расскажу на примере одного из наших проектов. Начнем собственно с самого начала. Проект был молодой, мы примерно около начала этого проекта.
Большая часть трафика в этом проекте — серверный. Особенность работы с серверным трафиком: мы можем легко решать некоторые проблемы. Если у нас есть специфика у одного из наших клиентов, то мы можем как-то договориться с ним, чтобы они что-то поменяли на своем конце, как-то обновили свои системы, что-то еще сделали, чтобы у нас лучше работало с ними. Можно выделить их в отдельный пул: мы можем просто взять одного клиента, у которого есть какая-то проблема, привязать его к другому пулу и решить проблему локально. Либо, в совсем тяжелых случаях, можно даже его забанить.
Первое, чем мы начали пользоваться, — это была обычная DNS-балансировка.
Пользуемся Round-robin DNS-пулами.
Каждый раз при запросе на DNS, пул ротируется, и сверху оказывается новый IP-адрес. Таким образом работает балансировка.
Проблемы обычного Round-Robin DNS:
Балансировка gdnsd
На помощь приходит gdnsd – это DNS сервер, который многие, наверное, знают, которым мы активно пользуемся и сейчас.
Через какой-то промежуток времени мы сталкиваемся с проблемой 512 байт.
Проблема 512 байт — это проблема практически всех DNS-серверов. Изначально, когда DNS только проектировался, максимальный MTU у модемов был 576 байт. Это 512 байт + 64 длины заголовка. Пакеты от DNS исторически не отсылают больше чем 576 байт по UDP. Если у нас пул длиннее, чем 512 байт, то мы отсылаем только часть пула, включаем в нем флаг truncated. Потом уже от клиента приходит запрос по TCP, переспрашивая нас опять это пул. И тогда мы присылаем ему полный пул, теперь уже по TCP.
Эта проблема была только у части наших клиентов, примерно у 15%. Мы смогли выделить их отдельно в пул и использовать для них weighted-пулы в gdnsd.
Бонус weighted-пулов в этом случае — их можно разбивать. Если у нас, скажем, 100 серверов, мы их разбиваем на 5 частей. Мы отдаем на каждый запрос один из этих маленьких подпулов, в которых всего 20 серверов. И Round-robin проходит по этим маленьким пулам, каждый раз он выдает новый пул. Внутри самого пулa тоже используется Round-Robin: он шаффлит эти айпишники и каждый раз выдает новые.
Веса gdnsd можно использовать помимо этого для, например, staging серверов. Если у вас есть более слабый инстанс, вы на него можете изначально отсылать гораздо меньше трафика и проверять, что что-то там сломалось, только на нём, отсылая на него достаточно маленький набор трафика. Или если у вас есть разные типы инстансов, либо вы используете разные сервера. (Я часто говорю «инстансы» потому что у нас всё в облаках, но для вашего конкретного случая это может быть не так.) То есть вы можете использовать разные типы серверов и с помощью gdnsd слать на них больше или меньше трафика.
Тут у нас тоже возникает проблема — DNS-кэширование. Часто, когда идет запрос этого пула, мы отдаем только маленький пул, и этот пул кэшируется. С этим пулом у нас продолжает жить какой-то клиент, не переспрашивая наш DNS. Такое случается, когда DNS-клиент плохо себя ведет, не придерживается TTL и работает только с маленьким ограниченным набором IP-адресов, не обновляя его. Если он получил изначально полный лист по TCP, это нормально. Но если он получил только маленький пул, который weighted, то это может быть проблемой.
Через какое-то время мы сталкиваемся с новой проблемой.
Те оставшиеся 85% серверного трафика всё ещё пользуются обычными мультифопулами, как это называется в gdnsd. С некоторыми из них начинаются проблемы.
Мы поняли, что проблема происходит только у амазоновских DNS. То есть у тех наших клиентов, которые сами хостятся в Amazon, при ресолве пула, в котором находится больше 253 хостов, им просто приходит ошибка NXDOMAIN, и они полностью не ресолвят этот целый пул.
Это произошло тогда, когда мы добавили около 20 хостов, и у нас их стало 270. Мы локализовали число до 253, мы поняли, что на этом количестве становится проблемно. Сейчас эту проблему уже починили. Но на тот момент мы поняли, что топчемся на месте, и надо как-то эту проблему решать дальше.
Так как мы находимся в облаках, первое, о чем мы подумали, — попробовать вертикальное масштабирование. Оно сработало, соответственно, мы сократили количество инстансов. Но опять же, это временное решение проблемы.
Мы решили попробовать что-то еще, тогда выбор пал на ELB.
ELB – это Elastic Load Balancing, решение от Amazon, которое балансирует трафик. Как это работает?
Они предоставляют вам CNAME, в данном случае это вот эта страшная строчка под www.site.com : elb, цифры, регион и так далее. И этот CNAME ресолвится на несколько внутренних айпишников инстансов, которые балансируют на наши бэкенды. В таком случае нам нужно всего один раз привязать их CNAME в нашем DNS к нашему пулу. Потом мы уже добавляем в группу серверы, на которые раскидывают балансировщики.
ELB умеет SSL Offload, к нему можно прицепить сертификат. Также он умеет HTTP status checks, чтобы понимать, насколько живые у нас инстансы.
Мы практически сразу стали сталкиваться с проблемами с ELB. Есть так называемый прогрев балансировщиков ELB. Это нужно, когда вы хотите пускать больше 20—30 тысяч запросов в секунду. Прежде чем перевести весь ваш трафик на ELB, вам нужно написать письмо в Amazon, сказать, что мы хотим пустить много трафика. Вам присылают письмо с кучей страшных вопросов про характеристики вашего трафика, сколько, когда, как долго вы собираетесь это всё поддерживать. Затем они добавляют новых инстансов в свой пул и готовы к наплыву трафика.
И даже при предварительном прогреве мы столкнулись с проблемой. Когда мы у них запросили 40 тысяч запросов в секунду, примерно на 30 тысячах у них все сломалось. Нам пришлось все это дело быстро откатывать.
Ещё у них есть балансировка по скорости ответов. Это алгоритм работы амазоновского балансировщика. Он смотрит насколько быстро ваши бэкенды отвечают. Если он видит, что быстро, то шлет туда больше трафика.
Проблема здесь в чем? Если ваш бэкенд отчаянно пятисотит [выдаёт код состояния HTTP 5XX, что говорит об ошибке сервера] и не справляется, то балансировщик думает, что бэкэнд очень быстро отдает ответы, и начинает слать ему ещё больше трафика, загибая ваш бэкэнд ещё сильнее. В наших реалиях это ещё проблемнее, потому что мы, как я уже рассказывал, обычно отсылаем 200-ый ответ, даже если всё плохо. Пользователь не должен видеть ошибку — просто посылаем пустой пиксель. То есть для нас эту проблему решить ещё сложнее.
На последней конференции Amazon они рассказывали, что если у вас что-то плохое происходит, то в exception’ы заворачивайте какие-нибудь таймауты по 100-200 мс, искусственно замедляя 500-ые ответы, чтобы амазоновской балансировщик понимал, что ваш бэкенд не справляется. Но вообще, по-хорошему надо делать правильные status checks. Тогда ваш бэкенд понимал бы, что есть проблемы, и отдавал бы на status checks проверки проблему, и его просто выкидывало бы из пула.
Теперь у Amazon появилось новое решение: Application Load Balancer (ALB). Это довольно интересное решение, но нам оно не сильно актуально, потому что оно для нас ничего не решает и скорее всего будет стоить гораздо больше. Их система с хостами стала сложнее.
Есть поддержка WebSocket, HTTP/2 и контейнеров. Если у вас Docker внутри одного инстанса, то он может распределять между ними.
В Google мы пользуемся GLB. Это довольно интересное решение. По сравнению с Amazon, у него есть много преимуществ.
Первое — у нас всего 1 IP. Когда вы создаете балансировщик в Google, вам даётся единственный айпишник, который вы можете привязать к своему сайту. Это значит, что вы можете привязать его даже к «голому» домену. CNAME же можно привязать к домену второго уровня.
Вам нужно создать всего один балансировщик по всем регионам. То есть в Amazon нам нужно в каждом регионе создавать по балансировщику, чтобы балансировать между инстансами внутри этого региона, а в Google — всего один балансировщик, всего один один IP, и он балансирует между всеми вашими инстансами по разным регионам.
Гугловский балансировщик умеет Sticky и по IP, и по cookie. Я рассказывал, зачем нужен Sticky — нам нужно одного пользователя переслать на один бэкэнд. Амазоновские балансировщики умеют только по cookie, то есть они сами на уровне балансировщика выдают cookie. Потом его проверяют, и если видно, что у пользователя cookie, соответствующий одному из инстансов, его отсылают на тот же самый. Гугловский умеет IP, что нам гораздо лучше, хоть и не всегда решает все проблемы.
У балансировщика Google есть Instant warm-up: его не надо никак прогревать, на него сразу можно отсылать до миллиона запросов. Миллион запросов — это то, что они обещают сами точно, и то, что я сам проверял. Думаю, дальше они растут как-то сами внутри.
Но при этом у них есть проблема с резким изменением числа бэкендов. В какой-то момент мы добавили около 100 новых хостов. На этом этапе гугловский балансировщик загнулся. Когда мы стали общаться с инженером из Google, они сказали: добавляйте по одному в минуту, тогда будет вам счастье.
Также недавно в их HTTP-балансировщике подрезали порты, которыми вы можете пользоваться при создании балансировщика. Раньше было обычное поле для ввода, сейчас можно выбрать только между 80 и 8080 портами. Для кого-то это может быть проблемой.
Ни у одного из этих облачных балансировщиков нет поддержки SNI. Если вам нужно поддерживать несколько доменов и несколько сертификатов, то вам нужно на каждый сертификат создавать по отдельному балансировщику и к нему привязывать. Это решаемая проблема, но такая ситуация может быть неудобной.