Если у вас зоопарк из серверов, то не стоит сравнивать абсолютные показатели. Нормализуйте.
Если у вас зоопарк из серверов, то не стоит сравнивать абсолютные показатели. Нормализуйте.

К нам обратился заказчик из сферы развлекательного видеостриминга с интересной проблемой - у него серверы падали не одновременно, а ему очень хотелось бы добиться синхронности.

Серверы, которые смущали заказчика работали в роли бэкенда для хранения видеофайлов. По сути, это было множество узлов, содержащих десятки терабайт видеофайлов, которые предварительно были нарезаны в разном разрешении конвертерами. Затем, все эти миллионы файлов отдавались во внешний мир с помощью nginx + kaltura, что позволяло перепаковывать на лету mp4 в сегменты DASH/HLS. Это позволяло хорошо переносить даже высокие нагрузки, отдавая плеером только нужные сегменты без резких всплесков.

Проблемы появились тогда, когда встал вопрос с георезервированием и масштабированием при росте нагрузок. Серверы внутри одной группы резервирования умирали не синхронно, так как представляли из себя весьма разнообразный зоопарк с разными провайдерами, шириной канала, дисками и RAID-контроллерами. Нам предстояло провести аудит всей этой красоты и перестроить почти с нуля весь мониторинг с методологией управления ресурсами.

Особенности архитектуры

Первый же вопрос, который возник у нас при аудите, почему не использовался полноценный коммерческий CDN? Ответ оказался весьма прозаичен - так дешевле. Архитектура видеохранилища позволяла достаточно хорошее горизонтальное масштабирование, а относительно стабильный трафик позволял делал аренду железных серверов с хорошим каналом более выгодным решением, чем сторонние коробочные решения. Платный CDN был все-таки настроен, но с петабайтными масштабами отдачи контента он был весьма дорог для заказчика и подключался только в аварийных ситуациях. Такое случалось редко, так как в большинстве случаев рост числа посетителей прогнозировался заранее, что позволяло неторопливо заказать еще один сервер и добавить в перегруженную группу.

Весь видео-контент был разделен на десятки групп. Каждая группа содержала в себе 3-8 серверов с идентичным контентом. При этом, каждая группа кроме последней работала полностью в режиме read-only. Последняя группа работала в смешанном режиме - в нее одновременно писались новые видео и из нее же шла раздача контента. Когда место на группе серверов заканчивалось, запись в нее прекращалась и в дальнейшем данные из нее только читались. Схема выглядела весьма работоспособно, но было несколько очень неприятных моментов:

  1. Серверы были разными. Нет, даже не так. Серверы были ЗООПАРКОМ. Политика диверсификации требовала иметь нескольких независимых друг от друга поставщиков с множеством локаций по всему миру. Естественно, железо арендовалось в разное время, с разными дисками, RAID-контроллерами и даже разной шириной канала.

  2. По ряду причин, на этом этапе было невозможно обеспечить полноценную балансировку нагрузки между серверами с health-check. То есть, если один сервер из кластера падал, то пользователи все равно получали его IP адрес в DNS. До ручного снятия нагрузки, часть пользователей продолжала тыкаться в мертвый узел и получала ошибки при загрузке контента.

  3. Из-за того, что в одной группе могли соседствовать серверы с каналом в 1 и 10 гигабит/с, было совершенно непонятно, когда уже пора докупать новые мощности. 

В итоге, как потом выяснилось, в какие-то группы серверы докупались избыточно, а в какие-то наоборот.

Серверы падают по очереди

Один из старых дашбордов с абсолютными значениями
Один из старых дашбордов с абсолютными значениями

Посмотрите на график выше. Можно ли понять, насколько хорошо сбалансирована нагрузка между отдельными узлами? При этом, в этой группе есть серверы с каналом в 1, 2.5 и 10 гигабит. А еще один узел хромает на правую лапу имеет странный контроллер, который может выдавать внезапные перегрузки по IOPS на ровном месте.

При анализе мы разделили серверы на две большие группы:

  1. Группа серверов с небольшим лимитом upload bandwidth (1G-2.5G)

  2. Группа серверов с большим лимитом upload bandwidth (10G)

Проблема заключалась в том, что иногда случались инциденты. Один из последних выглядел как множество внезапных азиатских пользователей, которые начинали тащить десятками гигабит весь доступный контент. Все это совпало с тем, что один из мощных узлов в группе находился в нерабочем состоянии из-за вылетевшего диска и длительной пересборки массива.

Первыми сдались серверы, которые имели самый широкий канал, упершись в IOPS. При этом, узлы с небольшим каналом отключались позже, но уже по причине лимитов по пропускной способности сети. У заказчика были инструменты для перераспределению трафика между серверами, но применялись они скорее эмпирически. Сравнивать узлы между собой было очень сложно.

Таким образом, мы получили две основные группы:

WAN-limited server group

К этой группе относятся серверы с пропускной способностью менее 2.5G. Порог определен эмпирически при анализе пиковых значений.

При росте нагрузки до критической эти серверы никогда не достигают критических значений CPU iowait - DoS происходит из-за перегрузки сети. При этом внутри этой группы отказ происходит при разной нагрузке - 1G уйдет в DoS раньше, чем 2G. Использовать показатель трафика в чистом виде без нормализации невозможно.

IOPS-limited server group

К этой группе относятся серверы с пропускной способностью более 2.5G.

При росте нагрузки до критической эти серверы никогда не достигают критических значений upload traffic - DoS происходит из-за перегрузки дисковой подсистемы.

Давайте нормализуем!

В случае, если все данные представлены в разных масштабах, нам надо их нормализовать перед тем, как что-то с ними делать. Именно поэтому, мы сразу решили отказаться на основном дашборде от абсолютных значений. Вместо этого мы выделили два показателя и разметили его от 0 до 100%:

  1. Значение cpu iowait - хорошо показывает перегрузку дисковой подсистемы. Мы эмпирически вывели по историческим данным, что системы заказчика приемлемо функционируют примерно до тех пор, пока iowait ниже 60%.

  2. Ширина канала. Здесь тоже все прозрачно - как только нагрузка доходит до лимита, пользователи начинают страдать из-за ограничений на стороне провайдера.

За 100% мы приняли состояние, когда сервер добрался до своего лимита по IOPS или каналу и ушел в DoS.

Нормализация по IOPS
Нормализация по IOPS
Нормализация по ширине канала
Нормализация по ширине канала

Таким образом, шкала стала относительной, и мы стали видеть, когда сервер упирается в свои личные лимиты. При этом, совершенно неважно, 1 это гигабит или 10 - данные теперь стали нормализованы.

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

Теперь мы можем сбалансировать нагрузку так, чтобы при чрезмерной нагрузке серверы одной группы отказали одновременно. Это будет говорить о том, что ресурсы утилизируются максимально эффективно. Хотя, конечно, в норме средняя нагрузка не должна превышать рассчитанные пороги.

Что у нас получилось

Итоговое решение для одной из групп. В идеале нормализованная нагрузка должна быть почти идентична.
Итоговое решение для одной из групп. В идеале нормализованная нагрузка должна быть почти идентична.

Мы получили многослойный бутерброд из формул, который совершенно не показывал реальную абсолютную нагрузку на сервер, но зато точно предсказывал, когда именно он откажет.

Представьте себе упряжку, где есть сильные и слабые ездовые собаки. Нам совершенно неважно, сколько именно лошадиных сил (или собачьих?) выдает каждая из них. Нам нужно, чтобы вся повозка ехала равномерно, а каждая из собак была нагружена в равной степени в зависимости от своих возможностей.

В итоге получили вот что:

  1. Автоматизировали весь процесс добавления новых узлов с помощью terraform/ansible с одновременной генерацией дашбордов, которые учитывают физические ограничения каждого сервера в формулах расчета при нормализации.

  2. Подготовили качественную модель, которая позволила добавлять новые узлы в нужный момент без ситуаций “три сервера нагружены наполовину, а четвертый уже лежит”.

  3. Серверы действительно стали падать совершенно синхронно. Реальный тест случился некоторое время спустя при мощном DDoS со стороны ботов-парсеров. Нагрузка почти одновременно уткнулась на всех узлах в свои лимиты - где-то в IOPS, где-то в ширину канала.

  4. Заказчик смог сохранить свою модель расширения инфраструктуры с использованием разнородного по мощности оборудования.

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

В дальнейшем, это позволило нам продолжить рефакторинг, внедрить кеширование с bcache, увеличив в десятки раз производительность отдельных узлов и вообще выбросить на мороз более половины серверов. Но об этом я расскажу в другой раз.

Ну а если вам нужно перебрать вашу инфраструктуру по винтику, настроить мониторинг и полностью все автоматизировать, приходите к нам в WiseOps. Мы поможем.

Комментарии (34)


  1. datacompboy
    04.05.2024 22:19
    +1

    Не, пусть мрут когда хотят. Абы N+1/N+2 сохранялись... (и да, обидно, что добавлять один Самый Супер Сильный в группу не смысла, он-то и есть тот самый +1)


    1. Meklon Автор
      04.05.2024 22:19
      +1

      На том этапе развития проблема была в том, что если сервер лег, то из нагрузки он автоматически не выводится. Пользователи страдали. Мы это реализовывали на более поздних этапах рефакторинга инфраструктуры.


  1. aamonster
    04.05.2024 22:19
    +7

    Задача вообще непонятна. Обычно ж стараются, чтобы всё разом не умирало, а не наоборот.


    1. Meklon Автор
      04.05.2024 22:19
      +2

      Тут проблема была в том, что ресурсы были несбалансированы между собой. Есть мощные и дохлые узлы. Если просто разделить трафик в равных пропорциях, часть узлов уже ляжет под нагрузкой, а часть будет нагружена наполовину от своих возможностей.
      Но вот задача правильной балансировки была трудновыполнима из-за того, что не было нормальной модели и нормализованного мониторинга нагрузки.


      1. sekuzmin
        04.05.2024 22:19
        +2

        @aamonster совершенно верно акцентирует внимание на несколько чудовищную формулировку задачи.

        К нам обратился заказчик ... у него серверы падали не одновременно

        Проблемы появились тогда, когда встал вопрос с георезервированием и масштабированием при росте нагрузок. Серверы внутри одной группы резервирования умирали не синхронно

        А вот цели проекта сформулированы просто великолепно

        Project Goals

        To develop a methodology for predicting the dynamics of reserve capacity and the need for storage expansion.

        https://wiseops.team/case-iac-development-for-video-hosting


        1. Meklon Автор
          04.05.2024 22:19
          +2

          Простите за такой кликбейт в формулировках. По сути, было необходимо обеспечить равномерность нагрузки на серверы с очень разными характеристиками, чтобы полностью утилизировать мощность.

          Если часть уже откажет, а часть останется функциональными, то это не спасет в этой архитектуре. Вся группа уже будет нерабочей. Но да, в условиях идеальной балансировки они действительно синхронно падают при DDoS. Конечно, не в этом была основная цель, просто забавное наблюдение и критерий хорошей балансировки.


        1. DaneSoul
          04.05.2024 22:19
          +6

          Ну так старый добрый кликбейт же.
          Я собственно из-за заголовка и зашел, стало интересно, зачем может понадобиться синхронно ронять все сервера.


      1. aamonster
        04.05.2024 22:19

        Я даже догадался, в чём была реальная проблема (глупо переплачивать за мощные сервера, которые работают с такой же нагрузкой, как хилые), но прозвучало крайне странно :-)


  1. alexdora
    04.05.2024 22:19
    +2

    Напрашивается вопрос, а нельзя сделать не пропорциональную нагрузку с перераспределением при падении узлов? Конечно, задача не очень простая потому что нужно проводить целое исследование для поиска оптимального алгоритма. Но это реально. Потому что…задача действительно странная. Обрубить стек серверов из-за отказа одного, но ведь если вы убиваете стек серверов в CDN трафик волшебным образом не пропадает, значит все это успешно ударит по другому стеку серверов который работает.


  1. LoveMeOrHateMe
    04.05.2024 22:19
    +14

    Очень даже молодцы. Не стали с умным видом рассказывать, мол у вас тут все не правильно, давайте все строить заново, а сначала разобрались с текущей ситуацией, помогли заказчику, а уж потом потихоньку можно будет привести все в божеский вид. Я думаю заказчик должен быть очень благодарен.


    1. Meklon Автор
      04.05.2024 22:19
      +2

      Мы всегда придерживаемся идеи, что заказчик не просто так долгое время что-то строил. Вначале быстро решаем то, что болит прямо сейчас, а потом уже итеративно движемся оптимальному варианту.


  1. achekalin
    04.05.2024 22:19

    Интересно, хоть каналы-то были безлимитные по объему в месяц? Или до некоторой величины оплачено, а далее погигабайтно?

    Н могу еще понять: если сервер выведен/умер, а его ip все еще запрашивается клиентами, то не так это и удобно. Тут уже клиентское ПО должно тестировать серверы и выбирать живые, разве не так решать проще всего?


    1. Meklon Автор
      04.05.2024 22:19
      +1

      Там зоопарк) одновременно были варианты:

      1. Канал безлимитный по общему трафику, но ограничен по ширине. Обычно это узлы по 1-2.5 гигабита.

      2. Канал органичен по ширине, в стоимость входит пакет трафика, потом за дополнительные деньги.

      3. Канал без формального лимита по ширине канала, пакета трафика нет, тарифицируются гигабайты.

        Финансовую оптимизацию мы позднее делали, там вообще весело было. До полноценного мониторинга было сложно посчитать вообще что и сколько стоит.

      Насчёт того, что мертвый сервер не должен отдаваться клиентам - я согласен. Но там были особенности, которые не давали это сделать.


  1. rPman
    04.05.2024 22:19

    Уже десять лет существует технология webtorrent в т.ч. для стриминга, но видеоконтент продолжают отдавать по старинке.

    Или у p2p технологий есть какая то неразрешимая фатальная проблема, почему ее не внедряют везде?


    1. php7
      04.05.2024 22:19

      Это то что с WebRTC?
      Я когда-то тестировал один сервис.
      Он не особо снимал нагрузку с серверов.


    1. unclejocker
      04.05.2024 22:19

      Все за NATом сидят, а если у обоих пиров NAT, то нужен еще сервер, который их соединит и будет через себя гнать трафик, проще напрямую отдать.


      1. Meklon Автор
        04.05.2024 22:19

        Возможно, IPv6 в итоге изменит ситуацию. Мы видели большие объемы трафика через него а ЮВА.


        1. slonopotamus
          04.05.2024 22:19
          +1

          Непонятно, как? На IPv6 все вместо NAT'а сидят за фаерволом на том же самом роутере, который не разрешает входящие соединения.


          1. Meklon Автор
            04.05.2024 22:19
            +2

            Я сейчас не про torrent, а в принципе про IPv6 трафик. А так согласен, это выглядит очень перспективно


      1. rPman
        04.05.2024 22:19
        +1

        NAT-ы бывают разные, типовой nat который по умолчанию у всех у кого роутер с wifi и динамическим/статическим ip, пролезает с помощью stun сервера (когда для начала разговора нужен третий, но весь трафик пойдет напрямую между пирами, даже если они оба за nat), вот с мобильными сложнее, там провайдеры могут нагородить вложенные nat.


        1. unclejocker
          04.05.2024 22:19

          Про типовой нат. Я даже проверил сейчас - у меня провайдер выдает мне серый адрес, он назначается роутеру и роутер внутри квартиры раздает клиентам (опять же через nat) второй слой серых адресов. Т.е. типовая конфигурация - двойной nat. Это крупнейший провайдер в Москве. И так уже лет 10. И думаю так будет у любого более-менее крупного провайдера, т.к. с нынешними ценами на ipv4 первое что приходит в голову для оптимизации расходов - это загнать всех клиентов за nat.


      1. blind_oracle
        04.05.2024 22:19

        TURN и ко давно эту проблему решает достаточно надёжно.


        1. unclejocker
          04.05.2024 22:19

          Насколько я понимаю, через TURN весь трафик и ходит при этом, а если трафик от клиента к клиенту ходит через ваш-же сервер/канал, то зачем огород городить?


          1. blind_oracle
            04.05.2024 22:19

            Нет, TURN нужен только чтобы дырявить NAT и сводить клиентов друг с другом (сообщая номера портов и т.п.). Трафик ходит напрямую.


            1. unclejocker
              04.05.2024 22:19

              Это STUN. А про TURN вот что пишут на webrtc org: For most WebRTC applications to function a server is required for relaying the traffic between peers, since a direct socket is often not possible between the clients (unless they reside on the same local network). The common way to solve this is by using a TURN server. The term stands for Traversal Using Relays around NAT, and it is a protocol for relaying network traffic.


              Ну и выше человек написал, что пробовал он, но нагрузка уменьшается незначительно, большинство клиентов не могут друг до друга достучаться. Для экономии адресов провайдеры сейчас городят nat на nat-е и nat-ом погоняет.


              1. blind_oracle
                04.05.2024 22:19

                Да, я два сокращения в голове перепутал. STUN конечно.


  1. sshmakov
    04.05.2024 22:19
    +1

    Итак, в очередной раз сферы развлекательного видеостриминга, пуст немного, но подстегнули прогресс.


    1. Meklon Автор
      04.05.2024 22:19
      +1

      У них часто интересные задачи , требующие необычных решений.


      1. datacompboy
        04.05.2024 22:19
        +1

        Интересный способ сказать, что там всегда всё через одно место...


        1. Meklon Автор
          04.05.2024 22:19

          Всякое бывает. Часто это довольно старые проекты, которые внезапно обнаружили, что им нужно обслуживать тяжёлые нагрузки, и сделали как смогли. Да, многие решения могут выглядеть несколько необычно. Но они работают и приносят доход.

          Поэтому, приходится все аккуратно и последовательно все оптимизировать.


  1. trublast
    04.05.2024 22:19
    +2

    В похожей ситуации использовали такой подход: m3u динамический, плейлисты отдаются высокопроизводительным бэкендом. Там высокий rps, но нет io, и сами плейлисты мелкие, поэтому bandwidth не занят у серверов.

    При генерации плейлиста учитывалась нагрузка на серверы, отдающие непосредственно видеочанки. Серверы выводились из балансировки при недоступности, или когда полоса была на пределе. А ещё автоматом подкидывалась раздача через cdn, когда полоса всех серверов группы была близка к пределу


    1. Meklon Автор
      04.05.2024 22:19

      О, спасибо. Очень пригодится, как раз сейчас оптимизируем вместе с их разработчиками.


  1. Kilmez
    04.05.2024 22:19

    Извините, что не совсем по теме вашего кейса

    У меня давно была открыта вкладка вашего сайта (на ru) с вакансиями девопсов, а теперь сайт полностью на en и ссылка на вакансии пропала. Можно её как то вернуть? Спасибо.


    1. Meklon Автор
      04.05.2024 22:19

      Без проблем, напиши мне в @meklon в telegram. Прямо сейчас у нас нет найма новых сотрудников.