Зараз маємо VictoriaMetrics + Grafana на звичайному EC2-інстансі, запущені з Docker Compose – то був Proof of Concept, прийшов час запускати “по-дорослому” – в Kubernetes, і всі конфіги вже винести в GitHub.
У VictoriaMetrics є чарти під кожен компонент, див. Victoria Metrics Helm Charts, і є чарти для запуску VictoriaMetrics Operator та victoria-metrics-k8s-stack
– аналог Kuber Prometheus Stack, який я використовував раніше.
Використовувати будемо саме victoria-metrics-k8s-stack
, який “під капотом” запустить VictoriaMetrics Operator, Grafana та kube-state-metrics, див. dependencies
.
Матеріал вийшов досить великий, але наче описав всі цікаві моменти по розгортанню повноцінного стеку моніторингу з VictoriaMetrics Kubernetes Monitoring Stack.
UPD: робив документацію по нашому моніторингу, вийшла ось така схема того, про що буде в цьому пості:
Зміст
Планування
Отже, що треба буде зробити:
- перевірити деплой чарту
victoria-metrics-k8s-stack
- подивитись і подумати, як запускати існуючі експортери – частина мають чарти, але ми маємо і самописні (див. – Prometheus: GitHub Exporter – пишемо власний експортер для GitHub API), тож їх треба буде пушити в Elastic Container Service і думати, як звідти пулити і запускати в Kubernetes
- секрети для моніторингу – паролі Grafana і все таке інше
- IRSA для експортерів – створити IAM Policy та ролі для ServiceAccounts
- перенесення алертів
- конфіг для VMAgent – збір метрик с експортерів
- запустити Grafana Loki
Стосовно логів – так, нещодавно вийшла VictoriaLogs, але вона ще в preview, не має підтримки збегірання в AWS S3, не має інтеграції з Grafana, та й взагалі поки не хочеться витрачати зайвий час, а Loki я вже більш-менш знаю. Можливо, запущу VictoriaLogs окремо, “погратись-подивитись”, а коли її вже інтегрують з Grafana – то заміню Loki на VictoriaLogs, бо зараз ми вже маємо дашборди з графіками з логів Loki.
Ще окремо треба буде глянути як там з persistance у VictoriaMetrics в Kubernetes – розмір, типи дисків і так далі. Можливо, подумати про їхні бекапи (VMBackup?).
На існуючому моніторингу маємо досить багато всього:
[simterm]
root@ip-172-31-89-117:/home/admin/docker-images/prometheus-grafana# tree . . ├── alertmanager │ ├── config.yml │ └── notifications.tmpl ├── docker-compose.yml ├── grafana │ ├── config.monitoring │ └── provisioning │ ├── dashboards │ │ └── dashboard.yml │ └── datasources │ └── datasource.yml ├── prometheus │ ├── alert.rules │ ├── alert.templates │ ├── blackbox-targets │ │ └── targets.yaml │ ├── blackbox.yml │ ├── cloudwatch-config.yaml │ ├── loki-alerts.yaml │ ├── loki-conf.yaml │ ├── prometheus.yml │ ├── promtail.yaml │ └── yace-config.yaml └── prometheus.yml
[/simterm]
Яке взагалі деплоїти? Через AWS CDK та його cluster.add_helm_chart()
– чи робити окремий степ в GitHub Actions з Helm?
Нам в будь-якому разі буде потрібен CDK – створити сертифікати з ACM, Lambda для логів в Loki, S3-корзини, IAM-ролі для експортерів тощо.
Але чомусь зовсім не хочеться тягнути в CDK деплой чартів, бо краще всеж відокремити деплой інфрастуктурних об’єктів від деплою самого стеку моніторинга.
Добре – зробимо окремо: CDK буде створювати ресурси в AWS, Helm буде деплоїти чарти. Чи чарт? Може – просто зробити власний чарт, а йому вже сабчартами підключити і VictoriaMetrics Stack, и експортери? Виглядає наче непоганою ідею. “Мінуси будуть?” (с)
Також нам треба буде створити Kubernetes Secrets та ConfigMaps з конфігами для VMAgent, Loki (див. Loki: збір логів з CloudWatch Logs з використанням Lambda Promtail), Alertmanager тощо. Робити їх з Kustomize? Чи просто YAML-маніфестами в директорії templates
нашого чарту?
Подивимось. Поки думаю, що таки Kustomize.
Тепер по порядку – що треба буде зробити:
- запустити експортери
- підключити конфіг до VMAgent, щоб почати збирати метрики з експортерів
- перевірити, як налаштовуються ServiceMonitors (VMServiceScrape у VictoriaMetrics)
- Grafana:
- датасорси
- дашборди
- додати Loki
- алерти
Поїхали. Почнемо з перевірки самого чарту victoria-metrics-k8s-stack
.
Встановлення VictoriaMetrics Stack Helm Chart
Додаємо репозиторії с залежностями:
[simterm]
$ helm repo add grafana https://grafana.github.io/helm-charts "grafana" has been added to your repositories $ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts "prometheus-community" has been added to your repositories
[/simterm]
І саму VictoriaMetrics:
[simterm]
$ helm repo add vm https://victoriametrics.github.io/helm-charts/ "vm" has been added to your repositories $ helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "vm" chart repository ...Successfully got an update from the "grafana" chart repository ...Successfully got an update from the "prometheus-community" chart repository Update Complete. ⎈Happy Helming!⎈
[/simterm]
Перевіряємо версії чарту victoria-metrics-k8s-stack
:
[simterm]
$ helm search repo vm/victoria-metrics-k8s-stack -l NAME CHART VERSION APP VERSION DESCRIPTION vm/victoria-metrics-k8s-stack 0.17.0 v1.91.3 Kubernetes monitoring on VictoriaMetrics stack.... vm/victoria-metrics-k8s-stack 0.16.4 v1.91.3 Kubernetes monitoring on VictoriaMetrics stack.... vm/victoria-metrics-k8s-stack 0.16.3 v1.91.2 Kubernetes monitoring on VictoriaMetrics stack.... ...
[/simterm]
Всі values можна взяти так:
[simterm]
$ helm show values vm/victoria-metrics-k8s-stack > default-values.yaml
[/simterm]
Або просто в репозиторії – values.yaml.
Мінімальний values для VictoriaMetrics chart
У VictoriaMetrics взагалі гарна документація, тож по ходу діла часто будемо користоватись API Docs.
Використаємо VMSingle замість VMCluster – проект у нас маленький, з VictoriaMetrics я тільки знайомлюсь, не хочеться ускладнювати систему.
Створюємо мінімальний конфіг:
# to confugire later victoria-metrics-operator: serviceAccount: create: false # to confugire later alertmanager: enabled: true # to confugire later vmalert: annotations: {} enabled: true # to confugire later vmagent: enabled: true grafana: enabled: true ingress: enabled: true annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/scheme: internet-facing hosts: - monitoring.dev.example.co
Деплоїмо в новий неймспейс:
[simterm]
$ helm upgrade --install victoria-metrics-k8s-stack -n dev-monitoring-ns --create-namespace vm/victoria-metrics-k8s-stack -f atlas-monitoring-dev-values.yaml
[/simterm]
Перевіряємо поди:
[simterm]
$ kk -n dev-monitoring-ns get pod NAME READY STATUS RESTARTS AGE victoria-metrics-k8s-stack-grafana-76867f56c4-6zth2 0/3 Init:0/1 0 5s victoria-metrics-k8s-stack-kube-state-metrics-79468c76cb-75kgp 0/1 Running 0 5s victoria-metrics-k8s-stack-prometheus-node-exporter-89ltc 1/1 Running 0 5s victoria-metrics-k8s-stack-victoria-metrics-operator-695bdxmcwn 0/1 ContainerCreating 0 5s vmsingle-victoria-metrics-k8s-stack-f7794d779-79d94 0/1 Pending 0 0s
[/simterm]
Та Ingress:
[simterm]
$ kk -n dev-monitoring-ns get ing NAME CLASS HOSTS ADDRESS PORTS AGE victoria-metrics-k8s-stack-grafana <none> monitoring.dev.example.co k8s-devmonit-victoria-***-***.us-east-1.elb.amazonaws.com 80 6m10s
[/simterm]
Чекаємо оновлення DNS, або просто відкриваємо доступ до Grafana Service – знаходимо його:
[simterm]
$ kk -n dev-monitoring-ns get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE victoria-metrics-k8s-stack-grafana ClusterIP 172.20.162.193 <none> 80/TCP 12m ...
[/simterm]
І виконуємо port-forward
:
[simterm]
$ kk -n dev-monitoring-ns port-forward svc/victoria-metrics-k8s-stack-grafana 8080:80 Forwarding from 127.0.0.1:8080 -> 3000 Forwarding from [::1]:8080 -> 3000
[/simterm]
В браузері переходимо до http://localhost:8080/
Username по дефолту admin, отримуємо його згенерований пароль:
[simterm]
$ kubectl -n dev-monitoring-ns get secret victoria-metrics-k8s-stack-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo 1Ev***Ko2
[/simterm]
Маємо вже готові дашборди (параметр defaultDashboardsEnabled
у values):
Тепер можна думати про інші налаштування.
Створення власного чарту для моніторинг-стеку
Отже, зробимо такий собі “umbrella chart“, який буде запускати і сам стек VictoriaMetrics, і експортери, і створювати всі необхідні Secrets/ConfgiMaps тощо.
Як воно буде працювати?
- створимо чарт
- йому в
dependencies
вписуємо VictoriaMetrics - через тіж
dependencies
додамо запуск екпортерів - в каталозі
templates
опишемо наші кастомні ресурси (ConfigMaps, VMRules, etc)
Згадаємо, як воно взагалі робиться – Helm Create, Helm: dependencies aka subcharts – обзор и пример, How to make a Helm chart in 10 minutes, One Chart to rule them all – How to implement Helm Subcharts.
Замість helm create
– зробимо все руками, бо він нагенерує забагато зайвих файлів.
В своєму репозиторії моніторингу створюємо каталоги:
[simterm]
$ mkdir -p victoriametrics/{templates,charts,values}
[/simterm]
Перевіряємо структуру:
[simterm]
$ tree victoriametrics victoriametrics ├── charts ├── templates └── values
[/simterm]
Переходимо в каталог victoriametrics
, створюємо файл Chart.yaml
:
apiVersion: v2 name: atlas-victoriametrics description: A Helm chart for Atlas Victoria Metrics kubernetes monitoring stack type: application version: 0.1.0 appVersion: "1.16.0"
Додавання subcharts
Далі додаємо dependencies
, починаємо з victoria-metrics-k8s-stack
.
Версії вже знаходили, згадаємо яка там була остання:
[simterm]
$ helm search repo vm/victoria-metrics-k8s-stack -l NAME CHART VERSION APP VERSION DESCRIPTION vm/victoria-metrics-k8s-stack 0.17.0 v1.91.3 Kubernetes monitoring on VictoriaMetrics stack.... vm/victoria-metrics-k8s-stack 0.16.4 v1.91.3 Kubernetes monitoring on VictoriaMetrics stack.... ...
[/simterm]
Додаємо з ~
в номері версії, щоб включити патчі до версії 0.17 (див. Dependencies):
apiVersion: v2 name: atlas-victoriametrics description: A Helm chart for Atlas Victoria Metrics kubernetes monitoring stack type: application version: 0.1.0 appVersion: "1.16.0" dependencies: - name: victoria-metrics-k8s-stack version: ~0.17.0 repository: https://victoriametrics.github.io/helm-charts/
Values для сабчартів
Далі, створюємо каталоги для values
:
[simterm]
$ mkdir -p values/{dev,prod}
[/simterm]
Копіюємо наш мінімальний конфіг у values/dev/
:
[simterm]
$ cp ../atlas-monitoring-dev-values.yaml values/dev/
[/simterm]
Потім всі загальні параметри винесемо в якійсь common-values.yaml
, а значення, которі будуть різні для Dev/Prod – по окремим файлам.
Оновлюємо наш values – додаємо блок victoria-metrics-k8s-stack
, бо він у нас тепер буде сабчартом:
victoria-metrics-k8s-stack: # no need yet victoria-metrics-operator: serviceAccount: create: true # to confugire later alertmanager: enabled: true # to confugire later vmalert: annotations: {} enabled: true # to confugire later vmagent: enabled: true grafana: enabled: true ingress: enabled: true annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/scheme: internet-facing hosts: - monitoring.dev.example.co
Загружаємо чарти з dependencies
:
[simterm]
$ helm dependency update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "vm" chart repository ...Successfully got an update from the "grafana" chart repository ...Successfully got an update from the "prometheus-community" chart repository Update Complete. ⎈Happy Helming!⎈ Saving 1 charts Downloading victoria-metrics-k8s-stack from repo https://victoriametrics.github.io/helm-charts/ Deleting outdated charts
[/simterm]
Перевіряємо каталог charts
:
[simterm]
$ ls -1 charts/ victoria-metrics-k8s-stack-0.17.0.tgz
[/simterm]
І робимо helm template
нового Helm-чарту з нашим VictoriaMetrics Stack, щоб перевірити, що сам чарт, його dependencies
і values
працюють:
[simterm]
$ helm template . -f values/dev/atlas-monitoring-dev-values.yaml --- # Source: victoriametrics/charts/victoria-metrics-k8s-stack/charts/grafana/templates/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: labels: helm.sh/chart: grafana-6.44.11 app.kubernetes.io/name: grafana app.kubernetes.io/instance: release-name ...
[/simterm]
Наче ОК – спробуємо задеплоїти – видаляємо старий реліз:
[simterm]
$ helm -n dev-monitoring-ns uninstall victoria-metrics-k8s-stack release "victoria-metrics-k8s-stack" uninstalled
[/simterm]
Service Invalid value: must be no more than 63 characters
Деплоїмо новий:
[simterm]
$ helm -n dev-monitoring-ns upgrade --install atlas-victoriametrics . -f values/dev/atlas-monitoring-dev-values.yaml Release "atlas-victoriametrics" does not exist. Installing it now. Error: 10 errors occurred: * Service "atlas-victoriametrics-victoria-metrics-k8s-stack-kube-controlle" is invalid: metadata.labels: Invalid value: "atlas-victoriametrics-victoria-metrics-k8s-stack-kube-controller-manager": must be no more than 63 characters
[/simterm]
Перевіряємо довжину імені:
[simterm]
$ echo atlas-victoriametrics-victoria-metrics-k8s-stack-kube-controller-manager | wc -c 73
[/simterm]
Щоб вирішити це – додаємо до values
параметр fullnameOverride
зі скороченим іменем:
victoria-metrics-k8s-stack: fullnameOverride: "vm-k8s-stack" ...
Деплоїмо ще раз:
[simterm]
$ helm -n dev-monitoring-ns upgrade --install atlas-victoriametrics . -f values/dev/atlas-monitoring-dev-values.yaml Release "atlas-victoriametrics" has been upgraded. Happy Helming! ...
[/simterm]
Перевіряємо ресурси:
[simterm]
$ kk -n dev-monitoring-ns get all NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/atlas-victoriametrics-grafana ClusterIP 172.20.93.0 <none> 80/TCP 0s service/atlas-victoriametrics-kube-state-metrics ClusterIP 172.20.113.37 <none> 8080/TCP 0s ...
[/simterm]
Наче все є – давайте додамо експортери.
Prometheus CloudWatch Exporter subchart
Для аутентифікації експортів в AWS використаємо IRSA, але тут описувати не буду, бо вже є у AWS: CDK та Python, IAM OIDC Provider, та Kubernetes Controllers, та й навряд чи ви це будете робити з AWS CDK та Python.
Тож будемо вважати, що IAM Role для експортера вже є – нам треба тільки встановити prometheus-cloudwatch-exporter
чарт і вказати ARN IAM-ролі.
Знову перевіряємо доступні версії:
[simterm]
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts $ helm search repo prometheus-community/prometheus-cloudwatch-exporter NAME CHART VERSION APP VERSION DESCRIPTION prometheus-community/prometheus-cloudwatch-expo... 0.25.1 0.15.4 A Helm chart for prometheus cloudwatch-exporter
[/simterm]
Додаємо його до нашого Chart.yaml
у dependencies
:
... dependencies: - name: victoria-metrics-k8s-stack version: ~0.17.0 repository: https://victoriametrics.github.io/helm-charts/ - name: prometheus-cloudwatch-exporter version: ~0.25.1 repository: https://prometheus-community.github.io/helm-charts
До файлу values/dev/atlas-monitoring-dev-values.yaml
додаємо параметр prometheus-cloudwatch-exporter.serviceAccount.annotations
з ARN нашої IAM-ролі і блок config
з метриками, які будемо збирати:
prometheus-cloudwatch-exporter: serviceAccount: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::492***148:role/atlas-monitoring-dev-CloudwatchExporterRole0613A27-EU5LW9XRWVRL config: |- region: us-east-1 metrics: - aws_namespace: AWS/Events aws_metric_name: FailedInvocations aws_dimensions: [RuleName] aws_statistics: [Sum, SampleCount] - aws_namespace: AWS/Events aws_metric_name: Invocations aws_dimensions: [EventBusName, RuleName] aws_statistics: [Sum, SampleCount]
Хоча якщо конфіг великий – то мабуть краще його робити через створення власного ConfigMap для експортеру.
Оновлюємо залежності:
[simterm]
$ helm dependency update
[/simterm]
Деплоїмо:
[simterm]
$ helm -n dev-monitoring-ns upgrade --install atlas-victoriametrics . -f values/dev/atlas-monitoring-dev-values.yaml
Перевіряємо под:
[simterm]
$ kk -n dev-monitoring-ns get pod | grep cloud atlas-victoriametrics-prometheus-cloudwatch-exporter-564ccfjm9j 1/1 Running 0 53s
[/simterm]
Та ServiceAccount:
[simterm]
$ kk -n dev-monitoring-ns get pod atlas-victoriametrics-prometheus-cloudwatch-exporter-64b6f6b9rv -o yaml ... - name: AWS_ROLE_ARN value: arn:aws:iam::492***148:role/atlas-monitoring-dev-CloudwatchExporterRole0613A27-EU5LW9XRWVRL - name: AWS_WEB_IDENTITY_TOKEN_FILE value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token ...
[/simterm]
Робимо port-forward
:
[simterm]
$ kk -n dev-monitoring-ns port-forward svc/atlas-victoriametrics-prometheus-cloudwatch-exporter 9106
[/simterm]
І з cURL глянемо, чи пішли метрики:
[simterm]
$ curl -s localhost:9106/metrics | grep aws_ # HELP aws_events_invocations_sum CloudWatch metric AWS/Events Invocations Dimensions: [EventBusName, RuleName] Statistic: Sum Unit: Count # TYPE aws_events_invocations_sum gauge aws_events_invocations_sum{job="aws_events",instance="",event_bus_name="***-staging",rule_name="***_WsConnectionEstablished-staging",} 2.0 1689598980000 aws_events_invocations_sum{job="aws_events",instance="",event_bus_name="***-prod",rule_name="***_ReminderTimeReached-prod",} 2.0 1689598740000 aws_events_invocations_sum{job="aws_events",instance="",event_bus_name="***-prod",rule_name="***_PushNotificationEvent-prod",} 2.0 1689598740000
[/simterm]
Є, чудово.
Тепер нам треба налаштувати VMAgent, щоб він почав збирати ці метрики з цього експортеру.
Збір метрик з експортерів: VMAgent && scrape_configs
Звична з Kube Prometheus Stack схема – це просто включити servicemonitor.enabled=true
в вальюсах чарту експотера, і Prometheus Operator створить ServiceMonitor та почне збирати метрики.
Проте з VictoriaMetrics це не спрацює, бо ServiceMonitor CRD є частиною kube-prometheus-stack, і ресурс ServiceMonitor просто не буде створено.
Натомість у VictoriaMetrics є власний аналог – VMServiceScrape, який можна створити з маніфесту, і йому вказати з якого ендпоінту збирати метрики. До того ж, VictoriaMetrics вміє створювати VMServiceScrape з існуючих ServiceMonitor, але це потребує установки самого ServiceMonitor CRD.
Також ми можемо передати список таргетів через inlineScrapeConfig
або additionalScrapeConfigs
, див. VMAgentSpec
.
Скоріш за все, у нас поки що буде inlineScrapeConfig
, бо конфіг не надто великий.
Ще цікаво взагалі глянути VMAgent values.yaml – наприклад, там є дефолтні scrape_configs
.
Ще один нюанс, которий треба мати на увазі – VMAgent не перевіряє конфіги таргетів, тобто якщо є помилка в YAML – то VMAgent просто ігнорує зміни, і не перезавантажує файл, при цьому в лог нічого не пише.
VMServiceScrape
Спочатку створимо VMServiceScrape вручну, щоб подивитись як воно взагалі працює.
Перевіряємо лейбли у CloudWatch Exporter Service:
[simterm]
$ kk -n dev-monitoring-ns describe svc atlas-victoriametrics-prometheus-cloudwatch-exporter Name: atlas-victoriametrics-prometheus-cloudwatch-exporter Namespace: dev-monitoring-ns Labels: app=prometheus-cloudwatch-exporter app.kubernetes.io/managed-by=Helm chart=prometheus-cloudwatch-exporter-0.25.1 heritage=Helm release=atlas-victoriametrics ...
[/simterm]
Описуємо VMServiceScrape з matchLabels
, де вказуємо лейбли сервісу експортера:
apiVersion: operator.victoriametrics.com/v1beta1 kind: VMServiceScrape metadata: name: prometheus-cloudwatch-exporter-vm-scrape namespace: dev-monitoring-ns spec: selector: matchLabels: app: prometheus-cloudwatch-exporter endpoints: - port: http
Деплоїмо:
[simterm]
$ kubectl apply -f vmsvcscrape.yaml vmservicescrape.operator.victoriametrics.com/prometheus-cloudwatch-exporter-vm-scrape created
[/simterm]
Перевіряємо всі vmservicescrape
– тут вже є пачка дефолтних, які створив сам VictoriaMetrics Operator:
[simterm]
$ kk -n dev-monitoring-ns get vmservicescrape NAME AGE prometheus-cloudwatch-exporter-vm-scrape 6m45s vm-k8s-stack-apiserver 4d22h vm-k8s-stack-coredns 4d22h vm-k8s-stack-grafana 4d22h vm-k8s-stack-kube-controller-manager 4d22h ...
[/simterm]
Конфіг VMAgent створюється в поді у файл /etc/vmagent/config_out/vmagent.env.yaml
.
Глянемо, чи додався там наш CloudWatch Exporter:
[simterm]
$ kk -n dev-monitoring-ns exec -ti vmagent-vm-k8s-stack-98d7678d4-cn8qd -c vmagent -- cat /etc/vmagent/config_out/vmagent.env.yaml global: scrape_interval: 25s external_labels: cluster: eks-dev-1-26-cluster prometheus: dev-monitoring-ns/vm-k8s-stack scrape_configs: - job_name: serviceScrape/dev-monitoring-ns/prometheus-cloudwatch-exporter-vm-scrape/0 honor_labels: false kubernetes_sd_configs: - role: endpoints namespaces: names: - dev-monitoring-ns ...
[/simterm]
І тепер маємо побачити метрики в самій VictoriaMetrics.
Відкриваємо порт:
[simterm]
$ kk -n dev-monitoring-ns port-forward svc/vmsingle-vm-k8s-stack 8429
[/simterm]
В браузері заходимо на http://localhost:8429/vmui/ і для перевірки робимо запит на будь-яку метрику від CloudWatch Exporter:
Добре – побачили, як вручну створити VMServiceScrape. Але що там з автоматизацією цього процесу? Бо якось не дуже хочеться через Kustomize свторювати VMServiceScrape для кожного сервісу.
VMServiceScrape з ServiceMonitor та VictoriaMetrics Prometheus Converter
Тож як вже писалось, для того, щоб в кластері створився об’єкт ServiceMonitor нам потрібен Custom Resource Definition з ServiceMonitor.
Можемо встановити його прямо з маніфесту в репозиторії kube-prometheus-stack
:
[simterm]
$ kubectl apply -fhttps://raw.githubusercontent.com/prometheus-community/helm-charts/main/charts/kube-prometheus-stack/charts/crds/crds/crd-servicemonitors.yaml customresourcedefinition.apiextensions.k8s.io/servicemonitors.monitoring.coreos.com created
[/simterm]
Оновлюмо наш values
– додаємо serviceMonitorenabled=true
:
... prometheus-cloudwatch-exporter: serviceAccount: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::492***148:role/atlas-monitoring-dev-CloudwatchExporterRole0613A27-EU5LW9XRWVRL eks.amazonaws.com/sts-regional-endpoints: "true" serviceMonitor: enabled: true ...
І у вальюсах victoria-metrics-k8s-stack
додаємо параметр operator.disable_prometheus_converter=false
:
victoria-metrics-k8s-stack: fullnameOverride: "vm-k8s-stack" # no need yet victoria-metrics-operator: serviceAccount: create: true operator: disable_prometheus_converter: false ...
Деплоїмо та перевіряємо, чи створено servicemonitor
:
[simterm]
$ kk -n dev-monitoring-ns get servicemonitors NAME AGE atlas-victoriametrics-prometheus-cloudwatch-exporter 2m22s
[/simterm]
І автоматом мав з’явитись vmservicescrape
:
[simterm]
$ kk -n dev-monitoring-ns get vmservicescrape NAME AGE atlas-victoriametrics-prometheus-cloudwatch-exporter 2m11s ...
[/simterm]
Глянемо targets
:
Все є.
Єдиний тут нюанс в тому, что при видалені ServiceMonitor – відповідний vmservicescrape
залишиться. Плюс сама необхідність в становленні стороннього CRD, який з часом треба буде якось оновлювати, бажано автоматично.
inlineScrapeConfig
Найбільш мабуть простий варіант – це описати конфіг через inlineScrapeConfig
прямо в values
нашого чарту:
... vmagent: enabled: true spec: externalLabels: cluster: "eks-dev-1-26-cluster" inlineScrapeConfig: | - job_name: cloudwatch-exporter-inline-job metrics_path: /metrics static_configs: - targets: ["atlas-victoriametrics-prometheus-cloudwatch-exporter:9106"] ...
Деплоймо і перевіряємо сам vmagent
:
[simterm]
$ kk -n dev-monitoring-ns get vmagent -o yaml apiVersion: v1 items: - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMAgent ... inlineScrapeConfig: | - job_name: cloudwatch-exporter-inline-job metrics_path: /metrics static_configs: - targets: ["atlas-victoriametrics-prometheus-cloudwatch-exporter:9106"] ...
[/simterm]
Ще раз глянемо таргети:
additionalScrapeConfigs
Більш безпечний варіант, якщо в параметрах є якісь токени/ключі доступу, але потребує створення окремого об’єкту Kubernetes Secret.
В принципі не проблема, бо ConfigMaps/Secrets все одно доведеться створювати, і якщо захочется винести конфіг таргетів окремим файлом – то, скоріш за все, перероблю на additionalScrapeConfigs
.
Зараз створимо вручну, просто глянути як воно буде працювати – беремо приклад прямо з документації:
apiVersion: v1 kind: Secret metadata: name: additional-scrape-configs stringData: prometheus-additional.yaml: | - job_name: cloudwatch-exporter-secret-job metrics_path: /metrics static_configs: - targets: ["atlas-victoriametrics-prometheus-cloudwatch-exporter:9106"]
Не забуваємо його задеплоїти 🙂
[simterm]
$ kubectl -n dev-monitoring-ns apply -f vmagent-targets-secret.yaml secret/additional-scrape-configs created
[/simterm]
Оновлюємо вальюси VMAgent – додаємо блок additionalScrapeConfigs
:
... vmagent: enabled: true spec: externalLabels: cluster: "eks-dev-1-26-cluster" additionalScrapeConfigs: name: additional-scrape-configs key: prometheus-additional.yaml inlineScrapeConfig: | - job_name: cloudwatch-exporter-inline-job metrics_path: /metrics static_configs: - targets: ["atlas-victoriametrics-prometheus-cloudwatch-exporter:9106"] ...
Оновлюємо деплой, та перевіряємо таргети:
Тепер, як маємо метрики – можемо переходити до Grafana.
Grafana provisioning
Що нам треба для Grafana? Плагіни, датасорси та дашборди.
Спершу додамо Data Sources, див. документацію.
Підключення Data Sources && Plugins
Якщо з дашбордами все більш-менш просто, то з Data Sources є питання: як в них передавати якісь секрети? Наприклад – для датасорсу Sentry треба задати токен, який в вальюсах чарту світити зовсім не хочеться, бо дані в GitHub ми не шифруємо, хоч репозиторії і приватні (див. git-crypt
– на минулому проекті був, в приципі робоче рішення).
Давайте спершу поглянемо як воно працює взагалі, потім подумаємо, як нам передати токен.
Будемо додавати Senrty Data Source, див. grafana-sentry-datasource
. Токен вже маємо – створено в sentry.io > User settings > User Auth Tokens.
В вальюси Grafana додаємо plugins
, де вказуємо ім’я плагіну grafana-sentry-datasource
(значення поля type
в документації вище) і описуємо блок additionalDataSources
з полем secureJsonData
, в якому вказуємо сам токен:
... grafana: enabled: true ingress: enabled: true annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/scheme: internet-facing hosts: - monitoring.dev.example.co plugins: - grafana-sentry-datasource additionalDataSources: - name: Sentry type: grafana-sentry-datasource access: proxy orgId: 1 version: 1 editable: true jsonData: url: https://sentry.io orgSlug: *** secureJsonData: authToken: 974***56b ...
Деплоїмо, перевіряємо плагін:
Та Data Source:
Окей, це працює.
Токен для Data Source через envFromSecret
Тепер спробуємо через змінну, значення для якої отримаємо з Kubernetes Secret за допомогою envFromSecret
.
Створимо Secret:
--- apiVersion: v1 kind: Secret metadata: name: grafana-datasource-sentry-token stringData: SENTRY_TOKEN: 974***56b
Оновлюємо вальюси Grafana – додаємо envFromSecret
, за допомогою якого отримаємо $SENTRY_TOKEN
, та використовуємо його у additionalDataSources
:
... grafana: ... envFromSecret: grafana-datasource-sentry-token additionalDataSources: - name: Sentry type: grafana-sentry-datasource access: proxy orgId: 1 version: 1 editable: true jsonData: url: https://sentry.io orgSlug: *** secureJsonData: authToken: ${SENTRY_TOKEN} ...
Деплоїмо, і перевіряємо змінну в поді Grafana:
[simterm]
$ kk -n dev-monitoring-ns exec -ti atlas-victoriametrics-grafana-64d9db677-g7l25 -c grafana -- printenv | grep SENTRY_TOKEN SENTRY_TOKEN=974***56b
[/simterm]
Перевіряємо конфіг датасорсів:
[simterm]
$ kk -n dev-monitoring-ns exec -ti atlas-victoriametrics-grafana-64d9db677-bpkw8 -c grafana -- cat /etc/grafana/provisioning/datasources/datasource.yaml ... apiVersion: 1 datasources: - name: VictoriaMetrics type: prometheus url: http://vmsingle-vm-k8s-stack.dev-monitoring-ns.svc:8429/ access: proxy isDefault: true jsonData: {} - access: proxy editable: true jsonData: orgSlug: *** url: https://sentry.io name: Sentry orgId: 1 secureJsonData: authToken: ${SENTRY_TOKEN} type: grafana-sentry-datasource version: 1
[/simterm]
І ще раз тестуємо датасорс:
Тож при такому підході ми можемо використати AWS Secrets and Configuration Provider (ASCP) (див. AWS: Kubernetes – інтеграція AWS Secrets Manager та Parameter Store):
- створити секрет в GitHub Actions Secrets
- при деплої AWS CDK взяти значення у змінну через
os.env("SECRET_NAME_VAR")
і створити секрет в AWS Secrets Manager - в
templates
нашого чарту створитиSecretProviderClass
з полемsecretObjects.secretName
для створення Kubernetes Secret
При запуску поду з Grafana вона цей секрет підключить до поду:
[simterm]
$ kk -n dev-monitoring-ns get pod atlas-victoriametrics-grafana-64d9db677-dlqfr -o yaml ... envFrom: - secretRef: name: grafana-datasource-sentry-token ...
[/simterm]
І передасть значення до самої Grafana.
Окей, це може працювати, хоча виглядає трохи заплутано.
Але є ще один варіант – з sidecar.datasources
.
Kubernetes Secret для всього Data Source і sidecar.datasources
Є другий варіант – створювати дата-сорси через sidecar container: можемо створити Kubernetes Secret з потрібною labels
, і в цьому сікреті додати датасорс. Див. Sidecar for datasources
В принципі – цілком робоча схема: створити маніфест секрету в каталозі templates
, і при виклику helm install
в GitHub Actions передати значення з --set
, а значення взяти з GitHub Actions Secrets. І виглядає простішою. Спробуємо.
У файлу templates/grafana-datasources-secret.yaml
описуємо Kubernetes Secret:
apiVersion: v1 kind: Secret metadata: name: grafana-datasources labels: grafana_datasource: 'true' stringData: sentry.yaml: |- apiVersion: 1 datasources: - name: Sentry type: grafana-sentry-datasource access: proxy orgId: 1 version: 1 editable: true jsonData: url: https://sentry.io orgSlug: *** secureJsonData: authToken: {{ .Values.grafana.sentry_token }}
Деплоїмо з --set
:
[simterm]
$ helm -n dev-monitoring-ns upgrade --install atlas-victoriametrics . -f values/dev/atlas-monitoring-dev-values.yaml --set grafana.sentry_token="974***56b"
[/simterm]
Перевіряємо конфіги датасорсів в поді Grafana:
[simterm]
$ kk -n dev-monitoring-ns exec -ti atlas-victoriametrics-grafana-5967b494f6-5zmjb -c grafana -- ls -l /etc/grafana/provisioning/datasources total 8 -rw-r--r-- 1 grafana 472 187 Jul 19 13:36 datasource.yaml -rw-r--r-- 1 grafana 472 320 Jul 19 13:36 sentry.yaml
[/simterm]
Зміст файлу sentry.yaml
:
[simterm]
$ kk -n dev-monitoring-ns exec -ti atlas-victoriametrics-grafana-5967b494f6-5zmjb -c grafana -- cat /etc/grafana/provisioning/datasources/sentry.yaml apiVersion: 1 datasources: - name: Sentry type: grafana-sentry-datasource access: proxy orgId: 1 version: 1 editable: true jsonData: url: https://sentry.io orgSlug: *** secureJsonData: authToken: 974***56b
[/simterm]
І ще раз датасорс в самій Grafana:
It’s a magic!
Підключення Dashboards
Отже, ми вже маємо Графану, і там є дашборди, які нам треба перенести в новий стек моніторингу, і деплоїти з GitHub-репозиторію.
Документація по імпорту дашборд – Import dashboards.
Для створення дашборд через Helm-чарт маємо аналогічний до grafana-sc-datasources
сайдкар-контейнер grafana-sc-dashboard
, який буде перевіряти всі ConfigMaps з лейблою, і підключати їх до поду. Див. Sidecar for dashboards.
Майте на увазі рекомендацію:
A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside one configmap is currently not properly mirrored in grafana.
Тобто – один ConfigMap на кожну дашборду.
Тож що нам треба зробити – це описати ConfigMap для кожної дашборди, і Grafana сама додасть їх до /tmp/dashboards
.
Експорт існуючої dashboard та Data Source UID not found
Щоб уникнути помилки з UID (“Failed to retrieve datasource Datasource f0f2c234-f0e6-4b6c-8ed1-01813daa84c9 was not found”) – йдемо до дашборди в існуючому інстансі Grafana, і додаємо нову змінну з типом Data Source:
Повторюємо для Loki, Sentry:
Та оновлюємо панелі – задаємо датасорс зі змінної:
Повторюємо теж саме для всіх запитів у Annotations та Variables:
Створюємо каталог для файлів, які потім будемо імпортити в Kubernetes:
[simterm]
$ mkdir -p grafana/dashboards/
[/simterm]
Та робимо Export дашборди в JSON і зберігаємо як grafana/dashboards/overview.json
:
Dashboard ConfigMap
В каталозі templates
створюємо маніфест для ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: overview-dashboard labels: grafana_dashboard: "1" data: overview.json: | {{ .Files.Get "grafana/dashboards/overview.json" | indent 4 }}
Тепер всі файли нашого проекту виглядають так:
Деплоїмо чарт та перевіряємо ConfigMap:
[simterm]
$ kk -n dev-monitoring-ns get cm overview-dashboard -o yaml | head apiVersion: v1 data: overview.json: | { "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "grafana",
[/simterm]
І перевіряємо в поді – чи додався файл до /tmp/dashboards
:
[simterm]
$ kubectl -n dev-monitoring-ns exec -ti atlas-victoriametrics-grafana-5967b494f6-gs4jm -c grafana -- ls -l /tmp/dashboards total 1032 ... -rw-r--r-- 1 grafana 472 74821 Jul 19 10:31 overview.json ...
[/simterm]
Та в самій Grafana:
І маємо наши графіки – поки не всі, бо запущено тільки один експортер:
Поїхали далі.
Що нам залишилось?
- GitHub exporter – зробити чарт, додати до загального чарту (чи просто створити маніфест з Deployment? там один под, нічного більше йому не треба)
- Loki
- алерти
GitHub exporter мабуть таки просто з Deployment зроблю – маніфест у templates
основного чарту, та й все – окремий чарт там не потрібен. Тут описувати не буду, бо це просто.
Тож давайте тоді зараз загадаємо, як там запускається Loki, бо коли робив це восени – то було трохи геморно. Сподіваюсь, нічого особливо не змінилося, і зможу просто взяти конфіг з Grafana Loki: архітектура та запуск в Kubernetes з AWS S3 storage та boltdb-shipper.
Запуск Grafana Loki з AWS S3
Що нам тут треба?
- створити S3
- IAM Policy && IAM Role для доступу до бакету
- ConfigMap з конфігом Loki
- додати чарт Loki сабчартом нашого основного чарту
AWS CDK для S3 та IAM Role
S3 та IAM описуємо з AWS CDK:
... ################################## ### Grafana Loki AWS resources ### ################################## ### AWS S3 to store logs data and indexes loki_bucket_name = f"{environment}-grafana-loki" bucket = s3.Bucket( self, 'GrafanaLokiBucket', bucket_name=loki_bucket_name, block_public_access=s3.BlockPublicAccess.BLOCK_ALL ) # Create an IAM Role to be assumed by Loki grafana_loki_role = iam.Role( self, 'GrafanaLokiRole', # for Role's Trust relationships assumed_by=iam.FederatedPrincipal( federated=oidc_provider_arn, conditions={ 'StringEquals': { f'{oidc_provider_url.replace("https://", "")}:sub': f'system:serviceaccount:{monitoring_namespace}:loki' } }, assume_role_action='sts:AssumeRoleWithWebIdentity' ) ) # Attach an IAM Policies to that Role grafana_loki_policy = iam.PolicyStatement( actions=[ "s3:ListBucket", "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], resources=[ f"arn:aws:s3:::{loki_bucket_name}", f"arn:aws:s3:::{loki_bucket_name}/*" ] ) grafana_loki_role.add_to_policy(grafana_loki_policy) ... CfnOutput( self, 'GrafanaLokiRoleArn', value=grafana_loki_role.role_arn ) ...
Деплоїмо:
[simterm]
$ cdk deploy atlas-monitoring-dev ... Outputs: atlas-monitoring-dev.CloudwatchExporterRoleArn = arn:aws:iam::492***148:role/atlas-monitoring-dev-CloudwatchExporterRole0613A27-EU5LW9XRWVRL atlas-monitoring-dev.GrafanaLokiRoleArn = arn:aws:iam::492***148:role/atlas-monitoring-dev-GrafanaLokiRole27EECE19-1HLODQFKFLDNK ...
[/simterm]
Можемо додавати чарт.
Деплой Loki Helm chart
Додаємо репозиторій, шукаємо останню версію чарту:
[simterm]
$ helm repo add grafana https://grafana.github.io/helm-charts $ helm search repo grafana/loki NAME CHART VERSION APP VERSION DESCRIPTION grafana/loki 5.8.9 2.8.2 Helm chart for Grafana Loki in simple, scalable... grafana/loki-canary 0.12.0 2.8.2 Helm chart for Grafana Loki Canary grafana/loki-distributed 0.69.16 2.8.2 Helm chart for Grafana Loki in microservices mode grafana/loki-simple-scalable 1.8.11 2.6.1 Helm chart for Grafana Loki in simple, scalable... grafana/loki-stack 2.9.10 v2.6.1 Loki: like Prometheus, but for logs.
[/simterm]
Тут знов купа чартів, коротко:
loki-canary
: система для аудіту роботи самої Lokiloki-distributed
: Loki у microservices modesimple-scalable
: deprecated, тепер це просто lokiloki-stack
: тут відразу все – Grafana, Promtail, etc
Ми візьмемо grafana/loki 5.8.9
. Додаємо в залежності нашого чарту у Chart.yaml
:
apiVersion: v2 name: atlas-victoriametrics description: A Helm chart for Atlas Victoria Metrics kubernetes monitoring stack type: application version: 0.1.0 appVersion: "1.16.0" dependencies: - name: victoria-metrics-k8s-stack version: ~0.17.0 repository: https://victoriametrics.github.io/helm-charts/ - name: prometheus-cloudwatch-exporter version: ~0.25.1 repository: https://prometheus-community.github.io/helm-charts - name: loki version: ~5.8.9 repository: https://grafana.github.io/helm-charts
Всі дефолтні values – тут>>>, я брав зі свого старого конфігу – все завелося:
... loki: loki: auth_enabled: false commonConfig: path_prefix: /var/loki replication_factor: 1 storage: bucketNames: chunks: dev-grafana-loki type: s3 schema_config: configs: - from: "2023-07-20" index: period: 24h prefix: loki_index_ store: boltdb-shipper object_store: s3 schema: v12 storage_config: aws: s3: s3://us-east-1/dev-grafana-loki insecure: false s3forcepathstyle: true boltdb_shipper: active_index_directory: /var/loki/index shared_store: s3 rulerConfig: storage: type: local local: directory: /var/loki/rules serviceAccount: create: true annotations: eks.amazonaws.com/role-arn: "arn:aws:iam::492***148:role/atlas-monitoring-dev-GrafanaLokiRole27EECE19-1HLODQFKFLDNK" write: replicas: 1 read: replicas: 1 backend: replicas: 1 test: enabled: false monitoring: dashboards: enabled: false rules: enabled: false alerts: enabled: false serviceMonitor: enabled: false selfMonitoring: enabled: false grafanaAgent: installOperator: false lokiCanary: enabled: false ...
Ще треба буде прикрутити алерти Loki, але це вже окремо (див. Grafana Loki: алерти з Ruler та labels з логів)
Деплой Promtail Helm chart
Запустимо в кластері Promtail, щоб по-перше перевірити роботу Loki, по-друге – всеж мати логи з кластеру.
Знаходимо версії чарта:
[simterm]
$ helm search repo grafana/promtail -l | head NAME CHART VERSION APP VERSION DESCRIPTION grafana/promtail 6.11.7 2.8.2 Promtail is an agent which ships the contents o... grafana/promtail 6.11.6 2.8.2 Promtail is an agent which ships the contents o... grafana/promtail 6.11.5 2.8.2 Promtail is an agent which ships the contents o... ...
[/simterm]
Додаємо сабчарт в dependencies
в нашому Chart.yaml
:
apiVersion: v2 name: atlas-victoriametrics description: A Helm chart for Atlas Victoria Metrics kubernetes monitoring stack type: application version: 0.1.0 appVersion: "1.16.0" dependencies: - name: victoria-metrics-k8s-stack version: ~0.17.0 repository: https://victoriametrics.github.io/helm-charts/ - name: prometheus-cloudwatch-exporter version: ~0.25.1 repository: https://prometheus-community.github.io/helm-charts - name: loki version: ~5.8.9 repository: https://grafana.github.io/helm-charts - name: promtail version: ~6.11.7 repository: https://grafana.github.io/helm-charts
Знаходимо Service для Loki:
[simterm]
$ kk -n dev-monitoring-ns get svc | grep loki-gateway loki-gateway ClusterIP 172.20.102.186 <none> 80/TCP 160m
[/simterm]
Додаємо вальюси для Promtail:
... promtail: loki: serviceName: "loki-gateway"
Деплоїмо, перевіряємо поди:
[simterm]
$ kk -n dev-monitoring-ns get pod | grep 'loki\|promtail' atlas-victoriametrics-promtail-cxwpz 0/1 Running 0 17m atlas-victoriametrics-promtail-hv94f 1/1 Running 0 17m loki-backend-0 0/1 Running 0 9m55s loki-gateway-749dcc85b6-5d26n 1/1 Running 0 3h4m loki-read-6cf6bc7654-df82j 1/1 Running 0 57s loki-write-0 0/1 Running 0 52s
[/simterm]
Додаємо Grafana Data Source через additionalDataSources
(див. Provision the data source):
... grafana: enabled: true ... additionalDataSources: - name: Loki type: loki access: proxy url: http://loki-gateway:80 jsonData: maxLines: 1000 ...
Деплоїмо, перевіряємо датасорси:
Та логи:
Тепер давайте глянемо, як там з алертами.
Налаштування алертів з VMAlert
Сам VMAlert && Alertmanager вже маємо з чарту, див. values – vmalert
та alertmanager
:
[simterm]
$ kk -n dev-monitoring-ns get pod | grep alert vmalert-vm-k8s-stack-dff5bf755-57rxd 2/2 Running 0 6d19h vmalertmanager-vm-k8s-stack-0 2/2 Running 0 6d19h
[/simterm]
Спочатку глянемо як конфігуриться Alertmanager, бо алерти будуть відправлятись через нього.
Конфігурація Alertmanager
Документація – VMAlertmanagerSpec.
Глянемо, де його конфіг:
[simterm]
$ kk -n dev-monitoring-ns describe pod vmalertmanager-vm-k8s-stack-0 ... Args: .... --config.file=/etc/alertmanager/config/alertmanager.yaml ... Mounts: ... /etc/alertmanager/config from config-volume (rw) ... Volumes: config-volume: Type: Secret (a volume populated by a Secret) SecretName: vmalertmanager-vm-k8s-stack-config ...
[/simterm]
Тобто файл /etc/alertmanager/config/alertmanager.yaml
береться з Kubernetes Secret vmalertmanager-vm-k8s-stack-config
:
[simterm]
$ kk -n dev-monitoring-ns get secret vmalertmanager-vm-k8s-stack-config -o yaml | yq '.data' { "alertmanager.yaml": "Z2x***GwK" }
[/simterm]
Перевіряємо зміст з base64 -d
або на сайті www.base64decode.org.
Тепер давайте додамо власний конфіг.
Тут знову ж таки треба буде подумати про секрет, бо в slack_api_url
маємо токен. Мабуть, зробимо як з Sentry-токеном – просто будемо передавати через --set
.
Оновлюємо values/dev/atlas-monitoring-dev-values.yaml
:
... alertmanager: enabled: true config: global: resolve_timeout: 5m slack_api_url: "" route: repeat_interval: 12h group_by: ["alertname"] receiver: 'slack-default' routes: [] receivers: - name: "slack-default" slack_configs: - channel: "#alerts-devops" send_resolved: true title: '{{ template "slack.monzo.title" . }}' icon_emoji: '{{ template "slack.monzo.icon_emoji" . }}' color: '{{ template "slack.monzo.color" . }}' text: '{{ template "slack.monzo.text" . }}' actions: # self - type: button text: ':grafana: overview' url: '{{ (index .Alerts 0).Annotations.grafana_url }}' - type: button text: ':grafana: Loki Logs' url: '{{ (index .Alerts 0).Annotations.logs_url }}' - type: button text: ':mag: Alert query' url: '{{ (index .Alerts 0).GeneratorURL }}' - type: button text: ':aws: AWS dashboard' url: '{{ (index .Alerts 0).Annotations.aws_dashboard_url }}' - type: button text: ':aws-cloudwatch: AWS CloudWatch Metrics' url: '{{ (index .Alerts 0).Annotations.aws_cloudwatch_url }}' - type: button text: ':aws-cloudwatch: AWS CloudWatch Logs' url: '{{ (index .Alerts 0).Annotations.aws_logs_url }}' ...
Хоча взагалі ми маємо власний непоганий темплейт для Slack, але поки глянемо, як виглядаю цей monzo.
Деплоїмо з --set victoria-metrics-k8s-stack.alertmanager.config.global.slack_api_url=$slack_url
:
[simterm]
$ slack_url="https://hooks.slack.com/services/T02***37X" $ helm -n dev-monitoring-ns upgrade --install atlas-victoriametrics . -f values/dev/atlas-monitoring-dev-values.yaml --set grafana.sentry_token=$sentry_token --set victoria-metrics-k8s-stack.alertmanager.config.global.slack_api_url=$slack_url --debug
[/simterm]
Та перевіримо.
Знаходимо Alertmanager Service:
[simterm]
$ kk -n dev-monitoring-ns get svc | grep alert vmalert-vm-k8s-stack ClusterIP 172.20.251.179 <none> 8080/TCP 6d20h vmalertmanager-vm-k8s-stack ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 6d20h
[/simterm]
Робимо port-forward
:
[simterm]
$ kk -n dev-monitoring-ns port-forward svc/vmalertmanager-vm-k8s-stack 9093
[/simterm]
І з cRUL відправляємо алерт:
[simterm]
$ curl -H 'Content-Type: application/json' -d '[{"labels":{"alertname":"testalert"}}]' http://127.0.0.1:9093/api/v1/alerts {"status":"success"}
[/simterm]
Дивимось в Слаку:
Wait, what?)))
Окей. Воно працює, але ці темплейти меседжів в Слак мені не подобаються, краще взяти ті, що в мене вже є на старому моніторингу.
Custom Slack messages template
Зараз кастомні темплейти підключені через ConfigMap vmalertmanager-vm-k8s-stack-0
:
[simterm]
... Volumes: ... templates-vm-k8s-stack-alertmanager-monzo-tpl: Type: ConfigMap (a volume populated by a ConfigMap) Name: vm-k8s-stack-alertmanager-monzo-tpl Optional: false ...
[/simterm]
А включаються параметром monzoTemplate.enabled=true
.
Також там же маємо templateFiles
, де можемо описати власні шаблони:
... alertmanager: enabled: true monzoTemplate: enabled: false templateFiles: slack.tmpl: |- {{/* Title of the Slack alert */}} {{ define "slack.title" -}} {{ if eq .Status "firing" }} :scream: {{- else -}} :relaxed: {{- end -}} [{{ .Status | toUpper -}} {{- if eq .Status "firing" -}}:{{ .Alerts.Firing | len }} {{- end }}] {{ (index .Alerts 0).Annotations.summary }} {{ end }} {{ define "slack.text" -}} {{ range .Alerts }} {{- if .Annotations.description -}} {{- "\n\n" -}} *Description*: {{ .Annotations.description }} {{- end }} {{- end }} {{- end }} ...
Деплоїмо і перевіряємо ConfigMap, який описано у custom-templates.yaml
:
[simterm]
$ kk -n dev-monitoring-ns get cm | grep extra vm-k8s-stack-alertmanager-extra-tpl 1 2m4s
[/simterm]
Перевіряємо волюми в поді:
[simterm]
$ kk -n dev-monitoring-ns exec -ti vmalertmanager-vm-k8s-stack-0 -- ls -l /etc/vm/templates/ Defaulted container "alertmanager" out of: alertmanager, config-reloader total 0 drwxrwxrwx 3 root root 78 Jul 20 10:06 vm-k8s-stack-alertmanager-extra-tpl
[/simterm]
І чекаємо на якийсь алерт:
Тепер все красиво. Поїхали до створення власних алертів.
Алерти для VMAlert з VMRules
Документація – VMAlert.
Отже – як до VMAlert додати наші алерти?
VMAlert використовуює VMRules, які вибирає за ruleSelector
:
[simterm]
$ kk -n dev-monitoring-ns get vmrule NAME AGE vm-k8s-stack-alertmanager.rules 6d19h vm-k8s-stack-etcd 6d19h vm-k8s-stack-general.rules 6d19h vm-k8s-stack-k8s.rules 6d19h ...
[/simterm]
Тобто – можемо описати в маніфестах потрібні рули, задеплоїти – і VMAlert їх підхопить.
Глянемо сам VMAlert – він у нас зараз один, і в принципі нам цього поки вистачить:
[simterm]
$ kk -n dev-monitoring-ns get vmalert vm-k8s-stack -o yaml apiVersion: operator.victoriametrics.com/v1beta1 kind: VMAlert ... spec: datasource: url: http://vmsingle-vm-k8s-stack.dev-monitoring-ns.svc:8429/ evaluationInterval: 15s extraArgs: remoteWrite.disablePathAppend: "true" image: tag: v1.91.3 notifiers: - url: http://vmalertmanager-vm-k8s-stack.dev-monitoring-ns.svc:9093 remoteRead: url: http://vmsingle-vm-k8s-stack.dev-monitoring-ns.svc:8429/ remoteWrite: url: http://vmsingle-vm-k8s-stack.dev-monitoring-ns.svc:8429/api/v1/write resources: {} selectAllByDefault: true
[/simterm]
Спробуємо додати тестовий алерт – створюємо файл victoriametrics/templates/vmalert-vmrules-test.yaml
з kind: VMRule
:
apiVersion: operator.victoriametrics.com/v1beta1 kind: VMRule metadata: name: vmrule-test # no need now, as we have one VMAlert with selectAllByDefault #labels: # project: devops spec: groups: - name: testing-rule rules: - alert: TestAlert expr: up == 1 for: 1s labels: severity: test job: '{{ "{{" }} $labels.job }}' summary: Testing VMRule annotations: value: 'Value: {{ "{{" }} $value }}' description: 'Monitoring job {{ "{{" }} $labels.job }} failed'
Тут додаємо костиль у вигляді "{{" }}
, бо {{ }}
використовується і самим Helm, і алертами.
Деплоїмо, перевіряємо VMRule vmrule-test
:
[simterm]
$ kk -n dev-monitoring-ns get vmrule vmrule-test -o yaml apiVersion: operator.victoriametrics.com/v1beta1 kind: VMRule ... spec: groups: - name: testing-rule rules: - alert: TestAlert annotations: description: Monitoring job {{ $labels.job }} failed value: 'Value: {{ $value }}' summary: Testing VMRule expr: up == 1 for: 1s labels: job: '{{ $labels.job }}' severity: test
[/simterm]
Чекаємо на алерт у Слаку:
Все є.
В принципі, на цьому все – основні моменти наче описав.
Потім ще глянемо як там зі storage і бекапами.