Всем привет! Несколько месяцев назад мы запустили в производство наш новый open-source проект — плагин Grafana для мониторинга kubernetes, который мы назвали DevOpsProdigy KubeGraf .
Исходный код плагина доступен по адресу публичный репозиторий на GitHub .
И в этой статье мы хотим поделиться с вами историей о том, как мы создавали плагин, какие инструменты использовали и с какими подводными камнями столкнулись в процессе разработки.
Пойдем!
Часть 0 – вводная: как мы дошли до этого момента?
Идея написать собственный плагин для Grafana пришла к нам совершенно случайно.Наша компания занимается сопровождением веб-проектов различного уровня сложности более 10 лет. За это время мы накопили большой объем экспертизы, интересных кейсов и опыта использования различных систем мониторинга.
И в какой-то момент мы спросили себя: «Есть ли волшебный инструмент для мониторинга Kubernetes, чтобы, как говорится, «поставил и забыл»Э».
Отраслевым стандартом мониторинга k8s, конечно, уже давно является Комбинация Прометей + Графана.
А в качестве готовых решений для этого стека имеется большой набор разного рода инструментов: prometheus-operator, набор дашбордов kubernetes-mixin, grafana-kubernetes-app. Плагин grafana-kubernetes-app показался нам наиболее интересным вариантом, но он не поддерживается уже больше года и, более того, не может работать с новыми версиями node-exporter и kube-state-metrics. И в какой-то момент мы решили: «А не стоит ли нам принять собственное решениеЭ» Какие идеи мы решили реализовать в нашем плагине:
- визуализация «карты приложений»: удобное представление приложений в кластере, сгруппированных по пространствам имен, развертываниям.
;
- визуализация связей типа «развертывание — сервис (+порты)».
- визуализация распределения приложений кластера по узлам кластера.
- сбор метрик и информации из нескольких источников: Prometheus и API-сервера k8s.
- мониторинг как инфраструктурной части (использование процессорного времени, памяти, дисковой подсистемы, сети), так и логики приложения — работоспособность подов, количество доступных реплик, информация о прохождении тестов живучести/готовности.
Часть 1. Что такое «плагин Grafana»?
С технической точки зрения плагин для Grafana представляет собой контроллер angular, который хранится в каталоге данных Grafana ( /вар/графана/плагины/ /dist/module.js ) и может быть загружен как модуль SystemJS. Также в этом каталоге должен находиться файл плагина.json, содержащий всю метаинформацию о вашем плагине: имя, версию, тип плагина, ссылки на репозиторий/сайт/лицензию, зависимости и так далее.
модуль.
ts
плагин.
json Как вы можете видеть на скриншоте, мы указали плагин.
type = app. Потому что плагины для Grafana могут быть трёх типов: панель : самый распространенный тип плагина — это панель для визуализации каких-либо метрик, используемая для построения различных дашбордов.
источник данных : плагин-коннектор к какому-либо источнику данных (например, источнику данных Prometheus, источнику данных ClickHouse, источнику данных ElasticSearch).
приложение : Плагин, который позволяет вам создавать собственное внешнее приложение внутри Grafana, создавать собственные html-страницы и вручную получать доступ к источнику данных для визуализации различных данных.
Также в качестве зависимостей могут использоваться плагины других типов (источник данных, панель) и различные дашборды.
Пример зависимостей плагина с type=app .
В качестве языка программирования вы можете использовать как JavaScript, так и TypeScript (мы выбрали именно его).
Подготовка к плагинам hello-world любого типа, который вы можете найди ссылку : в этом репозитории содержится большое количество starter-паков (есть даже экспериментальный пример плагина на React) с предустановленными и настроенными сборщиками.
Часть 2: подготовка местной среды
Для работы над плагином нам естественно понадобится кластер kubernetes со всеми предустановленными инструментами: prometheus, node-exporter, kube-state-metrics, grafana. Среда должна быть настроена быстро, легко и естественно, а для обеспечения горячей перезагрузки каталог данных Grafana должен быть смонтирован непосредственно с машины разработчика.Самый удобный, на наш взгляд, способ локальной работы с kubernetes — это миникуб .
Следующим шагом будет установка комбинации Prometheus + Grafana с помощью prometheus-operator. В Эта статья Подробно описан процесс установки prometheus-operator на миникубе.
Чтобы включить сохранение, необходимо установить параметр настойчивость: правда в файлеcharts/grafana/values.yaml добавьте свои собственные PV и PVC и укажите их в параметре persistence.existingClaim Наш окончательный сценарий запуска миникуба выглядит так:
minikube start --kubernetes-version=v1.13.4 --memory=4096 --bootstrapper=kubeadm --extra-config=scheduler.address=0.0.0.0 --extra-config=controller-manager.address=0.0.0.0 minikube mount /home/sergeisporyshev/Projects/Grafana:/var/grafana --gid=472 --uid=472 --9p-version=9p2000.L
Часть 3: фактическое развитие
Объектная модель Готовясь к реализации плагина, мы решили описать все основные сущности Kubernetes, с которыми будем работать, в виде классов TypeScript: pod, Deployment, daemonset, statefulset, job, cronjob, service, node, namespace. Каждый из этих классов наследуется от общего класса BaseModel, который описывает конструктор, деструктор, методы обновления и переключения видимости.Каждый из классов описывает вложенные связи с другими сущностями, например список модулей для сущности типа развертывание.
import {Pod} from ".
/pod"; import {Service} from ".
/service"; import {BaseModel} from '.
/traits/baseModel';
export class Deployment extends BaseModel{
pods: Array<Pod>;
services: Array<Service>;
constructor(data: any){
super(data);
this.pods = [];
this.services = [];
}
}
С помощью геттеров и сеттеров мы можем отображать или задавать нужные нам метрики сущности в удобной и читаемой форме.
Например, форматированный вывод выделяемых узлов процессора: get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}
Страницы
Список всех страниц нашего плагина изначально описан в нашем pluing.json в разделе зависимостей:
В блоке для каждой страницы мы должны указать ИМЯ СТРАНИЦЫ (оно потом преобразуется в слаг, по которому эта страница будет доступна); название компонента, отвечающего за работу этой страницы (список компонентов экспортируется в модуль.
ts); указание роли пользователя, для которого доступна работа с данной страницей, и настройки навигации по боковой панели.
В компоненте, отвечающем за работу страницы, мы должны задать templateUrl, передав туда путь к html-файлу с разметкой.
Внутри контроллера посредством внедрения зависимостей мы можем получить доступ к двум важным сервисам Angular:
- backendSrv — сервис, обеспечивающий взаимодействие с API-сервером Grafana;
- datasourceSrv — сервис, обеспечивающий локальное взаимодействие со всеми источниками данных, установленными в вашей Grafana (например, метод .
getAll() — возвращает список всех установленных источников данных; .
get( ) — возвращает объект экземпляра определенного источника данных.
Часть 4: источник данных
С точки зрения Grafana, datasource — это точно такой же плагин, как и все остальные: у него есть своя точка входа Module.js, есть файл с метаинформацией плагин.json. При разработке плагина с type=app мы можем взаимодействовать как с существующими источниками данных (например, prometheus-datasource), так и со своими собственными, которые мы можем хранить непосредственно в каталоге плагина (dist/datasource/*) или устанавливать как зависимость.
В нашем случае источник данных поставляется с кодом плагина.
Также необходимо иметь шаблон config.html и контроллер ConfigCtrl, который будет использоваться для страницы конфигурации экземпляра источника данных, и контроллер источника данных, который реализует логику работы вашего источника данных.
В плагине KubeGraf с точки зрения пользовательского интерфейса источником данных является экземпляр кластера kubernetes, реализующий следующие возможности (исходный код доступен связь ):
- сбор данных с api-сервера k8s (получение списка пространств имен, развертываний.
)
- проксирование запросов к prometheus-datasource (который выбирается в настройках плагина для каждого конкретного кластера) и форматирование ответов для использования данных как на статических страницах, так и в дашбордах.
- обновление данных на статических страницах плагина (с заданной частотой обновления).
- обработка запросов для создания листа-шаблона в grafana-dashboards (метод metriFindQuery())
- проверка соединения с финальным кластером k8s.
testDatasource(){
let url = '/api/v1/namespaces';
let _url = this.url;
if(this.accessViaToken)
_url += '/__proxy';
_url += url;
return this.backendSrv.datasourceRequest({
url: _url,
method: "GET",
headers: {"Content-Type": 'application/json'}
})
.
then(response => {
if (response.status === 200) {
return {status: "success", message: "Data source is OK", title: "Success"};
}else{
return {status: "error", message: "Data source is not OK", title: "Error"};
}
}, error => {
return {status: "error", message: "Data source is not OK", title: "Error"};
})
}
Отдельный интересный момент, на наш взгляд, — реализация механизма аутентификации и авторизации источника данных.
Обычно по умолчанию мы можем использовать встроенный компонент DatasourceHttpSettings компонента Grafana для настройки доступа к конечному источнику данных.
Используя этот компонент, мы можем настроить доступ к источнику данных http, указав URL-адрес и базовые настройки аутентификации/авторизации: логин-пароль или client-cert/client-key. Чтобы реализовать возможность настройки доступа с помощью токена-носителя (фактический стандарт для k8s), нам пришлось провести небольшую доработку.
Для решения этой проблемы можно использовать встроенный в Grafana механизм «Plugin Routes» (подробнее на сайте).
официальная страница документации ).
В настройках нашего источника данных мы можем объявить набор правил маршрутизации, которые будут обрабатываться прокси-сервером Grafana. Например, для каждого отдельного эндпоинта можно задать заголовки или урлы с возможностью шаблонизации, данные для которых можно брать из полей jsonData и secureJsonData (для хранения паролей или токенов в зашифрованном виде).
В нашем примере запросы типа /__proxy/api/v1/пространства имен будет проксировано на URL-адрес формы
/api/v1/namespaces с заголовком Authorization: Bearer.
Естественно, для работы с API-сервером k8s нам понадобится пользователь с доступом только для чтения, манифесты для создания которого вы также можете найти в исходный код плагина .
Часть 5: выпуск
Написав собственный плагин Grafana, вы, естественно, захотите сделать его общедоступным.
В Grafana это библиотека плагинов, доступная здесь.
grafana.com/grafana/plugins
Для того, чтобы ваш плагин был доступен в официальном магазине, вам необходимо сделать пиар в этот репозиторий добавив такой контент в файл repo.json:
где версия — это версия вашего плагина, URL — это ссылка на репозиторий, а коммит — это хеш коммита, для которого будет доступна конкретная версия плагина.
И на выходе вы увидите чудесную картинку типа:
Данные для него будут автоматически получены из ваших Readme.md, Changelog.md и файла plugin.json с описанием плагина.
Часть 6: вместо выводов
Мы не прекратили разработку нашего плагина после его выпуска.И сейчас мы работаем над корректным мониторингом использования ресурсов узлов кластера, внедряем новые функции для улучшения UX, а также собираем большое количество отзывов, полученных после установки плагина как от наших клиентов, так и от людей на GitHub (если вы оставите ваш вопрос или запрос на вытягивание, я буду очень рад :-)).
Надеемся, что эта статья поможет вам разобраться в таком замечательном инструменте, как Grafana, и, возможно, написать свой плагин.
Спасибо!) Теги: #github #DIY или Сделай сам #it инфраструктура #открытый исходный код #Kubernetes #разработка #Управление продуктом #мониторинг #k8s #itsumma #Grafana #plugin
-
Обзор Windows 7 – Окно В Будущее
19 Oct, 24 -
Взлом Lostfilm (Php)
19 Oct, 24