Маємо на проекті багато AWS Lambda функцій, з яких девелопери хочуть мати можливість відправляти метрики до нашого Prometheus, щоб додати власних алертів та графіків у Grafana.
Для цього у функціях використовується бібліотека Prometheus, яка дозволяє ці метрики створювати (див. Prometheus: створення Custom Prometheus Exporter на Python), але ж ми не маємо змоги нормально отримати ці дані з Prometheus, бо функції можуть жити декілька секунд, а Prometheus використовує PULL-модель, тобто він сам ходить до експортерів, та витягує звідти дані.
Що можемо зробити у випадку AWS Lambda – це додати Prometheus Pushgateway, який буде мати зовнішній ендпоінт, на який функції будуть слати свої метрики, а Prometheus буде забирати ці дані з Pushgateway, який виконує таку собі “проксі роль”.
Загальна схема роботи Prometheus та роль Pushgateway добре відображена на цій схемі:
Тож сьогодні запустимо Prometheus Pushgateway у Kubernetes використовуючи Helm-чарт, а чарт будемо встановлювати за допомогою Terraform.
Зміст
Pushgateway Helm chart
Спочатку, давайте подивимося, що у нас є у values чарту Pushgateway.
По факту, наразі нам тут можуть бути цікавими тільки два параметри – це Ingress та ServiceMonitor.
Напишемо свій values, для тесту задеплоїмо на Dev оточення, а потім додамо до Terraform, через який Pushgateway вже буде деплоїтися по всіх наших моніторинг-оточеннях:
ingress: enabled: true className: alb path: / pathType: Prefix annotations: alb.ingress.kubernetes.io/scheme: internal alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:638***021:certificate/e97f17e9-33f9-46e7-9b2b-d50de8a72219 alb.ingress.kubernetes.io/target-type: ip hosts: - test-pushgateway.monitoring.dev.example.com serviceMonitor: enabled: true namespace: monitoring additionalLabels: release: prometheus
Тут описуємо створення Kubernetes Ingress, якому на порт 443 відповідного AWS Application Load Balancer підключимо SSL сертифікат з Amazon Certificate Manager. В hosts
задаємо ім’я хоста, яке за допомогою ExternalDNS буде створено в AWS Route53.
І додаємо ServiceMonitor з лейблою release: prometheus
, щоб Prometheus із Kube Prometheus Stack його побачив.
Додаємо репозиторій Prometheus:
[simterm]
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts $ helm repo update
[/simterm]
І встановлюємо Pushgateway до неймспейсу monitoring
:
[simterm]
$ helm -n monitoring upgrade --install prometheus-pushgateway-test prometheus-community/prometheus-pushgateway -f pushgateway-values-dev.yaml ... NOTES: 1. Get the application URL by running these commands: http://test-pushgateway.monitoring.example.com/
[/simterm]
Перевіряємо Pod та Ingress:
[simterm]
$ kubectl get pod,ingress --namespace monitoring -l app.kubernetes.io/instance=prometheus-pushgateway-test NAME READY STATUS RESTARTS AGE pod/prometheus-pushgateway-test-6b5dfbdd7f-chzkf 1/1 Running 0 53s NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/prometheus-pushgateway-test alb test-pushgateway.monitoring.dev.example.com internal-k8s-monitori-promethe-***-***.us-west-2.elb.amazonaws.com 80 54s
[/simterm]
Pushgateway має власний веб-інтерфейс – відкриваємо доступ до його поду на порт 9091:
[simterm]
$ kubectl -n monitoring port-forward pod/prometheus-pushgateway-test-6b5dfbdd7f-chzkf 9091 Forwarding from 127.0.0.1:9091 -> 9091 Forwarding from [::1]:9091 -> 9091
[/simterm]
Та в браузері переходимо на http://localhost:9091:
Далі, перевіримо чи бачить сам Prometheus цей Pushgateway – відкриваємо порт 9090 до Prometheus Pod:
[simterm]
$ kk -n monitoring port-forward prometheus-prometheus-kube-prometheus-prometheus-0 9090 Forwarding from 127.0.0.1:9090 -> 9090 Forwarding from [::1]:9090 -> 9090
[/simterm]
Та переходимо до Status > Targets, і шукаємо Pushgateway target:
І перевіримо, чи потраплять метрики з Pushgateway до Prometheus.
Оскільки наш Ingress/ALB має тип internal
, тобто недоступний ззовні, то запустимо Kubernetes Pod з Ubuntu в Kubernetes-кластері:
[simterm]
$ kubectl run pod --rm -i --tty --image ubuntu -- bash If you don't see a command prompt, try pressing enter. root@pod:/#
[/simterm]
Встановлюємо в ньому curl
:
[simterm]
root@pod:/# apt update && apt -y install curl
[/simterm]
Та користуючись документацією відправимо запит, тільки порт не вказуємо, бо у нас він 443, SSL:
[simterm]
root@pod:/# echo "some_metric 3.14" | curl --data-binary @- https://test-pushgateway.monitoring.dev.exmaple.com/metrics/job/some_job
[/simterm]
Перевіряємо в Pushgateway:
Та у Prometheus:
Є, чудово.
Аутентифікація Pushgateway
Оскільки у нас Pushgateway працює на internal-ALB, то я не став поки робити аутентифікацію, бо він це все ще в процесі тестування, і поки невідомо як воно там зайде девелоперам.
Але у values є блок, з прикладом запуску контейнера з openshift/oauth-proxy
, а у Using OpenShift OAuth Proxy to secure your Applications on OpenShift наче непогано описано приклад його використання – якось можна буде спробувати.
Terraform та Helm для Pushgateway
“Так в проекті повелося” (с), що більша частина ресурсів у Kubernetes деплоїться за допомогою Terraform та його helm_release
resource.
У нас багато аккаунтів AWS, і в кожному буде свій ARN сертифікату, тож отримаємо його за допомогою Data Source (або можна створити власний за допомогою aws_acm_certificate
):
data "aws_acm_certificate" "wildcard" { domain = "*.${var.root_domain}" }
Змінна root_domain
у нас передається з основного модулю, та має вигляд monitoring.dev.example.com.
Для нашого values створюємо темплейт pushgateway-values.tpl.yaml
:
ingress: enabled: true className: alb path: / pathType: Prefix annotations: alb.ingress.kubernetes.io/scheme: internal alb.ingress.kubernetes.io/certificate-arn: ${acmWildcardArn} alb.ingress.kubernetes.io/target-type: ip hosts: - ${pushgatewayUrl} serviceMonitor: enabled: true namespace: monitoring additionalLabels: release: prometheus
І додаємо сам helm_release
, в якому у values[]
задаємо файл темплейту та пару змінних – ARN сертифікату, який отримали за допомогою data.aws_acm_certificate
, та домен для Ingress hosts
:
resource "helm_release" "pushgateway" { name = "prometheus-pushgateway" namespace = kubernetes_namespace.monitoring.id repository = "https://prometheus-community.github.io/helm-charts" chart = "prometheus-pushgateway" version = "2.1.3" max_history = 10 values = [ templatefile("${path.module}/configs/prometheus/pushgateway-values.tpl.yaml", { acmWildcardArn : data.aws_acm_certificate.wildcard.arn, pushgatewayUrl : "pushgateway.${var.root_domain}" }) ] }
Деплоїмо:
[simterm]
$ terraform apply ... module.monitoring.helm_release.pushgateway: Creating... module.monitoring.helm_release.pushgateway: Still creating... [10s elapsed] module.monitoring.helm_release.pushgateway: Still creating... [20s elapsed] module.monitoring.helm_release.pushgateway: Still creating... [30s elapsed] module.monitoring.helm_release.pushgateway: Creation complete after 32s [id=prometheus-pushgateway] ... Apply complete! Resources: 1 added, 1 changed, 0 destroyed.
[/simterm]
Перевіряємо Ingress та Pod:
[simterm]
$ kk -n monitoring get ingress,pod -l app.kubernetes.io/instance=prometheus-pushgateway NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/prometheus-pushgateway alb pushgateway.monitoring.dev.example.com internal-k8s-monitori-promethe-***-***.us-west-2.elb.amazonaws.com 80 10m NAME READY STATUS RESTARTS AGE pod/prometheus-pushgateway-55b9f5ffd6-sm9ck 1/1 Running 0 10m
[/simterm]
Все є.
Готово.