В пості Prometheus: запуск Pushgateway у Kubernetes з Helm та Terraform писав про те, як для Prometheus додати Pushgateway, який дозволяє використовувати Push-модель замість Pull, тобто – експортер може відправити метрики прямо в базу замість того, щоб чекати, коли до нього прийде сам Prometheus або VMAgent.
У VictoriaMetrics з цим набагато простіше, бо ніякого Pushgateway не потрібно – VictoriaMetrics “з коробки” вміє приймати метрики, і це одна з тих чудовіих фіч, чому я вибрав VictoriaMetrics, і досі їй радуюсь.
Отже, що є і треба зробити:
- в Kubernetes-кластері є VictoriaMetrics встановлена з VictoriaMetrics Operator – див. VictoriaMetrics: створення Kubernetes monitoring stack з власним Helm-чартом
- у нас є новий експортер для Notion, який буде запускатись в Kubernetes по крону раз на добу
- працювати він буде недовго, якісь секунди, тож “ходити” до нього з VMAgent ми не можемо
- тому замість Pull-моделі з VMAgent – використаємо Push-модель – експортер буде відправляти метрики прямо в VictoriaMetrics
Тож спочатку давайте глянемо, як в VictoriaMetrics пушити метрики взагалі, а потім спробуємо написати простий експортер.
Зміст
VictoriaMetrics API
Використовуємо ендпоінт /api/v1/import/prometheus
.
Запускаємо тестовий под:
$ kubectl -n dev-monitoring-ns run pod --rm -i --tty --image ubuntu -- bash
Встановлюємо curl
:
root@pod:/# apt update && apt -y install curl
Знаходимо Kubernetes Service для VMSingle:
$ kubectl -n dev-monitoring-ns get svc | grep vmsing vmsingle-vm-k8s-stack ClusterIP 172.20.45.38 <none> 8429/TCP 35d
Виконуємо запит на ендпоінт http://vmsingle-vm-k8s-stack:8429/api/v1/import/prometheus
:
root@pod:/# echo "some_metric 3.14" | curl --data-binary @- http://vmsingle-vm-k8s-stack:8429/api/v1/import/prometheus
І за півхвилини перевіряємо в VMui:
Все є, і ніяких тобі додаткових дій з Pushgateway!
Push метрик з експортера
Для тесту напишемо простий експортер:
#!/usr/bin/env python3 from time import sleep from prometheus_client import Counter, CollectorRegistry, push_to_gateway # local metrics "storage" registry = CollectorRegistry() # register a metric counter = Counter('counter_metric', 'Example metric', ["label_name"], registry=registry) while True: # increase metric's value to +1 counter.labels(label_name="label_value").inc() # push to the VictoriaMetrics push_to_gateway('localhost:8428/api/v1/import/prometheus', job='test_job', registry=registry) # make sure this code is working :-) print("pushed") # wait before next run sleep(15)
Тут:
- реєструємо “локальне сховище” для метрик (див. Overall structure)
- реєструємо метрику
counter_metric
з типом Counter - виконуємо її інкремент з
inc()
- і відправляємо в
localhost:8428/api/v1/import/prometheus
– це я перевіряв на тестовому інтансі, де VictoriaMetrics запущена з Docker Compose, тому тутlocalhost
Перевіряємо в самій VictoriaMetrics:
prometheus_client
, функції та grouping key
Трохи про те, як працює сам prometheus_client
:
push_to_gateway()
вregistry
будуть перезаписані всі метрики з однаковим набором labels (grouping key)pushadd_to_gateway()
перезапише метрики з однаковим іменем та grouping keydelete_from_gateway()
видалить метрики з заданим job та grouping key
Див. Exporting to a Pushgateway та Prometheus Pushgateway.
Kubernetes CronJob та Prometheus Exporter
І приклад того, як воно все буде виглядати в Kubernetes.
Сам експортер, який буде ходити в Notion та збирати дані (код функцій не покажу, бо робочі моменти):
#!/usr/bin/env python3 import os import requests from datetime import datetime from prometheus_client import Summary, CollectorRegistry, push_to_gateway ... ################################################### ### get_ios_ui_tests_status_and_failure_reasons ### ################################################### registry = CollectorRegistry() notion_ios_ui_test_last_100_results = Summary('notion_ios_ui_test_last_100_results', 'Status and failure reasons of last 100 iOS UI test runs', labelnames=['reason'], registry=registry) def get_last_ios_ui_test_results(): print(f"\nStarted get_last_ios_ui_test_results() checks at {datetime.now()}") ... for reason in reasons.keys(): notion_ios_ui_test_last_100_results.labels(reason=reason).observe(reasons[reason]) print(f"collected reason: {reason} = {reasons[reason]} records") def main(): try: get_last_ios_ui_test_results() push_to_gateway('vmsingle-vm-k8s-stack:8429/api/v1/import/prometheus', job='notion-exporter', registry=registry) except Exception as e: print("Notion API error occurred:", str(e)) if __name__ == '__main__': print(f"\nStarting Notion Exporter at {datetime.now()}") main()
Kubernetes CronJob та Secret для нього – поки в тестуванні, тож запускається кожну хвилину:
apiVersion: batch/v1 kind: CronJob metadata: name: notion-exporter-cronjob spec: schedule: "*/1 * * * *" jobTemplate: spec: template: metadata: labels: app: notion-exporter spec: containers: - name: notion-exporter-container image: 492***148.dkr.ecr.us-east-1.amazonaws.com/notion-exporter:latest imagePullPolicy: Always env: - name: NOTION_REPORTS_DATABASE_ID value: "fc2***8e0" envFrom: - secretRef: name: notion-exporter-secret restartPolicy: OnFailure --- apiVersion: v1 kind: Secret metadata: name: notion-exporter-secret type: Opaque stringData: NOTION_SECRET: "secret_SmX***ejH"
І дані в Grafana:
Готово.