Подключаем VictoriaMetrics в Deckhouse и настраиваем уведомления в Telegram
В статье мы рассмотрим, как в Kubernetes-кластере под управлением Deckhouse удобно и быстро настраивать мониторинг с уведомлениями в Telegram. Воспользуемся VictoriaMetrics для хранения метрик, добавим дашборд в Grafana, создадим алерт и настроим оповещение.
Подготовка окружения
Нам потребуются:
Установка VictoriaMetrics
Развернём VictoriaMetrics в пространстве имен victoria-metrics-test
, выполнив следующие команды для установки из Helm-чарта с конфигурацией по умолчанию:
helm repo add vm https://victoriametrics.github.io/helm-charts/ && \
helm repo update && \
helm upgrade --install victoria-metrics vm/victoria-metrics-single --namespace victoria-metrics-test --create-namespace
Подключение VictoriaMetrics к Prometheus
Внешнее хранилище метрик в Deckhouse подключается с помощью CustomResource PrometheusRemoteWrite:
---
apiVersion: deckhouse.io/v1
kind: PrometheusRemoteWrite
metadata:
name: victoria-metrics
spec:
url: http://victoria-metrics-victoria-metrics-single-server.victoria-metrics-test.svc.cluster.local:8428/api/v1/write
В минимальной конфигурации в ресурсе PrometheusRemoteWrite достаточно указать адрес VictoriaMetrics. Также при необходимости можно ввести данные для аутентификации и настроить преобразование label«ов перед отправкой данных.
Все использованные конфигурационные файлы доступны в репозитории.
Применим конфигурационный файл в кластере:
kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2023/03-monitoring/prometheus-remote-write.yaml
Здесь мы использовали подготовленный заранее template из репозитория на GitHub. Это не обязательно — применить файл с нужным содержимым в кластере можно любым удобным способом.
Подождем несколько минут и убедимся, что метрики поступают в кластер. Для этого достаточно посмотреть статус базы данных метрик на master-узле с помощью следующей команды:
curl $(kubectl --namespace victoria-metrics-test get ep -l "app=server" -o jsonpath="{.items[0].subsets[0].addresses[0].ip}"):8428/api/v1/status/tsdb
В результате должно отобразиться примерно следующее:
{"status":"success","data":{"totalSeries":100477,"totalLabelValuePairs":1099074,"seriesCountByMetricName":[{"name":"apiserver_request_slo_duration_seconds_bucket","value":15576},{"name":"apiserver_request_duration_seconds_bucket","value":8496},{"name":"etcd_request_duration_seconds_bucket","value":4284},{"name":"apiserver_response_sizes_bucket","value":3080},{"name":"apiserver_watch_events_sizes_bucket","value":1872},{"name":"trivy_vulnerability_id","value":1541},{"name":"workqueue_queue_duration_seconds_bucket","value":1089},{"name":"workqueue_work_duration_seconds_bucket","value":1089},{"name":"container_memory_failures_total","value":904},{"name":"scheduler_plugin_execution_duration_seconds_bucket","value":903}],"seriesCountByLabelName":[{"name":"__name__","value":100477},{"name":"prometheus","value":100477},{"name":"job","value":100171},{"name":"instance","value":99736},{"name":"tier","value":81434},{"name":"service","value":57725},{"name":"le","value":51720},{"name":"resource","value":36606},{"name":"version","value":34823},{"name":"namespace","value":33844}],"seriesCountByFocusLabelValue":[],"seriesCountByLabelValuePair":[{"name":"prometheus=deckhouse","value":100475},{"name":"tier=cluster","value":81434},{"name":"service=kubernetes","value":45705},{"name":"instance=192.168.199.9:6443","value":45196},{"name":"job=kube-apiserver","value":45196},{"name":"component=apiserver","value":31879},{"name":"version=v1","value":19859},{"name":"scope=cluster","value":19344},{"name":"container=kube-rbac-proxy","value":17796},{"name":"__name__=apiserver_request_slo_duration_seconds_bucket","value":15576}],"labelValueCountByLabelName":[{"name":"__name__","value":1870},{"name":"name","value":693},{"name":"resource","value":538},{"name":"le","value":379},{"name":"type","value":323},{"name":"secret","value":282},{"name":"hook","value":201},{"name":"kind","value":198},{"name":"controller_name","value":173},{"name":"installed_version","value":167}]}}
"status":"success"
указывает на то, что все работает как нужно; если totalSeries
больше нуля, то данные уже начали накапливаться.
Проконтролировать сбор метрик можно через веб-интерфейс VictoriaMetrics. Для этого пробросьте порт VictoriaMetrics на свой компьютер:
export POD_NAME=$(kubectl get pods --namespace victoria-metrics-test -l "app=server" -o jsonpath="{.items[0].metadata.name}") && kubectl --namespace victoria-metrics-test port-forward $POD_NAME 8428
Для успешного выполнения этой команды на машине, с которой выполняется запрос, должен быть настроен удаленный доступ для kubectl.
Веб-интерфейс станет доступен по адресу http://localhost:8428:
Перейдем на адрес http://localhost:8428/api/v1/status/tsdb — там также должен быть отображен статус "status":"success"
; значение totalSeries
больше нуля будет сигнализировать об успешном сборе метрик:
Теперь метрики хранятся в VictoriaMectrics. Подключим это хранилище к Grafana.
Подключение VictoriaMetrics к Grafana
Добавление нового datasource
Подключение datasource к Grafana в Deckhouse выполняется с помощью CustomResource GrafanaAdditionalDatasource:
---
apiVersion: deckhouse.io/v1
kind: GrafanaAdditionalDatasource
metadata:
name: victoria-metrics
spec:
access: Proxy
basicAuth: false
jsonData:
timeInterval: 30s
type: prometheus
url: http://victoria-metrics-victoria-metrics-single-server.victoria-metrics-test.svc.cluster.local:8428/
Применим его в кластере:
kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2023/03-monitoring/grafana-additional-datasource.yaml
Перезапустим Grafana и проверим ее готовность:
kubectl -n d8-monitoring get po -l app=grafana
Статус должен быть Running
:
kubectl -n d8-monitoring get po -l app=grafana
NAME READY STATUS RESTARTS AGE
grafana-56df555c67-glzqr 3/3 Running 0 67s
Проверка подключения
Зайдем в веб-интерфейс Grafana и перейдем на вкладку Configuration → Data sources:
В списке доступных источников должен отображаться victoria-metrics:
Откроем меню Explore:
Выберем victoria-metrics в качестве источника данных:
Раскроем Metrics browser: в нем должен отобразиться список метрик, полученных из VictoriaMetrics:
Все настроено и готово к работе.
Добавление алерта
Настроим уведомление о событиях, создав новый алерт.
В Deckhouse алерты описываются в CustomResource CustomPrometheusRules:
---
apiVersion: deckhouse.io/v1
kind: CustomPrometheusRules
metadata:
name: always-firing-alert
spec:
groups:
- name: cluster-state-alert.rules
rules:
- alert: PrometheusCanScrapeTragets
annotations:
description: This is a fake alert only for a demo.
summary: The alert shows that Prometheus can scrape targets.
expr: |
up{job="deckhouse"}
Созданный алерт «бесполезный» — он всегда активный, но хорошо подходит для целей тестирования.
Применим его в кластере:
kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2023/03-monitoring/custom-prometheus-rule.yaml
Для проверки перейдем в Prometheus по адресу <адрес_Grafana>/prometheus/
и откроем вкладку Alerts. В строке поиска введем имя алерта — PrometheusCanScrapeTragets:
Алерт создан.
Добавление дашборда в Grafana
Создадим дашборд Services Up в каталоге Services (через CustomResource GrafanaDashboardDefinition):
---
apiVersion: deckhouse.io/v1
kind: GrafanaDashboardDefinition
metadata:
name: up-services
spec:
folder: Services
definition: |
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": false,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 31,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 15,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 10,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "normal"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 26,
"w": 24,
"x": 0,
"y": 0
},
"id": 2,
"options": {
"legend": {
"calcs": [
"lastNotNull"
],
"displayMode": "table",
"placement": "right"
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.5.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "P0D6E4079E36703EB"
},
"editorMode": "code",
"exemplar": false,
"expr": "sum by (job, scrape_endpoint, scrape_source) (up)",
"format": "time_series",
"instant": false,
"legendFormat": "{{ job }} {{ scrape_source }}",
"range": true,
"refId": "A"
}
],
"title": "Up",
"transformations": [],
"type": "timeseries"
}
],
"refresh": "30s",
"schemaVersion": 36,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-3h",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"30s"
]
},
"timezone": "",
"title": "Services Up",
"uid": "f_8jGXenz",
"version": 1,
"weekStart": ""
}
И применим его в кластере:
kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2023/03-monitoring/grafana-dashboard-definition.yaml
Проверим, что все отработало, перейдя по пути Services → Services Up на вкладке Dashboards:
В созданном дашборде отобразится вот такой «частокол» алертов, привязанных ко всем сервисам Deckhouse в кластере:
Настройка уведомлений в Telegram
Подключение к Telegram
Если у вас уже есть ID чата, в который вы хотите получать уведомления, и токен бота, через которого вы хотите отправлять уведомления, то следующий этап можно пропустить и перейти сразу к настройке.
Создание бота и получение ID чата
Подробную инструкцию по созданию бота можно найти в документации Telegram.
В строке поиска клиента Telegram введем адрес https://t.me/botfather и найдем бота @BotFather
. Не перепутайте его с другими — у настоящего отображается значок верификации:
Выберем его и нажмем Start. Затем отправим боту сообщение /newbot
и ответим на поступившие вопросы, введя имя создаваемого бота и его ник.
Пример диалога создания бота @mytestalert2023bot
:
Мы получим токен бота и ссылку. Пройдем по ней к диалогу с созданным ботом (в примере это http://t.me/mytestalert2023bot
) и нажмем Start.
Теперь нужно узнать ID чата, куда будут отправляться сообщения.
Это могут быть как личные сообщения, так и группа или канал в Telegram. Во втором случае нужно предварительно добавить в них бота, а в конфиге указывать ID канала.
Узнаем ID учетной записи. Сделать это можно, выбрав бота @getmyid_bot
и нажав Start. В ответ отобразится ID учетной записи Telegram:
Проверим работу сообщений через API Telegram.
Выполним следующую команду, указав вместо XXX токен бота (обратите внимание на префикс bot
— токен идет после него), а вместо YYY — ID учетной записи Telegram:
curl -X POST "https://api.telegram.org/botXXX/sendMessage" -d "chat_id=YYY&text=text for test"
В ответ отобразится сообщение об успешной отправке:
{"ok":true,"result":{"message_id":2,"from":{"id":2222222222,"is_bot":true,"first_name":"mytestbot","username":"mytestalert2023bot"},"chat":{"id":2222222222,"first_name":"Joe","type":"private"},"date":1674327896,"text":"text for test"}}
…, а нам придет личное сообщение от созданного бота.
Настройка отправки уведомлений
Создадим Secret telegram-bot-secret
, указав токен бота:
kubectl create secret generic -n d8-monitoring telegram-bot-secret --from-literal=token=XXX
Создадим ресурс CustomAlertmanager:
---
apiVersion: deckhouse.io/v1alpha1
kind: CustomAlertmanager
metadata:
name: telegram
spec:
type: Internal
internal:
route:
groupBy: [ 'job' ]
groupWait: 30s
groupInterval: 5m
repeatInterval: 12h
receiver: 'telegram'
receivers:
- name: telegram
telegramConfigs:
- botToken:
key: token
name: telegram-bot-secret
chatID: 111
Применим его в кластере:
kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2023/03-monitoring/alertmanager.yaml
В пространстве имен db-monitoring
запустится Pod с AlertManager. Проверим, что он имеет статус Running
:
kubectl -n d8-monitoring get po -l alertmanager
Пример вывода:
NAME READY STATUS RESTARTS AGE
alertmanager-telegram-0 3/3 Running 1 (4m1s ago) 3m57s
Сейчас в журнале Alertmanager«а будут ошибки отправки, т. к. не указан ID чата, в который нужно отправлять сообщения. Посмотреть лог можно командой:
kubectl -n d8-monitoring logs alertmanager-telegram-0 -c alertmanager
ID чата указывается в параметре spec.internal.receivers.telegramConfigs.chatID
CustomAlertmanager.
Ресурс можно либо отредактировать вручную (kubectl edit customalertmanager telegram
), либо воспользоваться следующей командой, указав в переменной CHAT_ID
ID учетной записи Telegram:
CHAT_ID=2222222222 && \
kubectl patch customalertmanager telegram --type json -p "[{\"op\": \"replace\", \"path\": \"/spec/internal/receivers/0/telegramConfigs/0/chatID\", \"value\": ${CHAT_ID}}]"
Alertmanager обновит свою конфигурацию и пришлет сообщение об алерте PrometheusCanScrapeTragets, созданном ранее, а также сообщения о других алертах, активных в кластере.
Убираем за собой
Для удаления созданных выше ресурсов выполните:
kubectl delete prometheusremotewrite victoria-metrics
kubectl delete grafanaadditionaldatasource victoria-metrics
kubectl delete customprometheusrules always-firing-alert
kubectl delete grafanadashboarddefinitions up-services
kubectl delete customalertmanager telegram
helm uninstall victoria-metrics -n victoria-metrics-test
kubectl delete ns victoria-metrics-test
Заключение
Мы рассмотрели, как подключить новое хранилище метрик к кластеру под управлением Deckhouse, создать алерт и настроить уведомления в Telegram. Здесь стоит обратить внимание, что все действия и настройки выполняются через custom resources. Такой декларативный подход соответствует общему тренду, при котором описание конфигурации инфраструктуры хранится в репозитории и последний используется как единственный источник настроек (GitOps).
С предложениями и вопросами ждем вас в комментариях, а также в Telegram-чате deckhouse_ru, где вам всегда помогут. Также будем рады Issues (и, конечно, звёздам) в GitHub-репозитории Deckhouse.
P.S.
Читайте в нашем блоге: