OVHcloud Web Statistics: новый интерфейс статистики для вашего веб-сайта, размещенного в OVHcloud

Если вы когда-либо управляли или редактировали веб-сайт, у вас наверняка будет опыт отслеживания просмотров страниц и статистики посещений.

Если это так, то эта статья для вас! Будьте готовы вступить в 2020 год с совершенно новым интерфейсом!



Немного истории

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

Существуют два метода, которые помогут вам собрать эту информацию:

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

В 2004 году, чтобы обеспечить безопасность ваших данных, мы решили использовать локальное решение под названием Urchin… но пришло время меняться!

Почему?

  • Urchin был куплен Google, и программное обеспечение больше не выпускается. Таким образом, с 2012 года он не развивался.
  • Urchin основан на Flash Player. Поддержка Flash Player прекращена, и в 2020 году он будет остановлен компанией Adobe. Поддержки для него больше не будет.
  • Это не лучший опыт.
  • Urchin не позволяет пользователям визуализировать статистику субдоменов. (пример: app.mydomain.com)



Как мы предоставляем статистику вашего сайта?

Ежедневно мы вычисляем статистику по нескольким миллионам сайтов. Это особое требование, и существует несколько решений для его удовлетворения.

Что это за потребности:

  • Возможность максимально быстро вычислить статистику всех веб-сайтов.
  • Сводные данные для отображения анонимных данных.
  • Не встраивайте код / ​​трекер на свой сайт
  • Иметь простой в использовании интерфейс, соответствующий сегодняшним стандартам
  • Дайте вам возможность видеть на уровне поддоменов вашу статистику
  • Перенесите предыдущую статистику из Urchin, чтобы не потерять ее

Долгое время мы пытались избежать эффекта «придумано не здесь», потому что восстановление статистического инструмента — не наша основная работа. Поэтому мы перепробовали множество решений на рынке. Открытый исходный код или нет. Бесплатно или с лицензией. И мы не нашли решения, способного масштабировать наше количество журналов и вычислять статистику для всех веб-сайтов, которые мы размещаем!

Итак, мы решили разработать альтернативное решение и предложили его по умолчанию для всех: OVHcloud Web Statistics (или OWStats).

Так что нового?

Новый пользовательский интерфейс для быстрой визуализации наиболее актуальной статистики



Вы можете найти несколько разделов:



  • Панель управления : сводка действий в вашем домене с помощью панели управления. 
  • Браузеры : дополнительная техническая информация о различных браузерах и платформах, используемых для посещения вашего домена.
  • Геолокация : какая страна / регион посещает ваш домен (данные анонимны, поэтому это только общий обзор).
  • Запросы : Обзор самых просматриваемых страниц
  • Роботы : Анализ ботов, посещающих ваш домен
  • Статус : эволюция кода статуса и страницы с ошибками, которые следует изучить.

Было бы проще, если бы мы показали несколько картинок, не так ли?

Ну конечно бы! Здесь у вас есть:

Панель управления:



Страница геолокации:



И страницы статуса:



Некоторые цифры

Благодаря этому новому инструменту мы можем вычислять вашу статистику до 8 раз быстрее.
Мы также вычисляем 2,5 ТБ логов в день!

Хотите больше информации?

Этот пост является предварительным просмотром нашей входящей службы веб-статистики OVH. Мы вернемся к вам с дополнительными сообщениями о технических деталях по мере приближения даты выпуска!

Jerem: Agile-бот

В OVHCloud мы открываем исходный код для нашего проекта «Agility Telemetry». Джерем , как наш сборщик данных, является основным компонентом этого проекта. Джерем регулярно очищает нашу JIRA и извлекает определенные показатели для каждого проекта. Затем он пересылает их в наше приложение для длительного хранения, платформу данных метрик OVHCloud .



Концепции Agility с точки зрения разработчика

Чтобы помочь вам понять наши цели для Jerem , нам нужно объяснить некоторые концепции Agility, которые мы будем использовать. Во-первых, мы составим техническую ежеквартальную дорожную карту для продукта, в которой изложены все функции, которые мы планируем выпускать каждые три месяца. Это то, что мы называем эпосом .

ЧДля каждой эпопеи мы определяем задачи, которые необходимо будет выполнить. Для всех этих задач мы затем оцениваем сложность задач с помощью очков истории во время сеанса подготовки команды. Сюжетная точка отражает усилия, необходимые для выполнения конкретной задачи JIRA.

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

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

Как работает Джерем

В OVH мы используем JIRA для отслеживания нашей активности. Наш Jerem бот обрывки наших проектов из JIRA и экспорта всех необходимых данных для нашей OVHCloud Метрики платформы данных . Джерем также может передавать данные в любую базу данных, совместимую с Warp 10. В Grafana вы просто запрашиваете платформу Metrics (используя источник данных Warp10 ), например, с помощью нашей панели управления программами . Все ваши KPI теперь доступны на красивой панели инструментов!



Откройте для себя показатели Jerem

Теперь, когда у нас есть обзор основных задействованных концепций Agility, давайте погрузимся в Джерема! Как преобразовать эти концепции гибкости в показатели? Прежде всего, мы извлечем все показатели, относящиеся к эпикам (т.е. новым функциям). Затем мы подробно рассмотрим метрики спринта.

Эпические данные

Чтобы объяснить эпические метрики Джерема, мы начнем с создания новой. В этом примере мы назвали это Agile Telemetry. Мы добавляем лейбл Q2-20, что означает, что мы планируем выпустить его во втором квартале. Чтобы записать эпопею с Джеремом, вам нужно установить четверть для окончательной доставки! Затем мы просто добавим четыре задачи, как показано ниже:



Чтобы получить метрики, нам нужно оценить каждую отдельную задачу. Мы сделаем это вместе на подготовительных сессиях. В этом примере у нас есть собственные очки истории для каждой задачи. Например, мы оценили write a BlogPost about Jeremзадачу на 3.



В результате у Джерема теперь есть все необходимое, чтобы начать сбор эпических показателей. В этом примере представлены пять показателей:

  • jerem.jira.epic.storypoint
    : общее количество очков истории, необходимых для завершения этой эпопеи. Значение здесь 14 (сумма всех очков эпической истории). Этот показатель будет развиваться каждый раз, когда эпик обновляется путем добавления или удаления задач. 
  • jerem.jira.epic.storypoint.done
    : количество выполненных задач. В нашем примере мы уже выполнили 
    Write Jerem bot
    и 
    Deploy Jerem Bot
    , поэтому мы уже выполнили восемь пунктов истории.
  • jerem.jira.epic.storypoint.inprogress
    : количество «выполняемых» задач, например 
    Write a BlogPost about Jerem
    .
  • jerem.jira.epic.unestimated
    : количество неоцененных задач, как 
    Unestimated Task
    в нашем примере.
  • jerem.jira.epic.dependency
    : количество задач, у которых есть метки зависимостей, указывающие, что они являются обязательными для других эпиков или проектов.



Таким образом, для каждого эпика в проекте Джерем собирает пять уникальных показателей.

Данные спринта

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

Итак, давайте откроем новый спринт в JIRA и начнем работать над нашей задачей. Это дает нам следующее представление JIRA:



Джерем собирает следующие показатели для каждого спринта:

  • erem.jira.sprint.storypoint.total
    : общее количество очков истории, набранных в спринт.
  • jerem.jira.sprint.storypoint.inprogress
    : сюжетные точки, которые в настоящее время выполняются в рамках спринта.
  • jerem.jira.sprint.storypoint.done
    : количество очков истории, набранных на данный момент за спринт.
  • jerem.jira.sprint.events
    : даты начала и окончания спринта, записанные как строковые значения Warp10.



Как вы можете видеть в представлении «Показатели» выше, мы будем записывать каждую метрику спринта дважды. Мы делаем это, чтобы быстро просмотреть активный спринт, поэтому мы используем метку «текущий». Это также позволяет нам запрашивать прошлые спринты, используя настоящее имя спринта. Конечно, активный спринт также можно запросить по его имени.

Данные о препятствиях

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

Мы можем добавить в JIRA специальные билеты, чтобы отслеживать выполнение этой задачи. Это то, что мы называем «препятствием». Они маркируются в соответствии с их природой. Если, например, постановка требует вашего внимания, то это препятствие «Инфра». Вы также получите метрики для «Всего» (все виды препятствий), «Избыточности» (незапланированные задачи), «Поддержка» (помощь товарищам по команде) и «Исправление ошибок или другое» (для всех других видов препятствий).

Каждое препятствие принадлежит активному спринту, в котором оно было закрыто. Чтобы закрыть препятствие, вам нужно только пометить его как «Готово» или «Закрыто».

Мы также получаем такие показатели, как:

  • jerem.jira.impediment.TYPE.count
    : количество препятствий, возникших во время спринта.
  • jerem.jira.impediment.TYPE.timespent
    : количество времени, затраченного на устранение препятствий во время спринта.

TYPE соответствует виду зафиксированного препятствия. Поскольку мы не обнаружили никаких реальных препятствий, Джерем собирает только totalметрики.



Чтобы начать запись препятствий, мы просто создаем новую задачу JIRA, в которую добавляем метку «препятствие». Мы также устанавливаем его характер и фактическое время, потраченное на это.



В качестве препятствия мы также извлекаем глобальные метрики, которые всегда записывает Джерем:

  • jerem.jira.impediment.total.created: время, затраченное с даты создания на устранение препятствия. Это позволяет нам получить общее количество препятствий. Мы также можем записывать все действия с препятствиями, даже вне спринтов.

Для одного проекта Jira, как в нашем примере, вы можете ожидать около 300 показателей. Это может увеличиваться в зависимости от эпика, который вы создаете и помечаете в Jira, и того, который вы закрываете.

Панель управления Grafana

Нам нравится создавать информационные панели Grafana! Они дают команде и менеджеру много информации о ключевых показателях эффективности. Лучшее в этом для меня, как разработчика, — это то, что я понимаю, почему хорошо выполнять задачу JIRA!

На нашей первой панели управления Grafana вы найдете все лучшие KPI для управления программами. Начнем с глобального обзора:

Обзор квартальных данных



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

Данные активного спринта



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

Подробные данные



В последней части представлены более подробные данные. Используя переменную epic Grafana, мы можем проверять конкретные эпики, а также завершение более глобальных проектов. У вас также есть velocity chart, который отображает прошлый спринт и сравнивает ожидаемые баллы истории с фактически завершенными.

Панель управления Grafana доступна напрямую в проекте Jerem. Вы можете импортировать его прямо в Grafana, если у вас настроен действительный источник данных Warp 10.

Чтобы панель управления работала должным образом, вам необходимо настроить переменную проекта Grafana в виде списка WarpScript [ 'SAN' 'OTHER-PROJECT' ]. Если наш программный менеджер может это сделать, я уверен, вы сможете!

Настройка Jerem и автоматическая загрузка данных управления программами дают нам много полезного. Мне как разработчику это очень нравится, и я быстро привык отслеживать в JIRA гораздо больше событий, чем раньше. Вы можете напрямую видеть влияние ваших задач. Например, вы видите, как быстро продвигается дорожная карта, и можете определить любые узкие места, которые создают препятствия. Затем эти узкие места становятся эпопеями. Другими словами, как только мы начинаем использовать Jerem, мы просто заполняем его автоматически! Надеюсь, вам тоже понравится! Если у вас есть отзывы, мы будем рады их услышать.

Вклад в Apache HBase: настраиваемая балансировка данных

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



Контекст

Вы когда-нибудь задумывались, как:

  • мы генерируем графики для вашего сервера OVHcloud или пакета веб-хостинга?
  • наши внутренние команды контролируют свои собственные серверы и приложения?

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

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

Apache HBase , хранилище данных, построенное на основе Apache Hadoop , предоставляет эластичную распределенную карту с упорядочением по ключам. Таким образом, одна из ключевых особенностей Apache HBase для нас — это возможность сканировать , то есть получать ряд ключей. Благодаря этой функции мы можем оптимизировать тысячи точек данных .

У нас есть собственные выделенные кластеры, самый большой из которых имеет более 270 узлов для распределения наших рабочих нагрузок:

  • от 1,6 до 2 миллионов операций записи в секунду, 24/7
  • от 4 до 6 миллионов чтений в секунду
  • около 300 ТБ телеметрии, хранящейся в Apache HBase

Как вы, вероятно, можете себе представить, хранение 300 ТБ данных на 270 узлах сопряжено с некоторыми проблемами, связанными с перераспределением, поскольку каждый бит является горячими данными и должен быть доступен в любое время. Давайте нырнем!

Как работает балансировка в Apache HBase?

Прежде чем погрузиться в балансировщик, давайте посмотрим, как он работает. В Apache HBase данные разделяются на сегменты, вызываемые Regionsи распределяемые по ним RegionServers. Количество регионов будет увеличиваться по мере поступления данных, и в результате регионы будут разделены. Вот тут-то и пригодится Balancer. Он будет перемещать регионы, чтобы избежать появления горячих точек, RegionServerи эффективно распределяет нагрузку.



Фактическая реализация, называемая StochasticBalancer, использует подход, основанный на затратах:

  1. Сначала он вычисляет общую стоимость кластера, проходя через цикл 
    cost functions
    . Каждая функция стоимости возвращает число от 0 до 1 включительно , где 0 — это решение с наименьшей стоимостью и лучшим решением, а 1 — с максимально возможной стоимостью и наихудшим решением. Apache Hbase поставляется с несколькими функциями стоимости, которые измеряют такие вещи, как загрузка региона, загрузка таблицы, локальность данных, количество регионов на сервер RegionServer… Вычисленные затраты масштабируются с помощью соответствующих коэффициентов, определенных в конфигурации .
  2. Теперь, когда начальная стоимость вычислена, мы можем попробовать 
    Mutate
    наш кластер. Для этого Balancer создает случайный случай 
    nextAction
    , который может быть чем-то вроде замены двух регионов или перемещения одного региона на другой RegionServer . Действие применяется виртуально , после чего рассчитывается новая стоимость . Если новая стоимость ниже нашей предыдущей, действие сохраняется. В противном случае он пропускается. Эта операция повторяется 
    thousands of times
    , поэтому файл 
    Stochastic
    .
  3. В конце список допустимых действий применяется к фактическому кластеру.

Что у нас не работало?

Мы выяснили это для нашего конкретного варианта использования , который включает:

  • Один стол
  • Выделенные Apache HBase и Apache Hadoop, адаптированные к нашим требованиям
  • Хорошее распределение ключей

… Количество регионов на RegionServer было для нас настоящим пределом

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

В итоге мы получили разные группы оборудования: некоторые серверы могут обрабатывать только 180 регионов, тогда как самые большие могут обрабатывать более 900 . Из-за этого несоответствия нам пришлось отключить балансировщик нагрузки, чтобы избежать использования RegionCountSkewCostFunction , которая попыталась бы перенести все RegionServers в одно и то же количество регионов.



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

Открытый исходный код лежит в основе OVHcloud , и это означает, что мы создаем наши инструменты на основе программного обеспечения с открытым исходным кодом, но также мы вносим свой вклад и возвращаем его сообществу. Когда мы поговорили, мы увидели, что не только нас беспокоит проблема гетерогенного кластера. Мы решили переписать наш инструментарий, чтобы сделать его более общим, и внести его непосредственно в проект HBase .

Наш вклад

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

Второй вклад касался добавления дополнительной функции costFunction для балансировки регионов в соответствии с правилом емкости.

Как это работает?

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

rs[0-9] 200
rs1[0-9] 50



RegionServers с именами хостов, соответствующими первым правилам, будут иметь ограничение 200 , а остальные 50 . Если совпадений нет, устанавливается значение по умолчанию.

Благодаря этому правилу у нас есть две ключевые части информации:
  • максимальное число областей для этого кластера
  • то правила для каждого сервера

Они 
HeterogeneousRegionCountCostFunction 
постараются сбалансировать регионы по своим возможностям.

Возьмем пример… Представьте, что у нас есть 20 RS:



  • 10 RS, названный 
    rs0
    в 
    rs9
    , нагруженные 60 регионов каждый, каждый из которых может рукоятку 200 регионов.
  • 10 RS, названные 
    rs10
    в 
    rs19
    , нагруженные 60 регионов каждый, каждый из которых может обрабатывать 50 областей.


Итак, исходя из следующих правил

rs[0-9] 200
rs1[0-9] 50


… Мы видим, что вторая группа перегружена, тогда как в первой группе много места.

Мы знаем, что можем обрабатывать максимум 2500 регионов (200 × 10 + 50 × 10), и в настоящее время у нас есть 1200 регионов (60 × 20). Таким образом, система 
HeterogeneousRegionCountCostFunction
поймет, что кластер заполнен на 48,0% (1200/2500). Основываясь на этой информации, мы попытаемся поставить все серверы RegionServers на ~ 48% нагрузки в соответствии с правилами.



Куда дальше?

Благодаря участникам Apache HBase наши исправления теперь объединены в основную ветку. Как только сопровождающие Apache HBase опубликуют новый выпуск, мы развернем и будем использовать его в любом масштабе. Это позволит больше автоматизировать с нашей стороны и упростит операции для группы наблюдения.

Участие было потрясающим путешествием. Что мне больше всего нравится в открытом исходном коде, так это возможность внести свой вклад и создать более надежное программное обеспечение. У нас было мнение о том, как следует решать ту или иную проблему, но обсуждения с сообществом помогли нам уточнить ее . Мы поговорили с инженерами из других компаний, которые, как и мы , испытывали трудности с развертыванием облака Apache HBase , и благодаря этим обменам наш вклад становился все более и более актуальным.

TSL (или как запрашивать базы данных временных рядов)

В прошлом году мы выпустили TSL как инструмент с открытым исходным кодом для выполнения запросов к Деформация 10 платформы, и выдвижением, OVHcloud Метрики Платформа данных .



Но как она развивалась с тех пор? Готов ли TSL запрашивать другие базы данных временных рядов ? Что насчет состояний TSL в экосистеме Warp10 ?

TSL для запроса многих баз данных временных рядов

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

Год спустя мы теперь знаем, что это был не лучший путь. Исходя из того, что мы узнали, тот TSL-адаптер проект был открытым исходным кодом, как доказательство концепции , как TSL может быть использован для запроса не-Деформация 10 базы данных. Проще говоря, TSL-адаптер позволяет TSL запрашивать InfluxDB .

Что такое TSL-адаптер?

TSL-адаптер — это API Quarkus JAVA REST, который можно использовать для запроса серверной части. TSL-адаптер анализирует запрос TSL, идентифицирует операцию выборки и загружает исходные необработанные данные из серверной части. Затем он вычисляет операции TSL с данными, прежде чем вернуть результат пользователю. Основная цель TSL-Adapter - сделать TSL доступным поверх других TSDB .



Говоря конкретно, мы запускаем JAVA REST API, который интегрирует библиотеку WarpScript в среду выполнения. Затем TSL используется для компиляции запроса в действительный запрос WarpScript. Это полностью прозрачно и касается только запросов TSL на стороне пользователя.


Чтобы загрузить необработанные данные из InfluxDB, мы создали расширение WarpScript. Это расширение объединяет абстрактный класс, 
LOADSOURCERAW
который необходимо реализовать для создания источника данных TSL-Adapter. Для этого требуется всего два метода: 
find
и 
fetch
Find
собирает все селекторы серий, соответствующие запросу (имена классов, теги или метки), при этом 
fetch
фактически извлекает необработанные данные за определенный промежуток времени.

Приток запросов с TSL-адаптером

Для начала просто запустите InfluxDB локально на порту 8086. Затем давайте запустим агент Telegraf притока и запишем данные Telegraf на локальном экземпляре притока.

Затем убедитесь, что вы локально установили TSL-адаптер и обновили его конфигурацию, указав путь к tsl.soбиблиотеке.

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

Вы можете запустить TSL-адаптер с помощью следующего примера команды:

java -XX:TieredStopAtLevel=1 -Xverify:none -Djava.util.logging.manager=org.jboss.logmanager.LogManager -jar build/tsl-adaptor-0.0.1-SNAPSHOT-runner.jar


И это все! Теперь вы можете запрашивать свою базу данных притока с помощью TSL и TSL-адаптера.

Начнем с восстановления временного ряда, относящегося к измерениям диска.

curl --request POST \
  --url http://u:p@0.0.0.0:8080/api/v0/tsl \
  --data 'select("disk")'


Теперь давайте воспользуемся возможностями аналитики TSL!

Во-первых, мы хотели бы получить только данные, содержащие установленный режим rw.

curl --request POST \
  --url http://u:p@0.0.0.0:8080/api/v0/tsl \
  --data 'select("disk").where("mode=rw")'


Мы хотели бы получать максимальное значение через каждые пятиминутные интервалы за последние 20 минут. Таким образом, запрос TSL будет:

curl --request POST \
  --url http://u:p@0.0.0.0:8080/api/v0/tsl \
  --data 'select("disk").where("mode=rw").last(20m).sampleBy(5m,max)'


Теперь ваша очередь повеселиться с TSL и InfluxDB. Вы можете найти подробную информацию обо всех реализованных функциях в документации TSL. Наслаждайтесь исследованием!

Что нового в TSL с Warp10?

Изначально мы создавали TSL как прокси GO перед Warp10. TSL теперь интегрировал экосистему Warp 10 как расширение Warp10 или как библиотеку WASM ! Мы также добавили несколько новых собственных функций TSL, чтобы сделать язык еще богаче!

TSL как функция WarpScript

Чтобы TSL работал как функция Warp10, вам необходимо, чтобы tsl.soбиблиотека была доступна локально. Эту библиотеку можно найти в репозитории TSL на github. Мы также сделали расширение TSL WarpScript доступным в WarpFleet, репозитории расширений сообщества Warp 10.

Чтобы настроить расширение TSL на Warp 10, просто загрузите JAR, указанный в WarpFleet. Затем вы можете настроить расширение в файле конфигурации Warp 10:

warpscript.extensions = io.ovh.metrics.warp10.script.ext.tsl.TSLWarpScriptExtension
warpscript.tsl.libso.path = <PATH_TO_THE_tsl.so_FILE>


После перезагрузки Warp 10 все готово. Вы можете проверить, работает ли он, выполнив следующий запрос:

// You will need to put here a valid Warp10 token when computing a TSL select statement
// '<A_VALID_WARP_10_TOKEN>' 

// A valid TOKEN isn't needed on the create series statement in this example
// You can simply put an empty string
''

// Native TSL create series statement
 <'
    create(series('test').setValues("now", [-5m, 2], [0, 1])) 
'>
TSL


С помощью функции WarpScript TSL вы можете использовать собственные переменные WarpScript в своем скрипте, как показано в примере ниже:

// Set a Warp10 variable

NOW 'test' STORE

'' 

// A Warp10 variable can be reused in TSL script as a native TSL variable
 <'
    create(series('test').setValues("now", [-5m, 2], [0, 1])).add(test)
'>
TSL


TSL WASM

Чтобы расширить возможности использования TSL, мы также экспортировали его как библиотеку Wasm, так что вы можете использовать ее прямо в браузере! Версия библиотеки Wasm анализирует запросы TSL локально и генерирует WarpScript. Затем результат можно использовать для запроса к бэкэнду Warp 10. Более подробную информацию вы найдете на github TSL.

Новые возможности TSL

По мере роста популярности TSL мы обнаружили и исправили несколько ошибок, а также добавили некоторые дополнительные встроенные функции для новых вариантов использования.

Мы добавили setLabelFromNameметод, чтобы установить новую метку для серии на основе ее имени. Эта метка может быть точным названием серии или результатом регулярного выражения.

Мы также доработали sortметод, позволяющий пользователям сортировать набор серий на основе метаданных серии (т. Е. Селектора, имени или меток).

Наконец, мы добавили filterWithoutLabels, чтобы отфильтровать набор серий и удалить все серии, не содержащие конкретных меток.

Спасибо за прочтение! Я надеюсь, что вы попробуете TSL, так как я хотел бы услышать ваши отзывы.

Встреча в Париже Time Series

Мы рады провести в парижском офисе OVHcloud третью встречу Paris Time Series, организованную Николасом Штайнметцем. Во время этой встречи мы поговорим о TSL, а также познакомимся с платформой Redis Times Series.

Если вы свободны, мы будем рады встретить вас там!

Оповещение на основе сбора данных IPMI

Проблема, которую нужно решить…

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

Мы начали с разделения проблемы на четыре основных этапа:

    • Сбор информации
    • Хранилище данных

    • Аналитика данных
    • Визуализация / действия

Сбор информации

Как мы незаметно собирали большие объемы данных о состоянии серверов за короткие промежутки времени?



Какие данные собирать?

На современных серверах BMC (контроллер управления платой) позволяет нам контролировать обновления прошивки, перезагрузки и т. Д. Этот контроллер не зависит от системы, работающей на сервере. Кроме того, BMC дает нам доступ к датчикам для всех компонентов материнской платы через шину I2C. Для связи с BMC используется протокол IPMI, доступный через LAN (RMCP).

Что такое IPMI?

  • Интеллектуальный интерфейс управления платформой.
  • Возможности управления и мониторинга независимо от ОС хоста.
  • Под руководством INTEL, впервые опубликовано в 1998 году.
  • Поддерживается более чем 200 поставщиками компьютерных систем, такими как Cisco, DELL, HP, Intel, SuperMicro…

Зачем использовать IPMI?

  • Доступ к аппаратным датчикам (температура процессора, температура памяти, состояние шасси, мощность и т. Д.).
  • Отсутствие зависимости от ОС (т.е. безагентное решение)
  • Функции IPMI доступны после сбоя ОС / системы
  • Ограниченный доступ к функциям IPMI через права пользователя



Сбор данных из нескольких источников

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



Мы решили построить наш сборщик данных IPMI на платформе Akka. Akka — это набор инструментов и среда выполнения с открытым исходным кодом, упрощающие создание параллельных и распределенных приложений на JVM.

Фреймворк Akka определяет построенную над потоком абстракцию под названием «актер». Этот субъект — это объект, который обрабатывает сообщения. Эта абстракция упрощает создание многопоточных приложений, поэтому нет необходимости бороться с тупиками. Выбрав политику диспетчера для группы субъектов, вы можете настроить приложение, чтобы оно было полностью реактивным и адаптировалось к нагрузке. Таким образом, мы смогли разработать эффективный сборщик данных, который мог адаптироваться к нагрузке, поскольку мы намеревались получать значение каждого датчика каждую минуту.

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

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

REST API определен для связи со сборщиком данных двумя способами:

  • Отправить конфигурации
  • Для получения информации об отслеживаемых серверах

Узел кластера работает на одной JVM, и мы можем запустить один или несколько узлов на выделенном сервере. Каждый выделенный сервер, используемый в кластере, помещается в OVH VRACK. Пул шлюзов IPMI используется для доступа к BMC каждого сервера, при этом связь между шлюзом и сборщиком данных IPMI защищена соединениями IPSEC.



Хранилище данных



Разумеется, для хранения данных мы используем сервис OVH Metrics! Перед сохранением данных коллектор данных IPMI унифицирует показатели, квалифицируя каждый датчик. Окончательное название метрики определяется сущностью, к которой принадлежит датчик, и базовой единицей значения. Это упростит процессы последующей обработки и визуализацию / сравнение данных.

Каждый коллектор IPMI центра обработки данных отправляет свои данные на сервер кэширования в реальном времени Metrics с ограниченным временем сохранения. Вся важная информация сохраняется на сервере метрик OVH.

Аналитика данных



Мы храним наши метрики в warp10. Warp 10 поставляется с языком сценариев временных рядов: WarpScript, который пробуждает мощную аналитику, позволяющую легко манипулировать и постобработать (на стороне сервера) наши собранные данные.

Мы определили три уровня анализа для мониторинга работоспособности серверов:

  • Простая метрика порогового значения на сервер.
  • Используя службу метрических циклов OVH, мы собираем данные по стойке и по комнате и вычисляем среднее значение. Мы устанавливаем порог для этого среднего значения, это позволяет обнаруживать общие неисправности стоек или помещения в системе охлаждения или питания.
  • Служба OVH MLS выполняет обнаружение некоторых аномалий в стойках и помещениях, прогнозируя возможное изменение показателей в зависимости от прошлых значений. Если значение метрики находится за пределами этого шаблона, возникает аномалия.

Визуализация / действия

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





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

Циклы: обеспечение непрерывных запросов с помощью Observability FaaS


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

В команде Observability мы встречаем эти фрагменты как запросы в базе данных временных рядов (TSDB), чтобы выражать непрерывные запросы, которые отвечают за автоматизацию различных вариантов использования, таких как: удаление, сведение или любая бизнес-логика, которая должна манипулировать данными временных рядов.

Мы уже представили  TSL в предыдущем сообщении блога , в котором было продемонстрировано, как наши клиенты используют доступные протоколы OVH Metrics, такие как Graphite, OpenTSDB, PromQL и WarpScript ™, но когда дело доходит до манипулирования или даже создания новых данных , у вас нет много вариантов, хотя вы можете использовать WarpScript ™ или TSL в качестве языка сценариев вместо языка запросов.

В большинстве случаев эта бизнес-логика требует создания приложения, что требует больше времени, чем выражение логики в виде запроса, нацеленного на TSDB. Создание кода базового приложения — это первый шаг, за которым следует CI / CD (или любой процесс доставки) и настройка его мониторинга. Однако управление сотнями таких небольших приложений приведет к увеличению органических затрат из-за необходимости  поддерживать их вместе с базовой инфраструктурой.

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

Нам нужно было решение, которое сфокусировалось бы на бизнес-логике без необходимости запускать все приложение. Таким образом, кому-то, кто хочет создать файл JSON с ежедневным отчетом (например), нужно будет только выразить соответствующий запрос.



Вы не должны FaaS!

Планирование работы — старая привычная рутина. Будь то задания bash cron, раннеры или специализированные планировщики, когда дело доходит до упаковки фрагмента кода и его периодического запуска, для этого есть название: FaaS.

FaaS был создан с простой целью: сократить время разработки. Мы могли бы найти реализацию с открытым исходным кодом для оценки (например, OpenFaas ), но большинство из них полагалось на управляемый стек контейнеров. Наличие одного контейнера на запрос было бы очень дорогостоящим, плюс разогрев контейнера для выполнения функции, а затем его замораживание было бы очень контрпродуктивным.

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

#def <Циклы>

Именно тогда мы решили создать «Loops»: платформу приложений, на которой вы можете отправить код, который хотите запустить. Вот и все. Цель состоит в том, чтобы продвинуть функцию (буквально!), А не модуль, как это делают все текущие решения FaaS:

function dailyReport(event) {
    return Promise.resolve('Today, everything is fine !')
}


Затем вы можете выполнить его вручную, используя HTTP-вызов или планировщик, подобный Cron.

Оба эти аспекта необходимы, поскольку у вас может быть (например) ежемесячный отчет, но в один прекрасный день потребуется дополнительный, через 15 дней после последнего отчета. Циклы упростят создание нового отчета вручную в дополнение к ежемесячному.

Когда мы начали создавать Loops, были некоторые необходимые ограничения:

  • Эта платформа должна легко масштабироваться , чтобы поддерживать производственную нагрузку OVH.
  • Он должен быть высокодоступным
  • Он должен быть независимым от языка , потому что некоторые из нас предпочитают Python, а другие JavaScript.
  • Это должно быть надежно
  • Часть планирования не должна коррелировать с частью выполнения ( культура μService )
  • Он должен быть безопасным и изолированным, чтобы любой мог размещать непонятный код на платформе.

Реализация петель

Мы решили построить нашу первую версию на V8 . Мы выбрали JavaScript в качестве первого языка, потому что его легко изучить, а асинхронными потоками данных легко управлять с помощью Promises. Кроме того, он очень хорошо сочетается с FaaS, поскольку функции Javascript очень выразительны. Мы построили его на основе нового модуля виртуальной машины NodeJS , который позволяет выполнять код в выделенном контексте V8 .

Контекст V8 похож на объект (JSON), изолированный от вашего исполнения. В контексте вы можете найти собственные функции и объекты. Однако, если вы создадите новый контекст V8, вы увидите, что некоторые переменные или функции изначально недоступны (например, setTimeout (), setInterval () или Buffer ). Если вы хотите их использовать, вам придется внедрить их в свой новый контекст. Последнее, что нужно помнить, это то, что когда у вас есть новый контекст, вы можете легко выполнить сценарий JavaScript в строковой форме.

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

Мы не хотели выполнять скрипты с eval () , поскольку вызов этой функции позволяет выполнять JS-код в основном общем контексте с вызывающим его кодом. Затем вы можете получить доступ к тем же объектам, константам, переменным и т. Д. Эта проблема безопасности стала нарушением условий сделки для новой платформы.

Теперь мы знаем, как выполнять наши скрипты, давайте реализуем для них некоторое управление. Чтобы не иметь состояния , каждый экземпляр рабочего цикла Loops (то есть движок JavaScript, способный запускать код в контексте виртуальной машины) должен иметь последнюю версию каждого цикла (цикл — это сценарий, который нужно выполнить). Это означает, что когда пользователь отправляет новый цикл, мы должны синхронизировать его с каждым рабочим циклом. Эта модель хорошо согласуется с парадигмой pub / sub, и, поскольку мы уже используем Kafka в качестве инфраструктуры pub / sub, оставалось лишь создать специальную тему и использовать ее у рабочих. В этом случае публикация включает API, в который пользователь отправляет свои циклы, которые создают событие Kafka, содержащее тело функции. Поскольку у каждого воркера есть своя группа потребителей Kafka, все они получают одинаковые сообщения.

Рабочие подписываются на обновления Loops как потребители Kafka и поддерживают хранилище Loop, которое представляет собой встроенный ключ (хэш Loop) / значение (текущая версия функции). В части API хэши цикла используются в качестве параметров URL для определения того, какой цикл выполнять. После вызова цикл извлекается из карты, затем вводится в контекст V8 , выполняется и отбрасывается. Этот механизм перезагрузки горячего кода гарантирует, что каждый цикл может быть выполнен для каждого рабочего. Мы также можем использовать возможности наших балансировщиков нагрузки для распределения нагрузки на рабочих. Эта простая модель распределения позволяет избежать сложного планирования и упрощает обслуживание всей инфраструктуры.

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



Время выполнения циклов

Даже если базовый движок может запускать собственный Javascript, как указано выше, мы хотели, чтобы он выполнял более идиоматические запросы временных рядов, такие как TSL или WarpScript ™ . Для этого мы создали абстракцию Loops Runtime, которая оборачивает не только Javascript, но также запросы TSL и WarpScript ™ в код Javascript. Пользователи должны объявить цикл с его средой выполнения, после чего остается лишь вопрос работы оберток. Например, выполнение цикла WarpScript ™ включает в себя использование простого сценария WarpScript ™ и его отправку посредством HTTP-вызова запроса узла.



Обратная связь по петлям

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

Это приводит нас к одному особому условию: скрипты пользователя должны уметь определять, все ли в порядке или нет. В базовом движке JavaScript есть два способа сделать это : обратные вызовы и обещания.
Мы выбрали Promises, который предлагает лучшее асинхронное управление. Каждый цикл возвращает обещание в конце скрипта. Отклоненное обещание приведет к статусу ошибки HTTP 500, а решенное — к статусу HTTP 200.

Планирование циклов

При публикации Loops вы можете объявить несколько триггеров аналогично Cron. Каждый триггер будет выполнять HTTP-вызов вашего цикла с дополнительными параметрами.

На основе этой семантики для создания нескольких отчетов мы можем зарегистрировать одну функцию, которая будет планироваться в разных контекстах, определяемых различными параметрами (регион, скорость и т. Д.). См. Пример ниже:

functions:
  warp_apps_by_cells:
    handler: apps-by-cells.mc2
    runtime: ws
    timeout: 30
    environment:
    events:
      - agra:
          rate: R/2018-01-01T00:00:00Z/PT5M/ET1M
          params:
            cell: ovh-a-gra
      - abhs:
          rate: R/2018-01-01T00:00:00Z/PT5M/ET1M
          params:
            cell: ovh-a-bhs


Планирование основано на Metronome, который представляет собой планировщик событий с открытым исходным кодом, с особым упором на планирование, а не на выполнение. Это идеально подходит для циклов, поскольку циклы обрабатывают выполнение, а метроном управляет вызовами выполнения.

Петли трубопроводов

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

Болевые точки: масштабирование приложения NodeJS

Рабочие циклов — это приложения NodeJS. Большинство разработчиков NodeJS знают, что NodeJS использует однопоточный цикл обработки событий . Если вы не позаботитесь о потоковой модели своего приложения nodeJS, вы, скорее всего, пострадаете из-за недостаточной производительности, поскольку будет использоваться только один поток хоста.

NodeJS также имеет доступный модуль кластера , который позволяет приложению использовать несколько потоков. Вот почему в воркере Loops мы начинаем с потока N-1 для обработки вызовов API, где N — общее количество доступных потоков, в результате чего один остается выделенным для главного потока.

Главный поток отвечает за использование тем Kafka и поддержание хранилища Loops , а рабочий поток запускает сервер API. Для каждого запрошенного выполнения цикла он запрашивает у мастера содержимое скрипта и выполняет его в выделенном потоке.

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

Вывод

В этом посте мы предварительно ознакомились с Loops, масштабируемой, ориентированной на метрики FaaS с встроенной поддержкой JavaScript и расширенной поддержкой WarpScript ™ и TSL .

У нас еще есть несколько вещей, которые нужно улучшить, например импорт зависимостей в стиле ES5 и предварительный просмотр показателей для проектов циклов наших клиентов. Мы также планируем добавить больше сред выполнения , особенно WASM , что позволит использовать многие другие языки, которые могут быть ориентированы на него, например Go, Rust или Python , в соответствии с предпочтениями большинства разработчиков.

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

Этот инструмент был создан как часть набора продуктов Observability с учетом более высокого уровня абстракции, но вам также может потребоваться прямой доступ к API, чтобы реализовать собственную автоматизированную логику для ваших показателей. Вас заинтересует такая функция? Посетите наш канал Gitter, чтобы обсудить это с нами!

Как отслеживать свой кластер Kubernetes с помощью OVH Observability

Наши коллеги из команды K8S на прошлой неделе запустили решение OVH Managed Kubernetes, в котором они управляют главными компонентами Kubernetes и создают ваши узлы поверх нашего решения Public Cloud. Я не буду описывать здесь детали того, как это работает, но в блогах уже есть много сообщений об этом ( здесь и здесь, чтобы вы начали).

В команде Prescience мы используем Kubernetes уже больше года. Наш кластер включает 40 узлов, работающих поверх PCI. Мы постоянно запускаем около 800 модулей и в результате генерируем множество показателей.

Сегодня мы рассмотрим, как мы обрабатываем эти метрики для мониторинга нашего кластера Kubernetes, и (что не менее важно!) Как это сделать с вашим собственным кластером.

Показатели OVH

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

OVH Observability не зависит от серверной части, поэтому мы можем передавать метрики в одном формате и запрашивать в другом. Он может обрабатывать:

  • Graphite
  • InfluxDB
  • Metrics2.0
  • OpentTSDB
  • Prometheus
  • Warp10

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

Узлы мониторинга

Первое, что нужно контролировать, — это состояние узлов. Все остальное начинается с этого.

Чтобы контролировать ваши узлы, мы будем использовать Noderig и Beamium, как описано здесь. Мы также будем использовать Kubernetes DaemonSets для запуска процесса на всех наших узлах.



Итак, приступим к созданию пространства имен…

kubectl create namespace metrics


Затем создайте секрет с метриками токена записи, которые вы можете найти в панели управления OVH.

kubectl create secret generic w10-credentials --from-literal=METRICS_TOKEN=your-token -n metrics


Скопируйте metrics.ymlв файл и примените конфигурацию с помощью kubectl

metrics.yml
# This will configure Beamium to scrap noderig
# And push metrics to warp 10
# We also add the HOSTNAME to the labels of the metrics pushed
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: beamium-config
  namespace: metrics
data:
  config.yaml: |
    scrapers:
      nodering:
        url: http://0.0.0.0:9100/metrics
        period: 30000
        format: sensision
        labels:
          app: nodering

    sinks:
      warp:
        url: https://warp10.gra1.metrics.ovh.net/api/v0/update
        token: $METRICS_TOKEN

    labels:
      host: $HOSTNAME

    parameters:
      log-file: /dev/stdout
---
# This is a custom collector that report the uptime of the node
apiVersion: v1
kind: ConfigMap
metadata:
  name: noderig-collector
  namespace: metrics
data:
  uptime.sh: |
    #!/bin/sh
    echo 'os.uptime' `date +%s%N | cut -b1-10` `awk '{print $1}' /proc/uptime`
---
kind: DaemonSet
apiVersion: apps/v1
metadata:
  name: metrics-daemon
  namespace: metrics
spec:
  selector:
    matchLabels:
      name: metrics-daemon
  template:
    metadata:
      labels:
        name: metrics-daemon
    spec:
      terminationGracePeriodSeconds: 10
      hostNetwork: true
      volumes:
      - name: config
        configMap:
          name: beamium-config
      - name: noderig-collector
        configMap:
          name: noderig-collector
          defaultMode: 0777
      - name: beamium-persistence
        emptyDir:{}
      containers:
      - image: ovhcom/beamium:latest
        imagePullPolicy: Always
        name: beamium
        env:
        - name: HOSTNAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: TEMPLATE_CONFIG
          value: /config/config.yaml
        envFrom:
        - secretRef:
            name: w10-credentials
            optional: false
        resources:
          limits:
            cpu: "0.05"
            memory: 128Mi
          requests:
            cpu: "0.01"
            memory: 128Mi
        workingDir: /beamium
        volumeMounts:
        - mountPath: /config
          name: config
        - mountPath: /beamium
          name: beamium-persistence
      - image: ovhcom/noderig:latest
        imagePullPolicy: Always
        name: noderig
        args: ["-c", "/collectors", "--net", "3"]
        volumeMounts:
        - mountPath: /collectors/60/uptime.sh
          name: noderig-collector
          subPath: uptime.sh
        resources:
          limits:
            cpu: "0.05"
            memory: 128Mi
          requests:
            cpu: "0.01"
            memory: 128Mi

Не стесняйтесь менять уровни коллектора, если вам нужна дополнительная информация.

Затем примените конфигурацию с помощью kubectl…

$ kubectl apply -f metrics.yml
# Then, just wait a minutes for the pods to start
$ kubectl get all -n metrics
NAME                       READY   STATUS    RESTARTS   AGE
pod/metrics-daemon-2j6jh   2/2     Running   0          5m15s
pod/metrics-daemon-t6frh   2/2     Running   0          5m14s

NAME                          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE AGE
daemonset.apps/metrics-daemon 40        40        40      40           40          122d


Вы можете импортировать нашу панель управления в свою Grafana отсюда и сразу же просматривать некоторые показатели о ваших узлах.



OVH Метрики

Поскольку OVH Kube — это управляемая служба, вам не нужно контролировать apiserver, etcd или панель управления. Об этом позаботится команда OVH Kubernetes. Поэтому мы сосредоточимся на показателях cAdvisor и показателях состояния Kube.

Самым зрелым решением для динамического считывания метрик внутри Kube (на данный момент) является Prometheus.


В следующем выпуске Beamium мы сможем воспроизвести функции скребка Prometheus.


Чтобы установить сервер Prometheus, вам необходимо установить Helm в кластере…

kubectl -n kube-system create serviceaccount tiller
kubectl create clusterrolebinding tiller \
    --clusterrole cluster-admin \
    --serviceaccount=kube-system:tiller
helm init --service-account tiller


Затем вам нужно создать следующие два файла: prometheus.yml и values.yml.

# Based on https://github.com/prometheus/prometheus/blob/release-2.2/documentation/examples/prometheus-kubernetes.yml
serverFiles:
  prometheus.yml:
    remote_write:
    - url: "https://prometheus.gra1.metrics.ovh.net/remote_write"
      remote_timeout: 120s
      bearer_token: $TOKEN
      write_relabel_configs:
      # Filter metrics to keep
      - action: keep
        source_labels: [__name__]
        regex: "eagle.*|\
            kube_node_info.*|\
            kube_node_spec_taint.*|\
            container_start_time_seconds|\
            container_last_seen|\
            container_cpu_usage_seconds_total|\
            container_fs_io_time_seconds_total|\
            container_fs_write_seconds_total|\
            container_fs_usage_bytes|\
            container_fs_limit_bytes|\
            container_memory_working_set_bytes|\
            container_memory_rss|\
            container_memory_usage_bytes|\
            container_network_receive_bytes_total|\
            container_network_transmit_bytes_total|\
            machine_memory_bytes|\
            machine_cpu_cores"

    scrape_configs:
    # Scrape config for Kubelet cAdvisor.
    - job_name: 'kubernetes-cadvisor'
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      kubernetes_sd_configs:
      - role: node
      
      relabel_configs:
      - target_label: __address__
        replacement: kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        target_label: __metrics_path__
        replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
        
      metric_relabel_configs:
      # Only keep systemd important services like docker|containerd|kubelet and kubepods,
      # We also want machine_cpu_cores that don't have id, so we need to add the name of the metric in order to be matched
      # The string will concat id with name and the separator is a ;
      # `/;container_cpu_usage_seconds_total` OK
      # `/system.slice;container_cpu_usage_seconds_total` OK
      # `/system.slice/minion.service;container_cpu_usage_seconds_total` NOK, Useless
      # `/kubepods/besteffort/e2514ad43202;container_cpu_usage_seconds_total` Best Effort POD OK
      # `/kubepods/burstable/e2514ad43202;container_cpu_usage_seconds_total` Burstable POD OK
      # `/kubepods/e2514ad43202;container_cpu_usage_seconds_total` Guaranteed POD OK
      # `/docker/pod104329ff;container_cpu_usage_seconds_total` OK, Container that run on docker but not managed by kube
      # `;machine_cpu_cores` OK, there is no id on these metrics, but we want to keep them also
      - source_labels: [id,__name__]
        regex: "^((/(system.slice(/(docker|containerd|kubelet).service)?|(kubepods|docker).*)?);.*|;(machine_cpu_cores|machine_memory_bytes))$"
        action: keep
      # Remove Useless parents keys like `/kubepods/burstable` or `/docker`
      - source_labels: [id]
        regex: "(/kubepods/burstable|/kubepods/besteffort|/kubepods|/docker)"
        action: drop
        # cAdvisor give metrics per container and sometimes it sum up per pod
        # As we already have the child, we will sum up ourselves, so we drop metrics for the POD and keep containers metrics
        # Metrics for the POD don't have container_name, so we drop if we have just the pod_name
      - source_labels: [container_name,pod_name]
        regex: ";(.+)"
        action: drop
    
    # Scrape config for service endpoints.
    - job_name: 'kubernetes-service-endpoints'
      kubernetes_sd_configs:
      - role: endpoints
      
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
      - action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: namespace
      - source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: kubernetes_name

    # Example scrape config for pods
    #
    # The relabeling allows the actual pod scrape endpoint to be configured via the
    # following annotations:
    #
    # * `prometheus.io/scrape`: Only scrape pods that have a value of `true`
    # * `prometheus.io/path`: If the metrics path is not `/metrics` override this.
    # * `prometheus.io/port`: Scrape the pod on the indicated port instead of the
    # pod's declared ports (default is a port-free target if none are declared).
    - job_name: 'kubernetes-pods'
      kubernetes_sd_configs:
      - role: pod

      relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
        target_label: __address__
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: namespace
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: pod_name
      - source_labels: [__meta_kubernetes_pod_node_name]
        action: replace
        target_label: host
      - action: labeldrop
        regex: (pod_template_generation|job|release|controller_revision_hash|workload_user_cattle_io_workloadselector|pod_template_hash)


values.yml
alertmanager:
  enabled: false
pushgateway:
  enabled: false
nodeExporter:
  enabled: false
server:
  ingress:
    enabled: true
    annotations:
      kubernetes.io/ingress.class: traefik
      ingress.kubernetes.io/auth-type: basic
      ingress.kubernetes.io/auth-secret: basic-auth
    hosts:
    - prometheus.domain.com
  image:
    tag: v2.7.1
  persistentVolume:
    enabled: false


Не забудьте заменить свой токен!

Скребок Прометей довольно мощный. Вы можете изменить метку своего временного ряда, оставить несколько, которые соответствуют вашему регулярному выражению, и т. Д. Эта конфигурация удаляет множество бесполезных метрик, поэтому не стесняйтесь настраивать его, если вы хотите увидеть больше метрик cAdvisor (например).

Установите его с помощью Helm…

helm install stable/prometheus \
    --namespace=metrics \
    --name=metrics \
    --values=values/values.yaml \
    --values=values/prometheus.yaml


Добавить добавить секрет базовой аутентификации…

$ htpasswd -c auth foo
New password: <bar>
New password:
Re-type new password:
Adding password for user foo
$ kubectl create secret generic basic-auth --from-file=auth -n metrics
secret "basic-auth" created


Вы можете получить доступ к интерфейсу сервера Prometheus через prometheus.domain.com.



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

Интерфейсы Prometheus — хороший способ изучить ваши метрики, поскольку довольно просто отображать и контролировать вашу инфраструктуру. Вы можете найти нашу панель управления здесь.



Метрики ресурсов

Как сказал @ Martin Schneppenheim в этом посте, для правильного управления кластером Kubernetes вам также необходимо отслеживать ресурсы пода.

Мы установим Kube Eagle, который будет извлекать и предоставлять некоторые метрики о запросах и ограничениях ЦП и ОЗУ, чтобы они могли быть получены только что установленным сервером Prometheus.



Создайте файл с именем eagle.yml.

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  labels:
    app: kube-eagle
  name: kube-eagle
  namespace: kube-eagle
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  - pods
  verbs:
  - get
  - list
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  labels:
    app: kube-eagle
  name: kube-eagle
  namespace: kube-eagle
subjects:
- kind: ServiceAccount
  name: kube-eagle
  namespace: kube-eagle
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kube-eagle
---
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: kube-eagle
  labels:
    app: kube-eagle
  name: kube-eagle
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: kube-eagle
  name: kube-eagle
  labels:
    app: kube-eagle
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kube-eagle
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/metrics"
      labels:
        app: kube-eagle
    spec:
      serviceAccountName: kube-eagle
      containers:
      - name: kube-eagle
        image: "quay.io/google-cloud-tools/kube-eagle:1.0.0"
        imagePullPolicy: IfNotPresent
        env:
        - name: PORT
          value: "8080"
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        livenessProbe:
          httpGet:
            path: /health
            port: http
        readinessProbe:
          httpGet:
            path: /health
            port: http


$ kubectl create namespace kube-eagle
$ kubectl apply -f eagle.yml


Затем добавьте импорт этой панели управления Grafana (это та же панель, что и Kube Eagle, но перенесена на Warp10).



Теперь у вас есть простой способ контролировать ресурсы вашего модуля в кластере!

Пользовательские показатели

Как Прометей узнает, что ему нужно соскрести куба-орла? Если вы посмотрите на метаданные eagle.yml, вы увидите, что:

annotations:
  prometheus.io/scrape: "true"
  prometheus.io/port: "8080" # The port where to find the metrics
  prometheus.io/path: "/metrics" # The path where to find the metrics


Эти аннотации запустят процесс автоматического обнаружения Prometheus (описанный в prometheus.ymlстроке 114).

Это означает, что вы можете легко добавить эти аннотации к модулям или службам, которые содержат экспортер Prometheus, а затем пересылать эти метрики в OVH Observability. Вы можете найти неполный список экспортеров Прометея здесь.



Объемный анализ

Как вы видели на странице prometheus.yml, мы попытались отфильтровать множество бесполезных показателей. Например, cAdvisor в новом кластере, всего с тремя настоящими производственными модулями, а также со всей системой kube и пространством имен Prometheus, имеет около 2600 метрик на узел. Используя интеллектуальный подход к очистке, вы можете сократить это количество до 126 серий.

Вот таблица, показывающая приблизительное количество метрик, которые вы создадите, в зависимости от количества узлов (N) и количества производственных модулей (P), которые у вас есть:



Например, если вы запустите три узла с 60 подами, вы сгенерируете 264 * 3 + 32 * 60 ~ = 2700 метрик.

NB: модуль имеет уникальное имя, поэтому при повторном развертывании развертывания вы будете каждый раз создавать 32 новых метрики.

(1) Метрики Noderig: os.mem / os.cpu / os.disk.fs / os.load1 / os.net.dropped (in/out) / os.net.errs (in/out) / os.net.packets (in/out) / os.net.bytes (in/out)/ os.uptime

(2) метрики узлов cAdvisor: machine_memory_bytes / machine_cpu_cores

(3) Метрики узлов состояния Kube: kube_node_info

(4) Показатели узлов Kube Eagle: eagle_node_resource_allocatable_cpu_cores / eagle_node_resource_allocatable_memory_bytes / eagle_node_resource_limits_cpu_cores / eagle_node_resource_limits_memory_bytes / eagle_node_resource_requests_cpu_cores / eagle_node_resource_requests_memory_bytes / eagle_node_resource_usage_cpu_cores / eagle_node_resource_usage_memory_bytes

(5) С помощью наших фильтров мы будем отслеживать около пяти system.slices.

(6) Показатели указываются для каждого контейнера. Pod — это набор контейнеров (минимум два): ваш контейнер + контейнер паузы для сети. Таким образом, мы можем рассматривать (2 * 10 + 6) для количества метрик в пакете. 10 показателей из cAdvisor и шесть для сети (см. Ниже) и для system.slice у нас будет 10 + 6, потому что он рассматривается как один контейнер.

(7) cAdvisor предоставит следующие показатели для каждого контейнера :container_start_time_seconds / container_last_seen / container_cpu_usage_seconds_total / container_fs_io_time_seconds_total / container_fs_write_seconds_total / container_fs_usage_bytes / container_fs_limit_bytes / container_memory_working_set_bytes / container_memory_rss / container_memory_usage_bytes

(8) cAdvisor предоставит следующие показатели для каждого интерфейса: container_network_receive_bytes_total * per interface / container_network_transmit_bytes_total * per interface

(9) kube-dns / beamium-noderig-metrics / kube-proxy / canal / metrics-server

(10) Показатели модулей Kube Eagle: eagle_pod_container_resource_limits_cpu_cores / eagle_pod_container_resource_limits_memory_bytes / eagle_pod_container_resource_requests_cpu_cores / eagle_pod_container_resource_requests_memory_bytes / eagle_pod_container_resource_usage_cpu_cores / eagle_pod_container_resource_usage_memory_bytes

Вывод

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

Следующим шагом будет добавление системы предупреждений, чтобы уведомить вас, когда ваши узлы не работают (например). Для этого вы можете использовать бесплатный инструмент OVH Alert Monitoring.

Рекомендации по мониторингу наблюдаемости OVH

В команде OVH Observability (ранее Metrics) мы собираем, обрабатываем и анализируем большую часть данных мониторинга OVH. Он представляет около 500 миллионов уникальных показателей, перемещая точки данных с постоянной скоростью 5 миллионов в секунду.

Эти данные можно классифицировать двумя способами: мониторинг хоста или приложения. Мониторинг хоста в основном основан на аппаратных счетчиках (ЦП, память, сеть, диск…), тогда как мониторинг приложений основан на сервисе и его масштабируемости (запросы, обработка, бизнес-логика…).

Мы предоставляем эту услугу для внутренних команд, которые пользуются тем же опытом, что и наши клиенты. По сути, наша служба Observability — это SaaS с уровнем совместимости (поддерживающим InfluxDB, OpenTSDB, Warp10, Prometheus и Graphite), который позволяет ему интегрироваться с большинством существующих решений. Таким образом, команде, которая привыкла к определенному инструменту или уже развернула решение для мониторинга, не нужно будет тратить много времени или усилий при переходе на полностью управляемую и масштабируемую службу: они просто выбирают токен, используют правильный конечная точка, и все готово. Кроме того, наш уровень совместимости предлагает выбор: вы можете отправить свои данные с помощью OpenTSDB, а затем запросить их в PromQL или WarpScript. Подобное комбинирование протоколов приводит к уникальной совместимости с открытым исходным кодом, которая обеспечивает большую ценность.

Scollector, Snap, Telegraf, Graphite, Collectd…

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

В OVH мы используем наборы показателей, вырезанные лазером. У каждого хоста есть определенный шаблон (веб-сервер, база данных, автоматизация…), который экспортирует заданное количество показателей, которые можно использовать для диагностики работоспособности и мониторинга производительности приложений.

Такое детализированное управление приводит к большему пониманию для операционных команд, поскольку они знают, что доступно, и могут постепенно добавлять метрики для управления своими собственными услугами.

Beamium & Noderig — Идеальная посадка

Наши требования были довольно простыми:
Масштабируемость : мониторинг одного узла так же, как мы наблюдаем за тысячами
Laser-Cut : собирать только релевантные метрики
Надежность : мы хотим, чтобы метрики были доступны даже в наихудших условиях
Просто : Несколько компонентов plug-and-play вместо сложных
Эффективность : мы верим в беспроблемный сбор показателей

Первым решением был Beamium

Beamium обрабатывает два аспекта процесса мониторинга: данные приложения слом и показатели пересылки.

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

Источники, из которых Beamium будет извлекать данные, — это просто конечные точки HTTP Prometheus. Это означает, что это так же просто, как предоставить конечную точку HTTP и, в конечном итоге, добавить несколько параметров. Эти данные будут направляться в приемники, что позволяет нам фильтровать их во время процесса маршрутизации между источником и приемником. Приемники — это конечные точки Warp 10 ®, куда мы можем отправлять данные.

После очистки метрики сначала сохраняются на диске, а затем направляются в приемник. Механизм переключения диска при отказе (DFO) позволяет выполнять восстановление после сбоя в сети или удаленно. Таким образом, локально мы сохраняем логику вытягивания Prometheus, но децентрализованно, и мы обращаем ее вспять, чтобы протолкнуть для подачи на платформу, которая имеет много преимуществ:

  • поддержка транзакционной логики на платформе метрик
  • восстановление после разделения сети или недоступности платформы
  • двойная запись с согласованностью данных (поскольку в противном случае нет гарантии, что два экземпляра Prometheus будут очищать одни и те же данные с одной и той же меткой времени)

У нас много разных клиентов, некоторые из которых используют хранилище временных рядов для продукта Observability для управления потреблением продукта или транзакционными изменениями при лицензировании. Эти варианты использования не могут быть обработаны с помощью экземпляров Prometheus, которые лучше подходят для мониторинга на основе метрик.



Второй был Noderig

В ходе бесед с некоторыми из наших клиентов мы пришли к выводу, что существующие инструменты нуждаются в определенном уровне знаний, чтобы их можно было использовать в больших масштабах. Например, команда с кластером из 20 тыс. Узлов с Scollector в итоге получит более 10 миллионов метрик только для узлов… Фактически, в зависимости от конфигурации оборудования, Scollector будет генерировать от 350 до 1000 метрик из одного узла.

Это причина создания Noderig. Мы хотели, чтобы он был таким же простым в использовании, как экспортер узлов от Prometheus, но с более детализированным производством метрик по умолчанию.

Noderig собирает метрики ОС (ЦП, память, диск и сеть), используя семантику простого уровня. Это позволяет собирать нужное количество метрик для любого типа хоста, что особенно подходит для контейнерных сред.

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

Собранные метрики доступны через простую конечную точку отдыха, что позволяет вам видеть свои метрики в режиме реального времени и легко интегрировать их с Beamium.



Это работает?

Beamium и Noderig широко используются в OVH и поддерживают мониторинг очень больших инфраструктур. На момент написания мы собираем и храним сотни миллионов показателей с помощью этих инструментов. Так что они определенно работают!

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