В продолжение поста Kubernetes: мониторинг с Prometheus, в котором мы настроили мониторинг вручную, и более-менее разобрались с тем, как оно всё внутри работает — теперь попробуем прикрутить Prometheus Operator из Helm-репозитория.
Напомню, задача — поднять Prometheus и все необходимые експортёры в AWS Elastic Kubernetes Cluster, и с него через /federation передавать метрики на наш «центровой» Prometheus, где уже есть Alertmanager и Grafana.
Смутил целый набор чартов — есть просто Prometheus, есть kube-prometheus, есть prometheus-operator, причём от разных разработчиков:
description: Provides easy monitoring definitions for Kubernetes services, and deployment
and management of Prometheus instances.
name: stable/prometheus-operator
version: 8.14.0
Разница между stable/prometheus и stable/prometheus-operator в том, что в Operator включена Grafana с набором готовых дашборд и набор ServiceMonitors для сбора метрик с сервисов кластера, таких как CoreDNS, API Server, Scheduler, etc.
HELP redis_up Information about the Redis instance
TYPE redis_up gauge
redis_up 1
HELP redis_uptime_in_seconds uptime_in_seconds metric
TYPE redis_uptime_in_seconds gauge
redis_uptime_in_seconds 2793
Либо без дополнительного пода — делаем port-forward на redis-svc:
kk -n monitoring port-forward svc/redis-exporter-prometheus-redis-exporter 9121:9121
Forwarding from 127.0.0.1:9121 -> 9121
Forwarding from [::1]:9121 -> 9121
И проверяем с локальной машины:
curl localhost:9121/metrics
...
redis_up 1
HELP redis_uptime_in_seconds uptime_in_seconds metric
TYPE redis_uptime_in_seconds gauge
redis_uptime_in_seconds 8818
Хорошо — у нас есть приложение — Редис, есть его експортёр, который отдаёт нам метрики на порту 9121 по URI /metrics — теперь надо настроить Prometheus Operator на сбор метрик с него.
Создание Kubernetes ServiceMonitor
Проверим лейблы нашего redis_exporter:
kk -n monitoring get deploy redis-exporter-prometheus-redis-exporter -o yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
...
generation: 1
labels:
app: prometheus-redis-exporter
app.kubernetes.io/managed-by: Helm
chart: prometheus-redis-exporter-3.4.1
heritage: Helm
release: redis-exporter
...
И ещё раз глянем селектор serviceMonitorSelector ресурса prometheus:
В его labels задаём release: prometheus, что бы Prometheus его обнаружил, а в selector.matchLabels — указываем поиск сервисов с тегом release: redis-exporter.
Применяем:
kk -n monitoring apply -f redis-service-monitor.yaml
servicemonitor.monitoring.coreos.com/redis-servicemonitor created
И проверяем таргеты Prometheus:
Метрики Редиса:
Что надо дальше?
А дальше надо выпилить из Operator запуск Alertmanager и Grafana.
Prometheus Operator Helm deployment и конфигурация сервисов
Хотя — а зачем выпиливать Графану? Там уже есть пачка готовых дашборд — пусть остаётся.
Давайте сделаем иначе:
на каждый EKS кластер выкатываем Operator с Grafana, но без Alertmanager
на локальных кластеру Prometheus retention period для хранения метрик используем дефолтный — 2 недели, и локальные Grafana будут выводить графики за две недели
Alertmanager выпиливаем — будем использовать его с центрального сервера мониторинга — там уже настроены роуты, каналы, и прочее — надо будет только добавить алерты
центральный сервер мониторинга хранит метрики год, и там нарисуем свою дашборду(ы) Grafana
Значит надо будет создать два LoadBalancer — один с типом internet-facing для Grafana, и один для Prometheus — internal, т.к. к Prometheus в кластере будет ходить «центральный» Prometheus через AWS VPC Peering, и с /federation забирать у него метрики.
Error: UPGRADE FAILED: failed to create resource: Ingress.extensions "prometheus-grafana" is invalid: spec: Invalid value: []networking.IngressRule(nil): either `backend` or `rules` must be specified
Эм…
Думаете — в документации указано как его настроить? Счас…
I0617 11:37:48.272749 1 tags.go:43] monitoring/prometheus-grafana: modifying tags { ingress.k8s.aws/cluster: «bttrm-eks-dev-0», ingress.k8s.aws/stack: «monitoring/prometheus-grafana», kubernetes.io/service-name: «prometheus-grafa
na», kubernetes.io/service-port: «80», ingress.k8s.aws/resource: «monitoring/prometheus-grafana-prometheus-grafana:80», kubernetes.io/cluster/bttrm-eks-dev-0: «owned», kubernetes.io/namespace: «monitoring», kubernetes.io/ingress-name
: «prometheus-grafana»} on arn:aws:elasticloadbalancing:us-east-2:534***385:targetgroup/96759da8-e0b8253ac04c7ceacd7/35de144cca011059
E0617 11:37:48.310083 1 controller.go:217] kubebuilder/controller «msg»=»Reconciler error» «error»=»failed to reconcile targetGroups due to failed to reconcile targetGroup targets due to prometheus-grafana service is not of type NodePort or LoadBalancer and target-type is instance» «controller»=»alb-ingress-controller» «request»={«Namespace»:»monitoring»,»Name»:»prometheus-grafana»}
Хорошо — давайте добавим /target-type: "ip", что бы AWS ALB слал трафик прямо на под с Grafana, а не на WorkerNodes, заодно добавим валидные коды ответов:
Но теперь при открытии страницы dev-0.eks.monitor.example.com — ALB отдаёт 404:
curl -vL dev-0.eks.monitor.example.com
* Trying 3.***.***.247:80...
* Connected to dev-0.eks.monitor.example.com (3.***.***.247) port 80 (#0)
> GET / HTTP/1.1
> Host: dev-0.eks.monitor.example.com
> User-Agent: curl/7.70.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
...
< Location: /login
...
* Connection #0 to host dev-0.eks.monitor.example.com left intact
* Issue another request to this URL: 'http://dev-0.eks.monitor.example.com/login'
...
> GET /login HTTP/1.1
...
< HTTP/1.1 404 Not Found
< Server: awselb/2.0
Что тут происходит?
ALB принимает запрос к dev-0.eks.monitor.example.com, отправляет его на TargetGroup с Grafana
Grafana возвращает 302 /login
мы возвращаемся к ALB, но теперь в URI передаём /login
Проверяем правила Listener:
Ну, да — а в правилах балансера на все запросы кроме / мы возвращаем 404. Соответсвенно, и на /login тоже возвращается 404.
Очень хотелось бы увидеть комментарии разработчика, который дефолтным рулом path задал именно такое.
Возвращаемся к нашему values.yaml, добавляем path равным /*.
А hosts, что бы избежать ошибки «Invalid value: []networking.IngressRule(nil): either `backend` or `rules` must be specified» и не привязываться к конкретному домену можно задать просто в виде "":
И даже в Lens появились все графики вместо ошибок «Metrics are not available due to missing or invalid Prometheus configuration» и «Metrics not available at the moment«:
В целом — на этом, думаю, всё основное рассмотрели.
Можно прикручивать автоматизацию, и выкатывать в тестирование.